{"version":3,"sources":["fabric.js"],"names":["fabric","version","exports","document","window","require","jsdom","decodeURIComponent","createWindow","parentWindow","isTouchSupported","isLikelyNode","Buffer","SHARED_ATTRIBUTES","DPI","reNum","fontPaths","iMatrix","canvasModule","perfLimitSizeTotal","maxCacheSideLimit","minCacheSideLimit","charWidthsCache","devicePixelRatio","webkitDevicePixelRatio","mozDevicePixelRatio","_removeEventListener","eventName","handler","this","__eventListeners","eventListener","indexOf","util","array","fill","observe","arguments","length","prop","on","push","stopObserving","call","fire","options","listenersForEvent","i","len","filter","value","Observable","off","trigger","Collection","_objects","add","apply","_onObjectAdded","renderOnAddRemove","renderAll","insertAt","object","index","nonSplicing","objects","getObjects","splice","remove","somethingRemoved","_onObjectRemoved","forEachObject","callback","context","type","o","item","isEmpty","size","contains","complexity","reduce","memo","current","CommonMethods","_setOptions","set","_initGradient","filler","property","colorStops","Gradient","_initPattern","source","Pattern","_initClipping","clipTo","functionBody","getFunctionBody","Function","_setObject","obj","_set","key","get","toggle","global","sqrt","Math","atan2","pow","abs","PiBy180","PI","removeFromArray","idx","getRandomInt","min","max","floor","random","degreesToRadians","degrees","radiansToDegrees","radians","rotatePoint","point","origin","subtractEquals","v","rotateVector","Point","x","y","addEquals","vector","sin","cos","transformPoint","p","t","ignoreOffset","makeBoundingBoxFromPoints","points","xPoints","minX","maxX","width","yPoints","minY","maxY","left","top","height","invertTransform","a","r","toFixed","number","fractionDigits","parseFloat","Number","parseUnit","fontSize","unit","exec","Text","DEFAULT_SVG_FONT_SIZE","falseFunction","getKlass","namespace","string","camelize","charAt","toUpperCase","slice","resolveNamespace","parts","split","loadImage","url","crossOrigin","img","createImage","onload","onerror","log","src","enlivenObjects","reviver","onLoaded","numLoadedObjects","numTotalObjects","enlivenedObjects","forEach","fromObject","error","enlivenPatterns","patterns","numLoadedPatterns","numPatterns","enlivenedPatterns","pattern","groupSVGElements","elements","path","PathGroup","sourcePath","populateWithProperties","destination","properties","Object","prototype","toString","drawDashedLine","ctx","x2","y2","da","dx","dy","rot","dc","di","draw","save","translate","moveTo","rotate","restore","createCanvasElement","canvasEl","createElement","getContext","G_vmlCanvasManager","initElement","createAccessors","klass","propName","capitalizedPropName","setterName","getterName","proto","stateProperties","clipContext","receiver","beginPath","clip","multiplyTransformMatrices","b","is2x2","qrDecompose","angle","denom","scaleX","scaleY","skewX","skewY","translateX","translateY","customTransformMatrix","skewMatrixX","tan","scaleMatrix","resetObjectTransform","target","flipX","flipY","setAngle","fn","String","match","isTransparent","tolerance","_isTransparent","imageData","getImageData","l","data","parsePreserveAspectRatioAttribute","attribute","align","meetOrSlice","aspectRatioAttrs","pop","alignX","alignY","clearFabricFontCache","fontFamily","limitDimsByArea","ar","maximumArea","roughWidth","perfLimitSizeY","capValue","arcToSegmentsCache","segmentToBezierCache","boundsOfCurveCache","_join","Array","join","arcToSegments","toX","toY","rx","ry","large","sweep","rotateX","argsString","th","sinTh","cosTh","fromX","fromY","px","py","rx2","ry2","py2","px2","pl","root","s","cx","cy","cx1","cy1","mTheta","calcVectorAngle","dtheta","segments","ceil","result","mDelta","mT","th3","segmentToBezier","th2","argsString2","costh2","sinth2","costh3","sinth3","cp1X","cp1Y","cp2X","cp2Y","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","x0","y0","x1","y1","x3","y3","c","t1","t2","b2ac","sqrtb2ac","tvalues","bounds","mt","j","jlen","drawArc","fx","fy","coords","segs","segsNorm","bezierCurveTo","getBoundsOfArc","tx","ty","bound","find","byProperty","condition","searchElement","TypeError","n","POSITIVE_INFINITY","NEGATIVE_INFINITY","k","map","every","some","val","rv","invoke","method","args","value1","value2","extend","deep","Element","hasOwnProperty","clone","trim","replace","character","capitalize","firstLetterOnly","toLowerCase","escapeXml","Dummy","bind","thisArg","_this","concat","emptyFunction","IS_DONTENUM_BUGGY","addMethods","parent","superclass","constructor","returnValue","valueOf","Subclass","callSuper","methodName","parentMethod","superClassMethod","console","createClass","initialize","shift","subclasses","unknown","areHostMethods","methodNames","test","getElement","setElement","uid","getUniqueId","element","__uniqueID","createListener","wrappedHandler","e","event","addListener","removeListener","shouldUseAddListenerRemoveListener","documentElement","shouldUseAttachEventDetachEvent","listeners","handlers","addEventListener","removeEventListener","listener","attachEvent","detachEvent","existingHandler","handlersForEvent","pointerX","clientX","pointerY","clientY","_getPointer","pageProp","clientProp","touchProp","getPointer","srcElement","scroll","getScrollLeftTop","parseEl","supportsOpacity","style","opacity","supportsFilters","reOpacity","setOpacity","es","currentStyle","hasLayout","zoom","setStyle","styles","elementStyle","cssText","styleFloat","_slice","sliceCanConvertNodelists","getElementStyle","selectProp","toArray","arrayLike","childNodes","err","makeElement","tagName","attributes","el","className","htmlFor","setAttribute","docElement","body","scrollLeft","scrollTop","parentNode","host","nodeType","arr","defaultView","getComputedStyle","attr","undefined","makeElementUnselectable","onselectstart","unselectable","makeElementSelectable","getScript","headEl","getElementsByTagName","scriptEl","loading","onreadystatechange","readyState","appendChild","getById","id","getElementById","addClass","wrapElement","wrapper","replaceChild","getElementOffset","docElem","scrollLeftTop","doc","ownerDocument","box","offset","offsetAttributes","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","parseInt","getBoundingClientRect","clientLeft","clientTop","makeXHR","factories","ActiveXObject","XMLHttpRequest","emptyFn","request","param","onComplete","xhr","parameters","open","setRequestHeader","send","warn","noop","_requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","requestAnimFrame","animate","timestamp","time","start","Date","duration","finish","onChange","abort","easing","d","startValue","endValue","byValue","onStart","tick","ticktime","currentTime","timePerc","valuePerc","animateColor","fromColor","toColor","startColor","Color","getSource","endColor","begin","end","pos","color","posValue","colorEasing","normalize","asin","elastic","opts","easeInBounce","easeOutBounce","ease","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","easeOutSine","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInOutBounce","reAllowedSVGTagNames","reViewBoxTagNames","reNotAllowedAncestors","reAllowedParents","attributesMap","display","visibility","transform","fill-opacity","fill-rule","font-family","font-size","font-style","font-weight","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-decoration","text-anchor","colorAttributes","stroke","_getMultipleNodes","nodeNames","nodeName","nodeList","nodeArray","elementMatchesRule","selectors","firstMatching","parentMatching","selectorMatches","selector","doesSomeParentMatch","matcher","classNames","getAttribute","RegExp","elementById","node","nodelist","cssRules","gradientDefs","parseTransformAttribute","skewMatrix","matrix","commaWsp","reTransformList","reTransform","attributeValue","matrices","multiplierX","multiplierY","m","operation","combinedMatrix","reViewBoxAttrValue","applyViewboxTransform","viewBoxWidth","viewBoxHeight","viewBoxAttr","widthAttr","heightAttr","preserveAspectRatio","missingViewBox","missingDimAttr","toBeParsed","parsedDim","translateMatrix","firstChild","parseSVGDocument","parsingOptions","attrs","xlink","substr","el2","cloneNode","currentTrans","oldLength","el3","nodeValue","removeAttribute","parseUseDirectives","svgUid","__uid","descendants","selectNodes","hasAncestorWithNodeName","getGradientDefs","getCSSRules","parseElements","instances","reFontDeclaration","parseFontDeclaration","oStyle","fontStyle","fontWeight","lineHeight","isNaN","elList","idsToXlinkMap","parseAttributes","parentAttributes","ownAttributes","rule","getGlobalStylesForElement","parseStyleAttribute","normalizedAttr","normalizedValue","parsed","isArray","normalizedStyle","transformMatrix","visible","font","mergedAttrs","setAlpha","getAlpha","toRgba","_setStrokeFillOpacity","ElementsParser","parse","chunk","pair","parseStyleObject","parsePointsAttribute","parsedPoints","allRules","styleContents","textContent","text","ruleObj","propertyValuePairs","_rule","loadSVGFromURL","xml","responseXML","responseText","async","loadXML","results","_options","loadSVGFromString","DOMParser","parser","parseFromString","numElements","createObjects","_obj","createObject","fromElement","_createObject","checkIfDone","createCallback","resolveGradient","instanceFillValue","gradientId","that","scalarAdd","scalar","scalarAddEquals","subtract","scalarSubtract","scalarSubtractEquals","multiply","multiplyEquals","divide","divideEquals","eq","lt","lte","gt","gte","lerp","distanceFrom","midPointFrom","setXY","setX","setY","setFromPoint","swap","Intersection","status","appendPoint","appendPoints","intersectLineLine","a1","a2","b1","b2","uaT","ubT","uB","ua","ub","intersectLinePolygon","inter","intersectPolygonPolygon","points1","points2","intersectPolygonRectangle","r1","r2","topRight","bottomLeft","inter1","inter2","inter3","inter4","_tryParsingColor","setSource","hue2rgb","q","colorNameMap","sourceFromHex","sourceFromRgb","sourceFromHsl","_rgbToHsl","g","h","round","_source","toRgb","toHsl","hsl","toHsla","toHex","toHexa","alpha","toGrayscale","average","currentAlpha","toBlackWhite","threshold","overlayWith","otherColor","otherSource","reRGBa","reHSLa","reHex","aqua","black","blue","fuchsia","gray","grey","green","lime","maroon","navy","olive","orange","purple","red","silver","teal","white","yellow","fromRgb","fromSource","fromRgba","fromHsl","fromHsla","fromHex","isShortNotation","isRGBa","substring","oColor","getColorStop","colorAlpha","keyValuePairs","_convertPercentUnitsToValues","gradientUnits","propValue","addFactor","multFactor","ellipseMatrix","scaleFactor","offsetX","offsetY","gradientTransform","addColorStop","position","toObject","propertiesToInclude","toSVG","markup","commonAttributes","needsSwap","sort","group","reverse","minRadius","percentageShift","colorStop","toLive","gradient","createLinearGradient","createRadialGradient","instance","colorStopEls","forObject","repeat","setOptions","NUM_FRACTION_DIGITS","toDataURL","patternSource","patternWidth","patternHeight","patternOffsetX","patternOffsetY","patternImgSrc","complete","naturalWidth","naturalHeight","createPattern","Shadow","blur","affectStroke","includeDefaultValues","_parseShadow","shadow","shadowStr","offsetsAndBlur","reOffsetsAndBlur","fBoxX","fBoxY","StaticCanvas","CANVAS_INIT_ERROR","Error","_initStatic","backgroundColor","backgroundImage","overlayColor","overlayImage","stateful","controlsAboveOverlay","allowTouchScrolling","imageSmoothingEnabled","viewportTransform","backgroundVpt","overlayVpt","onBeforeScaleRotate","enableRetinaScaling","vptCoords","skipOffscreen","cb","_createLowerCanvas","_initOptions","_setImageSmoothing","interactive","_initRetinaScaling","setOverlayImage","setBackgroundImage","setBackgroundColor","setOverlayColor","calcOffset","_isRetinaScaling","getRetinaScaling","lowerCanvasEl","contextContainer","scale","_offset","image","__setBgOverlayImage","__setBgOverlayColor","webkitImageSmoothingEnabled","mozImageSmoothingEnabled","msImageSmoothingEnabled","oImageSmoothingEnabled","Image","_createCanvasElement","_applyCanvasStyle","getWidth","getHeight","setWidth","setDimensions","setHeight","dimensions","cssValue","cssOnly","_setBackstoreDimension","backstoreOnly","_setCssDimension","upperCanvasEl","cacheCanvasEl","wrapperEl","getZoom","setViewportTransform","vpt","activeGroup","_activeGroup","setCoords","calcViewportBoundaries","zoomToPoint","before","after","setZoom","absolutePan","relativePan","setupState","canvas","clearContext","clearRect","clear","_hasITextHandlers","_mouseUpITextHandler","_iTextInstances","canvasToDrawOn","renderCanvas","iVpt","tl","br","tr","bl","_renderBackground","_renderObjects","drawControls","_renderOverlay","render","_renderBackgroundOrOverlay","fillStyle","fillRect","getCenter","centerObjectH","_centerObject","getCenterPoint","centerObjectV","centerObject","center","viewportCenterObject","vpCenter","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","setPositionByOrigin","toDatalessJSON","toDatalessObject","_toObjectMethod","_toObjects","__serializeBgOverlay","excludeFromExport","_toObject","originalValue","bgImage","overlay","background","svgViewportTransformation","_setSVGPreamble","_setSVGHeader","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","row","rowIndex","charIndex","fontList","_setSVGObject","sendToBack","objs","unshift","bringToFront","sendBackwards","intersecting","newIdx","objsMoved","_findNewLowerIndex","intersectsWithObject","isContainedWithinObject","bringForward","_findNewUpperIndex","dispose","DataURLExporter","EMPTY_JSON","supports","setLineDash","toJSON","BaseBrush","strokeLineCap","strokeLineJoin","strokeDashArray","setShadow","_setBrushStyles","contextTop","strokeStyle","lineWidth","lineCap","lineJoin","_setShadow","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY","_resetShadow","PencilBrush","_points","onMouseDown","pointer","_prepareForDrawing","_captureDrawingPath","_render","onMouseMove","onMouseUp","_finalizeAndAddPath","_reset","_addPoint","pointerPoint","p1","p2","midPoint","quadraticCurveTo","lineTo","convertPointsToSVGPath","multSignX","multSignY","manyPoints","createPath","pathData","Path","strokeWidth","originX","originY","translateToGivenOrigin","closePath","CircleBrush","drawDot","addPoint","arc","radius","originalRenderOnAddRemove","circles","circle","Circle","Group","circleRadius","circleColor","SprayBrush","density","dotWidth","dotWidthVariance","randomOpacity","optimizeOverlapping","sprayChunks","addSprayChunk","rects","ilen","sprayChunk","rect","Rect","_getOptimizedRects","uniqueRects","uniqueRectsArray","sprayChunkPoints","globalAlpha","PatternBrush","getPatternSrc","patternCanvas","patternCtx","getPatternSrcFunction","getPattern","topLeft","_getLeftTopCoords","supportLineDash","Canvas","_initInteractive","_createCacheCanvas","uniScaleTransform","uniScaleKey","centeredScaling","centeredRotation","centeredKey","altActionKey","selection","selectionKey","altSelectionKey","selectionColor","selectionDashArray","selectionBorderColor","selectionLineWidth","hoverCursor","moveCursor","defaultCursor","freeDrawingCursor","rotationCursor","containerClass","perPixelTargetFind","targetFindTolerance","skipTargetFind","isDrawingMode","preserveObjectStacking","snapAngle","snapThreshold","stopContextMenu","fireRightClick","fireMiddleClick","_currentTransform","_groupSelector","_initWrapperElement","_createUpperCanvas","_initEventListeners","freeDrawingBrush","_chooseObjectsToRender","getActiveGroup","activeObject","getActiveObject","objsToRender","activeGroupObjects","contextTopDirty","renderTop","_drawSelection","_resetCurrentTransform","original","_shouldCenterTransform","action","_setOriginToCenter","mouseXSign","mouseYSign","containsPoint","xy","_normalizePointer","_findTargetCorner","calcTransformMatrix","invertedM","vptPointer","restorePointerVpt","isTargetTransparent","hasBorders","transparentCorners","contextCache","originalColor","selectionBackgroundColor","active","_renderControls","_shouldClearSelection","evented","selectable","centerTransform","altKey","_getOriginFromCorner","corner","_getActionFromCorner","_setupCurrentTransform","ex","ey","lastX","lastY","theta","shiftKey","_translateObject","newLeft","newTop","moveX","moveY","_changeSkewTransformOrigin","mouseMove","by","origins","0","skew","originA","originB","flipSign","skewSign","_skewObject","skewed","lockSkewingX","lockSkewingY","actualMouseByOrigin","constraintPosition","actualMouseByCenter","toLocalPoint","lastMouseByCenter","dim","_getTransformedDimensions","translateToOriginPoint","_setObjectSkew","localMouse","_dim","newValue","newDim","dimNoSkew","otherBy","_otherBy","_by","newDimMouse","atan","_scaleObject","lockScalingX","lockScalingY","lockScalingFlip","scaled","_setLocalMouse","_setObjectScale","changeX","changeY","forbidScalingX","forbidScalingY","_scaleObjectEqually","newScaleX","newScaleY","_flipObject","dist","lastDist","signX","signY","padding","_rotateObject","lastAngle","curAngle","hasRoated","rightAngleLocked","leftAngleLocked","setCursor","cursor","_resetObjectTransform","groupSelector","aleft","atop","_setLineDash","strokeRect","findTarget","skipGroup","activeTarget","activeTargetSubs","targets","_searchPossibleTargets","_fireOverOutEvents","overOpt","outOpt","hoveredTarget","_hoveredTarget","previousTarget","nextTarget","_checkTarget","isEditing","normalizedPointer","subTarget","subTargetCheck","ignoreZoom","cssScale","boundsWidth","boundsHeight","bottom","right","lowerCanvasClass","_copyCanvasStyle","class","touch-action","fromEl","toEl","getSelectionContext","getSelectionElement","_setActiveObject","_activeObject","onDeselect","setActiveObject","currentActiveObject","_discardActiveObject","discardActiveObject","_setActiveGroup","setActiveGroup","_discardActiveGroup","destroy","discardActiveGroup","deactivateAll","allObjects","deactivateAllWithDispatch","removeListeners","removeChild","_drawObjectsControls","originalProperties","_realizeGroupTransformOnObject","_unwindGroupTransformOnObject","originalValues","realizeTransform","_setCursorFromEvent","cursorOffset","mr","mb","ml","checkClick","which","button","cursorMap","_bindEvents","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","passive","eventjs","_onGesture","_onDrag","_onOrientationChange","_onShake","_onLongPress","eventsBinded","_onMouseUp","self","__onTransformGesture","__onDrag","__onMouseWheel","hiddenTextarea","focus","__onOrientationChange","__onShake","__onLongPress","stopPropagation","preventDefault","__onMouseDown","__onMouseUp","__onMouseMove","_shouldRender","isMoving","_previousPointer","_handleEvent","_isCurrentlyDrawing","_onMouseUpInDrawingMode","searchTarget","isClick","_finalizeCurrentTransform","actionPerformed","shouldRender","_maybeGroupObjects","__corner","eventType","targetObj","subTargets","_scaling","_restoreOriginXY","hasStateChanged","_previousOriginX","_previousOriginY","originPoint","_onMouseDownInDrawingMode","_onMouseMoveInDrawingMode","shouldGroup","_shouldGroup","_handleGrouping","_beforeTransform","saveState","_setCenterToOrigin","touches","_transformObject","reset","_beforeScaleTransform","_performTransformAction","_fire","_onScale","currentAction","_setCornerCursor","_getRotatedCornerCursor","hasRotatingPoint","getAngle","_updateActiveGroup","_createActiveGroup","saveCoords","removeWithUpdate","addWithUpdate","_createGroup","groupObjects","exitEditing","_groupSelectedObjects","_collectObjects","currentObject","selectionX1Y1","selectionX2Y2","intersectsWithRect","isContainedWithinRect","setObjectsCoords","supportQuality","format","quality","multiplier","cropping","__toDataURLWithMultiplier","origWidth","origHeight","scaledWidth","scaledHeight","newZoom","vp","newVp","originalInteractive","__toDataURL","toDataURLWithMultiplier","loadFromDatalessJSON","json","loadFromJSON","serialized","JSON","_enlivenObjects","_setBgOverlay","loaded","cbIfLoaded","__setBgOverlay","enlivedObject","_toDataURL","_toDataURLWithMultiplier","stringify","cloneWithoutData","backgroundImageOpacity","backgroundImageStretch","supportsLineDash","objectCaching","cornerSize","borderColor","borderDashArray","cornerColor","cornerStrokeColor","cornerStyle","cornerDashArray","fillRule","globalCompositeOperation","strokeMiterLimit","borderOpacityWhenMoving","borderScaleFactor","minScaleLimit","hasControls","rotatingPointOffset","lockMovementX","lockMovementY","lockRotation","lockUniScaling","statefullCache","noScaleCache","dirty","cacheProperties","_cacheProperties","_cacheCanvas","_cacheContext","_updateCacheCanvas","_limitCacheSize","dims","limitedDims","zoomX","capped","zoomY","_getCacheCanvasDimensions","objectScale","getObjectScaling","retina","_getNonTransformedDimensions","drawingWidth","drawingHeight","minCacheSize","dimensionsChanged","cacheWidth","cacheHeight","zoomChanged","shouldRedraw","additionalWidth","additionalHeight","shouldResizeCanvas","canvasWidth","canvasHeight","sizeGrowing","setTransform","cacheTranslationX","cacheTranslationY","fromLeft","_transformDone","_removeDefaultValues","scaling","shouldConstrainValue","isChanged","_constrainScale","setOnGroup","setSourcePath","getViewportTransform","isNotVisible","noTransform","isOnScreen","_setupCompositeOperation","drawSelectionBackground","_setOpacity","shouldCache","isCacheDirty","propertySet","drawObject","drawCacheOnCanvas","_removeCacheCanvas","needsItsOwnCache","isCaching","willDrawShadow","_setStrokeStyles","_setFillStyles","drawImage","skipCanvas","_removeShadow","miterLimit","dashArray","alternative","drawBordersInGroup","drawBorders","multX","multY","_applyPatternGradientTransform","patternTransform","_renderFill","_renderStroke","_renderDashedStroke","cloneAsImage","dataUrl","boundingRect","getBoundingRect","origParams","getLeft","getTop","originalCanvas","isType","setGradient","setPatternFill","setColor","shouldCenterOrigin","_resetOrigin","centerH","viewportCenterH","centerV","viewportCenterV","viewportCenter","getLocalPointer","pClicked","objectLeftTop","_fromObject","forceAsync","extraParam","originXOffset","originYOffset","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","leftTop","getPointByOrigin","adjustPosition","to","offsetFrom","offsetTo","hypotFull","xFull","yFull","_originalOriginX","_originalOriginY","multiplyMatrices","oCoords","aCoords","getCoords","absolute","calculate","calcCoords","pointTL","pointBR","other","lines","_getImageLines","_findCrossPoints","centerPoint","topline","rightline","bottomline","leftline","iLine","xcount","lineKey","getBoundingRectWidth","getBoundingRectHeight","scaleToWidth","boundingRectFactor","scaleToHeight","_calculateCurrentDimensions","currentWidth","currentHeight","_angle","_hypotenuse","mtr","skipAbsolute","_setCornerCoords","_calcRotateMatrix","rotateMatrix","dimensionMatrix","_calcDimensionsTransformMatrix","flipping","bbox","dimX","dimY","getSvgColorString","str","getSvgStyles","skipShadow","getSvgFilter","getSvgId","getSvgTransform","getSkewX","getSkewY","translatePart","anglePart","scalePart","skewXPart","skewYPart","addTranslateX","flipXPart","addTranslateY","getSvgTransformMatrix","_createBaseSVGMarkup","originalSet","saveProps","props","tmpObj","dashedPropertySet","keys","_isEqual","origValue","currentValue","firstPass","_controlsVisibility","isControlVisible","newTheta","cornerHypotenuse","cosHalfOffset","sinHalfOffset","wh","rotateHeight","scaleOffset","_drawControl","control","controlName","_getControlsVisibility","setControlVisible","setControlsVisibility","FX_DURATION","fxCenterObjectH","callbacks","empty","fxCenterObjectV","fxRemove","skipCallbacks","propsToAnimate","_animate","propPair","from","valueProgress","timeProgress","coordProps","makeEdgeToOriginGetter","propertyNames","originValues","axis1","axis2","dimension","nearest","farthest","Line","_setWidthHeight","_getLeftToOriginX","_getTopToOriginY","cp","calcLinePoints","origStrokeStyle","xMult","yMult","ATTRIBUTE_NAMES","parsedAttributes","line","pi","startAngle","endAngle","setRadius","startX","startY","endX","endY","largeFlag","getRadiusX","getRadiusY","Triangle","widthBy2","heightBy2","piBy2","Ellipse","getRx","getRy","ellipse","_initRxRy","w","isRounded","Polyline","_calcDimensions","pathOffset","diffX","diffY","commonRender","Polygon","_toString","commandLengths","repeatedCommands","M","fromArray","_parsePath","_setPositionDimensions","calcDim","_parseDimensions","_renderPathCommands","tempX","tempY","previous","subpathStartX","subpathStartY","controlX","controlY","chunks","addTransform","currentPath","coordsStr","coordsParsed","re","command","commandLength","repeatedCommand","klen","aX","aY","pathUrl","paths","parseDimensionsFromPaths","xC","yC","parentCache","caching","isSameColor","pathsToObject","originalDefaults","firstPathFill","pathFill","total","originalPaths","pathGroup","_lockProperties","isAlreadyGrouped","_updateObjectsCoords","_updateObjectsACoords","_calcBounds","skipCoordsChange","_updateObjectCoords","__origHasControls","objectLeft","objectTop","_restoreObjectsState","_setObjectActive","delegatedProperties","textDecoration","textAlign","objsToObject","_renderObject","originalHasRotatingPoint","_restoreObjectState","_originalLeft","_originalTop","hasMoved","onlyWidthHeight","iLen","jLen","_getBounds","minXY","maxXY","_lastScaleX","_lastScaleY","minimumScaleTrigger","filters","resizeFilters","_initElement","_element","_callback","_originalElement","_initConfig","applyFilters","_filteredEl","setCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","getSvgSrc","origFill","filtered","_src","setSrc","imgElement","forResizing","replacement","retinaScaling","minimumScale","applyTo","toBuffer","pngCompression","elementToDraw","imageMargins","_findMargins","_needsResize","marginX","marginY","scales","_resetWidthHeight","CSS_CANVAS","_initFilters","fromURL","imgOptions","preserveAR","_getAngleValueForStraighten","straighten","fxStraighten","straightenObject","fxStraightenObject","BaseFilter","Brightness","brightness","putImageData","Convolute","opaque","dstOff","scx","scy","srcOff","wt","weights","pixels","side","halfSide","sw","sh","output","createImageData","dst","alphaFac","GradientTransparency","Grayscale","Invert","Mask","mask","channel","maskEl","maskCanvasEl","maskData","Noise","noise","rand","Pixelate","blocksize","_i","_ilen","_j","_jlen","RemoveWhite","distance","limit","Sepia","avg","Sepia2","Tint","tintR","tintG","tintB","alpha1","Multiply","Blend","mode","tg","_r","_g","_b","isImage","_el","tmpCanvas","Resize","resizeType","lanczosLobes","rcpScaleX","rcpScaleY","oW","oH","dW","dH","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","multW","multH","signW","signH","doneW","doneH","stepW","stepH","tmpCtx","lobes","srcImg","destImg","srcData","destData","lanczos","xx","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","weight","fX","fY","xDiff","yDiff","chnl","origPix","w4","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","centerY","yy","centerX","w0","ColorMatrix","Contrast","contrast","contrastF","Saturate","saturate","adjust","_dimensionAffectingProps","_reNewline","_reSpacesAndTabs","textBackgroundColor","_fontSizeFraction","_fontSizeMult","charSpacing","__skipDimension","_initDimensions","_setTextStyles","_textLines","_splitTextIntoLines","_clearCache","_getTextWidth","cursorWidth","_getTextHeight","_renderTextLinesBackground","_renderText","_renderTextDecoration","_renderTextFill","_renderTextStroke","textBaseline","_getFontDeclaration","_getHeightOfSingleLine","_getHeightOfLine","maxWidth","_getLineWidth","currentLineWidth","_renderChars","chars","_char","shortM","additionalSpace","_getWidthOfCharSpacing","measureText","_renderTextLine","lineIndex","word","words","charOffset","wordsWidth","_getWidthOfWords","widthDiff","numSpaces","spaceWidth","leftOffset","_getLeftOffset","_getTopOffset","isEmptyStyles","_renderTextCommon","lineHeights","heightOfLine","maxHeight","_getLineLeftOffset","lineLeftOffset","lineTopOffset","originalFill","__lineWidths","__lineHeights","_shouldClearDimensionCache","shouldClear","_forceClearCache","_measureLine","finalWidth","halfOfVerticalBox","offsets","oLen","renderLinesAtOffset","additionalProperties","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","lineTop","textBgRects","textSpans","textTopOffset","textLeftOffset","_setSVGBg","_setSVGTextLineBg","_setSVGTextLineText","yPos","_getFillAttributes","_setSVGTextLineJustifed","fillColor","textHeightScaleFactor","scaledDiff","textHeight","offX","IText","selectionStart","selectionEnd","editable","editingBorderColor","cursorColor","cursorDelay","cursorDuration","_reSpace","_currentCursorOpacity","_selectionDirection","_abortCursorAnimation","__widthOfSpace","initBehavior","p3","setSelectionStart","_updateAndFire","setSelectionEnd","_fireSelectionChanged","_updateTextarea","getSelectionStyles","startIndex","endIndex","loc","get2DCursorLocation","_getStyleDeclaration","setSelectionStyles","_extendStyles","_getLineStyle","_setLineStyle","_setStyleDeclaration","clearContextTop","cursorOffsetCache","renderCursorOrSelection","_clearTextArea","boundaries","_getCursorBoundaries","renderCursor","renderSelection","getCurrentCharStyle","getCurrentCharFontSize","getCurrentCharColor","typeOfBoundaries","_getCursorBoundariesOffsets","lineLeft","topOffset","_getWidthOfChar","cursorLocation","charHeight","__isMousedown","startLine","endLine","realLineHeight","lineOffset","boxWidth","j2","j2len","_renderCharsFast","prevStyle","thisStyle","charsToRender","_hasStyleChanged","_renderChar","skipFillStrokeCheck","charWidth","shouldFill","shouldStroke","_charWidth","decl","_getHeightOfChar","_applyCharStylesGetWidth","jChar","fillText","strokeText","_renderCharDecoration","decoration","decorationWeight","positions","underline","line-through","overline","decorations","leftCache","topCache","widthCache","heightCache","colorCache","_getWidthOfCharsAt","_getCacheProp","styleDeclaration","_getFontCache","cacheProp","charDecl","_applyFontStyles","returnCloneOrEmpty","_deleteStyleDeclaration","_deleteLineStyle","_isMeasuring","_getWidthOfSpace","currentCharHeight","initAddedHandler","initRemovedHandler","initCursorSelectionHandlers","initDoubleClickSimulation","mouseMoveHandler","selected","_initCanvasHandlers","_removeCanvasHandlers","_tick","_currentTickState","_animateCursor","targetOpacity","completeMethod","tickState","isAborted","_onTickComplete","_cursorTimeout1","clearTimeout","_currentTickCompleteState","initDelayedCursor","restart","delay","abortCursorAnimation","_cursorTimeout2","selectAll","getSelectedText","findWordBoundaryLeft","startFrom","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","getNumNewLinesInSelectedText","selectedText","numNewLines","searchWordBoundary","direction","reNonWord","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditing","exitEditingOnOthers","initHiddenTextarea","_saveEditingProps","_setEditingProps","_textBeforeEdit","initMouseMoveHandler","getSelectionStartFromPointer","currentStart","currentEnd","__selectionStartOnMouseDown","restartCursorIfNeeded","inCompositionMode","_calcTextareaPosition","upperCanvas","_savedProps","_restoreEditingProps","overCursor","isTextChanged","_removeExtraneousStyles","_removeCharsFromTo","_removeSingleCharAndStyle","isBeginningOfLine","indexStyle","removeStyleObject","insertChars","_chars","useCopiedStyle","copiedTextStyle","insertChar","skipUpdate","styleObject","isEndOfLine","insertStyleObjects","insertNewlineStyleObject","shiftLineStyles","currentCharStyle","newLineStyles","somethingAdded","numIndex","insertCharStyleObject","currentLineStyles","currentLineStylesCloned","numericIndex","newStyle","clonedStyles","numericLine","_removeStyleObject","_getTextOnPreviousLine","lIndex","textOnPreviousLine","newCharIndexOnPrevLine","insertNewline","setSelectionStartEndWithShift","newSelection","setSelectionInBoundaries","__lastClickTime","__lastLastClickTime","__lastPointer","__newClickTime","newPointer","isTripleClick","_stopEvent","isDoubleClick","__lastIsEditing","__lastSelected","initMousedownHandler","initMouseupHandler","initClicks","__mousedownX","__mousedownY","setCursorByClick","_isObjectMoved","mouseOffset","prevWidth","widthOfLine","_getNewSelectionStartFromOffset","onKeyDown","onKeyUp","onInput","copy","cut","paste","onCompositionStart","onCompositionUpdate","onCompositionEnd","_clickHandlerInitialized","onClick","keysMap","8","9","27","13","33","34","35","36","37","38","39","40","46","ctrlKeysMapUp","67","88","ctrlKeysMapDown","65","keyCode","ctrlKey","metaKey","stopImmediatePropagation","_copyDone","diff","charsToInsert","offsetEnd","textLength","newTextLength","prevCompositionLength","compositionStart","forwardDelete","moveCursorRight","removeChars","clipboardData","_getClipboardData","setData","copiedText","getData","_getWidthBeforeCursor","textBeforeCursor","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","getUpCursorOffset","foundMatch","textOnLine","widthOfCharsOnLine","indexOnLine","widthOfChar","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","actionName","moveCursorRightWithShift","moveCursorRightWithoutShift","changed","_removeCharsNearCursor","leftLineBoundary","leftWordBoundary","_setSVGTextLineChars","_getSVGLineTopOffset","styleDecl","_createTextCharSpan","_createTextCharBg","lastHeight","fillStyles","Textbox","minWidth","dynamicMinWidth","__cachedLines","getTextboxControlVisibility","_generateStyleMap","realLineCount","realLineCharCount","charCount","_styleMap","_wrapText","wrapped","_wrapLine","_measureText","wordWidth","infixWidth","largestWordWidth","lineJustStarted","originalAlign","__oldScaleX","numLines","removed","lineLen","lineChars","getMinWidth","setObjectScaleOverridden","_refreshControlsVisibility","override","tmp","URL","HTTP","HTTPS","createImageAndCallBack","requestFs","eval","createCanvasForNode","nodeCanvasOptions","nodeCanvas","nodeCacheCanvas","fabricCanvas","Font","originaInitStatic","createPNGStream","createJPEGStream","origSetBackstoreDimension","oURL","port","protocol","req","hostname","response","setEncoding","statusCode","errno","ECONNREFUSED","message","readFile"],"mappings":"AAGA,IAAIA,OAASA,QAAU,CAAEC,QAAS,UACX,oBAAZC,UACTA,QAAQF,OAASA,QAGK,oBAAbG,UAA8C,oBAAXC,QAC5CJ,OAAOG,SAAWA,SAClBH,OAAOI,OAASA,OAEhBA,OAAOJ,OAASA,SAIhBA,OAAOG,SAAWE,QAAQ,SACvBC,MACCC,mBAAmB,+FAGnBP,OAAOG,SAASK,aAClBR,OAAOI,OAASJ,OAAOG,SAASK,eAEhCR,OAAOI,OAASJ,OAAOG,SAASM,cASpCT,OAAOU,iBAAmB,iBAAkBV,OAAOI,OAMnDJ,OAAOW,aAAiC,oBAAXC,QACW,oBAAXR,OAO7BJ,OAAOa,kBAAoB,CACzB,UACA,YACA,OAAQ,eAAgB,YACxB,UACA,SAAU,mBAAoB,iBAC9B,kBAAmB,oBACnB,iBAAkB,eAClB,MAOFb,OAAOc,IAAM,GACbd,OAAOe,MAAQ,+CACff,OAAOgB,UAAY,GACnBhB,OAAOiB,QAAU,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GACjCjB,OAAOkB,aAAe,SAQtBlB,OAAOmB,mBAAqB,QAQ5BnB,OAAOoB,kBAAoB,KAQ3BpB,OAAOqB,kBAAoB,IAK3BrB,OAAOsB,gBAAkB,GAMzBtB,OAAOuB,iBAAmBvB,OAAOI,OAAOmB,kBACdvB,OAAOI,OAAOoB,wBACdxB,OAAOI,OAAOqB,qBACd,EAG1B,WAOE,SAASC,EAAqBC,EAAWC,GACvC,GAAKC,KAAKC,iBAAiBH,GAA3B,CAGA,IAAII,EAAgBF,KAAKC,iBAAiBH,GACtCC,EACFG,EAAcA,EAAcC,QAAQJ,KAAY,EAGhD5B,OAAOiC,KAAKC,MAAMC,KAAKJ,GAAe,IAc1C,SAASK,EAAQT,EAAWC,GAK1B,GAJKC,KAAKC,mBACRD,KAAKC,iBAAmB,IAGD,IAArBO,UAAUC,OACZ,IAAK,IAAIC,KAAQZ,EACfE,KAAKW,GAAGD,EAAMZ,EAAUY,SAIrBV,KAAKC,iBAAiBH,KACzBE,KAAKC,iBAAiBH,GAAa,IAErCE,KAAKC,iBAAiBH,GAAWc,KAAKb,GAExC,OAAOC,KAcT,SAASa,EAAcf,EAAWC,GAChC,GAAKC,KAAKC,iBAAV,CAKA,GAAyB,IAArBO,UAAUC,OACZ,IAAKX,KAAaE,KAAKC,iBACrBJ,EAAqBiB,KAAKd,KAAMF,QAI/B,GAAyB,IAArBU,UAAUC,QAAwC,iBAZtCX,EAanB,IAAK,IAAIY,KAAQZ,EACfD,EAAqBiB,KAAKd,KAAMU,EAAMZ,EAAUY,SAIlDb,EAAqBiB,KAAKd,KAAMF,EAAWC,GAE7C,OAAOC,MAaT,SAASe,EAAKjB,EAAWkB,GACvB,GAAKhB,KAAKC,iBAAV,CAIA,IAAIgB,EAAoBjB,KAAKC,iBAAiBH,GAC9C,GAAKmB,EAAL,CAIA,IAAK,IAAIC,EAAI,EAAGC,EAAMF,EAAkBR,OAAQS,EAAIC,EAAKD,IACvDD,EAAkBC,IAAMD,EAAkBC,GAAGJ,KAAKd,KAAMgB,GAAW,IAKrE,OAHAhB,KAAKC,iBAAiBH,GAAamB,EAAkBG,OAAO,SAASC,GACnE,OAAiB,IAAVA,IAEFrB,OAQT7B,OAAOmD,WAAa,CAClBf,QAASA,EACTM,cAAeA,EACfE,KAAMA,EAENJ,GAAIJ,EACJgB,IAAKV,EACLW,QAAST,GA5Hb,GAoIA5C,OAAOsD,WAAa,CAElBC,SAAU,GAcVC,IAAK,WAEH,GADA3B,KAAK0B,SAASd,KAAKgB,MAAM5B,KAAK0B,SAAUlB,WACpCR,KAAK6B,eACP,IAAK,IAAIX,EAAI,EAAGT,EAASD,UAAUC,OAAQS,EAAIT,EAAQS,IACrDlB,KAAK6B,eAAerB,UAAUU,IAIlC,OADAlB,KAAK8B,mBAAqB9B,KAAK+B,YACxB/B,MAeTgC,SAAU,SAAUC,EAAQC,EAAOC,GACjC,IAAIC,EAAUpC,KAAKqC,aASnB,OARIF,EACFC,EAAQF,GAASD,EAGjBG,EAAQE,OAAOJ,EAAO,EAAGD,GAE3BjC,KAAK6B,gBAAkB7B,KAAK6B,eAAeI,GAC3CjC,KAAK8B,mBAAqB9B,KAAK+B,YACxB/B,MASTuC,OAAQ,WAIN,IAHA,IACIL,EADAE,EAAUpC,KAAKqC,aACRG,GAAmB,EAErBtB,EAAI,EAAGT,EAASD,UAAUC,OAAQS,EAAIT,EAAQS,KAItC,KAHfgB,EAAQE,EAAQjC,QAAQK,UAAUU,OAIhCsB,GAAmB,EACnBJ,EAAQE,OAAOJ,EAAO,GACtBlC,KAAKyC,kBAAoBzC,KAAKyC,iBAAiBjC,UAAUU,KAK7D,OADAlB,KAAK8B,mBAAqBU,GAAoBxC,KAAK+B,YAC5C/B,MAeT0C,cAAe,SAASC,EAAUC,GAEhC,IADA,IAAIR,EAAUpC,KAAKqC,aACVnB,EAAI,EAAGC,EAAMiB,EAAQ3B,OAAQS,EAAIC,EAAKD,IAC7CyB,EAAS7B,KAAK8B,EAASR,EAAQlB,GAAIA,EAAGkB,GAExC,OAAOpC,MASTqC,WAAY,SAASQ,GACnB,YAAoB,IAATA,EACF7C,KAAK0B,SAEP1B,KAAK0B,SAASN,OAAO,SAAS0B,GACnC,OAAOA,EAAED,OAASA,KAStBE,KAAM,SAAUb,GACd,OAAOlC,KAAKqC,aAAaH,IAO3Bc,QAAS,WACP,OAAoC,IAA7BhD,KAAKqC,aAAa5B,QAO3BwC,KAAM,WACJ,OAAOjD,KAAKqC,aAAa5B,QAQ3ByC,SAAU,SAASjB,GACjB,OAA4C,EAArCjC,KAAKqC,aAAalC,QAAQ8B,IAOnCkB,WAAY,WACV,OAAOnD,KAAKqC,aAAae,OAAO,SAAUC,EAAMC,GAE9C,OADAD,GAAQC,EAAQH,WAAaG,EAAQH,aAAe,GAEnD,KAQPhF,OAAOoF,cAAgB,CAMrBC,YAAa,SAASxC,GACpB,IAAK,IAAIN,KAAQM,EACfhB,KAAKyD,IAAI/C,EAAMM,EAAQN,KAS3BgD,cAAe,SAASC,EAAQC,IAC1BD,IAAUA,EAAOE,YAAgBF,aAAkBxF,OAAO2F,UAC5D9D,KAAKyD,IAAIG,EAAU,IAAIzF,OAAO2F,SAASH,KAU3CI,aAAc,SAASJ,EAAQC,EAAUjB,IACnCgB,IAAUA,EAAOK,QAAYL,aAAkBxF,OAAO8F,QAIxDtB,GAAYA,IAHZ3C,KAAKyD,IAAIG,EAAU,IAAIzF,OAAO8F,QAAQN,EAAQhB,KAWlDuB,cAAe,SAASlD,GACtB,GAAKA,EAAQmD,QAAoC,iBAAnBnD,EAAQmD,OAAtC,CAIA,IAAIC,EAAejG,OAAOiC,KAAKiE,gBAAgBrD,EAAQmD,aAC3B,IAAjBC,IACTpE,KAAKmE,OAAS,IAAIG,SAAS,MAAOF,MAOtCG,WAAY,SAASC,GACnB,IAAK,IAAI9D,KAAQ8D,EACfxE,KAAKyE,KAAK/D,EAAM8D,EAAI9D,KAWxB+C,IAAK,SAASiB,EAAKrD,GAYjB,MAXmB,iBAARqD,EACT1E,KAAKuE,WAAWG,GAGK,mBAAVrD,GAAgC,WAARqD,EACjC1E,KAAKyE,KAAKC,EAAKrD,EAAMrB,KAAK2E,IAAID,KAG9B1E,KAAKyE,KAAKC,EAAKrD,GAGZrB,MAGTyE,KAAM,SAASC,EAAKrD,GAClBrB,KAAK0E,GAAOrD,GASduD,OAAQ,SAAShB,GACf,IAAIvC,EAAQrB,KAAK2E,IAAIf,GAIrB,MAHqB,kBAAVvC,GACTrB,KAAKyD,IAAIG,GAAWvC,GAEfrB,MAQT2E,IAAK,SAASf,GACZ,OAAO5D,KAAK4D,KAKhB,SAAUiB,GAER,IAAIC,EAAOC,KAAKD,KACZE,EAAQD,KAAKC,MACbC,EAAMF,KAAKE,IACXC,EAAMH,KAAKG,IACXC,EAAUJ,KAAKK,GAAK,IAKxBjH,OAAOiC,KAAO,CAWZiF,gBAAiB,SAAShF,EAAOgB,GAC/B,IAAIiE,EAAMjF,EAAMF,QAAQkB,GAIxB,OAHa,IAATiE,GACFjF,EAAMiC,OAAOgD,EAAK,GAEbjF,GAWTkF,aAAc,SAASC,EAAKC,GAC1B,OAAOV,KAAKW,MAAMX,KAAKY,UAAYF,EAAMD,EAAM,IAAMA,GAUvDI,iBAAkB,SAASC,GACzB,OAAOA,EAAUV,GAUnBW,iBAAkB,SAASC,GACzB,OAAOA,EAAUZ,GAYnBa,YAAa,SAASC,EAAOC,EAAQH,GACnCE,EAAME,eAAeD,GACrB,IAAIE,EAAIjI,OAAOiC,KAAKiG,aAAaJ,EAAOF,GACxC,OAAO,IAAI5H,OAAOmI,MAAMF,EAAEG,EAAGH,EAAEI,GAAGC,UAAUP,IAW9CG,aAAc,SAASK,EAAQX,GAC7B,IAAIY,EAAM5B,KAAK4B,IAAIZ,GACfa,EAAM7B,KAAK6B,IAAIb,GAGnB,MAAO,CACLQ,EAHOG,EAAOH,EAAIK,EAAMF,EAAOF,EAAIG,EAInCH,EAHOE,EAAOH,EAAII,EAAMD,EAAOF,EAAII,IAgBvCC,eAAgB,SAASC,EAAGC,EAAGC,GAC7B,OAAIA,EACK,IAAI7I,OAAOmI,MAChBS,EAAE,GAAKD,EAAEP,EAAIQ,EAAE,GAAKD,EAAEN,EACtBO,EAAE,GAAKD,EAAEP,EAAIQ,EAAE,GAAKD,EAAEN,GAGnB,IAAIrI,OAAOmI,MAChBS,EAAE,GAAKD,EAAEP,EAAIQ,EAAE,GAAKD,EAAEN,EAAIO,EAAE,GAC5BA,EAAE,GAAKD,EAAEP,EAAIQ,EAAE,GAAKD,EAAEN,EAAIO,EAAE,KAShCE,0BAA2B,SAASC,GAClC,IAAIC,EAAU,CAACD,EAAO,GAAGX,EAAGW,EAAO,GAAGX,EAAGW,EAAO,GAAGX,EAAGW,EAAO,GAAGX,GAC5Da,EAAOjJ,OAAOiC,KAAKC,MAAMmF,IAAI2B,GAC7BE,EAAOlJ,OAAOiC,KAAKC,MAAMoF,IAAI0B,GAC7BG,EAAQvC,KAAKG,IAAIkC,EAAOC,GACxBE,EAAU,CAACL,EAAO,GAAGV,EAAGU,EAAO,GAAGV,EAAGU,EAAO,GAAGV,EAAGU,EAAO,GAAGV,GAC5DgB,EAAOrJ,OAAOiC,KAAKC,MAAMmF,IAAI+B,GAC7BE,EAAOtJ,OAAOiC,KAAKC,MAAMoF,IAAI8B,GAGjC,MAAO,CACLG,KAAMN,EACNO,IAAKH,EACLF,MAAOA,EACPM,OANW7C,KAAKG,IAAIsC,EAAOC,KAiB/BI,gBAAiB,SAASd,GACxB,IAAIe,EAAI,GAAKf,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAE,IAChCgB,EAAI,CAACD,EAAIf,EAAE,IAAKe,EAAIf,EAAE,IAAKe,EAAIf,EAAE,GAAIe,EAAIf,EAAE,IAC3CjE,EAAI3E,OAAOiC,KAAKyG,eAAe,CAAEN,EAAGQ,EAAE,GAAIP,EAAGO,EAAE,IAAMgB,GAAG,GAG5D,OAFAA,EAAE,IAAMjF,EAAEyD,EACVwB,EAAE,IAAMjF,EAAE0D,EACHuB,GAWTC,QAAS,SAASC,EAAQC,GACxB,OAAOC,WAAWC,OAAOH,GAAQD,QAAQE,KAU3CG,UAAW,SAAShH,EAAOiH,GACzB,IAAIC,EAAO,WAAWC,KAAKnH,GACvB4G,EAASE,WAAW9G,GAIxB,OAHKiH,IACHA,EAAWnK,OAAOsK,KAAKC,uBAEjBH,EAAK,IACX,IAAK,KACH,OAAON,EAAS9J,OAAOc,IAAM,KAE/B,IAAK,KACH,OAAOgJ,EAAS9J,OAAOc,IAAM,KAE/B,IAAK,KACH,OAAOgJ,EAAS9J,OAAOc,IAEzB,IAAK,KACH,OAAOgJ,EAAS9J,OAAOc,IAAM,GAE/B,IAAK,KACH,OAAOgJ,EAAS9J,OAAOc,IAAM,GAAK,GAEpC,IAAK,KACH,OAAOgJ,EAASK,EAElB,QACE,OAAOL,IAUbU,cAAe,WACb,OAAO,GAUTC,SAAU,SAAS/F,EAAMgG,GAGvB,OADAhG,EAAO1E,OAAOiC,KAAK0I,OAAOC,SAASlG,EAAKmG,OAAO,GAAGC,cAAgBpG,EAAKqG,MAAM,IACtE/K,OAAOiC,KAAK+I,iBAAiBN,GAAWhG,IASjDsG,iBAAkB,SAASN,GACzB,IAAKA,EACH,OAAO1K,OAGT,IACwB+C,EADpBkI,EAAQP,EAAUQ,MAAM,KACxBlI,EAAMiI,EAAM3I,OACZ+D,EAAMK,GAAU1G,OAAOI,OAE3B,IAAK2C,EAAI,EAAGA,EAAIC,IAAOD,EACrBsD,EAAMA,EAAI4E,EAAMlI,IAGlB,OAAOsD,GAWT8E,UAAW,SAASC,EAAK5G,EAAUC,EAAS4G,GAC1C,GAAKD,EAAL,CAKA,IAAIE,EAAMtL,OAAOiC,KAAKsJ,cAGtBD,EAAIE,OAAS,WACXhH,GAAYA,EAAS7B,KAAK8B,EAAS6G,GACnCA,EAAMA,EAAIE,OAASF,EAAIG,QAAU,MAInCH,EAAIG,QAAU,WACZzL,OAAO0L,IAAI,iBAAmBJ,EAAIK,KAClCnH,GAAYA,EAAS7B,KAAK8B,EAAS,MAAM,GACzC6G,EAAMA,EAAIE,OAASF,EAAIG,QAAU,MAOP,IAAxBL,EAAIpJ,QAAQ,SAAiBqJ,IAC/BC,EAAID,YAAcA,GAGpBC,EAAIK,IAAMP,OA3BR5G,GAAYA,EAAS7B,KAAK8B,EAAS2G,IAwCvCQ,eAAgB,SAAS3H,EAASO,EAAUkG,EAAWmB,GAGrD,SAASC,MACDC,IAAqBC,GACzBxH,GAAYA,EAASyH,GAIzB,IAAIA,EAAmB,GACnBF,EAAmB,EACnBC,GAVJ/H,EAAUA,GAAW,IAUS3B,OAGzB0J,EAKL/H,EAAQiI,QAAQ,SAAUvH,EAAGZ,GAEtBY,GAAMA,EAAED,KAID1E,OAAOiC,KAAKwI,SAAS9F,EAAED,KAAMgG,GACnCyB,WAAWxH,EAAG,SAAU0B,EAAK+F,GACjCA,IAAUH,EAAiBlI,GAASsC,GACpCwF,GAAWA,EAAQlH,EAAG0B,EAAK+F,GAC3BN,MAjBa,GAUbA,MAPFtH,GAAYA,EAASyH,IA6BzBI,gBAAiB,SAASC,EAAU9H,GAGlC,SAASsH,MACDS,IAAsBC,GAC1BhI,GAAYA,EAASiI,GAIzB,IAAIA,EAAoB,GACpBF,EAAoB,EACpBC,GAVJF,EAAWA,GAAY,IAUIhK,OAEtBkK,EAKLF,EAASJ,QAAQ,SAAUvD,EAAG5E,GACxB4E,GAAKA,EAAE9C,OACT,IAAI7F,OAAO8F,QAAQ6C,EAAG,SAAS+D,GAC7BD,EAAkB1I,GAAS2I,EAC3BZ,OAIFW,EAAkB1I,GAAS4E,EAC3BmD,OAbFtH,GAAYA,EAASiI,IA2BzBE,iBAAkB,SAASC,EAAU/J,EAASgK,GAC5C,IAAI/I,EAOJ,OALAA,EAAS,IAAI9D,OAAO8M,UAAUF,EAAU/J,QAEpB,IAATgK,IACT/I,EAAOiJ,WAAaF,GAEf/I,GAWTkJ,uBAAwB,SAASnH,EAAQoH,EAAaC,GACpD,GAAIA,GAA6D,mBAA/CC,OAAOC,UAAUC,SAAS1K,KAAKuK,GAC/C,IAAK,IAAInK,EAAI,EAAGC,EAAMkK,EAAW5K,OAAQS,EAAIC,EAAKD,IAC5CmK,EAAWnK,KAAM8C,IACnBoH,EAAYC,EAAWnK,IAAM8C,EAAOqH,EAAWnK,MAmBvDuK,eAAgB,SAASC,EAAKnF,EAAGC,EAAGmF,EAAIC,EAAIC,GAC1C,IAAIC,EAAKH,EAAKpF,EACVwF,EAAKH,EAAKpF,EACVrF,EAAM2D,EAAKgH,EAAKA,EAAKC,EAAKA,GAC1BC,EAAMhH,EAAM+G,EAAID,GAChBG,EAAKJ,EAAGpL,OACRyL,EAAK,EACLC,GAAO,EAQX,IANAT,EAAIU,OACJV,EAAIW,UAAU9F,EAAGC,GACjBkF,EAAIY,OAAO,EAAG,GACdZ,EAAIa,OAAOP,GAEXzF,EAAI,EACSA,EAANpF,GAEGA,GADRoF,GAAKsF,EAAGK,IAAOD,MAEb1F,EAAIpF,GAENuK,EAAIS,EAAO,SAAW,UAAU5F,EAAG,GACnC4F,GAAQA,EAGVT,EAAIc,WAWNC,oBAAqB,SAASC,GAO5B,OANAA,IAAaA,EAAWvO,OAAOG,SAASqO,cAAc,WAEjDD,EAASE,YAA4C,oBAAvBC,oBACjCA,mBAAmBC,YAAYJ,GAG1BA,GASThD,YAAa,WACX,OAAOvL,OAAOW,aACV,IAAKN,QAAQ,UAAe,OAC5BL,OAAOG,SAASqO,cAAc,QASpCI,gBAAiB,SAASC,GACxB,IAA6B9L,EAAG+L,EAC5BC,EAAqBC,EAAYC,EADjCC,EAAQL,EAAMzB,UAGlB,IAAKrK,EAAImM,EAAMC,gBAAgB7M,OAAQS,KAIrCiM,EAAa,OADbD,GADAD,EAAWI,EAAMC,gBAAgBpM,IACF8H,OAAO,GAAGC,cAAgBgE,EAAS/D,MAAM,IAKnEmE,EAHLD,EAAa,MAAQF,KAInBG,EAAMD,GACG,IAAI9I,SAAS,oBACnB2I,EADoD,OAGpDI,EAAMF,KACTE,EAAMF,GACG,IAAI7I,SAAS,QAAS,oBAC5B2I,EAD6D,eAYtEM,YAAa,SAASC,EAAU9B,GAC9BA,EAAIU,OACJV,EAAI+B,YACJD,EAASrJ,OAAOuH,GAChBA,EAAIgC,QAYNC,0BAA2B,SAAS7F,EAAG8F,EAAGC,GAExC,MAAO,CACL/F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GACvB9F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GACvB9F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GACvB9F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GACvBC,EAAQ,EAAI/F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAC1C+F,EAAQ,EAAI/F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,GAAK8F,EAAE,GAAK9F,EAAE,KAW9CgG,YAAa,SAAShG,GACpB,IAAIiG,EAAQ/I,EAAM8C,EAAE,GAAIA,EAAE,IACtBkG,EAAQ/I,EAAI6C,EAAE,GAAI,GAAK7C,EAAI6C,EAAE,GAAI,GACjCmG,EAASnJ,EAAKkJ,GACdE,GAAUpG,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAG,IAAMmG,EACxCE,EAAQnJ,EAAM8C,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAG,GAAIkG,GAC9C,MAAO,CACLD,MAAOA,EAAS5I,EAChB8I,OAAQA,EACRC,OAAQA,EACRC,MAAOA,EAAQhJ,EACfiJ,MAAO,EACPC,WAAYvG,EAAE,GACdwG,WAAYxG,EAAE,KAIlByG,sBAAuB,SAASN,EAAQC,EAAQC,GAC9C,IAAIK,EAAc,CAAC,EAAG,EAAGtJ,EAAIH,KAAK0J,IAAIN,EAAQhJ,IAAW,GACrDuJ,EAAc,CAACxJ,EAAI+I,GAAS,EAAG,EAAG/I,EAAIgJ,IAC1C,OAAO/P,OAAOiC,KAAKuN,0BAA0Be,EAAaF,GAAa,IAGzEG,qBAAsB,SAAUC,GAC9BA,EAAOX,OAAS,EAChBW,EAAOV,OAAS,EAChBU,EAAOT,MAAQ,EACfS,EAAOR,MAAQ,EACfQ,EAAOC,OAAQ,EACfD,EAAOE,OAAQ,EACfF,EAAOG,SAAS,IAQlB1K,gBAAiB,SAAS2K,GACxB,OAAQC,OAAOD,GAAIE,MAAM,+BAAiC,IAAI,IAWhEC,cAAe,SAASzD,EAAKnF,EAAGC,EAAG4I,GAIjB,EAAZA,IACMA,EAAJ7I,EACFA,GAAK6I,EAGL7I,EAAI,EAEE6I,EAAJ5I,EACFA,GAAK4I,EAGL5I,EAAI,GAIR,IAA2BtF,EAAvBmO,GAAiB,EACjBC,EAAY5D,EAAI6D,aAAahJ,EAAGC,EAAgB,EAAZ4I,GAAkB,EAAgB,EAAZA,GAAkB,GAC5EI,EAAIF,EAAUG,KAAKhP,OAGvB,IAAKS,EAAI,EAAGA,EAAIsO,IAGS,KADvBH,EADOC,EAAUG,KAAKvO,IACG,GAFRA,GAAK,GAUxB,OAFAoO,EAAY,KAELD,GAQTK,kCAAmC,SAASC,GAC1C,IAC6CC,EADzCC,EAAc,OACdC,EAAmBH,EAAUtG,MAAM,KAevC,OAbIyG,GAAoBA,EAAiBrP,SAEnB,UADpBoP,EAAcC,EAAiBC,QACe,UAAhBF,GAC5BD,EAAQC,EACRA,EAAc,QAEPC,EAAiBrP,SACxBmP,EAAQE,EAAiBC,QAMtB,CACLF,YAAaA,EACbG,OAJiB,SAAVJ,EAAmBA,EAAM1G,MAAM,EAAG,GAAK,OAK9C+G,OAJiB,SAAVL,EAAmBA,EAAM1G,MAAM,EAAG,GAAK,SAalDgH,qBAAsB,SAASC,GACxBA,EAGIhS,OAAOsB,gBAAgB0Q,WACvBhS,OAAOsB,gBAAgB0Q,GAH9BhS,OAAOsB,gBAAkB,IAgB7B2Q,gBAAiB,SAASC,EAAIC,GAC5B,IAAIC,EAAaxL,KAAKD,KAAKwL,EAAcD,GACrCG,EAAiBzL,KAAKW,MAAM4K,EAAcC,GAC9C,MAAO,CAAEhK,EAAGxB,KAAKW,MAAM6K,GAAa/J,EAAGgK,IAGzCC,SAAU,SAASjL,EAAKnE,EAAOoE,GAC7B,OAAOV,KAAKU,IAAID,EAAKT,KAAKS,IAAInE,EAAOoE,MAjsB3C,CAqsBsB,oBAAZpH,QAA0BA,QAAU2B,MAG9C,WAEE,IAAI0Q,EAAqB,GACrBC,EAAuB,GACvBC,EAAqB,GACrBC,EAAQC,MAAMvF,UAAUwF,KAM5B,SAASC,EAAcC,EAAKC,EAAKC,EAAIC,EAAIC,EAAOC,EAAOC,GACrD,IAAIC,EAAaX,EAAM/P,KAAKN,WAC5B,GAAIkQ,EAAmBc,GACrB,OAAOd,EAAmBc,GAG5B,IAAIpM,EAAKL,KAAKK,GAAIqM,EAAKF,EAAUnM,EAAK,IAClCsM,EAAQ3M,KAAK4B,IAAI8K,GACjBE,EAAQ5M,KAAK6B,IAAI6K,GACjBG,EAAQ,EAAGC,EAAQ,EAKnBC,GAAMH,EAAQV,EAAM,GAAMS,EAAQR,EAAM,GACxCa,GAAMJ,EAAQT,EAAM,GAAMQ,EAAQT,EAAM,GACxCe,GALJb,EAAKpM,KAAKG,IAAIiM,IAKCA,EAAIc,GAJnBb,EAAKrM,KAAKG,IAAIkM,IAIgBA,EAAIc,EAAMH,EAAKA,EAAII,EAAML,EAAKA,EACxDM,EAAKJ,EAAMC,EAAMD,EAAME,EAAMD,EAAME,EACnCE,EAAO,EAEX,GAAID,EAAK,EAAG,CACV,IAAIE,EAAIvN,KAAKD,KAAK,EAAIsN,GAAMJ,EAAMC,IAClCd,GAAMmB,EACNlB,GAAMkB,OAGND,GAAQhB,IAAUC,GAAS,EAAM,GACzBvM,KAAKD,KAAMsN,GAAMJ,EAAME,EAAMD,EAAME,IAG7C,IAAII,EAAKF,EAAOlB,EAAKY,EAAKX,EACtBoB,GAAMH,EAAOjB,EAAKU,EAAKX,EACvBsB,EAAMd,EAAQY,EAAKb,EAAQc,EAAW,GAANvB,EAChCyB,EAAMhB,EAAQa,EAAKZ,EAAQa,EAAW,GAANtB,EAChCyB,EAASC,EAAgB,EAAG,GAAId,EAAKS,GAAMpB,GAAKY,EAAKS,GAAMpB,GAC3DyB,EAASD,GAAiBd,EAAKS,GAAMpB,GAAKY,EAAKS,GAAMpB,IAAMU,EAAKS,GAAMpB,IAAMY,EAAKS,GAAMpB,GAE7E,IAAVE,GAAwB,EAATuB,EACjBA,GAAU,EAAIzN,EAEG,IAAVkM,GAAeuB,EAAS,IAC/BA,GAAU,EAAIzN,GAShB,IALA,IAAI0N,EAAW/N,KAAKgO,KAAKhO,KAAKG,IAAI2N,EAASzN,EAAK,IAC5C4N,EAAS,GAAIC,EAASJ,EAASC,EAC/BI,EAAK,EAAI,EAAInO,KAAK4B,IAAIsM,EAAS,GAAKlO,KAAK4B,IAAIsM,EAAS,GAAKlO,KAAK4B,IAAIsM,EAAS,GAC7EE,EAAMR,EAASM,EAEV/R,EAAI,EAAGA,EAAI4R,EAAU5R,IAC5B8R,EAAO9R,GAAKkS,EAAgBT,EAAQQ,EAAKxB,EAAOD,EAAOP,EAAIC,EAAIqB,EAAKC,EAAKQ,EAAItB,EAAOC,GACpFD,EAAQoB,EAAO9R,GAAG,GAClB2Q,EAAQmB,EAAO9R,GAAG,GAClByR,EAASQ,EACTA,GAAOF,EAGT,OADAvC,EAAmBc,GAAcwB,EAInC,SAASI,EAAgBC,EAAKF,EAAKxB,EAAOD,EAAOP,EAAIC,EAAIqB,EAAKC,EAAKQ,EAAItB,EAAOC,GAC5E,IAAIyB,EAAczC,EAAM/P,KAAKN,WAC7B,GAAImQ,EAAqB2C,GACvB,OAAO3C,EAAqB2C,GAG9B,IAAIC,EAASxO,KAAK6B,IAAIyM,GAClBG,EAASzO,KAAK4B,IAAI0M,GAClBI,EAAS1O,KAAK6B,IAAIuM,GAClBO,EAAS3O,KAAK4B,IAAIwM,GAClBlC,EAAMU,EAAQR,EAAKsC,EAAS/B,EAAQN,EAAKsC,EAASjB,EAClDvB,EAAMQ,EAAQP,EAAKsC,EAAS9B,EAAQP,EAAKsC,EAAShB,EAClDiB,EAAO/B,EAAQsB,IAAQvB,EAAQR,EAAKqC,EAAS9B,EAAQN,EAAKmC,GAC1DK,EAAO/B,EAAQqB,IAAQxB,EAAQP,EAAKqC,EAAS7B,EAAQP,EAAKmC,GAC1DM,EAAO5C,EAAMiC,GAAOvB,EAAQR,EAAKuC,EAAShC,EAAQN,EAAKqC,GACvDK,EAAO5C,EAAMgC,GAAOxB,EAAQP,EAAKuC,EAAS/B,EAAQP,EAAKqC,GAO3D,OALA9C,EAAqB2C,GAAe,CAClCK,EAAMC,EACNC,EAAMC,EACN7C,EAAKC,GAEAP,EAAqB2C,GAM9B,SAASV,EAAgBmB,EAAIC,EAAIC,EAAIC,GACnC,IAAIC,EAAKpP,KAAKC,MAAMgP,EAAID,GACpBK,EAAKrP,KAAKC,MAAMkP,EAAID,GACxB,OAAUE,GAANC,EACKA,EAAKD,EAGL,EAAIpP,KAAKK,IAAM+O,EAAKC,GAwE/B,SAASC,EAAiBC,EAAIC,EAAIC,EAAIC,EAAI9I,EAAIC,EAAI8I,EAAIC,GACpD,IAAInD,EAAaX,EAAM/P,KAAKN,WAC5B,GAAIoQ,EAAmBY,GACrB,OAAOZ,EAAmBY,GAG5B,IAII1J,EAAG8F,EAAGgH,EAAG7N,EAAG8N,EAAIC,EAAIC,EAAMC,EAJ1BlQ,EAAOC,KAAKD,KACZU,EAAMT,KAAKS,IAAKC,EAAMV,KAAKU,IAC3BP,EAAMH,KAAKG,IAAK+P,EAAU,GAC1BC,EAAS,CAAC,GAAI,IAGlBtH,EAAI,EAAI0G,EAAK,GAAKE,EAAK,EAAI7I,EAC3B7D,GAAK,EAAIwM,EAAK,EAAIE,EAAK,EAAI7I,EAAK,EAAI+I,EACpCE,EAAI,EAAIJ,EAAK,EAAIF,EAEjB,IAAK,IAAIpT,EAAI,EAAGA,EAAI,IAAKA,EAOvB,GANQ,EAAJA,IACF0M,EAAI,EAAI2G,EAAK,GAAKE,EAAK,EAAI7I,EAC3B9D,GAAK,EAAIyM,EAAK,EAAIE,EAAK,EAAI7I,EAAK,EAAI+I,EACpCC,EAAI,EAAIH,EAAK,EAAIF,GAGfrP,EAAI4C,GAAK,MAAb,CACE,GAAI5C,EAAI0I,GAAK,MACX,SAGE,GADJ7G,GAAK6N,EAAIhH,IACI7G,EAAI,GACfkO,EAAQrU,KAAKmG,QAIjBgO,EAAOnH,EAAIA,EAAI,EAAIgH,EAAI9M,GACZ,IAKP,GADJ+M,IAAOjH,GADPoH,EAAWlQ,EAAKiQ,MACQ,EAAIjN,KACd+M,EAAK,GACjBI,EAAQrU,KAAKiU,GAGX,GADJC,IAAOlH,EAAIoH,IAAa,EAAIlN,KACdgN,EAAK,GACjBG,EAAQrU,KAAKkU,IAKjB,IADA,IAAIvO,EAAGC,EAAiC2O,EAA9BC,EAAIH,EAAQxU,OAAQ4U,EAAOD,EAC9BA,KAGL7O,GADA4O,EAAK,GADLpO,EAAIkO,EAAQG,KAEFD,EAAKA,EAAKb,EAAO,EAAIa,EAAKA,EAAKpO,EAAIyN,EAAO,EAAIW,EAAKpO,EAAIA,EAAI4E,EAAO5E,EAAIA,EAAIA,EAAI2N,EACxFQ,EAAO,GAAGE,GAAK7O,EAEfC,EAAK2O,EAAKA,EAAKA,EAAKZ,EAAO,EAAIY,EAAKA,EAAKpO,EAAI0N,EAAO,EAAIU,EAAKpO,EAAIA,EAAI6E,EAAO7E,EAAIA,EAAIA,EAAI4N,EACxFO,EAAO,GAAGE,GAAK5O,EAGjB0O,EAAO,GAAGG,GAAQf,EAClBY,EAAO,GAAGG,GAAQd,EAClBW,EAAO,GAAGG,EAAO,GAAKX,EACtBQ,EAAO,GAAGG,EAAO,GAAKV,EACtB,IAAI3B,EAAS,CACX,CACEzM,EAAGf,EAAI5D,MAAM,KAAMsT,EAAO,IAC1B1O,EAAGhB,EAAI5D,MAAM,KAAMsT,EAAO,KAE5B,CACE3O,EAAGd,EAAI7D,MAAM,KAAMsT,EAAO,IAC1B1O,EAAGf,EAAI7D,MAAM,KAAMsT,EAAO,MAI9B,OADAtE,EAAmBY,GAAcwB,EAtInC7U,OAAOiC,KAAKkV,QAAU,SAAS5J,EAAK6J,EAAIC,EAAIC,GAW1C,IAVA,IAAItE,EAAKsE,EAAO,GACZrE,EAAKqE,EAAO,GACZzJ,EAAMyJ,EAAO,GACbpE,EAAQoE,EAAO,GACfnE,EAAQmE,EAAO,GAGfC,EAAO,CAAC,GAAI,GAAI,GAAI,IACpBC,EAAW3E,EAHNyE,EAAO,GAGkBF,EAFzBE,EAAO,GAE2BD,EAAIrE,EAAIC,EAAIC,EAAOC,EAAOtF,GAE5D9K,EAAI,EAAGC,EAAMwU,EAASlV,OAAQS,EAAIC,EAAKD,IAC9CwU,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKqU,EAC9BG,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKsU,EAC9BE,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKqU,EAC9BG,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKsU,EAC9BE,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKqU,EAC9BG,EAAKxU,GAAG,GAAKyU,EAASzU,GAAG,GAAKsU,EAC9B9J,EAAIkK,cAAchU,MAAM8J,EAAKgK,EAAKxU,KAgBtC/C,OAAOiC,KAAKyV,eAAiB,SAASN,EAAIC,EAAIrE,EAAIC,EAAIpF,EAAKqF,EAAOC,EAAOwE,EAAIC,GAK3E,IAHA,IAA0BC,EAAtBpE,EAAQ,EAAGC,EAAQ,EAAUqD,EAAS,GACtCQ,EAAO1E,EAAc8E,EAAKP,EAAIQ,EAAKP,EAAIrE,EAAIC,EAAIC,EAAOC,EAAOtF,GAExD9K,EAAI,EAAGC,EAAMuU,EAAKjV,OAAQS,EAAIC,EAAKD,IAC1C8U,EAAQ3B,EAAiBzC,EAAOC,EAAO6D,EAAKxU,GAAG,GAAIwU,EAAKxU,GAAG,GAAIwU,EAAKxU,GAAG,GAAIwU,EAAKxU,GAAG,GAAIwU,EAAKxU,GAAG,GAAIwU,EAAKxU,GAAG,IAC3GgU,EAAOtU,KAAK,CAAE2F,EAAGyP,EAAM,GAAGzP,EAAIgP,EAAI/O,EAAGwP,EAAM,GAAGxP,EAAIgP,IAClDN,EAAOtU,KAAK,CAAE2F,EAAGyP,EAAM,GAAGzP,EAAIgP,EAAI/O,EAAGwP,EAAM,GAAGxP,EAAIgP,IAClD5D,EAAQ8D,EAAKxU,GAAG,GAChB2Q,EAAQ6D,EAAKxU,GAAG,GAElB,OAAOgU,GA4FT/W,OAAOiC,KAAKiU,iBAAmBA,EAhQjC,GAqQA,WAEE,IAAInL,EAAQ4H,MAAMvF,UAAUrC,MA+N5B,SAAS+M,EAAK5V,EAAO6V,EAAYC,GAC/B,GAAK9V,GAA0B,IAAjBA,EAAMI,OAApB,CAIA,IAAIS,EAAIb,EAAMI,OAAS,EACnBuS,EAASkD,EAAa7V,EAAMa,GAAGgV,GAAc7V,EAAMa,GACvD,GAAIgV,EACF,KAAOhV,KACDiV,EAAU9V,EAAMa,GAAGgV,GAAalD,KAClCA,EAAS3S,EAAMa,GAAGgV,SAKtB,KAAOhV,KACDiV,EAAU9V,EAAMa,GAAI8R,KACtBA,EAAS3S,EAAMa,IAIrB,OAAO8R,GAhPJlC,MAAMvF,UAAUpL,UAMnB2Q,MAAMvF,UAAUpL,QAAU,SAAUiW,GAClC,GAAIpW,MAAAA,KACF,MAAM,IAAIqW,UAEZ,IAAItP,EAAIuE,OAAOtL,MAAOmB,EAAM4F,EAAEtG,SAAW,EACzC,GAAY,IAARU,EACF,OAAQ,EAEV,IAAImV,EAAI,EAUR,GATuB,EAAnB9V,UAAUC,UACZ6V,EAAIlO,OAAO5H,UAAU,MACX8V,EACRA,EAAI,EAES,IAANA,GAAWA,IAAMlO,OAAOmO,mBAAqBD,IAAMlO,OAAOoO,oBACjEF,GAAS,EAAJA,IAAU,GAAKvR,KAAKW,MAAMX,KAAKG,IAAIoR,MAGnCnV,GAALmV,EACF,OAAQ,EAGV,IADA,IAAIG,EAAS,GAALH,EAASA,EAAIvR,KAAKU,IAAItE,EAAM4D,KAAKG,IAAIoR,GAAI,GAC1CG,EAAItV,EAAKsV,IACd,GAAIA,KAAK1P,GAAKA,EAAE0P,KAAOL,EACrB,OAAOK,EAGX,OAAQ,IAIP3F,MAAMvF,UAAUlB,UAOnByG,MAAMvF,UAAUlB,QAAU,SAAS2E,EAAIpM,GACrC,IAAK,IAAI1B,EAAI,EAAGC,EAAMnB,KAAKS,SAAW,EAAGS,EAAIC,EAAKD,IAC5CA,KAAKlB,MACPgP,EAAGlO,KAAK8B,EAAS5C,KAAKkB,GAAIA,EAAGlB,QAMhC8Q,MAAMvF,UAAUmL,MAOnB5F,MAAMvF,UAAUmL,IAAM,SAAS1H,EAAIpM,GAEjC,IADA,IAAIoQ,EAAS,GACJ9R,EAAI,EAAGC,EAAMnB,KAAKS,SAAW,EAAGS,EAAIC,EAAKD,IAC5CA,KAAKlB,OACPgT,EAAO9R,GAAK8N,EAAGlO,KAAK8B,EAAS5C,KAAKkB,GAAIA,EAAGlB,OAG7C,OAAOgT,IAINlC,MAAMvF,UAAUoL,QAOnB7F,MAAMvF,UAAUoL,MAAQ,SAAS3H,EAAIpM,GACnC,IAAK,IAAI1B,EAAI,EAAGC,EAAMnB,KAAKS,SAAW,EAAGS,EAAIC,EAAKD,IAChD,GAAIA,KAAKlB,OAASgP,EAAGlO,KAAK8B,EAAS5C,KAAKkB,GAAIA,EAAGlB,MAC7C,OAAO,EAGX,OAAO,IAIN8Q,MAAMvF,UAAUqL,OAOnB9F,MAAMvF,UAAUqL,KAAO,SAAS5H,EAAIpM,GAClC,IAAK,IAAI1B,EAAI,EAAGC,EAAMnB,KAAKS,SAAW,EAAGS,EAAIC,EAAKD,IAChD,GAAIA,KAAKlB,MAAQgP,EAAGlO,KAAK8B,EAAS5C,KAAKkB,GAAIA,EAAGlB,MAC5C,OAAO,EAGX,OAAO,IAIN8Q,MAAMvF,UAAUnK,SAOnB0P,MAAMvF,UAAUnK,OAAS,SAAS4N,EAAIpM,GAEpC,IADA,IAAiBiU,EAAb7D,EAAS,GACJ9R,EAAI,EAAGC,EAAMnB,KAAKS,SAAW,EAAGS,EAAIC,EAAKD,IAC5CA,KAAKlB,OACP6W,EAAM7W,KAAKkB,GACP8N,EAAGlO,KAAK8B,EAASiU,EAAK3V,EAAGlB,OAC3BgT,EAAOpS,KAAKiW,IAIlB,OAAO7D,IAINlC,MAAMvF,UAAUnI,SAMnB0N,MAAMvF,UAAUnI,OAAS,SAAS4L,GAChC,IAEI8H,EAFA3V,EAAMnB,KAAKS,SAAW,EACtBS,EAAI,EAGR,GAAuB,EAAnBV,UAAUC,OACZqW,EAAKtW,UAAU,QAGf,OAAG,CACD,GAAIU,KAAKlB,KAAM,CACb8W,EAAK9W,KAAKkB,KACV,MAGF,KAAMA,GAAKC,EACT,MAAM,IAAIkV,UAKhB,KAAOnV,EAAIC,EAAKD,IACVA,KAAKlB,OACP8W,EAAK9H,EAAGlO,KAAK,KAAMgW,EAAI9W,KAAKkB,GAAIA,EAAGlB,OAGvC,OAAO8W,IAwFX3Y,OAAOiC,KAAKC,MAAQ,CAClBC,KAvCF,SAAcD,EAAOgB,GAEnB,IADA,IAAIoV,EAAIpW,EAAMI,OACPgW,KACLpW,EAAMoW,GAAKpV,EAEb,OAAOhB,GAmCP0W,OA7EF,SAAgB1W,EAAO2W,GAErB,IADA,IAAIC,EAAO/N,EAAMpI,KAAKN,UAAW,GAAIwS,EAAS,GACrC9R,EAAI,EAAGC,EAAMd,EAAMI,OAAQS,EAAIC,EAAKD,IAC3C8R,EAAO9R,GAAK+V,EAAKxW,OAASJ,EAAMa,GAAG8V,GAAQpV,MAAMvB,EAAMa,GAAI+V,GAAQ5W,EAAMa,GAAG8V,GAAQlW,KAAKT,EAAMa,IAEjG,OAAO8R,GAyEPxN,IAlDF,SAAanF,EAAO6V,GAClB,OAAOD,EAAK5V,EAAO6V,EAAY,SAASgB,EAAQC,GAC9C,OAAOD,EAASC,KAiDlB1R,IAhEF,SAAapF,EAAO6V,GAClB,OAAOD,EAAK5V,EAAO6V,EAAY,SAASgB,EAAQC,GAC9C,OAAiBA,GAAVD,MAlMb,GAsQA,WAUE,SAASE,EAAOhM,EAAapH,EAAQqT,GAInC,GAAIA,EACF,IAAKlZ,OAAOW,cAAgBkF,aAAkBsT,QAE5ClM,EAAcpH,OAEX,GAAIA,aAAkB8M,MAAO,CAChC1F,EAAc,GACd,IAAK,IAAIlK,EAAI,EAAGC,EAAM6C,EAAOvD,OAAQS,EAAIC,EAAKD,IAC5CkK,EAAYlK,GAAKkW,EAAO,GAAKpT,EAAO9C,GAAImW,QAGvC,GAAIrT,GAA4B,iBAAXA,EACxB,IAAK,IAAIJ,KAAYI,EACfA,EAAOuT,eAAe3T,KACxBwH,EAAYxH,GAAYwT,EAAO,GAAKpT,EAAOJ,GAAWyT,SAM1DjM,EAAcpH,OAIhB,IAAK,IAAIJ,KAAYI,EACnBoH,EAAYxH,GAAYI,EAAOJ,GAGnC,OAAOwH,EAcTjN,OAAOiC,KAAK6B,OAAS,CACnBmV,OAAQA,EACRI,MAPF,SAAevV,EAAQoV,GACrB,OAAOD,EAAO,GAAKnV,EAAQoV,KApD/B,GAmEOpI,OAAO1D,UAAUkM,OAMpBxI,OAAO1D,UAAUkM,KAAO,WAEtB,OAAOzX,KAAK0X,QAAQ,aAAc,IAAIA,QAAQ,aAAc,MAiDhEvZ,OAAOiC,KAAK0I,OAAS,CACnBC,SAvCF,SAAkBD,GAChB,OAAOA,EAAO4O,QAAQ,UAAW,SAASxI,EAAOyI,GAC/C,OAAOA,EAAYA,EAAU1O,cAAgB,MAsC/C2O,WAzBF,SAAoB9O,EAAQ+O,GAC1B,OAAO/O,EAAOE,OAAO,GAAGC,eACrB4O,EAAkB/O,EAAOI,MAAM,GAAKJ,EAAOI,MAAM,GAAG4O,gBAwBvDC,UAfF,SAAmBjP,GACjB,OAAOA,EAAO4O,QAAQ,KAAM,SACxBA,QAAQ,KAAM,UACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,UAgBtB,WAEE,IAAIxO,EAAQ4H,MAAMvF,UAAUrC,MACxBtH,EAAQ0C,SAASiH,UAAU3J,MAC3BoW,EAAQ,aAEP1T,SAASiH,UAAU0M,OAQtB3T,SAASiH,UAAU0M,KAAO,SAASC,GACjC,IAAmDlC,EAA/CmC,EAAQnY,KAAMiX,EAAO/N,EAAMpI,KAAKN,UAAW,GAe/C,OAbEwV,EADEiB,EAAKxW,OACC,WACN,OAAOmB,EAAMd,KAAKqX,EAAOnY,gBAAgBgY,EAAQhY,KAAOkY,EAASjB,EAAKmB,OAAOlP,EAAMpI,KAAKN,cAKlF,WACN,OAAOoB,EAAMd,KAAKqX,EAAOnY,gBAAgBgY,EAAQhY,KAAOkY,EAAS1X,YAGrEwX,EAAMzM,UAAYvL,KAAKuL,UACvByK,EAAMzK,UAAY,IAAIyM,EAEfhC,IA9Bb,GAsCA,WAEE,IAAI9M,EAAQ4H,MAAMvF,UAAUrC,MAAOmP,EAAgB,aAE/CC,EAAoB,WAClB,IAAK,IAAIxR,IAAK,CAAE0E,SAAU,GACxB,GAAU,aAAN1E,EACF,OAAO,EAGX,OAAO,EANW,GAUpByR,EAAa,SAASvL,EAAOhJ,EAAQwU,GACnC,IAAK,IAAI5U,KAAYI,EAEfJ,KAAYoJ,EAAMzB,WACmB,mBAA9ByB,EAAMzB,UAAU3H,KACyB,GAA/CI,EAAOJ,GAAY,IAAIzD,QAAQ,aAElC6M,EAAMzB,UAAU3H,GAAY,SAAUA,GACpC,OAAO,WAEL,IAAI6U,EAAazY,KAAK0Y,YAAYD,WAClCzY,KAAK0Y,YAAYD,WAAaD,EAC9B,IAAIG,EAAc3U,EAAOJ,GAAUhC,MAAM5B,KAAMQ,WAG/C,GAFAR,KAAK0Y,YAAYD,WAAaA,EAEb,eAAb7U,EACF,OAAO+U,GATe,CAYzB/U,GAGHoJ,EAAMzB,UAAU3H,GAAYI,EAAOJ,GAGjC0U,IACEtU,EAAOwH,WAAaF,OAAOC,UAAUC,WACvCwB,EAAMzB,UAAUC,SAAWxH,EAAOwH,UAEhCxH,EAAO4U,UAAYtN,OAAOC,UAAUqN,UACtC5L,EAAMzB,UAAUqN,QAAU5U,EAAO4U,WAM7C,SAASC,KAET,SAASC,EAAUC,GAKjB,IAJA,IAAIC,EAAe,KACfb,EAAQnY,KAGLmY,EAAMO,YAAYD,YAAY,CACnC,IAAIQ,EAAmBd,EAAMO,YAAYD,WAAWlN,UAAUwN,GAC9D,GAAIZ,EAAMY,KAAgBE,EAAkB,CAC1CD,EAAeC,EACf,MAGFd,EAAQA,EAAMO,YAAYD,WAAWlN,UAGvC,OAAKyN,EAIsB,EAAnBxY,UAAUC,OACduY,EAAapX,MAAM5B,KAAMkJ,EAAMpI,KAAKN,UAAW,IAC/CwY,EAAalY,KAAKd,MALbkZ,QAAQrP,IAAI,sBAAwBkP,EAAa,wCAAyC/Y,MA6CrG7B,OAAOiC,KAAK+Y,YA9BZ,WACE,IAAIX,EAAS,KACTnN,EAAanC,EAAMpI,KAAKN,UAAW,GAKvC,SAASwM,IACPhN,KAAKoZ,WAAWxX,MAAM5B,KAAMQ,WAJD,mBAAlB6K,EAAW,KACpBmN,EAASnN,EAAWgO,SAMtBrM,EAAMyL,WAAaD,EACnBxL,EAAMsM,WAAa,GAEfd,IACFK,EAAStN,UAAYiN,EAAOjN,UAC5ByB,EAAMzB,UAAY,IAAIsN,EACtBL,EAAOc,WAAW1Y,KAAKoM,IAEzB,IAAK,IAAI9L,EAAI,EAAGT,EAAS4K,EAAW5K,OAAQS,EAAIT,EAAQS,IACtDqX,EAAWvL,EAAO3B,EAAWnK,GAAIsX,GAOnC,OALKxL,EAAMzB,UAAU6N,aACnBpM,EAAMzB,UAAU6N,WAAaf,IAE/BrL,EAAMzB,UAAUmN,YAAc1L,GACxBzB,UAAUuN,UAAYA,EACrB9L,GA9GX,GAqHA,WAEE,IAAIuM,EAAU,UAId,SAASC,EAAevX,GACtB,IACI8E,EAAG7F,EADHuY,EAAc3I,MAAMvF,UAAUrC,MAAMpI,KAAKN,UAAW,GAC9CW,EAAMsY,EAAYhZ,OAC5B,IAAKS,EAAI,EAAGA,EAAIC,EAAKD,IAEnB,GADA6F,SAAW9E,EAAOwX,EAAYvY,KACzB,gCAAkCwY,KAAK3S,GAC1C,OAAO,EAGX,OAAO,EAIT,IAAI4S,EACAC,EAEMC,EAOJ9O,EARF+O,GACMD,EAAM,EACH,SAAUE,GACf,OAAOA,EAAQC,aAAeD,EAAQC,WAAa,aAAeH,OAgB1E,SAASI,EAAeJ,EAAK9Z,GAC3B,MAAO,CACLA,QAASA,EACTma,gBAI0BL,EAJWA,EAIN9Z,EAJWA,EAKrC,SAAUoa,GACfpa,EAAQe,KAAK6Y,EAAWE,GAAMM,GAAKhc,OAAOI,OAAO6b,UAFrD,IAA8BP,EAAK9Z,EAlB7BgL,EAAW,GAEf4O,EAAa,SAAUE,GACrB,OAAO9O,EAAS8O,IAGlBD,EAAa,SAAUC,EAAKE,GAC1BhP,EAAS8O,GAAOE,GA4BpB,IAcIM,EAAaC,EAdbC,EACEf,EAAerb,OAAOG,SAASkc,gBAAiB,mBAAoB,wBACpEhB,EAAerb,OAAOI,OAAQ,mBAAoB,uBAEpDkc,EACEjB,EAAerb,OAAOG,SAASkc,gBAAiB,cAAe,gBAC/DhB,EAAerb,OAAOI,OAAQ,cAAe,eAG/Cmc,EAAY,GAGZC,EAAW,GAWbL,EAPEC,GAEFF,EAAc,SAAUN,EAASja,EAAWC,EAASiB,GAEnD+Y,GAAWA,EAAQa,iBAAiB9a,EAAWC,GAAS0a,GAA0CzZ,IAGnF,SAAU+Y,EAASja,EAAWC,EAASiB,GACtD+Y,GAAWA,EAAQc,oBAAoB/a,EAAWC,GAAS0a,GAA0CzZ,KAIhGyZ,GAEPJ,EAAc,SAAUN,EAASja,EAAWC,GAC1C,GAAKga,EAAL,CAGA,IAAIF,EAAMC,EAAYC,GACtBH,EAAWC,EAAKE,GACXW,EAAUb,KACba,EAAUb,GAAO,IAEda,EAAUb,GAAK/Z,KAClB4a,EAAUb,GAAK/Z,GAAa,IAG9B,IAAIgb,EAAWb,EAAeJ,EAAK9Z,GACnC2a,EAAUb,GAAK/Z,GAAWc,KAAKka,GAC/Bf,EAAQgB,YAAY,KAAOjb,EAAWgb,EAASZ,kBAGhC,SAAUH,EAASja,EAAWC,GAC7C,GAAKga,EAAL,CAGA,IAAgCe,EAA5BjB,EAAMC,EAAYC,GACtB,GAAIW,EAAUb,IAAQa,EAAUb,GAAK/Z,GACnC,IAAK,IAAIoB,EAAI,EAAGC,EAAMuZ,EAAUb,GAAK/Z,GAAWW,OAAQS,EAAIC,EAAKD,KAC/D4Z,EAAWJ,EAAUb,GAAK/Z,GAAWoB,KACrB4Z,EAAS/a,UAAYA,IACnCga,EAAQiB,YAAY,KAAOlb,EAAWgb,EAASZ,gBAC/CQ,EAAUb,GAAK/Z,GAAWoB,GAAK,UAQvCmZ,EAAc,SAAUN,EAASja,EAAWC,GAC1C,GAAKga,EAAL,CAGA,IAjFsBF,EAAK/Z,EAiFvB+Z,EAAMC,EAAYC,GAItB,GAHKY,EAASd,KACZc,EAASd,GAAO,KAEbc,EAASd,GAAK/Z,GAAY,CAC7B6a,EAASd,GAAK/Z,GAAa,GAC3B,IAAImb,EAAkBlB,EAAQ,KAAOja,GACjCmb,GACFN,EAASd,GAAK/Z,GAAWc,KAAKqa,GAEhClB,EAAQ,KAAOja,IA3FK+Z,EA2FyBA,EA3FpB/Z,EA2FyBA,EA1F/C,SAAUqa,GACf,GAAIQ,EAASd,IAAQc,EAASd,GAAK/Z,GAEjC,IADA,IAAIob,EAAmBP,EAASd,GAAK/Z,GAC5BoB,EAAI,EAAGC,EAAM+Z,EAAiBza,OAAQS,EAAIC,EAAKD,IACtDga,EAAiBha,GAAGJ,KAAKd,KAAMma,GAAKhc,OAAOI,OAAO6b,SAwFtDO,EAASd,GAAK/Z,GAAWc,KAAKb,KAGf,SAAUga,EAASja,EAAWC,GAC7C,GAAKga,EAAL,CAGA,IAAIF,EAAMC,EAAYC,GACtB,GAAIY,EAASd,IAAQc,EAASd,GAAK/Z,GAEjC,IADA,IAAIob,EAAmBP,EAASd,GAAK/Z,GAC5BoB,EAAI,EAAGC,EAAM+Z,EAAiBza,OAAQS,EAAIC,EAAKD,IAClDga,EAAiBha,KAAOnB,GAC1Bmb,EAAiB5Y,OAAOpB,EAAG,MAerC/C,OAAOiC,KAAKia,YAAcA,EAU1Blc,OAAOiC,KAAKka,eAAiBA,EAqB7B,IAAIa,EAAW,SAASf,GAIlB,cAAeA,EAAMgB,UAAY7B,EAAUa,EAAMgB,QAAU,GAG7DC,EAAW,SAASjB,GAClB,cAAeA,EAAMkB,UAAY/B,EAAUa,EAAMkB,QAAU,GAGjE,SAASC,EAAYnB,EAAOoB,EAAUC,GACpC,IAAIC,EAA2B,aAAftB,EAAMvX,KAAsB,iBAAmB,UAE/D,OAAQuX,EAAMsB,IAActB,EAAMsB,GAAW,IACxCtB,EAAMsB,GAAW,GAAGF,IAAapB,EAAMsB,GAAW,GAAGF,GAAYpB,EAAMsB,GAAW,GAAGD,KAEtFrB,EAAMqB,GAGRtd,OAAOU,mBACTsc,EAAW,SAASf,GAClB,OAAOmB,EAAYnB,EAAO,QAAS,YAErCiB,EAAW,SAASjB,GAClB,OAAOmB,EAAYnB,EAAO,QAAS,aAIvCjc,OAAOiC,KAAKub,WA3CZ,SAAoBvB,GAClBA,IAAUA,EAAQjc,OAAOI,OAAO6b,OAEhC,IAAIL,EAAUK,EAAMxL,gBACEwL,EAAMwB,aAAerC,EAAUa,EAAMwB,WAAa,MAEpEC,EAAS1d,OAAOiC,KAAK0b,iBAAiB/B,GAE1C,MAAO,CACLxT,EAAG4U,EAASf,GAASyB,EAAOnU,KAC5BlB,EAAG6U,EAASjB,GAASyB,EAAOlU,MAmChCxJ,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOiC,KAAMjC,OAAOmD,YA3OhD,GAgPA,WAkCE,IAAIya,EAAU5d,OAAOG,SAASqO,cAAc,OACxCqP,EAAmD,iBAA1BD,EAAQE,MAAMC,QACvCC,EAAkD,iBAAzBJ,EAAQE,MAAM7a,OACvCgb,EAAY,wCAGZC,EAAa,SAAUtC,GAAW,OAAOA,GAEzCiC,EAEFK,EAAa,SAAStC,EAAS1Y,GAE7B,OADA0Y,EAAQkC,MAAMC,QAAU7a,EACjB0Y,GAGFoC,IAEPE,EAAa,SAAStC,EAAS1Y,GAC7B,IAAIib,EAAKvC,EAAQkC,MAWjB,OAVIlC,EAAQwC,eAAiBxC,EAAQwC,aAAaC,YAChDF,EAAGG,KAAO,GAERL,EAAU1C,KAAK4C,EAAGlb,SACpBC,EAAiB,OAATA,EAAkB,GAAM,iBAA4B,IAARA,EAAe,IACnEib,EAAGlb,OAASkb,EAAGlb,OAAOsW,QAAQ0E,EAAW/a,IAGzCib,EAAGlb,QAAU,kBAA6B,IAARC,EAAe,IAE5C0Y,IAIX5b,OAAOiC,KAAKsc,SA1DZ,SAAkB3C,EAAS4C,GACzB,IAAIC,EAAe7C,EAAQkC,MAC3B,IAAKW,EACH,OAAO7C,EAET,GAAsB,iBAAX4C,EAET,OADA5C,EAAQkC,MAAMY,SAAW,IAAMF,GACK,EAA7BA,EAAOxc,QAAQ,WAClBkc,EAAWtC,EAAS4C,EAAOzN,MAAM,0BAA0B,IAC3D6K,EAEN,IAAK,IAAInW,KAAY+Y,EACF,YAAb/Y,EACFyY,EAAWtC,EAAS4C,EAAO/Y,IAM3BgZ,EAHuC,UAAbhZ,GAAqC,aAAbA,OACV,IAA5BgZ,EAAaE,WAA6B,WAAa,aAC/DlZ,GAC+B+Y,EAAO/Y,GAG9C,OAAOmW,GA/BX,GAwEA,WAEE,IAAIgD,EAASjM,MAAMvF,UAAUrC,MAY7B,IAAI8T,EA0KAC,EAkBEhB,EACAiB,EAtLFC,EAAU,SAASC,GACjB,OAAOL,EAAOjc,KAAKsc,EAAW,IAGpC,IACEJ,EAA2BG,EAAQhf,OAAOG,SAAS+e,sBAAuBvM,MAE5E,MAAOwM,IAmBP,SAASC,EAAYC,EAASC,GAC5B,IAAIC,EAAKvf,OAAOG,SAASqO,cAAc6Q,GACvC,IAAK,IAAI9c,KAAQ+c,EACF,UAAT/c,EACFgd,EAAGC,UAAYF,EAAW/c,GAEV,QAATA,EACPgd,EAAGE,QAAUH,EAAW/c,GAGxBgd,EAAGG,aAAand,EAAM+c,EAAW/c,IAGrC,OAAOgd,EAwCT,SAAS5B,EAAiB/B,GAaxB,IAXA,IAAIrS,EAAO,EACPC,EAAM,EACNmW,EAAa3f,OAAOG,SAASkc,gBAC7BuD,EAAO5f,OAAOG,SAASyf,MAAQ,CAC7BC,WAAY,EAAGC,UAAW,GAOzBlE,IAAYA,EAAQmE,YAAcnE,EAAQoE,SAG/CpE,EAAUA,EAAQmE,YAAcnE,EAAQoE,QAExBhgB,OAAOG,UACrBoJ,EAAOqW,EAAKC,YAAcF,EAAWE,YAAc,EACnDrW,EAAMoW,EAAKE,WAAcH,EAAWG,WAAa,IAGjDvW,GAAQqS,EAAQiE,YAAc,EAC9BrW,GAAOoS,EAAQkE,WAAa,GAGL,IAArBlE,EAAQqE,UAC6C,UAArDjgB,OAAOiC,KAAK6c,gBAAgBlD,EAAS,eAK3C,MAAO,CAAErS,KAAMA,EAAMC,IAAKA,GAvGvBqV,IACHG,EAAU,SAASC,GAEjB,IADA,IAAIiB,EAAM,IAAIvN,MAAMsM,EAAU3c,QAASS,EAAIkc,EAAU3c,OAC9CS,KACLmd,EAAInd,GAAKkc,EAAUlc,GAErB,OAAOmd,IAsJTpB,EADE9e,OAAOG,SAASggB,aAAengB,OAAOG,SAASggB,YAAYC,iBAC3C,SAASxE,EAASyE,GAClC,IAAIvC,EAAQ9d,OAAOG,SAASggB,YAAYC,iBAAiBxE,EAAS,MAClE,OAAOkC,EAAQA,EAAMuC,QAAQC,GAIb,SAAS1E,EAASyE,GAClC,IAAInd,EAAQ0Y,EAAQkC,MAAMuC,GAI1B,OAHKnd,GAAS0Y,EAAQwC,eACpBlb,EAAQ0Y,EAAQwC,aAAaiC,IAExBnd,GAKL4a,EAAQ9d,OAAOG,SAASkc,gBAAgByB,MACxCiB,EAAa,eAAgBjB,EACzB,aACA,kBAAmBA,EACjB,gBACA,qBAAsBA,EACpB,mBACA,oBAAqBA,EACnB,kBACA,GAwCd9d,OAAOiC,KAAKse,wBAhCZ,SAAiC3E,GAU/B,YATqC,IAA1BA,EAAQ4E,gBACjB5E,EAAQ4E,cAAgBxgB,OAAOiC,KAAKuI,eAElCuU,EACFnD,EAAQkC,MAAMiB,GAAc,OAEW,iBAAzBnD,EAAQ6E,eACtB7E,EAAQ6E,aAAe,MAElB7E,GAuBT5b,OAAOiC,KAAKye,sBAdZ,SAA+B9E,GAU7B,YATqC,IAA1BA,EAAQ4E,gBACjB5E,EAAQ4E,cAAgB,MAEtBzB,EACFnD,EAAQkC,MAAMiB,GAAc,GAEW,iBAAzBnD,EAAQ6E,eACtB7E,EAAQ6E,aAAe,IAElB7E,GAuCT5b,OAAOiC,KAAK0e,UAxBZ,SAAmBvV,EAAK5G,GACtB,IAAIoc,EAAS5gB,OAAOG,SAAS0gB,qBAAqB,QAAQ,GACtDC,EAAW9gB,OAAOG,SAASqO,cAAc,UACzCuS,GAAU,EAGdD,EAAStV,OAAwBsV,EAASE,mBAAqB,SAAShF,GACtE,GAAI+E,EAAS,CACX,GAA+B,iBAApBlf,KAAKof,YACQ,WAApBpf,KAAKof,YACe,aAApBpf,KAAKof,WACP,OAEFF,GAAU,EACVvc,EAASwX,GAAKhc,OAAOI,OAAO6b,OAC5B6E,EAAWA,EAAStV,OAASsV,EAASE,mBAAqB,OAG/DF,EAASnV,IAAMP,EACfwV,EAAOM,YAAYJ,IAQvB9gB,OAAOiC,KAAKkf,QAxRZ,SAAiBC,GACf,MAAqB,iBAAPA,EAAkBphB,OAAOG,SAASkhB,eAAeD,GAAMA,GAwRvEphB,OAAOiC,KAAK+c,QAAUA,EACtBhf,OAAOiC,KAAKmd,YAAcA,EAC1Bpf,OAAOiC,KAAKqf,SAhOZ,SAAkB1F,EAAS4D,GACrB5D,IAA+E,KAAnE,IAAMA,EAAQ4D,UAAY,KAAKxd,QAAQ,IAAMwd,EAAY,OACvE5D,EAAQ4D,YAAc5D,EAAQ4D,UAAY,IAAM,IAAMA,IA+N1Dxf,OAAOiC,KAAKsf,YAnNZ,SAAqB3F,EAAS4F,EAASlC,GAQrC,MAPuB,iBAAZkC,IACTA,EAAUpC,EAAYoC,EAASlC,IAE7B1D,EAAQmE,YACVnE,EAAQmE,WAAW0B,aAAaD,EAAS5F,GAE3C4F,EAAQN,YAAYtF,GACb4F,GA4MTxhB,OAAOiC,KAAK0b,iBAAmBA,EAC/B3d,OAAOiC,KAAKyf,iBAzJZ,SAA0B9F,GACxB,IAAI+F,EAIAC,EAHAC,EAAMjG,GAAWA,EAAQkG,cACzBC,EAAM,CAAExY,KAAM,EAAGC,IAAK,GACtBwY,EAAS,CAAEzY,KAAM,EAAGC,IAAK,GAEzByY,EAAmB,CACjBC,gBAAiB,OACjBC,eAAiB,MACjBC,YAAiB,OACjBC,WAAiB,OAGvB,IAAKR,EACH,OAAOG,EAGT,IAAK,IAAI3B,KAAQ4B,EACfD,EAAOC,EAAiB5B,KAAUiC,SAASxD,EAAgBlD,EAASyE,GAAO,KAAO,EAUpF,OAPAsB,EAAUE,EAAIxF,qBACgC,IAAlCT,EAAQ2G,wBAClBR,EAAMnG,EAAQ2G,yBAGhBX,EAAgBjE,EAAiB/B,GAE1B,CACLrS,KAAMwY,EAAIxY,KAAOqY,EAAcrY,MAAQoY,EAAQa,YAAc,GAAKR,EAAOzY,KACzEC,IAAKuY,EAAIvY,IAAMoY,EAAcpY,KAAOmY,EAAQc,WAAa,GAAMT,EAAOxY,MA4H1ExJ,OAAOiC,KAAK6c,gBAAkBA,EAzShC,GA8SA,WAME,IAAI4D,EAAU,WAOZ,IANA,IAAIC,EAAY,CACd,WAAa,OAAO,IAAIC,cAAc,sBACtC,WAAa,OAAO,IAAIA,cAAc,mBACtC,WAAa,OAAO,IAAIA,cAAc,uBACtC,WAAa,OAAO,IAAIC,iBAEjB9f,EAAI4f,EAAUrgB,OAAQS,KAC7B,IAEE,GADU4f,EAAU5f,KAElB,OAAO4f,EAAU5f,GAGrB,MAAOoc,KAdG,GAkBd,SAAS2D,KA+CT9iB,OAAOiC,KAAK8gB,QAlCZ,SAAiB3X,EAAKvI,GAEpBA,IAAYA,EAAU,IAEtB,IAvCqBuI,EAAK4X,EAuCtBnK,EAAShW,EAAQgW,OAAShW,EAAQgW,OAAO/N,cAAgB,MACzDmY,EAAapgB,EAAQogB,YAAc,aACnCC,EAAMR,IACN9C,EAAO/c,EAAQ+c,MAAQ/c,EAAQsgB,WAwBnC,OArBAD,EAAIlC,mBAAqB,WACA,IAAnBkC,EAAIjC,aACNgC,EAAWC,GACXA,EAAIlC,mBAAqB8B,IAId,QAAXjK,IACF+G,EAAO,KAC2B,iBAAvB/c,EAAQsgB,aAtDA/X,EAuDGA,EAvDE4X,EAuDGngB,EAAQsgB,WAAjC/X,EAtDGA,GAAO,KAAKmQ,KAAKnQ,GAAO,IAAM,KAAO4X,IA0D5CE,EAAIE,KAAKvK,EAAQzN,GAAK,GAEP,SAAXyN,GAAgC,QAAXA,GACvBqK,EAAIG,iBAAiB,eAAgB,qCAGvCH,EAAII,KAAK1D,GACFsD,GApEX,GA+EAljB,OAAO0L,IAAM,aAMb1L,OAAOujB,KAAO,aAGS,oBAAZxI,SAET,CAAC,MAAO,QAAQ7O,QAAQ,SAAS0O,QAEI,IAAxBG,QAAQH,IACsB,mBAA9BG,QAAQH,GAAYnX,QAE7BzD,OAAO4a,GAAc,WACnB,OAAOG,QAAQH,GAAYnX,MAAMsX,QAAS1Y,eAQlD,WAEE,SAASmhB,IACP,OAAO,EAsDT,IAAIC,EAAoBzjB,OAAOI,OAAOsjB,uBACd1jB,OAAOI,OAAOujB,6BACd3jB,OAAOI,OAAOwjB,0BACd5jB,OAAOI,OAAOyjB,wBACd7jB,OAAOI,OAAO0jB,yBACd,SAAStf,GACPxE,OAAOI,OAAO2jB,WAAWvf,EAAU,IAAO,KAUpE,SAASwf,IACP,OAAOP,EAAkBhgB,MAAMzD,OAAOI,OAAQiC,WAGhDrC,OAAOiC,KAAKgiB,QA3DZ,SAAiBphB,GAEfmhB,EAAiB,SAASE,GACxBrhB,IAAYA,EAAU,IAEtB,IAE+BshB,EAF3BC,EAAQF,IAAc,IAAIG,KAC1BC,EAAWzhB,EAAQyhB,UAAY,IAC/BC,EAASH,EAAQE,EACjBE,EAAW3hB,EAAQ2hB,UAAYhB,EAC/BiB,EAAQ5hB,EAAQ4hB,OAASjB,EACzBP,EAAapgB,EAAQogB,YAAcO,EACnCkB,EAAS7hB,EAAQ6hB,QAAU,SAAS9b,EAAG6G,EAAGgH,EAAGkO,GAAI,OAAQlO,EAAI7P,KAAK6B,IAAIG,EAAI+b,GAAK/d,KAAKK,GAAK,IAAMwP,EAAIhH,GACnGmV,EAAa,eAAgB/hB,EAAUA,EAAQ+hB,WAAa,EAC5DC,EAAW,aAAchiB,EAAUA,EAAQgiB,SAAW,IACtDC,EAAUjiB,EAAQiiB,SAAWD,EAAWD,EAE5C/hB,EAAQkiB,SAAWliB,EAAQkiB,UAE3B,SAAUC,EAAKC,GACb,GAAIR,IACFxB,EAAW4B,EAAU,EAAG,OAD1B,CAIAV,EAAOc,IAAa,IAAIZ,KACxB,IAAIa,EAAqBX,EAAPJ,EAAgBG,EAAYH,EAAOC,EACjDe,EAAWD,EAAcZ,EACzBnf,EAAUuf,EAAOQ,EAAaN,EAAYE,EAASR,GACnDc,EAAYxe,KAAKG,KAAK5B,EAAUyf,GAAcE,GAClDN,EAASrf,EAASigB,EAAWD,GAClBZ,EAAPJ,EACFthB,EAAQogB,YAAcpgB,EAAQogB,aAGhCe,EAAiBgB,IAfnB,CAgBGZ,MA0BPpkB,OAAOiC,KAAK+hB,iBAAmBA,EA9EjC,GAiIEhkB,OAAOiC,KAAKojB,aApBZ,SAAsBC,EAAWC,EAASjB,EAAUzhB,GAClD,IAAI2iB,EAAa,IAAIxlB,OAAOylB,MAAMH,GAAWI,YACzCC,EAAW,IAAI3lB,OAAOylB,MAAMF,GAASG,YAEzC7iB,EAAUA,GAAW,GAErB7C,OAAOiC,KAAKgiB,QAAQjkB,OAAOiC,KAAK6B,OAAOmV,OAAOpW,EAAS,CACrDyhB,SAAUA,GAAY,IACtBM,WAAYY,EACZX,SAAUc,EACVb,QAASa,EACTjB,OAAQ,SAAUQ,EAAaN,EAAYE,EAASR,GAClD,IAlCkBsB,EAAOC,EAAKC,EAC9BC,EAiCIC,EAAWnjB,EAAQojB,YACfpjB,EAAQojB,YAAYf,EAAaZ,GACjC,EAAI1d,KAAK6B,IAAIyc,EAAcZ,GAAY1d,KAAKK,GAAK,IACzD,OArCkB2e,EAqCIhB,EArCGiB,EAqCSf,EArCJgB,EAqCaE,EApC3CD,EAAQ,QACNzD,SAAUsD,EAAM,GAAKE,GAAOD,EAAI,GAAKD,EAAM,IAAM,IAAM,IACvDtD,SAAUsD,EAAM,GAAKE,GAAOD,EAAI,GAAKD,EAAM,IAAM,IAAM,IACvDtD,SAAUsD,EAAM,GAAKE,GAAOD,EAAI,GAAKD,EAAM,IAAM,IAEvDG,GAAS,KAAOH,GAASC,EAAM7b,WAAW4b,EAAM,GAAKE,GAAOD,EAAI,GAAKD,EAAM,KAAO,GAClFG,GAAS,SAwCb,WAEE,SAASG,EAAUvc,EAAG8M,EAAG9N,EAAGwL,GAc1B,OAXEA,EAFExK,EAAI/C,KAAKG,IAAI0P,IACf9M,EAAI8M,EACA9N,EAAI,GAIE,IAAN8N,GAAiB,IAAN9M,EACThB,GAAK,EAAI/B,KAAKK,IAAML,KAAKuf,KAAK,GAG9Bxd,GAAK,EAAI/B,KAAKK,IAAML,KAAKuf,KAAK1P,EAAI9M,GAGnC,CAAEA,EAAGA,EAAG8M,EAAGA,EAAG9N,EAAGA,EAAGwL,EAAGA,GAGhC,SAASiS,EAAQC,EAAMzd,EAAG+b,GACxB,OAAO0B,EAAK1c,EACV/C,KAAKE,IAAI,EAAG,IAAM8B,GAAK,IACvBhC,KAAK4B,KAAMI,EAAI+b,EAAI0B,EAAKlS,IAAM,EAAIvN,KAAKK,IAAMof,EAAK1d,GA8QtD,SAAS2d,EAAa1d,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAOlO,EAAI8P,EAAe5B,EAAI/b,EAAG,EAAG6N,EAAGkO,GAAKlV,EAO9C,SAAS8W,EAAc3d,EAAG6G,EAAGgH,EAAGkO,GAC9B,OAAK/b,GAAK+b,GAAM,EAAI,KACXlO,GAAK,OAAS7N,EAAIA,GAAK6G,EAEvB7G,EAAK,EAAI,KACT6N,GAAK,QAAU7N,GAAM,IAAM,MAASA,EAAI,KAAQ6G,EAEhD7G,EAAK,IAAM,KACX6N,GAAK,QAAU7N,GAAM,KAAO,MAASA,EAAI,OAAU6G,EAGnDgH,GAAK,QAAU7N,GAAM,MAAQ,MAASA,EAAI,SAAY6G,EAoBjEzP,OAAOiC,KAAKukB,KAAO,CAMjBC,WAAY,SAAS7d,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAOlO,GAAK7N,GAAK+b,GAAK/b,EAAI6G,GAO5BiX,YAAa,SAAS9d,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAQlO,GAAK7N,GAAK+b,IAAM/b,EAAI,GAAK6G,GAOnCkX,cAAe,SAAS/d,EAAG6G,EAAGgH,EAAGkO,GAE/B,OADA/b,GAAM+b,EAAI,GACF,EACClO,EAAI,EAAI7N,EAAIA,EAAI6G,GAEjBgH,EAAI,KAAQ7N,GAAMA,EAAI,GAAK,GAAK6G,GAO1CmX,YAAa,SAAShe,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAOlO,GAAK7N,GAAK+b,GAAK/b,EAAIA,EAAI6G,GAGhCoX,aApVF,SAAsBje,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAOlO,IAAM7N,EAAIA,EAAI+b,EAAI,GAAK/b,EAAIA,EAAI,GAAK6G,GAoV3CqX,eA7UF,SAAwBle,EAAG6G,EAAGgH,EAAGkO,GAE/B,OADA/b,GAAK+b,EAAI,GACD,EACClO,EAAI,EAAI7N,EAAIA,EAAIA,EAAI6G,EAEtBgH,EAAI,IAAM7N,GAAK,GAAKA,EAAIA,EAAI,GAAK6G,GAyUxCsX,YAlUF,SAAqBne,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAOlO,GAAK7N,GAAK+b,GAAK/b,EAAIA,EAAIA,EAAI6G,GAkUlCuX,aA3TF,SAAsBpe,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAQlO,IAAM7N,EAAIA,EAAI+b,EAAI,GAAK/b,EAAIA,EAAIA,EAAI,GAAK6G,GA2ThDwX,eApTF,SAAwBre,EAAG6G,EAAGgH,EAAGkO,GAE/B,OADA/b,GAAK+b,EAAI,GACD,EACClO,EAAI,EAAI7N,EAAIA,EAAIA,EAAIA,EAAI6G,GAEzBgH,EAAI,IAAM7N,GAAK,GAAKA,EAAIA,EAAIA,EAAI,GAAK6G,GAgT7CyX,YAzSF,SAAqBte,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAOlO,GAAK7N,GAAK+b,GAAK/b,EAAIA,EAAIA,EAAIA,EAAI6G,GAyStC0X,aAlSF,SAAsBve,EAAG6G,EAAGgH,EAAGkO,GAC7B,OAAOlO,IAAM7N,EAAIA,EAAI+b,EAAI,GAAK/b,EAAIA,EAAIA,EAAIA,EAAI,GAAK6G,GAkSnD2X,eA3RF,SAAwBxe,EAAG6G,EAAGgH,EAAGkO,GAE/B,OADA/b,GAAK+b,EAAI,GACD,EACClO,EAAI,EAAI7N,EAAIA,EAAIA,EAAIA,EAAIA,EAAI6G,EAE9BgH,EAAI,IAAM7N,GAAK,GAAKA,EAAIA,EAAIA,EAAIA,EAAI,GAAK6G,GAuRhD4X,WAhRF,SAAoBze,EAAG6G,EAAGgH,EAAGkO,GAC3B,OAAQlO,EAAI7P,KAAK6B,IAAIG,EAAI+b,GAAK/d,KAAKK,GAAK,IAAMwP,EAAIhH,GAgRlD6X,YAzQF,SAAqB1e,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAOlO,EAAI7P,KAAK4B,IAAII,EAAI+b,GAAK/d,KAAKK,GAAK,IAAMwI,GAyQ7C8X,cAlQF,SAAuB3e,EAAG6G,EAAGgH,EAAGkO,GAC9B,OAAQlO,EAAI,GAAK7P,KAAK6B,IAAI7B,KAAKK,GAAK2B,EAAI+b,GAAK,GAAKlV,GAkQlD+X,WA3PF,SAAoB5e,EAAG6G,EAAGgH,EAAGkO,GAC3B,OAAc,IAAN/b,EAAW6G,EAAIgH,EAAI7P,KAAKE,IAAI,EAAG,IAAM8B,EAAI+b,EAAI,IAAMlV,GA2P3DgY,YApPF,SAAqB7e,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAQ/b,IAAM+b,EAAKlV,EAAIgH,EAAIA,GAAiC,EAA3B7P,KAAKE,IAAI,GAAI,GAAK8B,EAAI+b,IAAUlV,GAoPjEiY,cA7OF,SAAuB9e,EAAG6G,EAAGgH,EAAGkO,GAC9B,OAAU,IAAN/b,EACK6G,EAEL7G,IAAM+b,EACDlV,EAAIgH,GAEb7N,GAAK+b,EAAI,GACD,EACClO,EAAI,EAAI7P,KAAKE,IAAI,EAAG,IAAM8B,EAAI,IAAM6G,EAEtCgH,EAAI,GAA+B,EAAzB7P,KAAKE,IAAI,GAAI,KAAO8B,IAAU6G,GAmO/CkY,WA5NF,SAAoB/e,EAAG6G,EAAGgH,EAAGkO,GAC3B,OAAQlO,GAAK7P,KAAKD,KAAK,GAAKiC,GAAK+b,GAAK/b,GAAK,GAAK6G,GA4NhDmY,YArNF,SAAqBhf,EAAG6G,EAAGgH,EAAGkO,GAC5B,OAAOlO,EAAI7P,KAAKD,KAAK,GAAKiC,EAAIA,EAAI+b,EAAI,GAAK/b,GAAK6G,GAqNhDoY,cA9MF,SAAuBjf,EAAG6G,EAAGgH,EAAGkO,GAE9B,OADA/b,GAAK+b,EAAI,GACD,GACElO,EAAI,GAAK7P,KAAKD,KAAK,EAAIiC,EAAIA,GAAK,GAAK6G,EAExCgH,EAAI,GAAK7P,KAAKD,KAAK,GAAKiC,GAAK,GAAKA,GAAK,GAAK6G,GA0MnDqY,cAnMF,SAAuBlf,EAAG6G,EAAGgH,EAAGkO,GAC9B,IAAiBhc,EAAI,EACrB,OAAU,IAANC,EACK6G,EAGC,IADV7G,GAAK+b,GAEIlV,EAAIgH,GAER9N,IACHA,EAAQ,GAAJgc,IAGEyB,EADGF,EAXiBzP,EAWJA,EAAG9N,EAXnB,SAYcC,EAAG+b,GAAKlV,IAuL9BsY,eAhLF,SAAwBnf,EAAG6G,EAAGgH,EAAGkO,GAC/B,IAAiBhc,EAAI,EACrB,GAAU,IAANC,EACF,OAAO6G,EAGT,GAAU,IADV7G,GAAK+b,GAEH,OAAOlV,EAAIgH,EAER9N,IACHA,EAAQ,GAAJgc,GAEN,IAAI0B,EAAOH,EAXiBzP,EAWJA,EAAG9N,EAXnB,SAYR,OAAO0d,EAAK1c,EAAI/C,KAAKE,IAAI,GAAI,GAAK8B,GAAKhC,KAAK4B,KAAKI,EAAI+b,EAAI0B,EAAKlS,IAAM,EAAIvN,KAAKK,IAAMof,EAAK1d,GAAM0d,EAAK5P,EAAIhH,GAoKvGuY,iBA7JF,SAA0Bpf,EAAG6G,EAAGgH,EAAGkO,GACjC,IAAiBhc,EAAI,EACrB,GAAU,IAANC,EACF,OAAO6G,EAGT,GAAU,IADV7G,GAAK+b,EAAI,GAEP,OAAOlV,EAAIgH,EAER9N,IACHA,EAAIgc,GAAK,GAAM,MAEjB,IAAI0B,EAAOH,EAXiBzP,EAWJA,EAAG9N,EAXnB,SAYR,OAAIC,EAAI,GACE,GAAMwd,EAAQC,EAAMzd,EAAG+b,GAAKlV,EAE/B4W,EAAK1c,EAAI/C,KAAKE,IAAI,GAAI,IAAM8B,GAAK,IACtChC,KAAK4B,KAAKI,EAAI+b,EAAI0B,EAAKlS,IAAM,EAAIvN,KAAKK,IAAMof,EAAK1d,GAAM,GAAM0d,EAAK5P,EAAIhH,GA6IxEwY,WAtIF,SAAoBrf,EAAG6G,EAAGgH,EAAGkO,EAAGxQ,GAI9B,YAHUmM,IAANnM,IACFA,EAAI,SAECsC,GAAK7N,GAAK+b,GAAK/b,IAAMuL,EAAI,GAAKvL,EAAIuL,GAAK1E,GAmI9CyY,YA5HF,SAAqBtf,EAAG6G,EAAGgH,EAAGkO,EAAGxQ,GAI/B,YAHUmM,IAANnM,IACFA,EAAI,SAECsC,IAAM7N,EAAIA,EAAI+b,EAAI,GAAK/b,IAAMuL,EAAI,GAAKvL,EAAIuL,GAAK,GAAK1E,GAyH3D0Y,cAlHF,SAAuBvf,EAAG6G,EAAGgH,EAAGkO,EAAGxQ,GAKjC,YAJUmM,IAANnM,IACFA,EAAI,UAENvL,GAAK+b,EAAI,GACD,EACClO,EAAI,GAAK7N,EAAIA,IAAuB,GAAhBuL,GAAK,QAAgBvL,EAAIuL,IAAM1E,EAErDgH,EAAI,IAAM7N,GAAK,GAAKA,IAAuB,GAAhBuL,GAAK,QAAgBvL,EAAIuL,GAAK,GAAK1E,GA2GrE6W,aAAcA,EACdC,cAAeA,EACf6B,gBA3EF,SAAyBxf,EAAG6G,EAAGgH,EAAGkO,GAChC,OAAI/b,EAAI+b,EAAI,EAC6B,GAAhC2B,EAAkB,EAAJ1d,EAAO,EAAG6N,EAAGkO,GAAWlV,EAEJ,GAApC8W,EAAkB,EAAJ3d,EAAQ+b,EAAG,EAAGlO,EAAGkO,GAAe,GAAJlO,EAAUhH,IAnU/D,GAgZA,SAAU/I,GAER,aAOA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5BI,EAAQrZ,EAAOiC,KAAK6B,OAAOuV,MAC3BxP,EAAU7J,EAAOiC,KAAK4H,QACtBK,EAAYlK,EAAOiC,KAAKiI,UACxBsF,EAA4BxP,EAAOiC,KAAKuN,0BAExC6Y,EAAuB,iEACvBC,EAAoB,4CACpBC,EAAwB,oDACxBC,EAAmB,sBAEnBC,EAAgB,CACdrU,GAAsB,OACtBhM,EAAsB,OACtBwB,EAAsB,SACtByK,GAAsB,MACtBhM,EAAsB,MACtBqgB,QAAsB,UACtBC,WAAsB,UACtBC,UAAsB,kBACtBC,eAAsB,cACtBC,YAAsB,WACtBC,cAAsB,aACtBC,YAAsB,WACtBC,aAAsB,YACtBC,cAAsB,aACtBC,mBAAsB,kBACtBC,iBAAsB,gBACtBC,kBAAsB,iBACtBC,oBAAsB,mBACtBC,iBAAsB,gBACtBC,eAAsB,cACtBC,kBAAsB,iBACtBC,cAAsB,UACtB3L,QAAsB,WAGxB4L,EAAkB,CAChBC,OAAQ,gBACRznB,KAAQ,eA8Fd,SAAS0nB,EAAkBhI,EAAKiI,GAE9B,IADA,IAAIC,EAA0BC,EAAhBC,EAAY,GACjBlnB,EAAI,EAAGA,EAAI+mB,EAAUxnB,OAAQS,IACpCgnB,EAAWD,EAAU/mB,GACrBinB,EAAWnI,EAAIhB,qBAAqBkJ,GACpCE,EAAYA,EAAUhQ,OAAOtH,MAAMvF,UAAUrC,MAAMpI,KAAKqnB,IAE1D,OAAOC,EAoNT,SAASC,EAAmBtO,EAASuO,GACnC,IAAIC,EAAeC,GAAiB,EAMpC,OAJAD,EAAgBE,EAAgB1O,EAASuO,EAAUvY,SAC9BuY,EAAU7nB,SAC7B+nB,EAKJ,SAA6BzO,EAASuO,GACpC,IAAII,EAAUF,GAAiB,EAC/B,KAAOzO,EAAQmE,YAA8C,IAAhCnE,EAAQmE,WAAWE,UAAkBkK,EAAU7nB,QACtE+nB,IACFE,EAAWJ,EAAUvY,OAEvBgK,EAAUA,EAAQmE,WAClBsK,EAAiBC,EAAgB1O,EAAS2O,GAE5C,OAA4B,IAArBJ,EAAU7nB,OAdEkoB,CAAoB5O,EAASuO,IAEzCC,GAAiBC,GAAwC,IAArBF,EAAU7nB,OAkBvD,SAASgoB,EAAgB1O,EAAS2O,GAChC,IAEqCE,EAFjCV,EAAWnO,EAAQmO,SACnBW,EAAa9O,EAAQ+O,aAAa,SAClCvJ,EAAKxF,EAAQ+O,aAAa,MAS9B,GANAF,EAAU,IAAIG,OAAO,IAAMb,EAAU,KACrCQ,EAAWA,EAAShR,QAAQkR,EAAS,IACjCrJ,GAAMmJ,EAASjoB,SACjBmoB,EAAU,IAAIG,OAAO,IAAMxJ,EAAK,mBAAoB,KACpDmJ,EAAWA,EAAShR,QAAQkR,EAAS,KAEnCC,GAAcH,EAASjoB,OAEzB,IAAK,IAAIS,GADT2nB,EAAaA,EAAWxf,MAAM,MACN5I,OAAQS,KAC9B0nB,EAAU,IAAIG,OAAO,MAAQF,EAAW3nB,GAAK,mBAAoB,KACjEwnB,EAAWA,EAAShR,QAAQkR,EAAS,IAGzC,OAA2B,IAApBF,EAASjoB,OAOlB,SAASuoB,EAAYhJ,EAAKT,GACxB,IAAI7B,EAEJ,GADAsC,EAAIR,iBAAmB9B,EAAKsC,EAAIR,eAAeD,IAC3C7B,EACF,OAAOA,EAET,IAAIuL,EAAM/nB,EAAGgoB,EAAWlJ,EAAIhB,qBAAqB,KACjD,IAAK9d,EAAI,EAAGA,EAAIgoB,EAASzoB,OAAQS,IAE/B,GAAIqe,KADJ0J,EAAOC,EAAShoB,IACA4nB,aAAa,MAC3B,OAAOG,EAnXb9qB,EAAOgrB,SAAW,GAClBhrB,EAAOirB,aAAe,GA4GtBjrB,EAAOkrB,wBAA0B,WAyB/B,SAASC,EAAWC,EAAQtS,EAAMgN,GAChCsF,EAAOtF,GAAOlf,KAAK0J,IAAItQ,EAAOiC,KAAKwF,iBAAiBqR,EAAK,KAW3D,IAAI7X,EAAU,CACR,EACA,EACA,EACA,EACA,EACA,GAIF6I,EAAS9J,EAAOe,MAEhBsqB,EAAW,uBAyBXzC,EAAY,OATH,0BACO9e,EAAS,IAAMuhB,EACrB,IAAMvhB,EAAS,IAAMuhB,EACrB,IAAMvhB,EAAS,IAAMuhB,EACrB,IAAMvhB,EAAS,IAAMuhB,EACrB,IAAMvhB,EAAS,IAAMuhB,EACrB,IAAMvhB,EAAS,aAIJ,KAbT,6BAA+BA,EAAS,OACxCuhB,EAAW,IAAMvhB,EAAS,eAad,KAjBhB,yBAA2BA,EAAS,OAChCuhB,EAAW,IAAMvhB,EAAS,eAiBlB,KAtBX,0BAA4BA,EAAS,OAClCuhB,EAAW,IAAMvhB,EAAS,IAC1BuhB,EAAW,IAAMvhB,EAAS,eAqBjB,KA3Bb,yBAA2BA,EAAS,aA4BxB,KA1BZ,yBAA2BA,EAAS,aA4BhC,IAOZwhB,EAAkB,IAAIV,OAHN,YAFH,MAAQhC,EAAY,MAAQyC,EAAW,IAAMzC,EAAY,OAE5B,WAM1C2C,EAAc,IAAIX,OAAOhC,EAAW,KAExC,OAAO,SAAS4C,GAGd,IAAIJ,EAASnqB,EAAQgZ,SACjBwR,EAAW,GAIf,IAAKD,GAAmBA,IAAmBF,EAAgB/P,KAAKiQ,GAC9D,OAAOJ,EAGTI,EAAejS,QAAQgS,EAAa,SAASxa,GAE3C,IA1FiBqa,EAAQtS,EACvB4S,EACAC,EAlBgBP,EAAQtS,EACxBrQ,EAAyBD,EACzBJ,EAAOC,EA0BY+iB,EAAQtS,EA8EzB8S,EAAI,IAAIhB,OAAOhC,GAAWve,KAAK0G,GAAO9N,OAAO,SAAU8N,GAErD,QAAUA,IAEZ8a,EAAYD,EAAE,GACd9S,EAAO8S,EAAE7gB,MAAM,GAAGwN,IAAIvO,YAE1B,OAAQ6hB,GACN,IAAK,YAtFsB/S,EAuFDA,GAvFPsS,EAuFDA,GAtFf,GAAKtS,EAAK,GACG,IAAhBA,EAAKxW,SACP8oB,EAAO,GAAKtS,EAAK,IAqFb,MACF,IAAK,SACHA,EAAK,GAAK9Y,EAAOiC,KAAKwF,iBAAiBqR,EAAK,IAtH9BsS,EAuHDA,EAvHStS,EAuHDA,EAtHvBrQ,EAAM7B,KAAK6B,IAAIqQ,EAAK,IAAKtQ,EAAM5B,KAAK4B,IAAIsQ,EAAK,IACtCzQ,EAAPD,EAAI,EACY,IAAhB0Q,EAAKxW,SACP8F,EAAI0Q,EAAK,GACTzQ,EAAIyQ,EAAK,IAGXsS,EAAO,GAAK3iB,EACZ2iB,EAAO,GAAK5iB,EACZ4iB,EAAO,IAAM5iB,EACb4iB,EAAO,GAAK3iB,EACZ2iB,EAAO,GAAKhjB,GAAKK,EAAML,EAAII,EAAMH,GACjC+iB,EAAO,GAAK/iB,GAAKG,EAAMJ,EAAIK,EAAMJ,GA2G3B,MACF,IAAK,QAzGU+iB,EA0GDA,EAzGdM,GADuB5S,EA0GDA,GAzGH,GACnB6S,EAA+B,IAAhB7S,EAAKxW,OAAgBwW,EAAK,GAAKA,EAAK,GAEvDsS,EAAO,GAAKM,EACZN,EAAO,GAAKO,EAsGN,MACF,IAAK,QACHR,EAAWC,EAAQtS,EAAM,GACzB,MACF,IAAK,QACHqS,EAAWC,EAAQtS,EAAM,GACzB,MACF,IAAK,SACHsS,EAAStS,EAKb2S,EAAShpB,KAAK2oB,EAAOnR,UAErBmR,EAASnqB,EAAQgZ,WAInB,IADA,IAAI6R,EAAiBL,EAAS,GACL,EAAlBA,EAASnpB,QACdmpB,EAASvQ,QACT4Q,EAAiB9rB,EAAOiC,KAAKuN,0BAA0Bsc,EAAgBL,EAAS,IAElF,OAAOK,GAnJsB,GAoUjC,IAAIC,EAAqB,IAAInB,OAC3B,SACU5qB,EAAOe,MAAQ,gBACff,EAAOe,MAAQ,gBACff,EAAOe,MAAQ,gBACff,EAAOe,MAAQ,WAO3B,SAASirB,EAAsBpQ,GAE7B,IAGI3S,EACAI,EACA4iB,EAAcC,EAAed,EAAQ7L,EALrC4M,EAAcvQ,EAAQ+O,aAAa,WACnC7a,EAAS,EACTC,EAAS,EAITqc,EAAYxQ,EAAQ+O,aAAa,SACjC0B,EAAazQ,EAAQ+O,aAAa,UAClCviB,EAAIwT,EAAQ+O,aAAa,MAAQ,EACjCtiB,EAAIuT,EAAQ+O,aAAa,MAAQ,EACjC2B,EAAsB1Q,EAAQ+O,aAAa,wBAA0B,GACrE4B,GAAmBJ,IAAgB7D,EAAkB/M,KAAKK,EAAQmO,aAC1CoC,EAAcA,EAAYpb,MAAMgb,IACxDS,GAAmBJ,IAAcC,GAA4B,SAAdD,GAAuC,SAAfC,EACvEI,EAAaF,GAAkBC,EAC/BE,EAAY,GAAKC,EAAkB,GAMvC,GAJAD,EAAUvjB,MAAQ,EAClBujB,EAAUjjB,OAAS,EACnBijB,EAAUD,WAAaA,EAGrB,OAAOC,EAGT,GAAIH,EAGF,OAFAG,EAAUvjB,MAAQe,EAAUkiB,GAC5BM,EAAUjjB,OAASS,EAAUmiB,GACtBK,EA0BT,GAvBAzjB,GAAQe,WAAWmiB,EAAY,IAC/B9iB,GAAQW,WAAWmiB,EAAY,IAC/BF,EAAejiB,WAAWmiB,EAAY,IACtCD,EAAgBliB,WAAWmiB,EAAY,IAElCK,GAOHE,EAAUvjB,MAAQ8iB,EAClBS,EAAUjjB,OAASyiB,IAPnBQ,EAAUvjB,MAAQe,EAAUkiB,GAC5BM,EAAUjjB,OAASS,EAAUmiB,GAC7Bvc,EAAS4c,EAAUvjB,MAAQ8iB,EAC3Blc,EAAS2c,EAAUjjB,OAASyiB,GASK,UADnCI,EAAsBtsB,EAAOiC,KAAKsP,kCAAkC+a,IAC5Cza,SAEtB9B,EAASD,EAAmBC,EAATD,EAAkBC,EAASD,GAGjC,IAAXA,GAA2B,IAAXC,GAAyB,IAAT9G,GAAuB,IAATI,GAAoB,IAANjB,GAAiB,IAANC,EACzE,OAAOqkB,EAcT,IAXItkB,GAAKC,KACPskB,EAAkB,cAAgBziB,EAAU9B,GAAK,IAAM8B,EAAU7B,GAAK,MAGxE+iB,EAASuB,EAAkB,WAAa7c,EAC1B,QAEAC,EAAS,IACR9G,EAAO6G,EAAU,IACjBzG,EAAO0G,EAAU,KAEP,QAArB6L,EAAQmO,SAAoB,CAG9B,IAFAxK,EAAK3D,EAAQkG,cAActT,cAAc,KAElCoN,EAAQgR,YACbrN,EAAG2B,YAAYtF,EAAQgR,YAEzBhR,EAAQsF,YAAY3B,QAIpB6L,GADA7L,EAAK3D,GACO+O,aAAa,aAAeS,EAI1C,OADA7L,EAAGG,aAAa,YAAa0L,GACtBsB,EAyBT1sB,EAAO6sB,iBAAmB,SAAShL,EAAKrd,EAAUqH,EAASihB,GACzD,GAAKjL,EAAL,EAjLF,SAA4BA,GAG1B,IAFA,IAAIkJ,EAAWlB,EAAkBhI,EAAK,CAAC,MAAO,YAAa9e,EAAI,EAExDgoB,EAASzoB,QAAUS,EAAIgoB,EAASzoB,QAAQ,CAC7C,IAM6C+d,EAAMpJ,EAAG8V,EAAO1b,EANzDkO,EAAKwL,EAAShoB,GACdiqB,EAAQzN,EAAGoL,aAAa,cAAcsC,OAAO,GAC7C7kB,EAAImX,EAAGoL,aAAa,MAAQ,EAC5BtiB,EAAIkX,EAAGoL,aAAa,MAAQ,EAC5BuC,EAAMrC,EAAYhJ,EAAKmL,GAAOG,WAAU,GACxCC,GAAgBF,EAAIvC,aAAa,cAAgB,IAAM,cAAgBviB,EAAI,KAAOC,EAAI,IAC1EglB,EAAYtC,EAASzoB,OAGrC,GADA0pB,EAAsBkB,GAClB,SAAS3R,KAAK2R,EAAInD,UAAW,CAC/B,IAAIuD,EAAMJ,EAAIpL,cAActT,cAAc,KAC1C,IAAKyI,EAAI,EAA2B5F,GAAxB0b,EAAQG,EAAI5N,YAAsBhd,OAAQ2U,EAAI5F,EAAG4F,IAC3DoJ,EAAO0M,EAAMnoB,KAAKqS,GAClBqW,EAAI5N,aAAaW,EAAK0J,SAAU1J,EAAKkN,WAGvC,KAAOL,EAAIN,YACTU,EAAIpM,YAAYgM,EAAIN,YAEtBM,EAAMI,EAGR,IAAKrW,EAAI,EAA0B5F,GAAvB0b,EAAQxN,EAAGD,YAAsBhd,OAAQ2U,EAAI5F,EAAG4F,IAEpC,OADtBoJ,EAAO0M,EAAMnoB,KAAKqS,IACT8S,UAAsC,MAAlB1J,EAAK0J,UAAsC,eAAlB1J,EAAK0J,WAIrC,cAAlB1J,EAAK0J,SACPqD,EAAe/M,EAAKkN,UAAY,IAAMH,EAGtCF,EAAIxN,aAAaW,EAAK0J,SAAU1J,EAAKkN,YAIzCL,EAAIxN,aAAa,YAAa0N,GAC9BF,EAAIxN,aAAa,sBAAuB,KACxCwN,EAAIM,gBAAgB,MACPjO,EAAGQ,WACL0B,aAAayL,EAAK3N,GAEzBwL,EAASzoB,SAAW+qB,GACtBtqB,KAsIJ0qB,CAAmB5L,GAEnB,IAAI6L,EAAU1tB,EAAOmN,OAAOwgB,QACxB9qB,EAAUmpB,EAAsBnK,GAChC+L,EAAc5tB,EAAOiC,KAAK+c,QAAQ6C,EAAIhB,qBAAqB,MAI/D,GAHAhe,EAAQwI,YAAcyhB,GAAkBA,EAAezhB,YACvDxI,EAAQ6qB,OAASA,EAEU,IAAvBE,EAAYtrB,QAAgBtC,EAAOW,aAAc,CAKnD,IADA,IAAIuf,EAAM,GACDnd,EAAI,EAAGC,GAFhB4qB,EAAc/L,EAAIgM,YAAY,wBAEIvrB,OAAQS,EAAIC,EAAKD,IACjDmd,EAAInd,GAAK6qB,EAAY7qB,GAEvB6qB,EAAc1N,EAGhB,IAAItT,EAAWghB,EAAY3qB,OAAO,SAASsc,GAEzC,OADAyM,EAAsBzM,GACf8I,EAAqB9M,KAAKgE,EAAGwK,SAASxQ,QAAQ,OAAQ,OAhDjE,SAAiCqC,EAASmO,GACxC,KAAOnO,IAAYA,EAAUA,EAAQmE,aACnC,GAAInE,EAAQmO,UAAYA,EAASxO,KAAKK,EAAQmO,SAASxQ,QAAQ,OAAQ,OACjEqC,EAAQ+O,aAAa,uBACzB,OAAO,EAGX,OAAO,EA0CEmD,CAAwBvO,EAAIgJ,MAGhC3b,GAAaA,IAAaA,EAAStK,OACtCkC,GAAYA,EAAS,GAAI,KAI3BxE,EAAOirB,aAAayC,GAAU1tB,EAAO+tB,gBAAgBlM,GACrD7hB,EAAOgrB,SAAS0C,GAAU1tB,EAAOguB,YAAYnM,GAE7C7hB,EAAOiuB,cAAcrhB,EAAU,SAASshB,GAClC1pB,GACFA,EAAS0pB,EAAWrrB,IAErBwW,EAAMxW,GAAUgJ,EAASihB,MAG9B,IAAIqB,EAAoB,IAAIvD,OAC1B,qHAEE5qB,EAAOe,MACT,2CAA6Cf,EAAOe,MAAQ,eAE9DkY,EAAOjZ,EAAQ,CASbouB,qBAAsB,SAASlrB,EAAOmrB,GACpC,IAAItd,EAAQ7N,EAAM6N,MAAMod,GAExB,GAAKpd,EAAL,CAGA,IAAIud,EAAYvd,EAAM,GAGlBwd,EAAaxd,EAAM,GACnB5G,EAAW4G,EAAM,GACjByd,EAAazd,EAAM,GACnBiB,EAAajB,EAAM,GAEnBud,IACFD,EAAOC,UAAYA,GAEjBC,IACFF,EAAOE,WAAaE,MAAMzkB,WAAWukB,IAAeA,EAAavkB,WAAWukB,IAE1EpkB,IACFkkB,EAAOlkB,SAAWD,EAAUC,IAE1B6H,IACFqc,EAAOrc,WAAaA,GAElBwc,IACFH,EAAOG,WAA4B,WAAfA,EAA0B,EAAIA,KAYtDT,gBAAiB,SAASlM,GACxB,IAMItC,EAAW6B,EAAI4L,EADf0B,EAAS7E,EAAkBhI,EALhB,CACT,iBACA,iBACA,qBACA,uBAEE5K,EAAI,EACRgU,EAAe,GAAK0D,EAAgB,GAIxC,IAFA1X,EAAIyX,EAAOpsB,OAEJ2U,KAEL+V,GADAzN,EAAKmP,EAAOzX,IACD0T,aAAa,cACxBvJ,EAAK7B,EAAGoL,aAAa,MACjBqC,IACF2B,EAAcvN,GAAM4L,EAAMC,OAAO,IAEnChC,EAAa7J,GAAM7B,EAGrB,IAAK6B,KAAMuN,EAAe,CACxB,IAAIzB,EAAMjC,EAAa0D,EAAcvN,IAAK+L,WAAU,GAEpD,IADA5N,EAAK0L,EAAa7J,GACX8L,EAAIN,YACTrN,EAAG2B,YAAYgM,EAAIN,YAGvB,OAAO3B,GAYT2D,gBAAiB,SAAShT,EAAS0D,EAAYoO,GAE7C,GAAK9R,EAAL,CAIA,IAAI1Y,EAEAiH,EADA0kB,EAAmB,QAGD,IAAXnB,IACTA,EAAS9R,EAAQ+O,aAAa,WAG5B/O,EAAQmE,YAAcyI,EAAiBjN,KAAKK,EAAQmE,WAAWgK,YACjE8E,EAAmB7uB,EAAO4uB,gBAAgBhT,EAAQmE,WAAYT,EAAYoO,IAE5EvjB,EAAY0kB,GAAoBA,EAAiB1kB,UACtCyR,EAAQ+O,aAAa,cAAgB3qB,EAAOsK,KAAKC,sBAE5D,IAAIukB,EAAgBxP,EAAWra,OAAO,SAASC,EAAMmb,GAKnD,OAJAnd,EAAQ0Y,EAAQ+O,aAAatK,MAE3Bnb,EAAKmb,GAAQnd,GAERgC,GACN,IAGH4pB,EAAgB7V,EAAO6V,EACrB7V,EA9aN,SAAmC2C,EAAS8R,GAC1C,IAAIlP,EAAS,GACb,IAAK,IAAIuQ,KAAQ/uB,EAAOgrB,SAAS0C,GAC/B,GAAIxD,EAAmBtO,EAASmT,EAAK7jB,MAAM,MACzC,IAAK,IAAIzF,KAAYzF,EAAOgrB,SAAS0C,GAAQqB,GAC3CvQ,EAAO/Y,GAAYzF,EAAOgrB,SAAS0C,GAAQqB,GAAMtpB,GAIvD,OAAO+Y,EAqaIwQ,CAA0BpT,EAAS8R,GAAS1tB,EAAOivB,oBAAoBrT,KAEhF,IAAIsT,EAAgBC,EA5sBA9O,EAAMnd,EAAO2rB,EAAkB1kB,EAEjDilB,EADAC,EATiBhP,EAotBkBiP,EAAkB,GACvD,IAAK,IAAIjP,KAAQyO,EACfI,GAttBiB7O,EAstBcA,KAptBvBoI,EACHA,EAAcpI,GAEhBA,EAGeA,EA+sBe6O,EA/sBThsB,EA+sByB4rB,EAAczO,GA/sBhCwO,EA+sBuCA,EA/sBrB1kB,EA+sBuCA,EA7sBxFilB,OAAAA,EADAC,EAAoD,mBAA1CliB,OAAOC,UAAUC,SAAS1K,KAAKO,GAG/B,SAATmd,GAA4B,WAATA,GAAgC,SAAVnd,EAG5B,oBAATmd,EAELnd,EADY,SAAVA,EACM,KAGAA,EAAMqW,QAAQ,KAAM,KAAKrO,MAAM,OAAOqN,IAAI,SAASJ,GACzD,OAAOnO,WAAWmO,KAIN,oBAATkI,EAELnd,EADE2rB,GAAoBA,EAAiBU,gBAC/B/f,EACNqf,EAAiBU,gBAAiBvvB,EAAOkrB,wBAAwBhoB,IAG3DlD,EAAOkrB,wBAAwBhoB,GAGzB,YAATmd,GACPnd,EAAmB,SAAVA,GAA8B,WAAVA,EAEzB2rB,IAAiD,IAA7BA,EAAiBW,UACvCtsB,GAAQ,IAGM,YAATmd,GACPnd,EAAQ8G,WAAW9G,GACf2rB,QAAwD,IAA7BA,EAAiB9Q,UAC9C7a,GAAS2rB,EAAiB9Q,UAGZ,YAATsC,EACPnd,EAAkB,UAAVA,EAAoB,OAAmB,QAAVA,EAAkB,QAAU,SAGjEksB,EAASC,EAAUnsB,EAAMqV,IAAIrO,GAAaA,EAAUhH,EAAOiH,GAtC3DjH,EAAQ,GA0sBNisB,GAjqBKE,GAAWZ,MAAMW,GAAUlsB,EAAQksB,EAkqBxCE,EAAgBJ,GAAkBC,EAEhCG,GAAmBA,EAAgBG,MACrCzvB,EAAOouB,qBAAqBkB,EAAgBG,KAAMH,GAEpD,IAAII,EAAczW,EAAO4V,EAAkBS,GAC3C,OAAO9G,EAAiBjN,KAAKK,EAAQmO,UAAY2F,EAjqBrD,SAA+BpQ,GAC7B,IAAK,IAAIe,KAAQsJ,EAEf,QAAiD,IAAtCrK,EAAWqK,EAAgBtJ,KAA+C,KAArBf,EAAWe,GAA3E,CAIA,QAAgC,IAArBf,EAAWe,GAAuB,CAC3C,IAAKrgB,EAAOmN,OAAOC,UAAUiT,GAC3B,SAEFf,EAAWe,GAAQrgB,EAAOmN,OAAOC,UAAUiT,GAG7C,GAAyC,IAArCf,EAAWe,GAAMre,QAAQ,QAA7B,CAIA,IAAI+jB,EAAQ,IAAI/lB,EAAOylB,MAAMnG,EAAWe,IACxCf,EAAWe,GAAQ0F,EAAM4J,SAAS9lB,EAAQkc,EAAM6J,WAAatQ,EAAWqK,EAAgBtJ,IAAQ,IAAIwP,UAEtG,OAAOvQ,EA4oB0DwQ,CAAsBJ,KAYvFzB,cAAe,SAASrhB,EAAUpI,EAAU3B,EAASgJ,EAASihB,GAC5D,IAAI9sB,EAAO+vB,eAAenjB,EAAUpI,EAAU3B,EAASgJ,EAASihB,GAAgBkD,SAUlFf,oBAAqB,SAASrT,GAC5B,IAlf6ByS,EAC3BhO,EAAMnd,EAifJmrB,EAAS,GACTvQ,EAAQlC,EAAQ+O,aAAa,SAEjC,OAAK7M,IAIgB,iBAAVA,GAzfkBuQ,EA0fHA,EAAPvQ,EAxffvE,QAAQ,QAAS,IAAIrO,MAAM,KAAKgB,QAAQ,SAAU+jB,GACtD,IAAIC,EAAOD,EAAM/kB,MAAM,KAEvBmV,EAAO6P,EAAK,GAAG5W,OAAOK,cACtBzW,EAASgtB,EAAK,GAAG5W,OAEjB+U,EAAOhO,GAAQnd,KAOnB,SAA0B4a,EAAOuQ,GAC/B,IAAIhO,EAAMnd,EACV,IAAK,IAAIX,KAAQub,OACY,IAAhBA,EAAMvb,KAIjB8d,EAAO9d,EAAKoX,cACZzW,EAAQ4a,EAAMvb,GAEd8rB,EAAOhO,GAAQnd,GAoebitB,CAAiBrS,EAAOuQ,IAGnBA,GAUT+B,qBAAsB,SAASrnB,GAG7B,IAAKA,EACH,OAAO,KAOT,IAAuBhG,EAAGC,EAAtBqtB,EAAe,GAInB,IAFAttB,EAAI,EACJC,GAJA+F,GAFAA,EAASA,EAAOwQ,QAAQ,KAAM,KAAKD,QAEnBpO,MAAM,QAIT5I,OACNS,EAAIC,EAAKD,GAAK,EACnBstB,EAAa5tB,KAAK,CAChB2F,EAAG4B,WAAWjB,EAAOhG,IACrBsF,EAAG2B,WAAWjB,EAAOhG,EAAI,MAS7B,OAAOstB,GAWTrC,YAAa,SAASnM,GAKpB,IAJA,IAAIrD,EAASqD,EAAIhB,qBAAqB,SAClCyP,EAAW,GAGNvtB,EAAI,EAAGC,EAAMwb,EAAOlc,OAAQS,EAAIC,EAAKD,IAAK,CAEjD,IAAIwtB,EAAgB/R,EAAOzb,GAAGytB,aAAehS,EAAOzb,GAAG0tB,KAI1B,MAD7BF,EAAgBA,EAAchX,QAAQ,oBAAqB,KACzCD,QAGViX,EAAcxf,MAAM,sBACdwH,IAAI,SAASwW,GAAQ,OAAOA,EAAKzV,SACzCpN,QAAQ,SAAS6iB,GAMrB,IAJA,IAAIhe,EAAQge,EAAKhe,MAAM,4BACnB2f,EAAU,GACVC,EAD6B5f,EAAM,GAAGuI,OACLC,QAAQ,KAAM,IAAIrO,MAAM,WAEpDnI,EAAI,EAAGC,EAAM2tB,EAAmBruB,OAAQS,EAAIC,EAAKD,IAAK,CAC7D,IAAImtB,EAAOS,EAAmB5tB,GAAGmI,MAAM,WACnCzF,EAAWyqB,EAAK,GAChBhtB,EAAQgtB,EAAK,GACjBQ,EAAQjrB,GAAYvC,GAEtB6rB,EAAOhe,EAAM,IACR7F,MAAM,KAAKgB,QAAQ,SAAS0kB,GAEjB,MADdA,EAAQA,EAAMrX,QAAQ,QAAS,IAAID,UAI/BgX,EAASM,GACX5wB,EAAOiC,KAAK6B,OAAOmV,OAAOqX,EAASM,GAAQF,GAG3CJ,EAASM,GAAS5wB,EAAOiC,KAAK6B,OAAOuV,MAAMqX,QAKnD,OAAOJ,GAaTO,eAAgB,SAASzlB,EAAK5G,EAAUqH,EAAShJ,GAE/CuI,EAAMA,EAAImO,QAAQ,SAAU,IAAID,OAChC,IAAItZ,EAAOiC,KAAK8gB,QAAQ3X,EAAK,CAC3ByN,OAAQ,MACRoK,WAGF,SAAoBrZ,GAElB,IAAIknB,EAAMlnB,EAAEmnB,YACRD,IAAQA,EAAIzU,iBAAmBrc,EAAOI,OAAOwiB,eAAiBhZ,EAAEonB,gBAClEF,EAAM,IAAIlO,cAAc,qBACpBqO,MAAQ,QAEZH,EAAII,QAAQtnB,EAAEonB,aAAazX,QAAQ,qCAAsC,MAEtEuX,GAAQA,EAAIzU,iBACf7X,GAAYA,EAAS,MAGvBxE,EAAO6sB,iBAAiBiE,EAAIzU,gBAAiB,SAAU8U,EAASC,GAC9D5sB,GAAYA,EAAS2sB,EAASC,IAC7BvlB,EAAShJ,OAahBwuB,kBAAmB,SAAS1mB,EAAQnG,EAAUqH,EAAShJ,GAErD,IAAIgf,EACJ,GAFAlX,EAASA,EAAO2O,OAES,oBAAdgY,UAA2B,CACpC,IAAIC,EAAS,IAAID,UACbC,GAAUA,EAAOC,kBACnB3P,EAAM0P,EAAOC,gBAAgB7mB,EAAQ,kBAGhC3K,EAAOI,OAAOwiB,iBACrBf,EAAM,IAAIe,cAAc,qBACpBqO,MAAQ,QAEZpP,EAAIqP,QAAQvmB,EAAO4O,QAAQ,qCAAsC,MAGnEvZ,EAAO6sB,iBAAiBhL,EAAIxF,gBAAiB,SAAU8U,EAASC,GAC9D5sB,EAAS2sB,EAASC,IACjBvlB,EAAShJ,MAz9BlB,CA69BsB,oBAAZ3C,QAA0BA,QAAU2B,MAG9C7B,OAAO+vB,eAAiB,SAASnjB,EAAUpI,EAAU3B,EAASgJ,EAASihB,GACrEjrB,KAAK+K,SAAWA,EAChB/K,KAAK2C,SAAWA,EAChB3C,KAAKgB,QAAUA,EACfhB,KAAKgK,QAAUA,EACfhK,KAAK6rB,OAAU7qB,GAAWA,EAAQ6qB,QAAW,EAC7C7rB,KAAKirB,eAAiBA,GAGxB9sB,OAAO+vB,eAAe3iB,UAAU4iB,MAAQ,WACtCnuB,KAAKqsB,UAAY,IAAIvb,MAAM9Q,KAAK+K,SAAStK,QACzCT,KAAK4vB,YAAc5vB,KAAK+K,SAAStK,OAEjCT,KAAK6vB,iBAGP1xB,OAAO+vB,eAAe3iB,UAAUskB,cAAgB,WAC9C,IAAK,IAAI3uB,EAAI,EAAGC,EAAMnB,KAAK+K,SAAStK,OAAQS,EAAIC,EAAKD,IACnDlB,KAAK+K,SAAS7J,GAAG2c,aAAa,SAAU7d,KAAK6rB,QAC7C,SAAUiE,EAAM5uB,GACdghB,WAAW,WACT4N,EAAKC,aAAaD,EAAK/kB,SAAS7J,GAAIA,IACnC,GAHL,CAIGlB,KAAMkB,IAIb/C,OAAO+vB,eAAe3iB,UAAUwkB,aAAe,SAASrS,EAAIxb,GAC1D,IAAI8K,EAAQ7O,OAAOA,OAAOiC,KAAK0I,OAAO8O,WAAW8F,EAAGF,QAAQ9F,QAAQ,OAAQ,MAC5E,GAAI1K,GAASA,EAAMgjB,YACjB,IACEhwB,KAAKiwB,cAAcjjB,EAAO0Q,EAAIxb,GAEhC,MAAOob,GACLnf,OAAO0L,IAAIyT,QAIbtd,KAAKkwB,eAIT/xB,OAAO+vB,eAAe3iB,UAAU0kB,cAAgB,SAASjjB,EAAO0Q,EAAIxb,GAClE,GAAI8K,EAAMoiB,MACRpiB,EAAMgjB,YAAYtS,EAAI1d,KAAKmwB,eAAejuB,EAAOwb,GAAK1d,KAAKgB,aAExD,CACH,IAAIwD,EAAMwI,EAAMgjB,YAAYtS,EAAI1d,KAAKgB,SACrChB,KAAKowB,gBAAgB5rB,EAAK,QAC1BxE,KAAKowB,gBAAgB5rB,EAAK,UAC1BxE,KAAKgK,SAAWhK,KAAKgK,QAAQ0T,EAAIlZ,GACjCxE,KAAKqsB,UAAUnqB,GAASsC,EACxBxE,KAAKkwB,gBAIT/xB,OAAO+vB,eAAe3iB,UAAU4kB,eAAiB,SAASjuB,EAAOwb,GAC/D,IAAIvF,EAAQnY,KACZ,OAAO,SAASwE,GACd2T,EAAMiY,gBAAgB5rB,EAAK,QAC3B2T,EAAMiY,gBAAgB5rB,EAAK,UAC3B2T,EAAMnO,SAAWmO,EAAMnO,QAAQ0T,EAAIlZ,GACnC2T,EAAMkU,UAAUnqB,GAASsC,EACzB2T,EAAM+X,gBAIV/xB,OAAO+vB,eAAe3iB,UAAU6kB,gBAAkB,SAAS5rB,EAAKZ,GAE9D,IAAIysB,EAAoB7rB,EAAIG,IAAIf,GAChC,GAAK,SAAW8V,KAAK2W,GAArB,CAGA,IAAIC,EAAaD,EAAkBnnB,MAAM,EAAGmnB,EAAkB5vB,OAAS,GACnEtC,OAAOirB,aAAappB,KAAK6rB,QAAQyE,IACnC9rB,EAAIf,IAAIG,EACNzF,OAAO2F,SAASksB,YAAY7xB,OAAOirB,aAAappB,KAAK6rB,QAAQyE,GAAa9rB,MAIhFrG,OAAO+vB,eAAe3iB,UAAU2kB,YAAc,WACjB,KAArBlwB,KAAK4vB,cACT5vB,KAAKqsB,UAAYrsB,KAAKqsB,UAAUjrB,OAAO,SAASsc,GAE9C,OAAa,MAANA,IAET1d,KAAK2C,SAAS3C,KAAKqsB,aAKvB,SAAUxnB,GAER,aAIA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAkB/C,SAASmI,EAAMC,EAAGC,GAChBxG,KAAKuG,EAAIA,EACTvG,KAAKwG,EAAIA,EAlBPrI,EAAOmI,MACTnI,EAAOujB,KAAK,oCAIdvjB,EAAOmI,MAAQA,GAgBTiF,UAAiD,CAErD1I,KAAM,QAEN6V,YAAapS,EAOb3E,IAAK,SAAU4uB,GACb,OAAO,IAAIjqB,EAAMtG,KAAKuG,EAAIgqB,EAAKhqB,EAAGvG,KAAKwG,EAAI+pB,EAAK/pB,IASlDC,UAAW,SAAU8pB,GAGnB,OAFAvwB,KAAKuG,GAAKgqB,EAAKhqB,EACfvG,KAAKwG,GAAK+pB,EAAK/pB,EACRxG,MAQTwwB,UAAW,SAAUC,GACnB,OAAO,IAAInqB,EAAMtG,KAAKuG,EAAIkqB,EAAQzwB,KAAKwG,EAAIiqB,IAS7CC,gBAAiB,SAAUD,GAGzB,OAFAzwB,KAAKuG,GAAKkqB,EACVzwB,KAAKwG,GAAKiqB,EACHzwB,MAQT2wB,SAAU,SAAUJ,GAClB,OAAO,IAAIjqB,EAAMtG,KAAKuG,EAAIgqB,EAAKhqB,EAAGvG,KAAKwG,EAAI+pB,EAAK/pB,IASlDL,eAAgB,SAAUoqB,GAGxB,OAFAvwB,KAAKuG,GAAKgqB,EAAKhqB,EACfvG,KAAKwG,GAAK+pB,EAAK/pB,EACRxG,MAQT4wB,eAAgB,SAAUH,GACxB,OAAO,IAAInqB,EAAMtG,KAAKuG,EAAIkqB,EAAQzwB,KAAKwG,EAAIiqB,IAS7CI,qBAAsB,SAAUJ,GAG9B,OAFAzwB,KAAKuG,GAAKkqB,EACVzwB,KAAKwG,GAAKiqB,EACHzwB,MAST8wB,SAAU,SAAUL,GAClB,OAAO,IAAInqB,EAAMtG,KAAKuG,EAAIkqB,EAAQzwB,KAAKwG,EAAIiqB,IAU7CM,eAAgB,SAAUN,GAGxB,OAFAzwB,KAAKuG,GAAKkqB,EACVzwB,KAAKwG,GAAKiqB,EACHzwB,MASTgxB,OAAQ,SAAUP,GAChB,OAAO,IAAInqB,EAAMtG,KAAKuG,EAAIkqB,EAAQzwB,KAAKwG,EAAIiqB,IAU7CQ,aAAc,SAAUR,GAGtB,OAFAzwB,KAAKuG,GAAKkqB,EACVzwB,KAAKwG,GAAKiqB,EACHzwB,MAQTkxB,GAAI,SAAUX,GACZ,OAAQvwB,KAAKuG,IAAMgqB,EAAKhqB,GAAKvG,KAAKwG,IAAM+pB,EAAK/pB,GAQ/C2qB,GAAI,SAAUZ,GACZ,OAAQvwB,KAAKuG,EAAIgqB,EAAKhqB,GAAKvG,KAAKwG,EAAI+pB,EAAK/pB,GAQ3C4qB,IAAK,SAAUb,GACb,OAAQvwB,KAAKuG,GAAKgqB,EAAKhqB,GAAKvG,KAAKwG,GAAK+pB,EAAK/pB,GAS7C6qB,GAAI,SAAUd,GACZ,OAAQvwB,KAAKuG,EAAIgqB,EAAKhqB,GAAKvG,KAAKwG,EAAI+pB,EAAK/pB,GAQ3C8qB,IAAK,SAAUf,GACb,OAAQvwB,KAAKuG,GAAKgqB,EAAKhqB,GAAKvG,KAAKwG,GAAK+pB,EAAK/pB,GAS7C+qB,KAAM,SAAUhB,EAAMxpB,GAKpB,YAJiB,IAANA,IACTA,EAAI,IAENA,EAAIhC,KAAKU,IAAIV,KAAKS,IAAI,EAAGuB,GAAI,GACtB,IAAIT,EAAMtG,KAAKuG,GAAKgqB,EAAKhqB,EAAIvG,KAAKuG,GAAKQ,EAAG/G,KAAKwG,GAAK+pB,EAAK/pB,EAAIxG,KAAKwG,GAAKO,IAQhFyqB,aAAc,SAAUjB,GACtB,IAAIzkB,EAAK9L,KAAKuG,EAAIgqB,EAAKhqB,EACnBwF,EAAK/L,KAAKwG,EAAI+pB,EAAK/pB,EACvB,OAAOzB,KAAKD,KAAKgH,EAAKA,EAAKC,EAAKA,IAQlC0lB,aAAc,SAAUlB,GACtB,OAAOvwB,KAAKuxB,KAAKhB,IAQnB/qB,IAAK,SAAU+qB,GACb,OAAO,IAAIjqB,EAAMvB,KAAKS,IAAIxF,KAAKuG,EAAGgqB,EAAKhqB,GAAIxB,KAAKS,IAAIxF,KAAKwG,EAAG+pB,EAAK/pB,KAQnEf,IAAK,SAAU8qB,GACb,OAAO,IAAIjqB,EAAMvB,KAAKU,IAAIzF,KAAKuG,EAAGgqB,EAAKhqB,GAAIxB,KAAKU,IAAIzF,KAAKwG,EAAG+pB,EAAK/pB,KAOnEgF,SAAU,WACR,OAAOxL,KAAKuG,EAAI,IAAMvG,KAAKwG,GAS7BkrB,MAAO,SAAUnrB,EAAGC,GAGlB,OAFAxG,KAAKuG,EAAIA,EACTvG,KAAKwG,EAAIA,EACFxG,MAQT2xB,KAAM,SAAUprB,GAEd,OADAvG,KAAKuG,EAAIA,EACFvG,MAQT4xB,KAAM,SAAUprB,GAEd,OADAxG,KAAKwG,EAAIA,EACFxG,MAQT6xB,aAAc,SAAUtB,GAGtB,OAFAvwB,KAAKuG,EAAIgqB,EAAKhqB,EACdvG,KAAKwG,EAAI+pB,EAAK/pB,EACPxG,MAOT8xB,KAAM,SAAUvB,GACd,IAAIhqB,EAAIvG,KAAKuG,EACTC,EAAIxG,KAAKwG,EACbxG,KAAKuG,EAAIgqB,EAAKhqB,EACdvG,KAAKwG,EAAI+pB,EAAK/pB,EACd+pB,EAAKhqB,EAAIA,EACTgqB,EAAK/pB,EAAIA,GAOXgR,MAAO,WACL,OAAO,IAAIlR,EAAMtG,KAAKuG,EAAGvG,KAAKwG,KA5UpC,CAgVsB,oBAAZnI,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAGA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAa/C,SAAS4zB,EAAaC,GACpBhyB,KAAKgyB,OAASA,EACdhyB,KAAKkH,OAAS,GAbZ/I,EAAO4zB,aACT5zB,EAAOujB,KAAK,2CAedvjB,EAAO4zB,aAAeA,EAEtB5zB,EAAO4zB,aAAaxmB,UAAwD,CAE1EmN,YAAaqZ,EAQbE,YAAa,SAAUhsB,GAErB,OADAjG,KAAKkH,OAAOtG,KAAKqF,GACVjG,MASTkyB,aAAc,SAAUhrB,GAEtB,OADAlH,KAAKkH,OAASlH,KAAKkH,OAAOkR,OAAOlR,GAC1BlH,OAcX7B,EAAO4zB,aAAaI,kBAAoB,SAAUC,EAAIC,EAAIC,EAAIC,GAC5D,IAAIvf,EACAwf,GAAOD,EAAGhsB,EAAI+rB,EAAG/rB,IAAM6rB,EAAG5rB,EAAI8rB,EAAG9rB,IAAM+rB,EAAG/rB,EAAI8rB,EAAG9rB,IAAM4rB,EAAG7rB,EAAI+rB,EAAG/rB,GACjEksB,GAAOJ,EAAG9rB,EAAI6rB,EAAG7rB,IAAM6rB,EAAG5rB,EAAI8rB,EAAG9rB,IAAM6rB,EAAG7rB,EAAI4rB,EAAG5rB,IAAM4rB,EAAG7rB,EAAI+rB,EAAG/rB,GACjEmsB,GAAMH,EAAG/rB,EAAI8rB,EAAG9rB,IAAM6rB,EAAG9rB,EAAI6rB,EAAG7rB,IAAMgsB,EAAGhsB,EAAI+rB,EAAG/rB,IAAM8rB,EAAG7rB,EAAI4rB,EAAG5rB,GACpE,GAAW,IAAPksB,EAAU,CACZ,IAAIC,EAAKH,EAAME,EACXE,EAAKH,EAAMC,EACX,GAAKC,GAAMA,GAAM,GAAK,GAAKC,GAAMA,GAAM,GACzC5f,EAAS,IAAI+e,EAAa,iBACnBE,YAAY,IAAI9zB,EAAOmI,MAAM8rB,EAAG7rB,EAAIosB,GAAMN,EAAG9rB,EAAI6rB,EAAG7rB,GAAI6rB,EAAG5rB,EAAImsB,GAAMN,EAAG7rB,EAAI4rB,EAAG5rB,KAGtFwM,EAAS,IAAI+e,OAKb/e,EAAS,IAAI+e,EADH,IAARS,GAAqB,IAARC,EACW,aAGA,YAG9B,OAAOzf,GAaT7U,EAAO4zB,aAAac,qBAAuB,SAAST,EAAIC,EAAInrB,GAK1D,IAJA,IAEIorB,EAAIC,EAAIO,EAFR9f,EAAS,IAAI+e,EACbtxB,EAASyG,EAAOzG,OAGXS,EAAI,EAAGA,EAAIT,EAAQS,IAC1BoxB,EAAKprB,EAAOhG,GACZqxB,EAAKrrB,GAAQhG,EAAI,GAAKT,GACtBqyB,EAAQf,EAAaI,kBAAkBC,EAAIC,EAAIC,EAAIC,GAEnDvf,EAAOkf,aAAaY,EAAM5rB,QAK5B,OAH2B,EAAvB8L,EAAO9L,OAAOzG,SAChBuS,EAAOgf,OAAS,gBAEXhf,GAUT7U,EAAO4zB,aAAagB,wBAA0B,SAAUC,EAASC,GAI/D,IAHA,IAAIjgB,EAAS,IAAI+e,EACbtxB,EAASuyB,EAAQvyB,OAEZS,EAAI,EAAGA,EAAIT,EAAQS,IAAK,CAC/B,IAAIkxB,EAAKY,EAAQ9xB,GACbmxB,EAAKW,GAAS9xB,EAAI,GAAKT,GACvBqyB,EAAQf,EAAac,qBAAqBT,EAAIC,EAAIY,GAEtDjgB,EAAOkf,aAAaY,EAAM5rB,QAK5B,OAH2B,EAAvB8L,EAAO9L,OAAOzG,SAChBuS,EAAOgf,OAAS,gBAEXhf,GAWT7U,EAAO4zB,aAAamB,0BAA4B,SAAUhsB,EAAQisB,EAAIC,GACpE,IAAI5tB,EAAM2tB,EAAG3tB,IAAI4tB,GACb3tB,EAAM0tB,EAAG1tB,IAAI2tB,GACbC,EAAW,IAAIl1B,EAAOmI,MAAMb,EAAIc,EAAGf,EAAIgB,GACvC8sB,EAAa,IAAIn1B,EAAOmI,MAAMd,EAAIe,EAAGd,EAAIe,GACzC+sB,EAASxB,EAAac,qBAAqBrtB,EAAK6tB,EAAUnsB,GAC1DssB,EAASzB,EAAac,qBAAqBQ,EAAU5tB,EAAKyB,GAC1DusB,EAAS1B,EAAac,qBAAqBptB,EAAK6tB,EAAYpsB,GAC5DwsB,EAAS3B,EAAac,qBAAqBS,EAAY9tB,EAAK0B,GAC5D8L,EAAS,IAAI+e,EAUjB,OARA/e,EAAOkf,aAAaqB,EAAOrsB,QAC3B8L,EAAOkf,aAAasB,EAAOtsB,QAC3B8L,EAAOkf,aAAauB,EAAOvsB,QAC3B8L,EAAOkf,aAAawB,EAAOxsB,QAEA,EAAvB8L,EAAO9L,OAAOzG,SAChBuS,EAAOgf,OAAS,gBAEXhf,IAxKX,CA2KsB,oBAAZ3U,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAiB/C,SAASylB,EAAMM,GACRA,EAIHlkB,KAAK2zB,iBAAiBzP,GAHtBlkB,KAAK4zB,UAAU,CAAC,EAAG,EAAG,EAAG,IAwT7B,SAASC,EAAQ/sB,EAAGgtB,EAAG/sB,GAOrB,OANIA,EAAI,IACNA,GAAK,GAEC,EAAJA,IACFA,GAAK,GAEHA,EAAI,EAAI,EACHD,EAAc,GAATgtB,EAAIhtB,GAASC,EAEvBA,EAAI,GACC+sB,EAEL/sB,EAAI,EAAI,EACHD,GAAKgtB,EAAIhtB,IAAM,EAAI,EAAIC,GAAK,EAE9BD,EAzVL3I,EAAOylB,MACTzlB,EAAOujB,KAAK,qCAuBdvjB,EAAOylB,MAAQA,EAEfzlB,EAAOylB,MAAMrY,UAAiD,CAM5DooB,iBAAkB,SAASzP,GACzB,IAAIlgB,EAEAkgB,KAASN,EAAMmQ,eACjB7P,EAAQN,EAAMmQ,aAAa7P,IAGf,gBAAVA,IACFlgB,EAAS,CAAC,IAAK,IAAK,IAAK,IAGtBA,IACHA,EAAS4f,EAAMoQ,cAAc9P,IAE1BlgB,IACHA,EAAS4f,EAAMqQ,cAAc/P,IAE1BlgB,IACHA,EAAS4f,EAAMsQ,cAAchQ,IAE1BlgB,IAEHA,EAAS,CAAC,EAAG,EAAG,EAAG,IAEjBA,GACFhE,KAAK4zB,UAAU5vB,IAYnBmwB,UAAW,SAASpsB,EAAGqsB,EAAGxmB,GACxB7F,GAAK,IAAKqsB,GAAK,IAAKxmB,GAAK,IAEzB,IAAIymB,EAAG/hB,EAAG9C,EACN/J,EAAMtH,EAAOiC,KAAKC,MAAMoF,IAAI,CAACsC,EAAGqsB,EAAGxmB,IACnCpI,EAAMrH,EAAOiC,KAAKC,MAAMmF,IAAI,CAACuC,EAAGqsB,EAAGxmB,IAIvC,GAFA4B,GAAK/J,EAAMD,GAAO,EAEdC,IAAQD,EACV6uB,EAAI/hB,EAAI,MAEL,CACH,IAAIwQ,EAAIrd,EAAMD,EAEd,OADA8M,EAAQ,GAAJ9C,EAAUsT,GAAK,EAAIrd,EAAMD,GAAOsd,GAAKrd,EAAMD,GACvCC,GACN,KAAKsC,EACHssB,GAAKD,EAAIxmB,GAAKkV,GAAKsR,EAAIxmB,EAAI,EAAI,GAC/B,MACF,KAAKwmB,EACHC,GAAKzmB,EAAI7F,GAAK+a,EAAI,EAClB,MACF,KAAKlV,EACHymB,GAAKtsB,EAAIqsB,GAAKtR,EAAI,EAGtBuR,GAAK,EAGP,MAAO,CACLtvB,KAAKuvB,MAAU,IAAJD,GACXtvB,KAAKuvB,MAAU,IAAJhiB,GACXvN,KAAKuvB,MAAU,IAAJ9kB,KAQfqU,UAAW,WACT,OAAO7jB,KAAKu0B,SAOdX,UAAW,SAAS5vB,GAClBhE,KAAKu0B,QAAUvwB,GAOjBwwB,MAAO,WACL,IAAIxwB,EAAShE,KAAK6jB,YAClB,MAAO,OAAS7f,EAAO,GAAK,IAAMA,EAAO,GAAK,IAAMA,EAAO,GAAK,KAOlEgqB,OAAQ,WACN,IAAIhqB,EAAShE,KAAK6jB,YAClB,MAAO,QAAU7f,EAAO,GAAK,IAAMA,EAAO,GAAK,IAAMA,EAAO,GAAK,IAAMA,EAAO,GAAK,KAOrFywB,MAAO,WACL,IAAIzwB,EAAShE,KAAK6jB,YACd6Q,EAAM10B,KAAKm0B,UAAUnwB,EAAO,GAAIA,EAAO,GAAIA,EAAO,IAEtD,MAAO,OAAS0wB,EAAI,GAAK,IAAMA,EAAI,GAAK,KAAOA,EAAI,GAAK,MAO1DC,OAAQ,WACN,IAAI3wB,EAAShE,KAAK6jB,YACd6Q,EAAM10B,KAAKm0B,UAAUnwB,EAAO,GAAIA,EAAO,GAAIA,EAAO,IAEtD,MAAO,QAAU0wB,EAAI,GAAK,IAAMA,EAAI,GAAK,KAAOA,EAAI,GAAK,KAAO1wB,EAAO,GAAK,KAO9E4wB,MAAO,WACL,IAA+B7sB,EAAGqsB,EAAGxmB,EAAjC5J,EAAShE,KAAK6jB,YAWlB,OARA9b,EAAkB,KADlBA,EAAI/D,EAAO,GAAGwH,SAAS,KAChB/K,OAAiB,IAAMsH,EAAKA,EAGnCqsB,EAAkB,KADlBA,EAAIpwB,EAAO,GAAGwH,SAAS,KAChB/K,OAAiB,IAAM2zB,EAAKA,EAGnCxmB,EAAkB,KADlBA,EAAI5J,EAAO,GAAGwH,SAAS,KAChB/K,OAAiB,IAAMmN,EAAKA,EAE5B7F,EAAEkB,cAAgBmrB,EAAEnrB,cAAgB2E,EAAE3E,eAO/C4rB,OAAQ,WACN,IAA+B/sB,EAM/B,OAFAA,EAAkB,KADlBA,GADAA,EAAgB,IAFH9H,KAAK6jB,YAEP,IACLrY,SAAS,KACR/K,OAAiB,IAAMqH,EAAKA,EAE5B9H,KAAK40B,QAAU9sB,EAAEmB,eAO1B8kB,SAAU,WACR,OAAO/tB,KAAK6jB,YAAY,IAQ1BiK,SAAU,SAASgH,GACjB,IAAI9wB,EAAShE,KAAK6jB,YAGlB,OAFA7f,EAAO,GAAK8wB,EACZ90B,KAAK4zB,UAAU5vB,GACRhE,MAOT+0B,YAAa,WACX,IAAI/wB,EAAShE,KAAK6jB,YACdmR,EAAUvU,UAAsB,GAAZzc,EAAO,GAAuB,IAAZA,EAAO,GAAwB,IAAZA,EAAO,IAAWgE,QAAQ,GAAI,IACvFitB,EAAejxB,EAAO,GAE1B,OADAhE,KAAK4zB,UAAU,CAACoB,EAASA,EAASA,EAASC,IACpCj1B,MAQTk1B,aAAc,SAASC,GACrB,IAAInxB,EAAShE,KAAK6jB,YACdmR,GAAuB,GAAZhxB,EAAO,GAAuB,IAAZA,EAAO,GAAwB,IAAZA,EAAO,IAAWgE,QAAQ,GAC1EitB,EAAejxB,EAAO,GAM1B,OAJAmxB,EAAYA,GAAa,IAEzBH,EAAW5sB,OAAO4sB,GAAW5sB,OAAO+sB,GAAc,EAAI,IACtDn1B,KAAK4zB,UAAU,CAACoB,EAASA,EAASA,EAASC,IACpCj1B,MAQTo1B,YAAa,SAASC,GACdA,aAAsBzR,IAC1ByR,EAAa,IAAIzR,EAAMyR,IASzB,IANA,IAAIriB,EAAS,GACT8hB,EAAQ90B,KAAK+tB,WAEb/pB,EAAShE,KAAK6jB,YACdyR,EAAcD,EAAWxR,YAEpB3iB,EAAI,EAAGA,EAAI,EAAGA,IACrB8R,EAAOpS,KAAKmE,KAAKuvB,MAAmB,GAAZtwB,EAAO9C,GALhB,GAK0Co0B,EAAYp0B,KAKvE,OAFA8R,EAAO,GAAK8hB,EACZ90B,KAAK4zB,UAAU5gB,GACRhT,OAWX7B,EAAOylB,MAAM2R,OAAS,mIAQtBp3B,EAAOylB,MAAM4R,OAAS,+FAQtBr3B,EAAOylB,MAAM6R,MAAQ,yDASrBt3B,EAAOylB,MAAMmQ,aAAe,CAC1B2B,KAAS,UACTC,MAAS,UACTC,KAAS,UACTC,QAAS,UACTC,KAAS,UACTC,KAAS,UACTC,MAAS,UACTC,KAAS,UACTC,OAAS,UACTC,KAAS,UACTC,MAAS,UACTC,OAAS,UACTC,OAAS,UACTC,IAAS,UACTC,OAAS,UACTC,KAAS,UACTC,MAAS,UACTC,OAAS,WAmCXx4B,EAAOylB,MAAMgT,QAAU,SAAS1S,GAC9B,OAAON,EAAMiT,WAAWjT,EAAMqQ,cAAc/P,KAS9C/lB,EAAOylB,MAAMqQ,cAAgB,SAAS/P,GACpC,IAAIhV,EAAQgV,EAAMhV,MAAM0U,EAAM2R,QAC9B,GAAIrmB,EAAO,CACT,IAAInH,EAAI0Y,SAASvR,EAAM,GAAI,KAAO,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,IAAM,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,GAC5FklB,EAAI3T,SAASvR,EAAM,GAAI,KAAO,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,IAAM,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,GAC5FtB,EAAI6S,SAASvR,EAAM,GAAI,KAAO,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,IAAM,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,GAEhG,MAAO,CACLuR,SAAS1Y,EAAG,IACZ0Y,SAAS2T,EAAG,IACZ3T,SAAS7S,EAAG,IACZsB,EAAM,GAAK/G,WAAW+G,EAAM,IAAM,KAaxC/Q,EAAOylB,MAAMkT,SAAWlT,EAAMgT,QAQ9Bz4B,EAAOylB,MAAMmT,QAAU,SAAS7S,GAC9B,OAAON,EAAMiT,WAAWjT,EAAMsQ,cAAchQ,KAW9C/lB,EAAOylB,MAAMsQ,cAAgB,SAAShQ,GACpC,IAAIhV,EAAQgV,EAAMhV,MAAM0U,EAAM4R,QAC9B,GAAKtmB,EAAL,CAIA,IAGInH,EAAGqsB,EAAGxmB,EAHNymB,GAAOlsB,WAAW+G,EAAM,IAAM,IAAO,KAAO,IAAO,IACnDoD,EAAInK,WAAW+G,EAAM,KAAO,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,GACxDM,EAAIrH,WAAW+G,EAAM,KAAO,KAAKwK,KAAKxK,EAAM,IAAM,IAAM,GAG5D,GAAU,IAANoD,EACFvK,EAAIqsB,EAAIxmB,EAAI4B,MAET,CACH,IAAIskB,EAAItkB,GAAK,GAAMA,GAAK8C,EAAI,GAAK9C,EAAI8C,EAAI9C,EAAI8C,EACzCxL,EAAQ,EAAJ0I,EAAQskB,EAEhB/rB,EAAI8rB,EAAQ/sB,EAAGgtB,EAAGO,EAAI,EAAI,GAC1BD,EAAIP,EAAQ/sB,EAAGgtB,EAAGO,GAClBzmB,EAAIimB,EAAQ/sB,EAAGgtB,EAAGO,EAAI,EAAI,GAG5B,MAAO,CACLtvB,KAAKuvB,MAAU,IAAJvsB,GACXhD,KAAKuvB,MAAU,IAAJF,GACXrvB,KAAKuvB,MAAU,IAAJ1mB,GACXsB,EAAM,GAAK/G,WAAW+G,EAAM,IAAM,KAYtC/Q,EAAOylB,MAAMoT,SAAWpT,EAAMmT,QAS9B54B,EAAOylB,MAAMqT,QAAU,SAAS/S,GAC9B,OAAON,EAAMiT,WAAWjT,EAAMoQ,cAAc9P,KAU9C/lB,EAAOylB,MAAMoQ,cAAgB,SAAS9P,GACpC,GAAIA,EAAMhV,MAAM0U,EAAM6R,OAAQ,CAC5B,IAAIp0B,EAAQ6iB,EAAMhb,MAAMgb,EAAM/jB,QAAQ,KAAO,GACzC+2B,EAAoC,IAAjB71B,EAAMZ,QAAiC,IAAjBY,EAAMZ,OAC/C02B,EAA2B,IAAjB91B,EAAMZ,QAAiC,IAAjBY,EAAMZ,OACtCsH,EAAImvB,EAAmB71B,EAAM2H,OAAO,GAAK3H,EAAM2H,OAAO,GAAM3H,EAAM+1B,UAAU,EAAG,GAC/EhD,EAAI8C,EAAmB71B,EAAM2H,OAAO,GAAK3H,EAAM2H,OAAO,GAAM3H,EAAM+1B,UAAU,EAAG,GAC/ExpB,EAAIspB,EAAmB71B,EAAM2H,OAAO,GAAK3H,EAAM2H,OAAO,GAAM3H,EAAM+1B,UAAU,EAAG,GAC/EtvB,EAAIqvB,EAAUD,EAAmB71B,EAAM2H,OAAO,GAAK3H,EAAM2H,OAAO,GAAM3H,EAAM+1B,UAAU,EAAG,GAAM,KAEnG,MAAO,CACL3W,SAAS1Y,EAAG,IACZ0Y,SAAS2T,EAAG,IACZ3T,SAAS7S,EAAG,IACZzF,YAAYsY,SAAS3Y,EAAG,IAAM,KAAKE,QAAQ,OAYjD7J,EAAOylB,MAAMiT,WAAa,SAAS7yB,GACjC,IAAIqzB,EAAS,IAAIzT,EAEjB,OADAyT,EAAOzD,UAAU5vB,GACVqzB,IAtfX,CAyfsB,oBAAZh5B,QAA0BA,QAAU2B,MAG9C,WAGE,SAASs3B,EAAa5Z,GACpB,IAEIwG,EAAOqT,EAAYrb,EAFnBD,EAAQyB,EAAGoL,aAAa,SACxB3I,EAASzC,EAAGoL,aAAa,WAAa,EAM1C,GADA3I,GADAA,EAAShY,WAAWgY,IAAW,KAAKzG,KAAKyG,GAAU,IAAM,IACvC,EAAI,EAAa,EAATA,EAAa,EAAIA,EACvClE,EAAO,CACT,IAAIub,EAAgBvb,EAAM5S,MAAM,WAEgB,KAA5CmuB,EAAcA,EAAc/2B,OAAS,IACvC+2B,EAAcznB,MAGhB,IAAK,IAAI7O,EAAIs2B,EAAc/2B,OAAQS,KAAO,CAExC,IAAImI,EAAQmuB,EAAct2B,GAAGmI,MAAM,WAC/B3E,EAAM2E,EAAM,GAAGoO,OACfpW,EAAQgI,EAAM,GAAGoO,OAET,eAAR/S,EACFwf,EAAQ7iB,EAEO,iBAARqD,IACPwX,EAAU7a,IAiBhB,OAZK6iB,IACHA,EAAQxG,EAAGoL,aAAa,eAAiB,cAEtC5M,IACHA,EAAUwB,EAAGoL,aAAa,iBAI5ByO,GADArT,EAAQ,IAAI/lB,OAAOylB,MAAMM,IACN6J,WACnB7R,EAAU0Q,MAAMzkB,WAAW+T,IAAY,EAAI/T,WAAW+T,GACtDA,GAAWqb,EAEJ,CACLpX,OAAQA,EACR+D,MAAOA,EAAMsQ,QACbtY,QAASA,GAyBb,IAAI1E,EAAQrZ,OAAOiC,KAAK6B,OAAOuV,MAqV/B,SAASigB,EAA6Bx1B,EAAQjB,EAAS02B,GACrD,IAAIC,EAAWC,EAAY,EAAGC,EAAa,EAAGC,EAAgB,GAC9D,IAAK,IAAIp3B,KAAQM,EACO,aAAlBA,EAAQN,GACVM,EAAQN,GAAQ,EAES,cAAlBM,EAAQN,KACfM,EAAQN,GAAQ,GAElBi3B,EAAYxvB,WAAWnH,EAAQN,GAAO,IAEpCm3B,EAD2B,iBAAlB72B,EAAQN,IAAsB,SAASgZ,KAAK1Y,EAAQN,IAChD,IAGA,EAEF,OAATA,GAA0B,OAATA,GAA0B,OAATA,GACpCm3B,GAAgC,sBAAlBH,EAAwCz1B,EAAOqF,MAAQ,EACrEswB,EAA8B,sBAAlBF,GAAwCz1B,EAAOyF,MAAY,GAEvD,OAAThH,GAA0B,OAATA,IACxBm3B,GAAgC,sBAAlBH,EAAwCz1B,EAAO2F,OAAS,EACtEgwB,EAA8B,sBAAlBF,GAAwCz1B,EAAO0F,KAAW,GAExE3G,EAAQN,GAAQi3B,EAAYE,EAAaD,EAE3C,GAAoB,YAAhB31B,EAAOY,MACQ,OAAf7B,EAAQoyB,IACU,sBAAlBsE,GACAz1B,EAAOkP,KAAOlP,EAAOmP,GAAI,CAE3B,IAAI2mB,EAAc91B,EAAOmP,GAAKnP,EAAOkP,GACrC2mB,EAAgB,aAAeC,EAAc,IACzC/2B,EAAQyT,KACVzT,EAAQyT,IAAMsjB,GAEZ/2B,EAAQ4K,KACV5K,EAAQ4K,IAAMmsB,GAGlB,OAAOD,EArXT35B,OAAO2F,SAAW3F,OAAOiC,KAAK+Y,YAAoD,CAOhF6e,QAAS,EAOTC,QAAS,EAOT7e,WAAY,SAASpY,GACnBA,IAAYA,EAAU,IAEtB,IAAIyU,EAAS,GAEbzV,KAAKuf,GAAKphB,OAAOmN,OAAOwgB,QACxB9rB,KAAK6C,KAAO7B,EAAQ6B,MAAQ,SAE5B4S,EAAS,CACPjB,GAAIxT,EAAQyU,OAAOjB,IAAM,EACzBC,GAAIzT,EAAQyU,OAAOhB,IAAM,EACzB9I,GAAI3K,EAAQyU,OAAO9J,IAAM,EACzBC,GAAI5K,EAAQyU,OAAO7J,IAAM,GAGT,WAAd5L,KAAK6C,OACP4S,EAAO0d,GAAKnyB,EAAQyU,OAAO0d,IAAM,EACjC1d,EAAO2d,GAAKpyB,EAAQyU,OAAO2d,IAAM,GAEnCpzB,KAAKyV,OAASA,EACdzV,KAAK6D,WAAa7C,EAAQ6C,WAAWqF,QACjClI,EAAQk3B,oBACVl4B,KAAKk4B,kBAAoBl3B,EAAQk3B,mBAEnCl4B,KAAKg4B,QAAUh3B,EAAQg3B,SAAWh4B,KAAKg4B,QACvCh4B,KAAKi4B,QAAUj3B,EAAQi3B,SAAWj4B,KAAKi4B,SAQzCE,aAAc,SAASt0B,GACrB,IAAK,IAAIu0B,KAAYv0B,EAAY,CAC/B,IAAIqgB,EAAQ,IAAI/lB,OAAOylB,MAAM/f,EAAWu0B,IACxCp4B,KAAK6D,WAAWjD,KAAK,CACnBuf,OAAQhY,WAAWiwB,GACnBlU,MAAOA,EAAMsQ,QACbtY,QAASgI,EAAM6J,aAGnB,OAAO/tB,MAQTq4B,SAAU,SAASC,GACjB,IAAIr2B,EAAS,CACXY,KAAM7C,KAAK6C,KACX4S,OAAQzV,KAAKyV,OACb5R,WAAY7D,KAAK6D,WACjBm0B,QAASh4B,KAAKg4B,QACdC,QAASj4B,KAAKi4B,QACdC,kBAAmBl4B,KAAKk4B,kBAAoBl4B,KAAKk4B,kBAAkB9f,SAAWpY,KAAKk4B,mBAIrF,OAFA/5B,OAAOiC,KAAK+K,uBAAuBnL,KAAMiC,EAAQq2B,GAE1Cr2B,GASTs2B,MAAO,SAASt2B,GACd,IACIu2B,EAAQC,EADRhjB,EAAS+B,EAAMxX,KAAKyV,QAAQ,GACF5R,EAAa2T,EAAMxX,KAAK6D,YAAY,GAC9D60B,EAAYjjB,EAAO0d,GAAK1d,EAAO2d,GAMnC,GAJAvvB,EAAW80B,KAAK,SAAS7wB,EAAG8F,GAC1B,OAAO9F,EAAEqY,OAASvS,EAAEuS,UAGhBle,EAAO22B,OAA+B,eAAtB32B,EAAO22B,MAAM/1B,KACjC,IAAK,IAAInC,KAAQ+U,EACF,OAAT/U,GAA0B,OAATA,EACnB+U,EAAO/U,IAASV,KAAKg4B,QAAU/1B,EAAOqF,MAAQ,EAE9B,OAAT5G,GAA0B,OAATA,IACxB+U,EAAO/U,IAASV,KAAKi4B,QAAUh2B,EAAO2F,OAAS,GAmCrD,GA9BA6wB,EAAmB,aAAez4B,KAAKuf,GACxB,mCACXvf,KAAKk4B,oBACPO,GAAoB,8BAAgCz4B,KAAKk4B,kBAAkBnnB,KAAK,KAAO,OAEvE,WAAd/Q,KAAK6C,KACP21B,EAAS,CACP,mBACAC,EACA,QAAShjB,EAAOjB,GAChB,SAAUiB,EAAOhB,GACjB,SAAUgB,EAAO9J,GACjB,SAAU8J,EAAO7J,GACjB,QAGmB,WAAd5L,KAAK6C,OAEZ21B,EAAS,CACP,mBACAC,EACA,QAASC,EAAYjjB,EAAOjB,GAAKiB,EAAO9J,GACxC,SAAU+sB,EAAYjjB,EAAOhB,GAAKgB,EAAO7J,GACzC,QAAS8sB,EAAYjjB,EAAO0d,GAAK1d,EAAO2d,GACxC,SAAUsF,EAAYjjB,EAAO9J,GAAK8J,EAAOjB,GACzC,SAAUkkB,EAAYjjB,EAAO7J,GAAK6J,EAAOhB,GACzC,SAIc,WAAdzU,KAAK6C,KAAmB,CAC1B,GAAI61B,EAAW,EAEb70B,EAAaA,EAAWuU,UACbygB,UACX,IAAK,IAAI33B,EAAI,EAAGA,EAAI2C,EAAWpD,OAAQS,IACrC2C,EAAW3C,GAAGif,OAAS,EAAItc,EAAW3C,GAAGif,OAG7C,IAAI2Y,EAAY/zB,KAAKS,IAAIiQ,EAAO0d,GAAI1d,EAAO2d,IAC3C,GAAgB,EAAZ0F,EAEF,CAAA,IACIC,EAAkBD,EADN/zB,KAAKU,IAAIgQ,EAAO0d,GAAI1d,EAAO2d,IAE3C,IAASlyB,EAAI,EAAGA,EAAI2C,EAAWpD,OAAQS,IACrC2C,EAAW3C,GAAGif,QAAU4Y,GAAmB,EAAIl1B,EAAW3C,GAAGif,SAKnE,IAASjf,EAAI,EAAGA,EAAI2C,EAAWpD,OAAQS,IAAK,CAC1C,IAAI83B,EAAYn1B,EAAW3C,GAC3Bs3B,EAAO53B,KACL,SACE,WAAgC,IAAnBo4B,EAAU7Y,OAAgB,IACvC,uBAAwB6Y,EAAU9U,MACX,OAAtB8U,EAAU9c,QAAmB,kBAAoB8c,EAAU9c,QAAU,IACxE,SAMJ,OAFAsc,EAAO53B,KAAoB,WAAdZ,KAAK6C,KAAoB,sBAAwB,uBAEvD21B,EAAOznB,KAAK,KAUrBkoB,OAAQ,SAASvtB,EAAKzJ,GACpB,IAAIi3B,EAAUx4B,EAAM+U,EAAStX,OAAOiC,KAAK6B,OAAOuV,MAAMxX,KAAKyV,QAE3D,GAAKzV,KAAK6C,KAAV,CAIA,GAAIZ,EAAO22B,OAA+B,eAAtB32B,EAAO22B,MAAM/1B,KAC/B,IAAKnC,KAAQ+U,EACE,OAAT/U,GAA0B,OAATA,EACnB+U,EAAO/U,KAAUV,KAAKg4B,QAAU/1B,EAAOqF,MAAQ,EAE/B,OAAT5G,GAA0B,OAATA,IACxB+U,EAAO/U,KAAUV,KAAKi4B,QAAUh2B,EAAO2F,OAAS,GAKpC,WAAd5H,KAAK6C,KACPq2B,EAAWxtB,EAAIytB,qBACb1jB,EAAOjB,GAAIiB,EAAOhB,GAAIgB,EAAO9J,GAAI8J,EAAO7J,IAErB,WAAd5L,KAAK6C,OACZq2B,EAAWxtB,EAAI0tB,qBACb3jB,EAAOjB,GAAIiB,EAAOhB,GAAIgB,EAAO0d,GAAI1d,EAAO9J,GAAI8J,EAAO7J,GAAI6J,EAAO2d,KAGlE,IAAK,IAAIlyB,EAAI,EAAGC,EAAMnB,KAAK6D,WAAWpD,OAAQS,EAAIC,EAAKD,IAAK,CAC1D,IAAIgjB,EAAQlkB,KAAK6D,WAAW3C,GAAGgjB,MAC3BhI,EAAUlc,KAAK6D,WAAW3C,GAAGgb,QAC7BiE,EAASngB,KAAK6D,WAAW3C,GAAGif,YAET,IAAZjE,IACTgI,EAAQ,IAAI/lB,OAAOylB,MAAMM,GAAO4J,SAAS5R,GAAS8R,UAEpDkL,EAASf,aAAahY,EAAQ+D,GAGhC,OAAOgV,MAIX/6B,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO2F,SAAU,CAazCksB,YAAa,SAAStS,EAAI2b,GAmCxB,IACIx2B,EAIA4S,EAAQqiB,EA3SSpa,EATAA,EA+SjB4b,EAAe5b,EAAGsB,qBAAqB,QAEvC0Y,EAAgBha,EAAGoL,aAAa,kBAAoB,oBACpDoP,EAAoBxa,EAAGoL,aAAa,qBACpCjlB,EAAa,GAUJ,YANXhB,EADkB,mBAAhB6a,EAAGwK,UAAiD,mBAAhBxK,EAAGwK,SAClC,SAGA,UAIPzS,EA7TG,CACLjB,IAFqBkJ,EA8TMA,GA5TpBoL,aAAa,OAAS,EAC7BrU,GAAIiJ,EAAGoL,aAAa,OAAS,EAC7Bnd,GAAI+R,EAAGoL,aAAa,OAAS,OAC7Bld,GAAI8R,EAAGoL,aAAa,OAAS,GA2TX,WAATjmB,IACP4S,EAvTG,CACLjB,IAFqBkJ,EAwTMA,GAtTpBoL,aAAa,OAASpL,EAAGoL,aAAa,OAAS,MACtDrU,GAAIiJ,EAAGoL,aAAa,OAASpL,EAAGoL,aAAa,OAAS,MACtDqK,GAAI,EACJxnB,GAAI+R,EAAGoL,aAAa,OAAS,MAC7Bld,GAAI8R,EAAGoL,aAAa,OAAS,MAC7BsK,GAAI1V,EAAGoL,aAAa,MAAQ,QAoT5B,IAAK,IAAI5nB,EAAIo4B,EAAa74B,OAAQS,KAChC2C,EAAWjD,KAAK02B,EAAagC,EAAap4B,KAG5C42B,EAAgBL,EAA6B4B,EAAU5jB,EAAQiiB,GAE/D,IAAIwB,EAAW,IAAI/6B,OAAO2F,SAAS,CACjCjB,KAAMA,EACN4S,OAAQA,EACR5R,WAAYA,EACZm0B,SAAUqB,EAAS3xB,KACnBuwB,SAAUoB,EAAS1xB,MAMrB,OAHIuwB,GAAuC,KAAlBJ,KACvBoB,EAAShB,kBAAoB/5B,OAAOkrB,yBAAyB6O,GAAqB,IAAMJ,IAEnFoB,GAWTK,UAAW,SAAS/0B,EAAKxD,GAGvB,OAFAA,IAAYA,EAAU,IACtBy2B,EAA6BjzB,EAAKxD,EAAQyU,OAAQ,kBAC3C,IAAItX,OAAO2F,SAAS9C,MAvZjC,GA2cA,WAEE,aAEA,IAAIgH,EAAU7J,OAAOiC,KAAK4H,QAW1B7J,OAAO8F,QAAU9F,OAAOiC,KAAK+Y,YAAmD,CAO9EqgB,OAAQ,SAORxB,QAAS,EAOTC,QAAS,EAQT7e,WAAY,SAASpY,EAAS2B,GAK5B,GAJA3B,IAAYA,EAAU,IAEtBhB,KAAKuf,GAAKphB,OAAOmN,OAAOwgB,QACxB9rB,KAAKy5B,WAAWz4B,IACXA,EAAQgD,QAAWhD,EAAQgD,QAAoC,iBAAnBhD,EAAQgD,OACvDrB,GAAYA,EAAS3C,WAIvB,QAA2D,IAAhD7B,OAAOiC,KAAKiE,gBAAgBrD,EAAQgD,QAC7ChE,KAAKgE,OAAS,IAAIM,SAASnG,OAAOiC,KAAKiE,gBAAgBrD,EAAQgD,SAC/DrB,GAAYA,EAAS3C,UAElB,CAEH,IAAImY,EAAQnY,KACZA,KAAKgE,OAAS7F,OAAOiC,KAAKsJ,cAC1BvL,OAAOiC,KAAKkJ,UAAUtI,EAAQgD,OAAQ,SAASyF,GAC7C0O,EAAMnU,OAASyF,EACf9G,GAAYA,EAASwV,OAU3BkgB,SAAU,SAASC,GACjB,IACIt0B,EAAQ/B,EADRy3B,EAAsBv7B,OAAOmN,OAAOouB,oBAyBxC,MArB2B,mBAAhB15B,KAAKgE,OACdA,EAASiL,OAAOjP,KAAKgE,QAGa,iBAApBhE,KAAKgE,OAAO8F,IAC1B9F,EAAShE,KAAKgE,OAAO8F,IAGS,iBAAhB9J,KAAKgE,QAAuBhE,KAAKgE,OAAO21B,YACtD31B,EAAShE,KAAKgE,OAAO21B,aAGvB13B,EAAS,CACPY,KAAM,UACNmB,OAAQA,EACRw1B,OAAQx5B,KAAKw5B,OACbxB,QAAShwB,EAAQhI,KAAKg4B,QAAS0B,GAC/BzB,QAASjwB,EAAQhI,KAAKi4B,QAASyB,IAEjCv7B,OAAOiC,KAAK+K,uBAAuBnL,KAAMiC,EAAQq2B,GAE1Cr2B,GASTs2B,MAAO,SAASt2B,GACd,IAAI23B,EAAuC,mBAAhB55B,KAAKgE,OAAwBhE,KAAKgE,SAAWhE,KAAKgE,OACzE61B,EAAeD,EAActyB,MAAQrF,EAAOqF,MAC5CwyB,EAAgBF,EAAchyB,OAAS3F,EAAO2F,OAC9CmyB,EAAiB/5B,KAAKg4B,QAAU/1B,EAAOqF,MACvC0yB,EAAiBh6B,KAAKi4B,QAAUh2B,EAAO2F,OACvCqyB,EAAgB,GAcpB,MAboB,aAAhBj6B,KAAKw5B,QAAyC,cAAhBx5B,KAAKw5B,SACrCM,EAAgB,GAEE,aAAhB95B,KAAKw5B,QAAyC,cAAhBx5B,KAAKw5B,SACrCK,EAAe,GAEbD,EAAc9vB,IAChBmwB,EAAgBL,EAAc9vB,IAEvB8vB,EAAcD,YACrBM,EAAgBL,EAAcD,aAGzB,sBAAwB35B,KAAKuf,GACtB,QAAUwa,EACV,QAAUC,EACV,YAAcH,EACd,aAAeC,EAAgB,iCAEhBF,EAActyB,MAC3B,aAAesyB,EAAchyB,OAC7B,iBAAmBqyB,EAC1B,4BAKXR,WAAY,SAASz4B,GACnB,IAAK,IAAIN,KAAQM,EACfhB,KAAKU,GAAQM,EAAQN,IASzBu4B,OAAQ,SAASvtB,GACf,IAAI1H,EAAgC,mBAAhBhE,KAAKgE,OAAwBhE,KAAKgE,SAAWhE,KAAKgE,OAGtE,IAAKA,EACH,MAAO,GAIT,QAA0B,IAAfA,EAAO8F,IAAqB,CACrC,IAAK9F,EAAOk2B,SACV,MAAO,GAET,GAA4B,IAAxBl2B,EAAOm2B,cAA+C,IAAzBn2B,EAAOo2B,cACtC,MAAO,GAGX,OAAO1uB,EAAI2uB,cAAcr2B,EAAQhE,KAAKw5B,WA3K5C,GAiLA,SAAU30B,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3C6J,EAAU7J,EAAOiC,KAAK4H,QAEtB7J,EAAOm8B,OACTn8B,EAAOujB,KAAK,sCAUdvjB,EAAOm8B,OAASn8B,EAAOiC,KAAK+Y,YAAkD,CAO5E+K,MAAO,aAMPqW,KAAM,EAONvC,QAAS,EAOTC,QAAS,EAOTuC,cAAc,EAOdC,sBAAsB,EAOtBrhB,WAAY,SAASpY,GAMnB,IAAK,IAAIN,IAJc,iBAAZM,IACTA,EAAUhB,KAAK06B,aAAa15B,IAGbA,EACfhB,KAAKU,GAAQM,EAAQN,GAGvBV,KAAKuf,GAAKphB,EAAOmN,OAAOwgB,SAQ1B4O,aAAc,SAASC,GACrB,IAAIC,EAAYD,EAAOljB,OACnBojB,EAAiB18B,EAAOm8B,OAAOQ,iBAAiBtyB,KAAKoyB,IAAc,GAGvE,MAAO,CACL1W,OAHU0W,EAAUljB,QAAQvZ,EAAOm8B,OAAOQ,iBAAkB,KAAO,cAGtDrjB,OACbugB,QAASvX,SAASoa,EAAe,GAAI,KAAO,EAC5C5C,QAASxX,SAASoa,EAAe,GAAI,KAAO,EAC5CN,KAAM9Z,SAASoa,EAAe,GAAI,KAAO,IAS7CrvB,SAAU,WACR,MAAO,CAACxL,KAAKg4B,QAASh4B,KAAKi4B,QAASj4B,KAAKu6B,KAAMv6B,KAAKkkB,OAAOnT,KAAK,QASlEwnB,MAAO,SAASt2B,GACd,IAAI84B,EAAQ,GAAIC,EAAQ,GAAItB,EAAsBv7B,EAAOmN,OAAOouB,oBAC5DvZ,EAAShiB,EAAOiC,KAAKiG,aACnB,CAAEE,EAAGvG,KAAKg4B,QAASxxB,EAAGxG,KAAKi4B,SAC3B95B,EAAOiC,KAAKwF,kBAAkB3D,EAAO8L,QAe3C,OAZI9L,EAAOqF,OAASrF,EAAO2F,SAGzBmzB,EAAwF,IAAhF/yB,GAASjD,KAAKG,IAAIib,EAAO5Z,GAAKvG,KAAKu6B,MAAQt4B,EAAOqF,MAAOoyB,GALpD,GAMbsB,EAAyF,IAAjFhzB,GAASjD,KAAKG,IAAIib,EAAO3Z,GAAKxG,KAAKu6B,MAAQt4B,EAAO2F,OAAQ8xB,GANrD,IAQXz3B,EAAO4M,QACTsR,EAAO5Z,IAAM,GAEXtE,EAAO6M,QACTqR,EAAO3Z,IAAM,GAGb,qBAAuBxG,KAAKuf,GAAK,SAAWyb,EAAQ,eAAiB,IAAM,EAAIA,GAAS,UAC7ED,EAAQ,cAAgB,IAAM,EAAIA,GAAS,0DAElD/yB,EAAQhI,KAAKu6B,KAAOv6B,KAAKu6B,KAAO,EAAI,EAAGb,GAAuB,wCAC3C1xB,EAAQmY,EAAO5Z,EAAGmzB,GACvC,SAAW1xB,EAAQmY,EAAO3Z,EAAGkzB,GAAuB,0DACvB15B,KAAKkkB,MAAQ,iLAchDmU,SAAU,WACR,GAAIr4B,KAAKy6B,qBACP,MAAO,CACLvW,MAAOlkB,KAAKkkB,MACZqW,KAAMv6B,KAAKu6B,KACXvC,QAASh4B,KAAKg4B,QACdC,QAASj4B,KAAKi4B,QACduC,aAAcx6B,KAAKw6B,cAGvB,IAAIh2B,EAAM,GAAK6I,EAAQlP,EAAOm8B,OAAO/uB,UAQrC,MANA,CAAC,QAAS,OAAQ,UAAW,UAAW,gBAAgBlB,QAAQ,SAAS3J,GACnEV,KAAKU,KAAU2M,EAAM3M,KACvB8D,EAAI9D,GAAQV,KAAKU,KAElBV,MAEIwE,KAWXrG,EAAOm8B,OAAOQ,iBAAmB,0FArLnC,CAuLsB,oBAAZz8B,QAA0BA,QAAU2B,MAG9C,WAEE,aAEA,GAAI7B,OAAO88B,aACT98B,OAAOujB,KAAK,+CADd,CAMA,IAAItK,EAASjZ,OAAOiC,KAAK6B,OAAOmV,OAC5ByI,EAAmB1hB,OAAOiC,KAAKyf,iBAC/Bxa,EAAkBlH,OAAOiC,KAAKiF,gBAC9B2C,EAAU7J,OAAOiC,KAAK4H,QACtBnB,EAAiB1I,OAAOiC,KAAKyG,eAC7BgB,EAAkB1J,OAAOiC,KAAKyH,gBAE9BqzB,EAAoB,IAAIC,MAAM,yCAelCh9B,OAAO88B,aAAe98B,OAAOiC,KAAK+Y,YAAYhb,OAAOoF,cAA2D,CAQ9G6V,WAAY,SAASsE,EAAI1c,GACvBA,IAAYA,EAAU,IAEtBhB,KAAKo7B,YAAY1d,EAAI1c,IASvBq6B,gBAAiB,GAWjBC,gBAAiB,KASjBC,aAAc,GAWdC,aAAc,KAOdf,sBAAsB,EAOtBgB,UAAU,EASV35B,mBAAmB,EAQnBqC,OAAQ,KAORu3B,sBAAsB,EAOtBC,qBAAqB,EAOrBC,uBAAuB,EAOvBC,kBAAmB19B,OAAOiB,QAAQgZ,SAQlC0jB,eAAe,EAQfC,YAAY,EAKZC,oBAAqB,aAOrBC,qBAAqB,EAWrBC,UAAW,GAUXC,eAAe,EAOff,YAAa,SAAS1d,EAAI1c,GACxB,IAAIo7B,EAAKj+B,OAAO88B,aAAa1vB,UAAUxJ,UAAUkW,KAAKjY,MACtDA,KAAK0B,SAAW,GAChB1B,KAAKq8B,mBAAmB3e,GACxB1d,KAAKs8B,aAAat7B,GAClBhB,KAAKu8B,qBAEAv8B,KAAKw8B,aACRx8B,KAAKy8B,qBAGHz7B,EAAQw6B,cACVx7B,KAAK08B,gBAAgB17B,EAAQw6B,aAAcY,GAEzCp7B,EAAQs6B,iBACVt7B,KAAK28B,mBAAmB37B,EAAQs6B,gBAAiBc,GAE/Cp7B,EAAQq6B,iBACVr7B,KAAK48B,mBAAmB57B,EAAQq6B,gBAAiBe,GAE/Cp7B,EAAQu6B,cACVv7B,KAAK68B,gBAAgB77B,EAAQu6B,aAAca,GAE7Cp8B,KAAK88B,cAMPC,iBAAkB,WAChB,OAAoC,IAA5B5+B,OAAOuB,kBAA0BM,KAAKi8B,qBAOhDe,iBAAkB,WAChB,OAAOh9B,KAAK+8B,mBAAqB5+B,OAAOuB,iBAAmB,GAM7D+8B,mBAAoB,WACbz8B,KAAK+8B,qBAGV/8B,KAAKi9B,cAAcpf,aAAa,QAAS7d,KAAKsH,MAAQnJ,OAAOuB,kBAC7DM,KAAKi9B,cAAcpf,aAAa,SAAU7d,KAAK4H,OAASzJ,OAAOuB,kBAE/DM,KAAKk9B,iBAAiBC,MAAMh/B,OAAOuB,iBAAkBvB,OAAOuB,oBAS9Do9B,WAAY,WAEV,OADA98B,KAAKo9B,QAAUvd,EAAiB7f,KAAKi9B,eAC9Bj9B,MAkDT08B,gBAAiB,SAAUW,EAAO16B,EAAU3B,GAC1C,OAAOhB,KAAKs9B,oBAAoB,eAAgBD,EAAO16B,EAAU3B,IAkDnE27B,mBAAoB,SAAUU,EAAO16B,EAAU3B,GAC7C,OAAOhB,KAAKs9B,oBAAoB,kBAAmBD,EAAO16B,EAAU3B,IAwBtE67B,gBAAiB,SAAStB,EAAc54B,GACtC,OAAO3C,KAAKu9B,oBAAoB,eAAgBhC,EAAc54B,IAwBhEi6B,mBAAoB,SAASvB,EAAiB14B,GAC5C,OAAO3C,KAAKu9B,oBAAoB,kBAAmBlC,EAAiB14B,IAOtE45B,mBAAoB,WAClB,IAAI7wB,EAAM1L,KAAK4M,aAEflB,EAAIkwB,sBAAwBlwB,EAAIkwB,uBAAyBlwB,EAAI8xB,6BACxD9xB,EAAI+xB,0BAA4B/xB,EAAIgyB,yBAA2BhyB,EAAIiyB,uBACxEjyB,EAAIkwB,sBAAwB57B,KAAK47B,uBAWnC0B,oBAAqB,SAAS15B,EAAUy5B,EAAO16B,EAAU3B,GAavD,MAZqB,iBAAVq8B,EACTl/B,OAAOiC,KAAKkJ,UAAU+zB,EAAO,SAAS5zB,GACpCA,IAAQzJ,KAAK4D,GAAY,IAAIzF,OAAOy/B,MAAMn0B,EAAKzI,IAC/C2B,GAAYA,EAAS8G,IACpBzJ,KAAMgB,GAAWA,EAAQwI,cAG5BxI,GAAWq8B,EAAM5D,WAAWz4B,GAC5BhB,KAAK4D,GAAYy5B,EACjB16B,GAAYA,EAAS06B,IAGhBr9B,MAUTu9B,oBAAqB,SAAS35B,EAAUsgB,EAAOvhB,GAI7C,OAHA3C,KAAK4D,GAAYsgB,EACjBlkB,KAAK0D,cAAcwgB,EAAOtgB,GAC1B5D,KAAK+D,aAAamgB,EAAOtgB,EAAUjB,GAC5B3C,MAMT69B,qBAAsB,SAASnxB,GAC7B,IAAIqN,EAAU5b,OAAOiC,KAAKqM,oBAAoBC,GAI9C,GAHKqN,EAAQkC,QACXlC,EAAQkC,MAAQ,KAEblC,EACH,MAAMmhB,EAER,QAAkC,IAAvBnhB,EAAQnN,WACjB,MAAMsuB,EAER,OAAOnhB,GAOTuiB,aAAc,SAAUt7B,GACtBhB,KAAKwD,YAAYxC,GAEjBhB,KAAKsH,MAAQtH,KAAKsH,OAASmZ,SAASzgB,KAAKi9B,cAAc31B,MAAO,KAAO,EACrEtH,KAAK4H,OAAS5H,KAAK4H,QAAU6Y,SAASzgB,KAAKi9B,cAAcr1B,OAAQ,KAAO,EAEnE5H,KAAKi9B,cAAchhB,QAIxBjc,KAAKi9B,cAAc31B,MAAQtH,KAAKsH,MAChCtH,KAAKi9B,cAAcr1B,OAAS5H,KAAK4H,OAEjC5H,KAAKi9B,cAAchhB,MAAM3U,MAAQtH,KAAKsH,MAAQ,KAC9CtH,KAAKi9B,cAAchhB,MAAMrU,OAAS5H,KAAK4H,OAAS,KAEhD5H,KAAK67B,kBAAoB77B,KAAK67B,kBAAkB3yB,UAQlDmzB,mBAAoB,SAAU3vB,GAC5B1M,KAAKi9B,cAAgB9+B,OAAOiC,KAAKkf,QAAQ5S,IAAa1M,KAAK69B,qBAAqBnxB,GAEhFvO,OAAOiC,KAAKqf,SAASzf,KAAKi9B,cAAe,gBAErCj9B,KAAKw8B,aACPx8B,KAAK89B,kBAAkB99B,KAAKi9B,eAG9Bj9B,KAAKk9B,iBAAmBl9B,KAAKi9B,cAAcrwB,WAAW,OAOxDmxB,SAAU,WACR,OAAO/9B,KAAKsH,OAOd02B,UAAW,WACT,OAAOh+B,KAAK4H,QAYdq2B,SAAU,SAAU58B,EAAOL,GACzB,OAAOhB,KAAKk+B,cAAc,CAAE52B,MAAOjG,GAASL,IAY9Cm9B,UAAW,SAAU98B,EAAOL,GAC1B,OAAOhB,KAAKk+B,cAAc,CAAEt2B,OAAQvG,GAASL,IAc/Ck9B,cAAe,SAAUE,EAAYp9B,GACnC,IAAIq9B,EAIJ,IAAK,IAAI39B,KAFTM,EAAUA,GAAW,GAEJo9B,EACfC,EAAWD,EAAW19B,GAEjBM,EAAQs9B,UACXt+B,KAAKu+B,uBAAuB79B,EAAM09B,EAAW19B,IAC7C29B,GAAY,MAGTr9B,EAAQw9B,eACXx+B,KAAKy+B,iBAAiB/9B,EAAM29B,GAWhC,OARAr+B,KAAKy8B,qBACLz8B,KAAKu8B,qBACLv8B,KAAK88B,aAEA97B,EAAQs9B,SACXt+B,KAAK+B,YAGA/B,MAWTu+B,uBAAwB,SAAU79B,EAAMW,GAatC,OAZArB,KAAKi9B,cAAcv8B,GAAQW,EAEvBrB,KAAK0+B,gBACP1+B,KAAK0+B,cAAch+B,GAAQW,GAGzBrB,KAAK2+B,gBACP3+B,KAAK2+B,cAAcj+B,GAAQW,GAG7BrB,KAAKU,GAAQW,EAENrB,MAWTy+B,iBAAkB,SAAU/9B,EAAMW,GAWhC,OAVArB,KAAKi9B,cAAchhB,MAAMvb,GAAQW,EAE7BrB,KAAK0+B,gBACP1+B,KAAK0+B,cAAcziB,MAAMvb,GAAQW,GAG/BrB,KAAK4+B,YACP5+B,KAAK4+B,UAAU3iB,MAAMvb,GAAQW,GAGxBrB,MAOT6+B,QAAS,WACP,OAAO7+B,KAAK67B,kBAAkB,IAShCiD,qBAAsB,SAAUC,GAC9B,IAAqC98B,EAAjC+8B,EAAch/B,KAAKi/B,aACvBj/B,KAAK67B,kBAAoBkD,EACzB,IAAK,IAAI79B,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,KACnDe,EAASjC,KAAK0B,SAASR,IAChB03B,OAAS32B,EAAOi9B,WAJgC,GAAsB,GAW/E,OALIF,GACFA,EAAYE,WAP2C,GAAsB,GAS/El/B,KAAKm/B,yBACLn/B,KAAK+B,YACE/B,MAUTo/B,YAAa,SAAUn5B,EAAO5E,GAE5B,IAAIg+B,EAASp5B,EAAO84B,EAAM/+B,KAAK67B,kBAAkB3yB,MAAM,GACvDjD,EAAQY,EAAeZ,EAAO4B,EAAgB7H,KAAK67B,oBACnDkD,EAAI,GAAK19B,EACT09B,EAAI,GAAK19B,EACT,IAAIi+B,EAAQz4B,EAAeZ,EAAO84B,GAGlC,OAFAA,EAAI,IAAMM,EAAO94B,EAAI+4B,EAAM/4B,EAC3Bw4B,EAAI,IAAMM,EAAO74B,EAAI84B,EAAM94B,EACpBxG,KAAK8+B,qBAAqBC,IASnCQ,QAAS,SAAUl+B,GAEjB,OADArB,KAAKo/B,YAAY,IAAIjhC,OAAOmI,MAAM,EAAG,GAAIjF,GAClCrB,MASTw/B,YAAa,SAAUv5B,GACrB,IAAI84B,EAAM/+B,KAAK67B,kBAAkB3yB,MAAM,GAGvC,OAFA61B,EAAI,IAAM94B,EAAMM,EAChBw4B,EAAI,IAAM94B,EAAMO,EACTxG,KAAK8+B,qBAAqBC,IASnCU,YAAa,SAAUx5B,GACrB,OAAOjG,KAAKw/B,YAAY,IAAIrhC,OAAOmI,OAChCL,EAAMM,EAAIvG,KAAK67B,kBAAkB,IACjC51B,EAAMO,EAAIxG,KAAK67B,kBAAkB,MAQtCliB,WAAY,WACV,OAAO3Z,KAAKi9B,eAOdp7B,eAAgB,SAAS2C,GACvBxE,KAAKy7B,UAAYj3B,EAAIk7B,aACrBl7B,EAAIC,KAAK,SAAUzE,MACnBwE,EAAI06B,YACJl/B,KAAKe,KAAK,eAAgB,CAAE6N,OAAQpK,IACpCA,EAAIzD,KAAK,UAOX0B,iBAAkB,SAAS+B,GACzBxE,KAAKe,KAAK,iBAAkB,CAAE6N,OAAQpK,IACtCA,EAAIzD,KAAK,kBACFyD,EAAIm7B,QASbC,aAAc,SAASl0B,GAErB,OADAA,EAAIm0B,UAAU,EAAG,EAAG7/B,KAAKsH,MAAOtH,KAAK4H,QAC9B5H,MAOT4M,WAAY,WACV,OAAO5M,KAAKk9B,kBAQd4C,MAAO,WAcL,OAbA9/B,KAAK0B,SAASjB,OAAS,EACvBT,KAAKs7B,gBAAkB,KACvBt7B,KAAKw7B,aAAe,KACpBx7B,KAAKq7B,gBAAkB,GACvBr7B,KAAKu7B,aAAe,GAChBv7B,KAAK+/B,oBACP//B,KAAKuB,IAAI,WAAYvB,KAAKggC,sBAC1BhgC,KAAKigC,gBAAkB,KACvBjgC,KAAK+/B,mBAAoB,GAE3B//B,KAAK4/B,aAAa5/B,KAAKk9B,kBACvBl9B,KAAKe,KAAK,kBACVf,KAAK+B,YACE/B,MAQT+B,UAAW,WACT,IAAIm+B,EAAiBlgC,KAAKk9B,iBAE1B,OADAl9B,KAAKmgC,aAAaD,EAAgBlgC,KAAK0B,UAChC1B,MAUTm/B,uBAAwB,WACtB,IAAIj4B,EAAS,GAAKI,EAAQtH,KAAK+9B,WAAYn2B,EAAS5H,KAAKg+B,YACrDoC,EAAOv4B,EAAgB7H,KAAK67B,mBAMhC,OALA30B,EAAOm5B,GAAKx5B,EAAe,CAAEN,EAAG,EAAGC,EAAG,GAAK45B,GAC3Cl5B,EAAOo5B,GAAKz5B,EAAe,CAAEN,EAAGe,EAAOd,EAAGoB,GAAUw4B,GACpDl5B,EAAOq5B,GAAK,IAAIpiC,OAAOmI,MAAMY,EAAOo5B,GAAG/5B,EAAGW,EAAOm5B,GAAG75B,GACpDU,EAAOs5B,GAAK,IAAIriC,OAAOmI,MAAMY,EAAOm5B,GAAG95B,EAAGW,EAAOo5B,GAAG95B,GACpDxG,KAAKk8B,UAAYh1B,GAWnBi5B,aAAc,SAASz0B,EAAKtJ,GAC1BpC,KAAKm/B,yBACLn/B,KAAK4/B,aAAal0B,GAClB1L,KAAKe,KAAK,iBACNf,KAAKmE,QACPhG,OAAOiC,KAAKmN,YAAYvN,KAAM0L,GAEhC1L,KAAKygC,kBAAkB/0B,GAEvBA,EAAIU,OAEJV,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK67B,mBAC9B77B,KAAK0gC,eAAeh1B,EAAKtJ,GACzBsJ,EAAIc,WACCxM,KAAK07B,sBAAwB17B,KAAKw8B,aACrCx8B,KAAK2gC,aAAaj1B,GAEhB1L,KAAKmE,QACPuH,EAAIc,UAENxM,KAAK4gC,eAAel1B,GAChB1L,KAAK07B,sBAAwB17B,KAAKw8B,aACpCx8B,KAAK2gC,aAAaj1B,GAEpB1L,KAAKe,KAAK,iBAQZ2/B,eAAgB,SAASh1B,EAAKtJ,GAC5B,IAAK,IAAIlB,EAAI,EAAGT,EAAS2B,EAAQ3B,OAAQS,EAAIT,IAAUS,EACrDkB,EAAQlB,IAAMkB,EAAQlB,GAAG2/B,OAAOn1B,IASpCo1B,2BAA4B,SAASp1B,EAAK9H,GACxC,IAAI3B,EAASjC,KAAK4D,EAAW,SACzB3B,IACFyJ,EAAIq1B,UAAY9+B,EAAOg3B,OACnBh3B,EAAOg3B,OAAOvtB,EAAK1L,MACnBiC,EAEJyJ,EAAIs1B,SACF/+B,EAAO+1B,SAAW,EAClB/1B,EAAOg2B,SAAW,EAClBj4B,KAAKsH,MACLtH,KAAK4H,UAET3F,EAASjC,KAAK4D,EAAW,YAEnB5D,KAAK4D,EAAW,SAClB8H,EAAIU,OACJV,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK67B,oBAEhC55B,EAAO4+B,OAAOn1B,GACd1L,KAAK4D,EAAW,QAAU8H,EAAIc,YAQlCi0B,kBAAmB,SAAS/0B,GAC1B1L,KAAK8gC,2BAA2Bp1B,EAAK,eAOvCk1B,eAAgB,SAASl1B,GACvB1L,KAAK8gC,2BAA2Bp1B,EAAK,YAQvCu1B,UAAW,WACT,MAAO,CACLt5B,IAAK3H,KAAKg+B,YAAc,EACxBt2B,KAAM1H,KAAK+9B,WAAa,IAU5BmD,cAAe,SAAUj/B,GACvB,OAAOjC,KAAKmhC,cAAcl/B,EAAQ,IAAI9D,OAAOmI,MAAMtG,KAAKihC,YAAYv5B,KAAMzF,EAAOm/B,iBAAiB56B,KAUpG66B,cAAe,SAAUp/B,GACvB,OAAOjC,KAAKmhC,cAAcl/B,EAAQ,IAAI9D,OAAOmI,MAAMrE,EAAOm/B,iBAAiB76B,EAAGvG,KAAKihC,YAAYt5B,OAUjG25B,aAAc,SAASr/B,GACrB,IAAIs/B,EAASvhC,KAAKihC,YAElB,OAAOjhC,KAAKmhC,cAAcl/B,EAAQ,IAAI9D,OAAOmI,MAAMi7B,EAAO75B,KAAM65B,EAAO55B,OAUzE65B,qBAAsB,SAASv/B,GAC7B,IAAIw/B,EAAWzhC,KAAK0hC,cAEpB,OAAO1hC,KAAKmhC,cAAcl/B,EAAQw/B,IAUpCE,sBAAuB,SAAS1/B,GAC9B,IAAIw/B,EAAWzhC,KAAK0hC,cAEpB,OADA1hC,KAAKmhC,cAAcl/B,EAAQ,IAAI9D,OAAOmI,MAAMm7B,EAASl7B,EAAGtE,EAAOm/B,iBAAiB56B,IACzExG,MAUT4hC,sBAAuB,SAAS3/B,GAC9B,IAAIw/B,EAAWzhC,KAAK0hC,cAEpB,OAAO1hC,KAAKmhC,cAAcl/B,EAAQ,IAAI9D,OAAOmI,MAAMrE,EAAOm/B,iBAAiB76B,EAAGk7B,EAASj7B,KAQzFk7B,YAAa,WACX,IAAIH,EAASvhC,KAAKihC,YACdb,EAAOv4B,EAAgB7H,KAAK67B,mBAChC,OAAOh1B,EAAe,CAAEN,EAAGg7B,EAAO75B,KAAMlB,EAAG+6B,EAAO55B,KAAOy4B,IAU3De,cAAe,SAASl/B,EAAQs/B,GAG9B,OAFAt/B,EAAO4/B,oBAAoBN,EAAQ,SAAU,UAC7CvhC,KAAK+B,YACE/B,MAQT8hC,eAAgB,SAAUxJ,GACxB,OAAOt4B,KAAK+hC,iBAAiBzJ,IAQ/BD,SAAU,SAAUC,GAClB,OAAOt4B,KAAKgiC,gBAAgB,WAAY1J,IAQ1CyJ,iBAAkB,SAAUzJ,GAC1B,OAAOt4B,KAAKgiC,gBAAgB,mBAAoB1J,IAMlD0J,gBAAiB,SAAUjpB,EAAYuf,GAErC,IAAI7oB,EAAO,CACTrN,QAASpC,KAAKiiC,WAAWlpB,EAAYuf,IAOvC,OAJAlhB,EAAO3H,EAAMzP,KAAKkiC,qBAAqBnpB,EAAYuf,IAEnDn6B,OAAOiC,KAAK+K,uBAAuBnL,KAAMyP,EAAM6oB,GAExC7oB,GAMTwyB,WAAY,SAASlpB,EAAYuf,GAC/B,OAAOt4B,KAAKqC,aAAajB,OAAO,SAASa,GACvC,OAAQA,EAAOkgC,oBACdzrB,IAAI,SAAS2iB,GACd,OAAOr5B,KAAKoiC,UAAU/I,EAAUtgB,EAAYuf,IAC3Ct4B,OAMLoiC,UAAW,SAAS/I,EAAUtgB,EAAYuf,GACxC,IAAI+J,EAECriC,KAAKy6B,uBACR4H,EAAgBhJ,EAASoB,qBACzBpB,EAASoB,sBAAuB,GAGlC,IAAIx4B,EAASo3B,EAAStgB,GAAYuf,GAIlC,OAHKt4B,KAAKy6B,uBACRpB,EAASoB,qBAAuB4H,GAE3BpgC,GAMTigC,qBAAsB,SAASnpB,EAAYuf,GACzC,IAAI7oB,EAAO,GAAK6yB,EAAUtiC,KAAKs7B,gBAAiBiH,EAAUviC,KAAKw7B,aAoB/D,OAlBIx7B,KAAKq7B,kBACP5rB,EAAK+yB,WAAaxiC,KAAKq7B,gBAAgBhD,SACnCr4B,KAAKq7B,gBAAgBhD,SAASC,GAC9Bt4B,KAAKq7B,iBAGPr7B,KAAKu7B,eACP9rB,EAAK8yB,QAAUviC,KAAKu7B,aAAalD,SAC7Br4B,KAAKu7B,aAAalD,SAASC,GAC3Bt4B,KAAKu7B,cAEP+G,IAAYA,EAAQH,oBACtB1yB,EAAK6rB,gBAAkBt7B,KAAKoiC,UAAUE,EAASvpB,EAAYuf,IAEzDiK,IAAYA,EAAQJ,oBACtB1yB,EAAK+rB,aAAex7B,KAAKoiC,UAAUG,EAASxpB,EAAYuf,IAGnD7oB,GAUTgzB,2BAA2B,EAuC3BlK,MAAO,SAASv3B,EAASgJ,GACvBhJ,IAAYA,EAAU,IAEtB,IAAIw3B,EAAS,GAeb,OAbAx4B,KAAK0iC,gBAAgBlK,EAAQx3B,GAC7BhB,KAAK2iC,cAAcnK,EAAQx3B,GAE3BhB,KAAK4iC,sBAAsBpK,EAAQ,mBACnCx4B,KAAK6iC,sBAAsBrK,EAAQ,kBAAmBxuB,GAEtDhK,KAAK8iC,eAAetK,EAAQxuB,GAE5BhK,KAAK4iC,sBAAsBpK,EAAQ,gBACnCx4B,KAAK6iC,sBAAsBrK,EAAQ,eAAgBxuB,GAEnDwuB,EAAO53B,KAAK,UAEL43B,EAAOznB,KAAK,KAMrB2xB,gBAAiB,SAASlK,EAAQx3B,GAC5BA,EAAQ+hC,kBAGZvK,EAAO53B,KACL,iCAAmCI,EAAQgiC,UAAY,QAAU,yBAC/D,kDACE,0DAORL,cAAe,SAASnK,EAAQx3B,GAC9B,IAEI+9B,EAFAz3B,EAAQtG,EAAQsG,OAAStH,KAAKsH,MAC9BM,EAAS5G,EAAQ4G,QAAU5H,KAAK4H,OAC3Bq7B,EAAU,gBAAkBjjC,KAAKsH,MAAQ,IAAMtH,KAAK4H,OAAS,KAClE8xB,EAAsBv7B,OAAOmN,OAAOouB,oBAEpC14B,EAAQiiC,QACVA,EAAU,YACFjiC,EAAQiiC,QAAQ18B,EAAI,IACpBvF,EAAQiiC,QAAQz8B,EAAI,IACpBxF,EAAQiiC,QAAQ37B,MAAQ,IACxBtG,EAAQiiC,QAAQr7B,OAAS,KAG7B5H,KAAKyiC,4BACP1D,EAAM/+B,KAAK67B,kBACXoH,EAAU,YACFj7B,GAAS+2B,EAAI,GAAKA,EAAI,GAAIrF,GAAuB,IACjD1xB,GAAS+2B,EAAI,GAAKA,EAAI,GAAIrF,GAAuB,IACjD1xB,EAAQhI,KAAKsH,MAAQy3B,EAAI,GAAIrF,GAAuB,IACpD1xB,EAAQhI,KAAK4H,OAASm3B,EAAI,GAAIrF,GAAuB,MAIjElB,EAAO53B,KACL,QACE,sCACA,8CACA,iBACA,UAAW0G,EAAO,KAClB,WAAYM,EAAQ,KACpBq7B,EACA,0BACF,gCAAiC9kC,OAAOC,QAAS,YACjD,WACE4B,KAAKkjC,2BACLljC,KAAKmjC,6BACP,cAQJA,2BAA4B,WAC1B,IAAIhrB,EAAQnY,KAOZ,MANa,CAAC,kBAAmB,gBAAgB0W,IAAI,SAAShW,GACxD,IAAIJ,EAAO6X,EAAMzX,GACjB,GAAIJ,GAAQA,EAAK24B,OACf,OAAO34B,EAAKi4B,MAAMpgB,GAAO,KAGnBpH,KAAK,KAUrBmyB,yBAA0B,WAKxB,IAJA,IAAiC1+B,EAAK2L,EAClC8L,EAAOmnB,EAAKC,EAAiBC,EAD7B9K,EAAS,GAAI+K,EAAW,GAExBpkC,EAAYhB,OAAOgB,UAAWiD,EAAUpC,KAAKqC,aAExCnB,EAAI,EAAGC,EAAMiB,EAAQ3B,OAAQS,EAAIC,EAAKD,IAG7C,GADAiP,GADA3L,EAAMpC,EAAQlB,IACGiP,YACiB,IAA9B3L,EAAI3B,KAAK1C,QAAQ,UAAkBojC,EAASpzB,IAAgBhR,EAAUgR,KAG1EozB,EAASpzB,IAAc,EAClB3L,EAAImY,QAIT,IAAK0mB,KADLpnB,EAAQzX,EAAImY,OAGV,IAAK2mB,KADLF,EAAMnnB,EAAMonB,IAILE,EADLpzB,EADQizB,EAAIE,GACOnzB,aACUhR,EAAUgR,KACrCozB,EAASpzB,IAAc,GAM/B,IAAK,IAAIiF,KAAKmuB,EACZ/K,GAAU,CACR,qBACA,uBAAyBpjB,EAAG,OAC5B,mBAAqBjW,EAAUiW,GAAI,QACnC,WACArE,KAAK,IAaT,OAVIynB,IACFA,EAAS,CACP,4BACA,cACAA,EACA,MACA,cACAznB,KAAK,KAGFynB,GAMTsK,eAAgB,SAAStK,EAAQxuB,GAE/B,IADA,IAAIqvB,EACKn4B,EAAI,EAAGkB,EAAUpC,KAAKqC,aAAclB,EAAMiB,EAAQ3B,OAAQS,EAAIC,EAAKD,KAC1Em4B,EAAWj3B,EAAQlB,IACNihC,mBAGbniC,KAAKwjC,cAAchL,EAAQa,EAAUrvB,IAQzCw5B,cAAe,SAAShL,EAAQa,EAAUrvB,GACxCwuB,EAAO53B,KAAKy4B,EAASd,MAAMvuB,KAM7B64B,sBAAuB,SAASrK,EAAQ50B,EAAUoG,GAC5ChK,KAAK4D,IAAa5D,KAAK4D,GAAU20B,OACnCC,EAAO53B,KAAKZ,KAAK4D,GAAU20B,MAAMvuB,KAOrC44B,sBAAuB,SAASpK,EAAQ50B,GACtC,IAAID,EAAS3D,KAAK4D,GAClB,GAAKD,EAGL,GAAIA,EAAOs1B,OAAQ,CACjB,IAAIO,EAAS71B,EAAO61B,OACpBhB,EAAO53B,KACL,8BAA+BZ,KAAKsH,MAAQ,EAAG,IAAKtH,KAAK4H,OAAS,EAAG,KACnE,OAAQjE,EAAOq0B,QAAUh4B,KAAKsH,MAAQ,EAAG,QAAS3D,EAAOs0B,QAAUj4B,KAAK4H,OAAS,EAAG,KACpF,UACc,aAAX4xB,GAAoC,cAAXA,EACtB71B,EAAOK,OAAOsD,MACdtH,KAAKsH,MACX,aACc,aAAXkyB,GAAoC,cAAXA,EACtB71B,EAAOK,OAAO4D,OACd5H,KAAK4H,OACX,sBAAwBjE,EAAO4b,GAAK,KACtC,mBAIFiZ,EAAO53B,KACL,qBACE,UAAWZ,KAAKsH,MAChB,aAActH,KAAK4H,OACnB,WAAY5H,KAAK4D,GAAW,IAC9B,eAaN6/B,WAAY,SAAUxhC,GACpB,IAAKA,EACH,OAAOjC,KAET,IACIkB,EAAGsD,EAAKk/B,EADR1E,EAAch/B,KAAKi/B,aAEvB,GAAIh9B,IAAW+8B,EAEb,IAAK99B,GADLwiC,EAAO1E,EAAYt9B,UACLjB,OAAQS,KACpBsD,EAAMk/B,EAAKxiC,GACXmE,EAAgBrF,KAAK0B,SAAU8C,GAC/BxE,KAAK0B,SAASiiC,QAAQn/B,QAIxBa,EAAgBrF,KAAK0B,SAAUO,GAC/BjC,KAAK0B,SAASiiC,QAAQ1hC,GAExB,OAAOjC,KAAK+B,WAAa/B,KAAK+B,aAUhC6hC,aAAc,SAAU3hC,GACtB,IAAKA,EACH,OAAOjC,KAET,IACIkB,EAAGsD,EAAKk/B,EADR1E,EAAch/B,KAAKi/B,aAEvB,GAAIh9B,IAAW+8B,EAEb,IADA0E,EAAO1E,EAAYt9B,SACdR,EAAI,EAAGA,EAAIwiC,EAAKjjC,OAAQS,IAC3BsD,EAAMk/B,EAAKxiC,GACXmE,EAAgBrF,KAAK0B,SAAU8C,GAC/BxE,KAAK0B,SAASd,KAAK4D,QAIrBa,EAAgBrF,KAAK0B,SAAUO,GAC/BjC,KAAK0B,SAASd,KAAKqB,GAErB,OAAOjC,KAAK+B,WAAa/B,KAAK+B,aAUhC8hC,cAAe,SAAU5hC,EAAQ6hC,GAC/B,IAAK7hC,EACH,OAAOjC,KAGT,IACIkB,EAAGsD,EAAKc,EAAKy+B,EAAQL,EADrB1E,EAAch/B,KAAKi/B,aACQ+E,EAAY,EAE3C,GAAI/hC,IAAW+8B,EAEb,IADA0E,EAAO1E,EAAYt9B,SACdR,EAAI,EAAGA,EAAIwiC,EAAKjjC,OAAQS,IAC3BsD,EAAMk/B,EAAKxiC,GAED,EAAI8iC,GADd1+B,EAAMtF,KAAK0B,SAASvB,QAAQqE,MAE1Bu/B,EAASz+B,EAAM,EACfD,EAAgBrF,KAAK0B,SAAU8C,GAC/BxE,KAAK0B,SAASY,OAAOyhC,EAAQ,EAAGv/B,IAElCw/B,SAKU,KADZ1+B,EAAMtF,KAAK0B,SAASvB,QAAQ8B,MAG1B8hC,EAAS/jC,KAAKikC,mBAAmBhiC,EAAQqD,EAAKw+B,GAC9Cz+B,EAAgBrF,KAAK0B,SAAUO,GAC/BjC,KAAK0B,SAASY,OAAOyhC,EAAQ,EAAG9hC,IAIpC,OADAjC,KAAK+B,WAAa/B,KAAK+B,YAChB/B,MAMTikC,mBAAoB,SAAShiC,EAAQqD,EAAKw+B,GACxC,IAAIC,EAEJ,GAAID,EAIF,IAAK,IAAI5iC,GAHT6iC,EAASz+B,GAGU,EAAQ,GAALpE,IAAUA,EAAG,CAMjC,GAJqBe,EAAOiiC,qBAAqBlkC,KAAK0B,SAASR,KAC1Ce,EAAOkiC,wBAAwBnkC,KAAK0B,SAASR,KAC7ClB,KAAK0B,SAASR,GAAGijC,wBAAwBliC,GAE1C,CAClB8hC,EAAS7iC,EACT,YAKJ6iC,EAASz+B,EAAM,EAGjB,OAAOy+B,GAUTK,aAAc,SAAUniC,EAAQ6hC,GAC9B,IAAK7hC,EACH,OAAOjC,KAGT,IACIkB,EAAGsD,EAAKc,EAAKy+B,EAAQL,EADrB1E,EAAch/B,KAAKi/B,aACQ+E,EAAY,EAE3C,GAAI/hC,IAAW+8B,EAEb,IAAK99B,GADLwiC,EAAO1E,EAAYt9B,UACLjB,OAAQS,KACpBsD,EAAMk/B,EAAKxiC,IACXoE,EAAMtF,KAAK0B,SAASvB,QAAQqE,IAClBxE,KAAK0B,SAASjB,OAAS,EAAIujC,IACnCD,EAASz+B,EAAM,EACfD,EAAgBrF,KAAK0B,SAAU8C,GAC/BxE,KAAK0B,SAASY,OAAOyhC,EAAQ,EAAGv/B,IAElCw/B,SAIF1+B,EAAMtF,KAAK0B,SAASvB,QAAQ8B,MAChBjC,KAAK0B,SAASjB,OAAS,IAEjCsjC,EAAS/jC,KAAKqkC,mBAAmBpiC,EAAQqD,EAAKw+B,GAC9Cz+B,EAAgBrF,KAAK0B,SAAUO,GAC/BjC,KAAK0B,SAASY,OAAOyhC,EAAQ,EAAG9hC,IAIpC,OADAjC,KAAK+B,WAAa/B,KAAK+B,YAChB/B,MAMTqkC,mBAAoB,SAASpiC,EAAQqD,EAAKw+B,GACxC,IAAIC,EAEJ,GAAID,EAIF,IAAK,IAAI5iC,GAHT6iC,EAASz+B,GAGU,EAAGpE,EAAIlB,KAAK0B,SAASjB,SAAUS,EAAG,CAMnD,GAJqBe,EAAOiiC,qBAAqBlkC,KAAK0B,SAASR,KAC1Ce,EAAOkiC,wBAAwBnkC,KAAK0B,SAASR,KAC7ClB,KAAK0B,SAASR,GAAGijC,wBAAwBliC,GAE1C,CAClB8hC,EAAS7iC,EACT,YAKJ6iC,EAASz+B,EAAM,EAGjB,OAAOy+B,GAUTz3B,OAAQ,SAAUrK,EAAQC,GAGxB,OAFAmD,EAAgBrF,KAAK0B,SAAUO,GAC/BjC,KAAK0B,SAASY,OAAOJ,EAAO,EAAGD,GACxBjC,KAAK+B,WAAa/B,KAAK+B,aAQhCuiC,QAAS,WAEP,OADAtkC,KAAK8/B,QACE9/B,MAOTwL,SAAU,WACR,MAAO,oBAAsBxL,KAAKmD,aAAe,iBACxBnD,KAAKqC,aAAa5B,OAAS,SAIxD2W,EAAOjZ,OAAO88B,aAAa1vB,UAAWpN,OAAOmD,YAC7C8V,EAAOjZ,OAAO88B,aAAa1vB,UAAWpN,OAAOsD,YAC7C2V,EAAOjZ,OAAO88B,aAAa1vB,UAAWpN,OAAOomC,iBAE7CntB,EAAOjZ,OAAO88B,aAAgD,CAO5DuJ,WAAY,yCAWZC,SAAU,SAAU1rB,GAClB,IAAI2E,EAAKvf,OAAOiC,KAAKqM,sBAErB,IAAKiR,IAAOA,EAAG9Q,WACb,OAAO,KAGT,IAAIlB,EAAMgS,EAAG9Q,WAAW,MACxB,IAAKlB,EACH,OAAO,KAGT,OAAQqN,GAEN,IAAK,eACH,YAAmC,IAArBrN,EAAI6D,aAEpB,IAAK,cACH,YAAkC,IAApB7D,EAAIg5B,YAEpB,IAAK,YACH,YAA+B,IAAjBhnB,EAAGic,UAEnB,IAAK,uBACH,IAEE,OADAjc,EAAGic,UAAU,aAAc,IACpB,EAET,MAAOxf,IACP,OAAO,EAET,QACE,OAAO,SAoBfhc,OAAO88B,aAAa1vB,UAAUo5B,OAASxmC,OAAO88B,aAAa1vB,UAAU8sB,UApqDvE,GA8qDAl6B,OAAOymC,UAAYzmC,OAAOiC,KAAK+Y,YAAqD,CAOlF+K,MAAO,eAOP5c,MAAO,EASPqzB,OAAQ,KAORkK,cAAe,QAOfC,eAAgB,QAOhBC,gBAAiB,KAQjBC,UAAW,SAAShkC,GAElB,OADAhB,KAAK26B,OAAS,IAAIx8B,OAAOm8B,OAAOt5B,GACzBhB,MAOTilC,gBAAiB,WACf,IAAIv5B,EAAM1L,KAAK2/B,OAAOuF,WAEtBx5B,EAAIy5B,YAAcnlC,KAAKkkB,MACvBxY,EAAI05B,UAAYplC,KAAKsH,MACrBoE,EAAI25B,QAAUrlC,KAAK6kC,cACnBn5B,EAAI45B,SAAWtlC,KAAK8kC,eAChB9kC,KAAK+kC,iBAAmB5mC,OAAO88B,aAAawJ,SAAS,gBACvD/4B,EAAIg5B,YAAY1kC,KAAK+kC,kBAQzBQ,WAAY,WACV,GAAKvlC,KAAK26B,OAAV,CAIA,IAAIjvB,EAAM1L,KAAK2/B,OAAOuF,WAClBzoB,EAAOzc,KAAK2/B,OAAOd,UAEvBnzB,EAAI85B,YAAcxlC,KAAK26B,OAAOzW,MAC9BxY,EAAI+5B,WAAazlC,KAAK26B,OAAOJ,KAAO9d,EACpC/Q,EAAIg6B,cAAgB1lC,KAAK26B,OAAO3C,QAAUvb,EAC1C/Q,EAAIi6B,cAAgB3lC,KAAK26B,OAAO1C,QAAUxb,IAO5CmpB,aAAc,WACZ,IAAIl6B,EAAM1L,KAAK2/B,OAAOuF,WAEtBx5B,EAAI85B,YAAc,GAClB95B,EAAI+5B,WAAa/5B,EAAIg6B,cAAgBh6B,EAAIi6B,cAAgB,KAY3DxnC,OAAO0nC,YAAc1nC,OAAOiC,KAAK+Y,YAAYhb,OAAOymC,UAAsD,CAOxGxrB,WAAY,SAASumB,GACnB3/B,KAAK2/B,OAASA,EACd3/B,KAAK8lC,QAAU,IAOjBC,YAAa,SAASC,GACpBhmC,KAAKimC,mBAAmBD,GAGxBhmC,KAAKkmC,oBAAoBF,GACzBhmC,KAAKmmC,WAOPC,YAAa,SAASJ,GACpBhmC,KAAKkmC,oBAAoBF,GAGzBhmC,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAKmmC,WAMPE,UAAW,WACTrmC,KAAKsmC,uBAOPL,mBAAoB,SAASD,GAE3B,IAAIl/B,EAAI,IAAI3I,OAAOmI,MAAM0/B,EAAQz/B,EAAGy/B,EAAQx/B,GAE5CxG,KAAKumC,SACLvmC,KAAKwmC,UAAU1/B,GAEf9G,KAAK2/B,OAAOuF,WAAW54B,OAAOxF,EAAEP,EAAGO,EAAEN,IAOvCggC,UAAW,SAASvgC,GACQ,EAAtBjG,KAAK8lC,QAAQrlC,QAAcwF,EAAMirB,GAAGlxB,KAAK8lC,QAAQ9lC,KAAK8lC,QAAQrlC,OAAS,KAG3ET,KAAK8lC,QAAQllC,KAAKqF,IAOpBsgC,OAAQ,WACNvmC,KAAK8lC,QAAQrlC,OAAS,EAEtBT,KAAKilC,kBACLjlC,KAAKulC,cAOPW,oBAAqB,SAASF,GAC5B,IAAIS,EAAe,IAAItoC,OAAOmI,MAAM0/B,EAAQz/B,EAAGy/B,EAAQx/B,GACvDxG,KAAKwmC,UAAUC,IAOjBN,QAAS,WACP,IAAmCjlC,EAAGC,EAAlCuK,EAAO1L,KAAK2/B,OAAOuF,WACnB9+B,EAAIpG,KAAK2/B,OAAO9D,kBAChB6K,EAAK1mC,KAAK8lC,QAAQ,GAClBa,EAAK3mC,KAAK8lC,QAAQ,GAUtB,GARAp6B,EAAIU,OACJV,EAAIqb,UAAU3gB,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAC9CsF,EAAI+B,YAMwB,IAAxBzN,KAAK8lC,QAAQrlC,QAAgBimC,EAAGngC,IAAMogC,EAAGpgC,GAAKmgC,EAAGlgC,IAAMmgC,EAAGngC,EAAG,CAC/D,IAAIc,EAAQtH,KAAKsH,MAAQ,IACzBo/B,EAAK,IAAIvoC,OAAOmI,MAAMogC,EAAGngC,EAAGmgC,EAAGlgC,GAC/BmgC,EAAK,IAAIxoC,OAAOmI,MAAMqgC,EAAGpgC,EAAGogC,EAAGngC,GAC/BkgC,EAAGngC,GAAKe,EACRq/B,EAAGpgC,GAAKe,EAIV,IAFAoE,EAAIY,OAAOo6B,EAAGngC,EAAGmgC,EAAGlgC,GAEftF,EAAI,EAAGC,EAAMnB,KAAK8lC,QAAQrlC,OAAQS,EAAIC,EAAKD,IAAK,CAGnD,IAAI0lC,EAAWF,EAAGjV,aAAakV,GAC/Bj7B,EAAIm7B,iBAAiBH,EAAGngC,EAAGmgC,EAAGlgC,EAAGogC,EAASrgC,EAAGqgC,EAASpgC,GAEtDkgC,EAAK1mC,KAAK8lC,QAAQ5kC,GAClBylC,EAAK3mC,KAAK8lC,QAAQ5kC,EAAI,GAKxBwK,EAAIo7B,OAAOJ,EAAGngC,EAAGmgC,EAAGlgC,GACpBkF,EAAIqc,SACJrc,EAAIc,WAQNu6B,uBAAwB,SAAS7/B,GAC/B,IAAehG,EAAX8J,EAAO,GAAO1D,EAAQtH,KAAKsH,MAAQ,IACnCo/B,EAAK,IAAIvoC,OAAOmI,MAAMY,EAAO,GAAGX,EAAGW,EAAO,GAAGV,GAC7CmgC,EAAK,IAAIxoC,OAAOmI,MAAMY,EAAO,GAAGX,EAAGW,EAAO,GAAGV,GAC7CrF,EAAM+F,EAAOzG,OAAQumC,EAAY,EAAGC,EAAY,EAAGC,EAAmB,EAAN/lC,EAOpE,IALI+lC,IACFF,EAAY9/B,EAAO,GAAGX,EAAIogC,EAAGpgC,GAAK,EAAIW,EAAO,GAAGX,IAAMogC,EAAGpgC,EAAI,EAAI,EACjE0gC,EAAY//B,EAAO,GAAGV,EAAImgC,EAAGngC,GAAK,EAAIU,EAAO,GAAGV,IAAMmgC,EAAGngC,EAAI,EAAI,GAEnEwE,EAAKpK,KAAK,KAAM8lC,EAAGngC,EAAIygC,EAAY1/B,EAAO,IAAKo/B,EAAGlgC,EAAIygC,EAAY3/B,EAAO,KACpEpG,EAAI,EAAGA,EAAIC,EAAKD,IAAK,CACxB,IAAKwlC,EAAGxV,GAAGyV,GAAK,CACd,IAAIC,EAAWF,EAAGjV,aAAakV,GAI/B37B,EAAKpK,KAAK,KAAM8lC,EAAGngC,EAAG,IAAKmgC,EAAGlgC,EAAG,IAAKogC,EAASrgC,EAAG,IAAKqgC,EAASpgC,EAAG,KAErEkgC,EAAKx/B,EAAOhG,GACPA,EAAI,EAAKgG,EAAOzG,SACnBkmC,EAAKz/B,EAAOhG,EAAI,IAQpB,OALIgmC,IACFF,EAAYN,EAAGngC,EAAIW,EAAOhG,EAAI,GAAGqF,EAAI,EAAImgC,EAAGngC,IAAMW,EAAOhG,EAAI,GAAGqF,EAAI,GAAK,EACzE0gC,EAAYP,EAAGlgC,EAAIU,EAAOhG,EAAI,GAAGsF,EAAI,EAAIkgC,EAAGlgC,IAAMU,EAAOhG,EAAI,GAAGsF,EAAI,GAAK,GAE3EwE,EAAKpK,KAAK,KAAM8lC,EAAGngC,EAAIygC,EAAY1/B,EAAO,IAAKo/B,EAAGlgC,EAAIygC,EAAY3/B,GAC3D0D,GAQTm8B,WAAY,SAASC,GACnB,IAAIp8B,EAAO,IAAI7M,OAAOkpC,KAAKD,EAAU,CACnC9mC,KAAM,KACNynB,OAAQ/nB,KAAKkkB,MACbojB,YAAatnC,KAAKsH,MAClBu9B,cAAe7kC,KAAK6kC,cACpBC,eAAgB9kC,KAAK8kC,eACrBC,gBAAiB/kC,KAAK+kC,gBACtBwC,QAAS,SACTC,QAAS,WAEPpP,EAAW,IAAIj6B,OAAOmI,MAAM0E,EAAKtD,KAAMsD,EAAKrD,KAYhD,OAXAqD,EAAKu8B,QAAUppC,OAAOmN,OAAOC,UAAUg8B,QACvCv8B,EAAKw8B,QAAUrpC,OAAOmN,OAAOC,UAAUi8B,QACvCpP,EAAWptB,EAAKy8B,uBACdrP,EAAU,SAAU,SAAUptB,EAAKu8B,QAASv8B,EAAKw8B,SACnDx8B,EAAKrD,IAAMywB,EAAS5xB,EACpBwE,EAAKtD,KAAO0wB,EAAS7xB,EACjBvG,KAAK26B,SACP36B,KAAK26B,OAAOH,cAAe,EAC3BxvB,EAAKg6B,UAAUhlC,KAAK26B,SAGf3vB,GAQTs7B,oBAAqB,WACTtmC,KAAK2/B,OAAOuF,WAClBwC,YAEJ,IAAIN,EAAWpnC,KAAK+mC,uBAAuB/mC,KAAK8lC,SAAS/0B,KAAK,IAC9D,GAAiB,0BAAbq2B,EAAJ,CASA,IAAIp8B,EAAOhL,KAAKmnC,WAAWC,GAE3BpnC,KAAK2/B,OAAOh+B,IAAIqJ,GAChBA,EAAKk0B,YAELl/B,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAK4lC,eACL5lC,KAAK2/B,OAAO59B,YAGZ/B,KAAK2/B,OAAO5+B,KAAK,eAAgB,CAAEiK,KAAMA,SAdvChL,KAAK2/B,OAAO59B,eAwBpB5D,OAAOwpC,YAAcxpC,OAAOiC,KAAK+Y,YAAYhb,OAAOymC,UAAsD,CAOxGt9B,MAAO,GAOP8R,WAAY,SAASumB,GACnB3/B,KAAK2/B,OAASA,EACd3/B,KAAKkH,OAAS,IAOhB0gC,QAAS,SAAS5B,GAChB,IAAI//B,EAAQjG,KAAK6nC,SAAS7B,GACtBt6B,EAAM1L,KAAK2/B,OAAOuF,WAClB9+B,EAAIpG,KAAK2/B,OAAO9D,kBACpBnwB,EAAIU,OACJV,EAAIqb,UAAU3gB,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAE9CsF,EAAIq1B,UAAY96B,EAAM3F,KACtBoL,EAAI+B,YACJ/B,EAAIo8B,IAAI7hC,EAAMM,EAAGN,EAAMO,EAAGP,EAAM8hC,OAAQ,EAAa,EAAVhjC,KAAKK,IAAQ,GACxDsG,EAAIg8B,YACJh8B,EAAIpL,OAEJoL,EAAIc,WAMNu5B,YAAa,SAASC,GACpBhmC,KAAKkH,OAAOzG,OAAS,EACrBT,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAKulC,aACLvlC,KAAK4nC,QAAQ5B,IAOfI,YAAa,SAASJ,GACpBhmC,KAAK4nC,QAAQ5B,IAMfK,UAAW,WACT,IAAI2B,EAA4BhoC,KAAK2/B,OAAO79B,kBAC5C9B,KAAK2/B,OAAO79B,mBAAoB,EAIhC,IAFA,IAAImmC,EAAU,GAEL/mC,EAAI,EAAGC,EAAMnB,KAAKkH,OAAOzG,OAAQS,EAAIC,EAAKD,IAAK,CACtD,IAAI+E,EAAQjG,KAAKkH,OAAOhG,GACpBgnC,EAAS,IAAI/pC,OAAOgqC,OAAO,CACzBJ,OAAQ9hC,EAAM8hC,OACdrgC,KAAMzB,EAAMM,EACZoB,IAAK1B,EAAMO,EACX+gC,QAAS,SACTC,QAAS,SACTlnC,KAAM2F,EAAM3F,OAGlBN,KAAK26B,QAAUuN,EAAOlD,UAAUhlC,KAAK26B,QAErCsN,EAAQrnC,KAAKsnC,GAEf,IAAItP,EAAQ,IAAIz6B,OAAOiqC,MAAMH,EAAS,CAAEV,QAAS,SAAUC,QAAS,WACpE5O,EAAM+G,OAAS3/B,KAAK2/B,OAEpB3/B,KAAK2/B,OAAOh+B,IAAIi3B,GAChB54B,KAAK2/B,OAAO5+B,KAAK,eAAgB,CAAEiK,KAAM4tB,IAEzC54B,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAK4lC,eACL5lC,KAAK2/B,OAAO79B,kBAAoBkmC,EAChChoC,KAAK2/B,OAAO59B,aAOd8lC,SAAU,SAAS7B,GACjB,IAAIS,EAAe,IAAItoC,OAAOmI,MAAM0/B,EAAQz/B,EAAGy/B,EAAQx/B,GAEnD6hC,EAAelqC,OAAOiC,KAAKmF,aACXR,KAAKU,IAAI,EAAGzF,KAAKsH,MAAQ,IAAKtH,KAAKsH,MAAQ,IAAM,EAEjEghC,EAAc,IAAInqC,OAAOylB,MAAM5jB,KAAKkkB,OACnB4J,SAAS3vB,OAAOiC,KAAKmF,aAAa,EAAG,KAAO,KAC5CyoB,SAOrB,OALAyY,EAAasB,OAASM,EACtB5B,EAAanmC,KAAOgoC,EAEpBtoC,KAAKkH,OAAOtG,KAAK6lC,GAEVA,KASXtoC,OAAOoqC,WAAapqC,OAAOiC,KAAK+Y,YAAahb,OAAOymC,UAAqD,CAOvGt9B,MAAoB,GAOpBkhC,QAAoB,GAOpBC,SAAoB,EAOpBC,iBAAoB,EAOpBC,eAAsB,EAOtBC,qBAAsB,EAOtBxvB,WAAY,SAASumB,GACnB3/B,KAAK2/B,OAASA,EACd3/B,KAAK6oC,YAAc,IAOrB9C,YAAa,SAASC,GACpBhmC,KAAK6oC,YAAYpoC,OAAS,EAC1BT,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAKulC,aAELvlC,KAAK8oC,cAAc9C,GACnBhmC,KAAK6gC,UAOPuF,YAAa,SAASJ,GACpBhmC,KAAK8oC,cAAc9C,GACnBhmC,KAAK6gC,UAMPwF,UAAW,WACT,IAAI2B,EAA4BhoC,KAAK2/B,OAAO79B,kBAC5C9B,KAAK2/B,OAAO79B,mBAAoB,EAIhC,IAFA,IAAIinC,EAAQ,GAEH7nC,EAAI,EAAG8nC,EAAOhpC,KAAK6oC,YAAYpoC,OAAQS,EAAI8nC,EAAM9nC,IAGxD,IAFA,IAAI+nC,EAAajpC,KAAK6oC,YAAY3nC,GAEzBkU,EAAI,EAAGC,EAAO4zB,EAAWxoC,OAAQ2U,EAAIC,EAAMD,IAAK,CAEvD,IAAI8zB,EAAO,IAAI/qC,OAAOgrC,KAAK,CACzB7hC,MAAO2hC,EAAW7zB,GAAG9N,MACrBM,OAAQqhC,EAAW7zB,GAAG9N,MACtBI,KAAMuhC,EAAW7zB,GAAG7O,EAAI,EACxBoB,IAAKshC,EAAW7zB,GAAG5O,EAAI,EACvB+gC,QAAS,SACTC,QAAS,SACTlnC,KAAMN,KAAKkkB,QAGblkB,KAAK26B,QAAUuO,EAAKlE,UAAUhlC,KAAK26B,QACnCoO,EAAMnoC,KAAKsoC,GAIXlpC,KAAK4oC,sBACPG,EAAQ/oC,KAAKopC,mBAAmBL,IAGlC,IAAInQ,EAAQ,IAAIz6B,OAAOiqC,MAAMW,EAAO,CAAExB,QAAS,SAAUC,QAAS,WAClE5O,EAAM+G,OAAS3/B,KAAK2/B,OAEpB3/B,KAAK2/B,OAAOh+B,IAAIi3B,GAChB54B,KAAK2/B,OAAO5+B,KAAK,eAAgB,CAAEiK,KAAM4tB,IAEzC54B,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YACrCllC,KAAK4lC,eACL5lC,KAAK2/B,OAAO79B,kBAAoBkmC,EAChChoC,KAAK2/B,OAAO59B,aAOdqnC,mBAAoB,SAASL,GAK3B,IAFA,IAAuBrkC,EAAnB2kC,EAAc,GAETnoC,EAAI,EAAGC,EAAM4nC,EAAMtoC,OAAQS,EAAIC,EAAKD,IAEtCmoC,EADL3kC,EAAMqkC,EAAM7nC,GAAGwG,KAAO,GAAKqhC,EAAM7nC,GAAGyG,OAElC0hC,EAAY3kC,GAAOqkC,EAAM7nC,IAG7B,IAAIooC,EAAmB,GACvB,IAAK5kC,KAAO2kC,EACVC,EAAiB1oC,KAAKyoC,EAAY3kC,IAGpC,OAAO4kC,GAMTzI,OAAQ,WACN,IAAIn1B,EAAM1L,KAAK2/B,OAAOuF,WACtBx5B,EAAIq1B,UAAY/gC,KAAKkkB,MAErB,IAAI9d,EAAIpG,KAAK2/B,OAAO9D,kBACpBnwB,EAAIU,OACJV,EAAIqb,UAAU3gB,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAE9C,IAAK,IAAIlF,EAAI,EAAGC,EAAMnB,KAAKupC,iBAAiB9oC,OAAQS,EAAIC,EAAKD,IAAK,CAChE,IAAI+E,EAAQjG,KAAKupC,iBAAiBroC,QACL,IAAlB+E,EAAMiW,UACfxQ,EAAI89B,YAAcvjC,EAAMiW,SAE1BxQ,EAAIs1B,SAAS/6B,EAAMM,EAAGN,EAAMO,EAAGP,EAAMqB,MAAOrB,EAAMqB,OAEpDoE,EAAIc,WAMNs8B,cAAe,SAAS9C,GACtBhmC,KAAKupC,iBAAmB,GAIxB,IAFA,IAAIhjC,EAAGC,EAAGc,EAAOygC,EAAS/nC,KAAKsH,MAAQ,EAE9BpG,EAAI,EAAGA,EAAIlB,KAAKwoC,QAAStnC,IAAK,CAErCqF,EAAIpI,OAAOiC,KAAKmF,aAAaygC,EAAQz/B,EAAIwhC,EAAQ/B,EAAQz/B,EAAIwhC,GAC7DvhC,EAAIrI,OAAOiC,KAAKmF,aAAaygC,EAAQx/B,EAAIuhC,EAAQ/B,EAAQx/B,EAAIuhC,GAG3DzgC,EADEtH,KAAK0oC,iBACCvqC,OAAOiC,KAAKmF,aAElBR,KAAKU,IAAI,EAAGzF,KAAKyoC,SAAWzoC,KAAK0oC,kBACjC1oC,KAAKyoC,SAAWzoC,KAAK0oC,kBAGf1oC,KAAKyoC,SAGf,IAAIxiC,EAAQ,IAAI9H,OAAOmI,MAAMC,EAAGC,GAChCP,EAAMqB,MAAQA,EAEVtH,KAAK2oC,gBACP1iC,EAAMiW,QAAU/d,OAAOiC,KAAKmF,aAAa,EAAG,KAAO,KAGrDvF,KAAKupC,iBAAiB3oC,KAAKqF,GAG7BjG,KAAK6oC,YAAYjoC,KAAKZ,KAAKupC,qBAU/BprC,OAAOsrC,aAAetrC,OAAOiC,KAAK+Y,YAAYhb,OAAO0nC,YAAyD,CAE5G6D,cAAe,WAEb,IAEIC,EAAgBxrC,OAAOG,SAASqO,cAAc,UAC9Ci9B,EAAaD,EAAc/8B,WAAW,MAU1C,OARA+8B,EAAcriC,MAAQqiC,EAAc/hC,OAAS6gC,GAE7CmB,EAAW7I,UAAY/gC,KAAKkkB,MAC5B0lB,EAAWn8B,YACXm8B,EAAW9B,IAAIW,GAAcA,GAAcA,GAAc,EAAa,EAAV1jC,KAAKK,IAAQ,GACzEwkC,EAAWlC,YACXkC,EAAWtpC,OAEJqpC,GAGTE,sBAAuB,WACrB,OAAO56B,OAAOjP,KAAK0pC,eAAehyB,QAAQ,aAAc,IAAM1X,KAAKkkB,MAAQ,MAM7E4lB,WAAY,WACV,OAAO9pC,KAAK2/B,OAAOuF,WAAW7K,cAAcr6B,KAAKgE,QAAUhE,KAAK0pC,gBAAiB,WAMnFzE,gBAAiB,WACfjlC,KAAK8Y,UAAU,mBACf9Y,KAAK2/B,OAAOuF,WAAWC,YAAcnlC,KAAK8pC,cAM5C3C,WAAY,SAASC,GACnB,IAAIp8B,EAAOhL,KAAK8Y,UAAU,aAAcsuB,GACpC2C,EAAU/+B,EAAKg/B,oBAAoBxZ,UAAUxlB,EAAKs8B,YAAc,GAOpE,OALAt8B,EAAK+c,OAAS,IAAI5pB,OAAO8F,QAAQ,CAC/BD,OAAQhE,KAAKgE,QAAUhE,KAAK6pC,wBAC5B7R,SAAU+R,EAAQxjC,EAClB0xB,SAAU8R,EAAQvjC,IAEbwE,KAKX,WAEE,IAAI2Q,EAAaxd,OAAOiC,KAAKub,WACzB/V,EAAmBzH,OAAOiC,KAAKwF,iBAC/BE,EAAmB3H,OAAOiC,KAAK0F,iBAC/Bd,EAAQD,KAAKC,MACbE,EAAMH,KAAKG,IACX+kC,EAAkB9rC,OAAO88B,aAAawJ,SAAS,eAwpDnD,IAAK,IAAI/jC,KA1nDTvC,OAAO+rC,OAAS/rC,OAAOiC,KAAK+Y,YAAYhb,OAAO88B,aAAoD,CAQjG7hB,WAAY,SAASsE,EAAI1c,GACvBA,IAAYA,EAAU,IAEtBhB,KAAKo7B,YAAY1d,EAAI1c,GACrBhB,KAAKmqC,mBACLnqC,KAAKoqC,sBAQPC,mBAAwB,EAWxBC,YAAuB,WASvBC,iBAAwB,EASxBC,kBAAwB,EAWxBC,YAAuB,SAWvBC,aAAwB,WAOxBlO,aAAwB,EAOxBmO,WAAwB,EAWxBC,aAAwB,WAYxBC,gBAA2B,KAO3BC,eAAwB,2BAOxBC,mBAAwB,GAOxBC,qBAAwB,2BAOxBC,mBAAwB,EAOxBC,YAAwB,OAOxBC,WAAwB,OAOxBC,cAAwB,UAOxBC,kBAAwB,YAOxBC,eAAwB,YAOxBC,eAAwB,mBAOxBC,oBAAwB,EAOxBC,oBAAwB,EAOxBC,gBAAwB,EAUxBC,eAAwB,EAQxBC,wBAAwB,EAQxBC,UAAW,EASXC,cAAe,KAQfC,iBAAiB,EAQjBC,gBAAgB,EAQhBC,iBAAiB,EAKjB9B,iBAAkB,WAChBnqC,KAAKksC,kBAAoB,KACzBlsC,KAAKmsC,eAAiB,KACtBnsC,KAAKosC,sBACLpsC,KAAKqsC,qBACLrsC,KAAKssC,sBAELtsC,KAAKy8B,qBAELz8B,KAAKusC,iBAAmBpuC,OAAO0nC,aAAe,IAAI1nC,OAAO0nC,YAAY7lC,MAErEA,KAAK88B,cAQP0P,uBAAwB,WACtB,IAEIvqC,EAFA+8B,EAAch/B,KAAKysC,iBACnBC,EAAe1sC,KAAK2sC,kBACZC,EAAe,GAAIC,EAAqB,GAEpD,IAAK7N,IAAe0N,GAAkB1sC,KAAK4rC,uBAiBzCgB,EAAe5sC,KAAK0B,aAjB6C,CACjE,IAAK,IAAIR,EAAI,EAAGT,EAAST,KAAK0B,SAASjB,OAAQS,EAAIT,EAAQS,IACzDe,EAASjC,KAAK0B,SAASR,GACjB89B,GAAgBA,EAAY97B,SAASjB,IAAYA,IAAWyqC,EAIhEG,EAAmBjsC,KAAKqB,GAHxB2qC,EAAahsC,KAAKqB,GAMlB+8B,IACFA,EAAYv6B,KAAK,WAAYooC,GAC7BD,EAAahsC,KAAKo+B,IAEpB0N,GAAgBE,EAAahsC,KAAK8rC,GAKpC,OAAOE,GAQT7qC,UAAW,YACL/B,KAAK8sC,iBAAoB9sC,KAAKmsC,gBAAmBnsC,KAAK2rC,gBACxD3rC,KAAK4/B,aAAa5/B,KAAKklC,YACvBllC,KAAK8sC,iBAAkB,GAEzB,IAAI5M,EAAiBlgC,KAAKk9B,iBAE1B,OADAl9B,KAAKmgC,aAAaD,EAAgBlgC,KAAKwsC,0BAChCxsC,MAST+sC,UAAW,WACT,IAAIrhC,EAAM1L,KAAKklC,WAUf,OATAllC,KAAK4/B,aAAal0B,GAGd1L,KAAK2qC,WAAa3qC,KAAKmsC,gBACzBnsC,KAAKgtC,eAAethC,GAGtB1L,KAAKe,KAAK,gBACVf,KAAK8sC,iBAAkB,EAChB9sC,MAOTitC,uBAAwB,WACtB,IAAIlmC,EAAI/G,KAAKksC,kBAEbnlC,EAAE6H,OAAOnL,IAAI,CACXwK,OAAQlH,EAAEmmC,SAASj/B,OACnBC,OAAQnH,EAAEmmC,SAASh/B,OACnBC,MAAOpH,EAAEmmC,SAAS/+B,MAClBC,MAAOrH,EAAEmmC,SAAS9+B,MAClB1G,KAAMX,EAAEmmC,SAASxlC,KACjBC,IAAKZ,EAAEmmC,SAASvlC,MAGd3H,KAAKmtC,uBAAuBpmC,EAAE6H,QACf,WAAb7H,EAAEqmC,OACJptC,KAAKqtC,mBAAmBtmC,EAAE6H,SAGR,WAAd7H,EAAEwgC,UACc,UAAdxgC,EAAEwgC,QACJxgC,EAAEumC,YAAc,EAGhBvmC,EAAEumC,WAAa,GAGD,WAAdvmC,EAAEygC,UACc,WAAdzgC,EAAEygC,QACJzgC,EAAEwmC,YAAc,EAGhBxmC,EAAEwmC,WAAa,GAInBxmC,EAAEwgC,QAAU,SACZxgC,EAAEygC,QAAU,WAIdzgC,EAAEwgC,QAAUxgC,EAAEmmC,SAAS3F,QACvBxgC,EAAEygC,QAAUzgC,EAAEmmC,SAAS1F,UAW3BgG,cAAe,SAAUrzB,EAAGvL,EAAQ3I,GAClC,IAEIwnC,EADAzH,EAAU//B,GAASjG,KAAK2b,WAAWxB,GADtB,GAYjB,OAPEszB,EADE7+B,EAAOgqB,OAAShqB,EAAOgqB,QAAU54B,KAAKysC,iBACnCzsC,KAAK0tC,kBAAkB9+B,EAAOgqB,MAAOoN,GAGrC,CAAEz/B,EAAGy/B,EAAQz/B,EAAGC,EAAGw/B,EAAQx/B,GAI1BoI,EAAO4+B,cAAcC,IAAO7+B,EAAO++B,kBAAkB3H,IAM/D0H,kBAAmB,SAAUzrC,EAAQ+jC,GACnC,IAAIjc,EAAI9nB,EAAO2rC,sBACXC,EAAY1vC,OAAOiC,KAAKyH,gBAAgBkiB,GACxC+jB,EAAa9tC,KAAK+tC,kBAAkB/H,GACxC,OAAO7nC,OAAOiC,KAAKyG,eAAeinC,EAAYD,IAUhDG,oBAAqB,SAAUp/B,EAAQrI,EAAGC,GACxC,IAAIynC,EAAar/B,EAAOq/B,WACpBC,EAAqBt/B,EAAOs/B,mBAC5BxiC,EAAM1L,KAAKmuC,aACXC,EAAgBx/B,EAAOy/B,yBAE3Bz/B,EAAOq/B,WAAar/B,EAAOs/B,oBAAqB,EAChDt/B,EAAOy/B,yBAA2B,GAElC3iC,EAAIU,OACJV,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK67B,mBAC9BjtB,EAAOiyB,OAAOn1B,GACdA,EAAIc,UAEJoC,EAAO0/B,QAAU1/B,EAAO2/B,gBAAgB7iC,GAExCkD,EAAOq/B,WAAaA,EACpBr/B,EAAOs/B,mBAAqBA,EAC5Bt/B,EAAOy/B,yBAA2BD,EAElC,IAAIj/B,EAAgBhR,OAAOiC,KAAK+O,cAC9BzD,EAAKnF,EAAGC,EAAGxG,KAAKyrC,qBAIlB,OAFAzrC,KAAK4/B,aAAal0B,GAEXyD,GAQTq/B,sBAAuB,SAAUr0B,EAAGvL,GAClC,IAAIowB,EAAch/B,KAAKysC,iBACnBC,EAAe1sC,KAAK2sC,kBAExB,OACG/9B,GAEAA,GACCowB,IACCA,EAAY97B,SAAS0L,IACtBowB,IAAgBpwB,IACfuL,EAAEna,KAAK4qC,eAETh8B,IAAWA,EAAO6/B,SAElB7/B,IACEA,EAAO8/B,YACRhC,GACAA,IAAiB99B,GAQvBu+B,uBAAwB,SAAUv+B,GAChC,GAAKA,EAAL,CAIA,IACI+/B,EADA5nC,EAAI/G,KAAKksC,kBAUb,MAPiB,UAAbnlC,EAAEqmC,QAAmC,WAAbrmC,EAAEqmC,QAAoC,WAAbrmC,EAAEqmC,OACrDuB,EAAkB3uC,KAAKuqC,iBAAmB37B,EAAO27B,gBAE7B,WAAbxjC,EAAEqmC,SACTuB,EAAkB3uC,KAAKwqC,kBAAoB57B,EAAO47B,kBAG7CmE,GAAmB5nC,EAAE6nC,OAAS7nC,EAAE6nC,SAMzCC,qBAAsB,SAASjgC,EAAQkgC,GACrC,IAAI5oC,EAAS,CACXK,EAAGqI,EAAO24B,QACV/gC,EAAGoI,EAAO44B,SAiBZ,MAde,OAAXsH,GAA8B,OAAXA,GAA8B,OAAXA,EACxC5oC,EAAOK,EAAI,QAEO,OAAXuoC,GAA8B,OAAXA,GAA8B,OAAXA,IAC7C5oC,EAAOK,EAAI,QAGE,OAAXuoC,GAA8B,OAAXA,GAA8B,OAAXA,EACxC5oC,EAAOM,EAAI,SAEO,OAAXsoC,GAA8B,OAAXA,GAA8B,OAAXA,IAC7C5oC,EAAOM,EAAI,OAGNN,GAMT6oC,qBAAsB,SAASngC,EAAQkgC,EAAQ30B,GAC7C,IAAK20B,EACH,MAAO,OAGT,OAAQA,GACN,IAAK,MACH,MAAO,SACT,IAAK,KACL,IAAK,KACH,OAAO30B,EAAEna,KAAK0qC,cAAgB,QAAU,SAC1C,IAAK,KACL,IAAK,KACH,OAAOvwB,EAAEna,KAAK0qC,cAAgB,QAAU,SAC1C,QACE,MAAO,UASbsE,uBAAwB,SAAU70B,EAAGvL,GACnC,GAAKA,EAAL,CAIA,IAAIo3B,EAAUhmC,KAAK2b,WAAWxB,GAC1B20B,EAASlgC,EAAO++B,kBAAkB3tC,KAAK2b,WAAWxB,GAAG,IACrDizB,EAASptC,KAAK+uC,qBAAqBngC,EAAQkgC,EAAQ30B,GACnDjU,EAASlG,KAAK6uC,qBAAqBjgC,EAAQkgC,GAE/C9uC,KAAKksC,kBAAoB,CACvBt9B,OAAQA,EACRw+B,OAAQA,EACR0B,OAAQA,EACR7gC,OAAQW,EAAOX,OACfC,OAAQU,EAAOV,OACfC,MAAOS,EAAOT,MACdC,MAAOQ,EAAOR,MACd4pB,QAASgO,EAAQz/B,EAAIqI,EAAOlH,KAC5BuwB,QAAS+N,EAAQx/B,EAAIoI,EAAOjH,IAC5B4/B,QAASrhC,EAAOK,EAChBihC,QAASthC,EAAOM,EAChByoC,GAAIjJ,EAAQz/B,EACZ2oC,GAAIlJ,EAAQx/B,EACZ2oC,MAAOnJ,EAAQz/B,EACf6oC,MAAOpJ,EAAQx/B,EACfkB,KAAMkH,EAAOlH,KACbC,IAAKiH,EAAOjH,IACZ0nC,MAAOzpC,EAAiBgJ,EAAOb,OAC/BzG,MAAOsH,EAAOtH,MAAQsH,EAAOX,OAC7Bq/B,WAAY,EACZC,WAAY,EACZ+B,SAAUn1B,EAAEm1B,SACZV,OAAQz0B,EAAEna,KAAKyqC,cAGjBzqC,KAAKksC,kBAAkBgB,SAAW,CAChCxlC,KAAMkH,EAAOlH,KACbC,IAAKiH,EAAOjH,IACZsG,OAAQW,EAAOX,OACfC,OAAQU,EAAOV,OACfC,MAAOS,EAAOT,MACdC,MAAOQ,EAAOR,MACdm5B,QAASrhC,EAAOK,EAChBihC,QAASthC,EAAOM,GAGlBxG,KAAKitC,2BAUPsC,iBAAkB,SAAUhpC,EAAGC,GAC7B,IAAIugB,EAAY/mB,KAAKksC,kBACjBt9B,EAASmY,EAAUnY,OACnB4gC,EAAUjpC,EAAIwgB,EAAUiR,QACxByX,EAASjpC,EAAIugB,EAAUkR,QACvByX,GAAS9gC,EAAOjK,IAAI,kBAAoBiK,EAAOlH,OAAS8nC,EACxDG,GAAS/gC,EAAOjK,IAAI,kBAAoBiK,EAAOjH,MAAQ8nC,EAI3D,OAFAC,GAAS9gC,EAAOnL,IAAI,OAAQ+rC,GAC5BG,GAAS/gC,EAAOnL,IAAI,MAAOgsC,GACpBC,GAASC,GAQlBC,2BAA4B,SAASC,EAAW9oC,EAAG+oC,GACjD,IAAIlsC,EAAW,UAAWmsC,EAAU,CAAEC,EAAG,UACrCC,EAAOlpC,EAAE6H,OAAOT,MAAO+hC,EAAU,OAAQC,EAAU,QACnDrB,EAAsB,OAAb/nC,EAAE+nC,QAAgC,OAAb/nC,EAAE+nC,OAAkB,GAAK,EACvDsB,EAAW,EAEfP,EAAwB,EAAZA,EAAgB,GAAK,EACtB,MAAPC,IACFG,EAAOlpC,EAAE6H,OAAOR,MAChB8hC,EAAU,MACVC,EAAU,SACVvsC,EAAW,WAEbmsC,GAAS,GAAKG,EACdH,EAAQ,GAAKI,EAEbppC,EAAE6H,OAAOC,QAAUuhC,IAAa,GAChCrpC,EAAE6H,OAAOE,QAAUshC,IAAa,GAI9BrpC,EAAEnD,GAFS,IAATqsC,GACFlpC,EAAEspC,UAAYvB,EAASe,EAAYO,EACrBL,GAASF,KAGvBI,EAAc,EAAPA,EAAW,GAAK,EAETF,GADdhpC,EAAEspC,SAAWJ,GACgBnB,EAASsB,KAY1CE,YAAa,SAAU/pC,EAAGC,EAAGspC,GAC3B,IACuBS,EADnBxpC,EAAI/G,KAAKksC,kBACTt9B,EAAS7H,EAAE6H,OACX4hC,EAAe5hC,EAAOjK,IAAI,gBAC1B8rC,EAAe7hC,EAAOjK,IAAI,gBAE9B,GAAK6rC,GAAuB,MAAPV,GAAgBW,GAAuB,MAAPX,EACnD,OAAO,EAIT,IAGIY,EAAqBC,EAHrBpP,EAAS3yB,EAAOwyB,iBAChBwP,EAAsBhiC,EAAOiiC,aAAa,IAAI1yC,OAAOmI,MAAMC,EAAGC,GAAI,SAAU,UAAUspC,GACtFgB,EAAoBliC,EAAOiiC,aAAa,IAAI1yC,OAAOmI,MAAMS,EAAEooC,MAAOpoC,EAAEqoC,OAAQ,SAAU,UAAUU,GACvDiB,EAAMniC,EAAOoiC,4BAW1D,OATAhxC,KAAK4vC,2BAA2BgB,EAAsBE,EAAmB/pC,EAAG+oC,GAC5EY,EAAsB9hC,EAAOiiC,aAAa,IAAI1yC,OAAOmI,MAAMC,EAAGC,GAAIO,EAAEwgC,QAASxgC,EAAEygC,SAASsI,GACxFa,EAAqB/hC,EAAOqiC,uBAAuB1P,EAAQx6B,EAAEwgC,QAASxgC,EAAEygC,SAExE+I,EAASvwC,KAAKkxC,eAAeR,EAAqB3pC,EAAG+oC,EAAIiB,GACzDhqC,EAAEooC,MAAQ5oC,EACVQ,EAAEqoC,MAAQ5oC,EAEVoI,EAAOizB,oBAAoB8O,EAAoB5pC,EAAEwgC,QAASxgC,EAAEygC,SACrD+I,GAQTW,eAAgB,SAASC,EAAYpqB,EAAW+oB,EAAIsB,GAClD,IAA+BC,EAAUd,EACNe,EAAQC,EACvCC,EAASC,EAAUC,EAAKC,EAAaxjC,EAAOC,EAF5CQ,EAASmY,EAAUnY,OACnByhC,EAAWtpB,EAAUspB,SAmCzB,OA3BEjiC,EALS,MAAP0hC,GACF0B,EAAU,IACVC,EAAW,IACXC,EAAM,IACNvjC,EAAQ,EACAS,EAAOR,QAGfojC,EAAU,IACVC,EAAW,IACXC,EAAM,IACNvjC,EAAQS,EAAOT,MACP,GAGVojC,EAAY3iC,EAAOoiC,0BAA0B7iC,EAAOC,GAGlDijC,GAFFM,EAAc,EAAI5sC,KAAKG,IAAIisC,GAAcI,EAAUzB,KAChC,EACN,GAGXuB,EAAWhB,EAAWtrC,KAAK6sC,KAAMD,EAAc/iC,EAAO,QAAU8iC,IAC/BH,EAAUC,GAAW5iC,EAAO,QAAU6iC,KAC5DtzC,OAAOiC,KAAK0F,iBAAiBurC,IAE1Cd,EAAS3hC,EAAO,OAAS8iC,KAASL,EAClCziC,EAAOnL,IAAI,OAASiuC,EAAKL,GACS,IAA9BziC,EAAO,OAAS6iC,KAClBH,EAAS1iC,EAAOoiC,4BAChBK,EAAYD,EAAKI,GAAWF,EAAOE,GAAY5iC,EAAO,QAAU6iC,GAChE7iC,EAAOnL,IAAI,QAAUguC,EAAUJ,IAE1Bd,GAYTsB,aAAc,SAAUtrC,EAAGC,EAAGspC,GAC5B,IAAI/oC,EAAI/G,KAAKksC,kBACTt9B,EAAS7H,EAAE6H,OACXkjC,EAAeljC,EAAOjK,IAAI,gBAC1BotC,EAAenjC,EAAOjK,IAAI,gBAC1BqtC,EAAkBpjC,EAAOjK,IAAI,mBAEjC,GAAImtC,GAAgBC,EAClB,OAAO,EAIT,IAE8CE,EAF1CtB,EAAqB/hC,EAAOqiC,uBAAuBriC,EAAOwyB,iBAAkBr6B,EAAEwgC,QAASxgC,EAAEygC,SACzF2J,EAAaviC,EAAOiiC,aAAa,IAAI1yC,OAAOmI,MAAMC,EAAGC,GAAIO,EAAEwgC,QAASxgC,EAAEygC,SACtEuJ,EAAMniC,EAAOoiC,4BASjB,OAPAhxC,KAAKkyC,eAAef,EAAYpqC,GAGhCkrC,EAASjyC,KAAKmyC,gBAAgBhB,EAAYpqC,EAAG+qC,EAAcC,EAAcjC,EAAIkC,EAAiBjB,GAG9FniC,EAAOizB,oBAAoB8O,EAAoB5pC,EAAEwgC,QAASxgC,EAAEygC,SACrDyK,GAOTE,gBAAiB,SAAShB,EAAYpqB,EAAW+qB,EAAcC,EAAcjC,EAAIkC,EAAiBZ,GAChG,IACIgB,EAASC,EAASpkC,EAAQC,EAD1BU,EAASmY,EAAUnY,OAAQ0jC,GAAiB,EAAOC,GAAiB,EAAON,GAAS,EAgCxF,OA7BAhkC,EAASkjC,EAAW5qC,EAAIqI,EAAOX,OAASmjC,EAAK7qC,EAC7C2H,EAASijC,EAAW3qC,EAAIoI,EAAOV,OAASkjC,EAAK5qC,EAC7C4rC,EAAUxjC,EAAOX,SAAWA,EAC5BokC,EAAUzjC,EAAOV,SAAWA,EAExB8jC,GAAmB/jC,GAAU,GAAKA,EAASW,EAAOX,SACpDqkC,GAAiB,GAGfN,GAAmB9jC,GAAU,GAAKA,EAASU,EAAOV,SACpDqkC,GAAiB,GAGR,YAAPzC,GAAqBgC,GAAiBC,EAGhCjC,EAIM,MAAPA,GAAelhC,EAAOjK,IAAI,kBAGnB,MAAPmrC,GAAelhC,EAAOjK,IAAI,mBACjC4tC,GAAkBR,GAAiBnjC,EAAOnL,IAAI,SAAUyK,KAAY+jC,EAASA,GAAUI,GAHvFC,GAAkBR,GAAiBljC,EAAOnL,IAAI,SAAUwK,KAAYgkC,EAASA,GAAUG,IAJvFE,GAAkBR,GAAiBljC,EAAOnL,IAAI,SAAUwK,KAAYgkC,EAASA,GAAUG,GACvFG,GAAkBR,GAAiBnjC,EAAOnL,IAAI,SAAUyK,KAAY+jC,EAASA,GAAUI,IAJvFC,GAAkBC,IAAmBN,EAASjyC,KAAKwyC,oBAAoBrB,EAAYviC,EAAQmY,EAAWqqB,IAYxGrqB,EAAU0rB,UAAYxkC,EACtB8Y,EAAU2rB,UAAYxkC,EACtBokC,GAAkBC,GAAkBvyC,KAAK2yC,YAAY5rB,EAAW+oB,GACzDmC,GAOTO,oBAAqB,SAASrB,EAAYviC,EAAQmY,EAAWqqB,GAE3D,IAGIa,EAHAW,EAAOzB,EAAW3qC,EAAI2qC,EAAW5qC,EACjCssC,EAAWzB,EAAK5qC,EAAIugB,EAAUmmB,SAASh/B,OAASU,EAAOV,OAC5CkjC,EAAK7qC,EAAIwgB,EAAUmmB,SAASj/B,OAASW,EAAOX,OAC/C6kC,EAAQ3B,EAAW5qC,EAAIxB,KAAKG,IAAIisC,EAAW5qC,GACnDwsC,EAAQ5B,EAAW3qC,EAAIzB,KAAKG,IAAIisC,EAAW3qC,GAS/C,OALAugB,EAAU0rB,UAAYK,EAAQ/tC,KAAKG,IAAI6hB,EAAUmmB,SAASj/B,OAAS2kC,EAAOC,GAC1E9rB,EAAU2rB,UAAYK,EAAQhuC,KAAKG,IAAI6hB,EAAUmmB,SAASh/B,OAAS0kC,EAAOC,GAC1EZ,EAASlrB,EAAU0rB,YAAc7jC,EAAOX,QAAU8Y,EAAU2rB,YAAc9jC,EAAOV,OACjFU,EAAOnL,IAAI,SAAUsjB,EAAU0rB,WAC/B7jC,EAAOnL,IAAI,SAAUsjB,EAAU2rB,WACxBT,GAMTU,YAAa,SAAS5rB,EAAW+oB,GAC3B/oB,EAAU0rB,UAAY,GAAY,MAAP3C,IACH,SAAtB/oB,EAAUwgB,QACZxgB,EAAUwgB,QAAU,QAES,UAAtBxgB,EAAUwgB,UACjBxgB,EAAUwgB,QAAU,SAIpBxgB,EAAU2rB,UAAY,GAAY,MAAP5C,IACH,QAAtB/oB,EAAUygB,QACZzgB,EAAUygB,QAAU,SAES,WAAtBzgB,EAAUygB,UACjBzgB,EAAUygB,QAAU,SAQ1B0K,eAAgB,SAASf,EAAYpqC,GACnC,IAAI6H,EAAS7H,EAAE6H,OAAQ6N,EAAOzc,KAAK6+B,UAC/BmU,EAAUpkC,EAAOokC,QAAUv2B,EAEb,UAAd1V,EAAEwgC,QACJ4J,EAAW5qC,IAAM,EAEI,WAAdQ,EAAEwgC,UACT4J,EAAW5qC,GAAoB,EAAfQ,EAAEumC,WACd6D,EAAW5qC,EAAI,IACjBQ,EAAEumC,YAAcvmC,EAAEumC,aAIJ,WAAdvmC,EAAEygC,QACJ2J,EAAW3qC,IAAM,EAEI,WAAdO,EAAEygC,UACT2J,EAAW3qC,GAAoB,EAAfO,EAAEwmC,WACd4D,EAAW3qC,EAAI,IACjBO,EAAEwmC,YAAcxmC,EAAEwmC,aAKlBroC,EAAIisC,EAAW5qC,GAAKysC,EAClB7B,EAAW5qC,EAAI,EACjB4qC,EAAW5qC,GAAKysC,EAGhB7B,EAAW5qC,GAAKysC,EAIlB7B,EAAW5qC,EAAI,EAGbrB,EAAIisC,EAAW3qC,GAAKwsC,EAClB7B,EAAW3qC,EAAI,EACjB2qC,EAAW3qC,GAAKwsC,EAGhB7B,EAAW3qC,GAAKwsC,EAIlB7B,EAAW3qC,EAAI,GAWnBysC,cAAe,SAAU1sC,EAAGC,GAE1B,IAAIO,EAAI/G,KAAKksC,kBAEb,GAAInlC,EAAE6H,OAAOjK,IAAI,gBACf,OAAO,EAGT,IAAIuuC,EAAYluC,EAAM+B,EAAEmoC,GAAKnoC,EAAEY,IAAKZ,EAAEkoC,GAAKloC,EAAEW,MACzCyrC,EAAWnuC,EAAMwB,EAAIO,EAAEY,IAAKpB,EAAIQ,EAAEW,MAClCqG,EAAQjI,EAAiBqtC,EAAWD,EAAYnsC,EAAEsoC,OAClD+D,GAAY,EAEhB,GAAyB,EAArBrsC,EAAE6H,OAAOi9B,UAAe,CAC1B,IAAIA,EAAa9kC,EAAE6H,OAAOi9B,UACtBC,EAAiB/kC,EAAE6H,OAAOk9B,eAAiBD,EAC3CwH,EAAmBtuC,KAAKgO,KAAKhF,EAAQ89B,GAAaA,EAClDyH,EAAkBvuC,KAAKW,MAAMqI,EAAQ89B,GAAaA,EAElD9mC,KAAKG,IAAI6I,EAAQulC,GAAmBxH,EACtC/9B,EAAQulC,EAEDvuC,KAAKG,IAAI6I,EAAQslC,GAAoBvH,IAC5C/9B,EAAQslC,GAiBZ,OAZItlC,EAAQ,IACVA,EAAQ,IAAMA,GAEhBA,GAAS,IAELhH,EAAE6H,OAAOb,QAAUA,EACrBqlC,GAAY,EAGZrsC,EAAE6H,OAAOb,MAAQA,EAGZqlC,GAQTG,UAAW,SAAUlyC,GACnBrB,KAAK0+B,cAAcziB,MAAMu3B,OAASnyC,GAOpCoyC,sBAAuB,SAAU7kC,GAC/BA,EAAOX,OAAS,EAChBW,EAAOV,OAAS,EAChBU,EAAOT,MAAQ,EACfS,EAAOR,MAAQ,EACfQ,EAAOG,SAAS,IAOlBi+B,eAAgB,SAAUthC,GACxB,IAAIgoC,EAAgB1zC,KAAKmsC,eACrBzkC,EAAOgsC,EAAchsC,KACrBC,EAAM+rC,EAAc/rC,IACpBgsC,EAAQzuC,EAAIwC,GACZksC,EAAO1uC,EAAIyC,GAaf,GAXI3H,KAAK8qC,iBACPp/B,EAAIq1B,UAAY/gC,KAAK8qC,eAErBp/B,EAAIs1B,SACF0S,EAAczE,IAAc,EAAPvnC,EAAY,GAAKA,GACtCgsC,EAAcxE,IAAa,EAANvnC,EAAW,GAAKA,GACrCgsC,EACAC,IAIC5zC,KAAKirC,oBAAuBjrC,KAAKgrC,qBAOtC,GAJAt/B,EAAI05B,UAAYplC,KAAKirC,mBACrBv/B,EAAIy5B,YAAcnlC,KAAKgrC,qBAGc,EAAjChrC,KAAK+qC,mBAAmBtqC,SAAewpC,EAAiB,CAE1D,IAAIn4B,EAAK4hC,EAAczE,GA5hCT,IA4hCuC,EAAPvnC,EAAY,EAAIisC,GAC1D5hC,EAAK2hC,EAAcxE,GA7hCT,IA6hCsC,EAANvnC,EAAW,EAAIisC,GAE7DloC,EAAI+B,YAEJtP,OAAOiC,KAAKqL,eAAeC,EAAKoG,EAAIC,EAAID,EAAK6hC,EAAO5hC,EAAI/R,KAAK+qC,oBAC7D5sC,OAAOiC,KAAKqL,eAAeC,EAAKoG,EAAIC,EAAK6hC,EAAO,EAAG9hC,EAAK6hC,EAAO5hC,EAAK6hC,EAAO,EAAG5zC,KAAK+qC,oBACnF5sC,OAAOiC,KAAKqL,eAAeC,EAAKoG,EAAIC,EAAID,EAAIC,EAAK6hC,EAAM5zC,KAAK+qC,oBAC5D5sC,OAAOiC,KAAKqL,eAAeC,EAAKoG,EAAK6hC,EAAQ,EAAG5hC,EAAID,EAAK6hC,EAAQ,EAAG5hC,EAAK6hC,EAAM5zC,KAAK+qC,oBAEpFr/B,EAAIg8B,YACJh8B,EAAIqc,cAGJ5pB,OAAOmN,OAAOC,UAAUsoC,aAAa/yC,KAAKd,KAAM0L,EAAK1L,KAAK+qC,oBAC1Dr/B,EAAIooC,WACFJ,EAAczE,GA5iCF,IA4iCgC,EAAPvnC,EAAY,EAAIisC,GACrDD,EAAcxE,GA7iCF,IA6iC+B,EAANvnC,EAAW,EAAIisC,GACpDD,EACAC,IAWNG,WAAY,SAAU55B,EAAG65B,GACvB,IAAIh0C,KAAK0rC,eAAT,CAIA,IAIIuI,EAAcC,EAHdlO,EAAUhmC,KAAK2b,WAAWxB,GADb,GAEb6kB,EAAch/B,KAAKysC,iBACnBC,EAAe1sC,KAAK2sC,kBAMxB,GADA3sC,KAAKm0C,QAAU,GACXnV,IAAgBgV,GAAahV,IAAgBh/B,KAAKo0C,uBAAuB,CAACpV,GAAcgH,GAE1F,OADAhmC,KAAKq0C,mBAAmBrV,EAAa7kB,GAC9B6kB,EAGT,GAAI0N,GAAgBA,EAAaiB,kBAAkB3H,GAEjD,OADAhmC,KAAKq0C,mBAAmB3H,EAAcvyB,GAC/BuyB,EAET,GAAIA,GAAgBA,IAAiB1sC,KAAKo0C,uBAAuB,CAAC1H,GAAe1G,GAAU,CACzF,IAAKhmC,KAAK4rC,uBAER,OADA5rC,KAAKq0C,mBAAmB3H,EAAcvyB,GAC/BuyB,EAGPuH,EAAevH,EACfwH,EAAmBl0C,KAAKm0C,QACxBn0C,KAAKm0C,QAAU,GAInB,IAAIvlC,EAAS5O,KAAKo0C,uBAAuBp0C,KAAK0B,SAAUskC,GAMxD,OALI7rB,EAAEna,KAAK6qC,kBAAoBj8B,GAAUqlC,GAAgBrlC,IAAWqlC,IAClErlC,EAASqlC,EACTj0C,KAAKm0C,QAAUD,GAEjBl0C,KAAKq0C,mBAAmBzlC,EAAQuL,GACzBvL,IAMTylC,mBAAoB,SAASzlC,EAAQuL,GACnC,IAAIm6B,EAASC,EAAQC,EAAgBx0C,KAAKy0C,eACtCD,IAAkB5lC,IACpB0lC,EAAU,CAAEn6B,EAAGA,EAAGvL,OAAQA,EAAQ8lC,eAAgB10C,KAAKy0C,gBACvDF,EAAS,CAAEp6B,EAAGA,EAAGvL,OAAQ5O,KAAKy0C,eAAgBE,WAAY/lC,GAC1D5O,KAAKy0C,eAAiB7lC,GAEpBA,EACE4lC,IAAkB5lC,IAChB4lC,IACFx0C,KAAKe,KAAK,YAAawzC,GACvBC,EAAczzC,KAAK,WAAYwzC,IAEjCv0C,KAAKe,KAAK,aAAcuzC,GACxB1lC,EAAO7N,KAAK,YAAauzC,IAGpBE,IACPx0C,KAAKe,KAAK,YAAawzC,GACvBC,EAAczzC,KAAK,WAAYwzC,KAOnCK,aAAc,SAAS5O,EAASxhC,GAC9B,GAAIA,GACAA,EAAImpB,SACJnpB,EAAIiqC,SACJzuC,KAAKwtC,cAAc,KAAMhpC,EAAKwhC,GAAS,CACzC,IAAKhmC,KAAKwrC,qBAAsBhnC,EAAIgnC,oBAAwBhnC,EAAIqwC,UAO9D,OAAO,EALP,IADoB70C,KAAKguC,oBAAoBxpC,EAAKwhC,EAAQz/B,EAAGy/B,EAAQx/B,GAEnE,OAAO,IAYf4tC,uBAAwB,SAAShyC,EAAS4jC,GAMxC,IAHA,IAAIp3B,EAA4BkmC,EAAmBC,EAAvC7zC,EAAIkB,EAAQ3B,OAGjBS,KACL,GAAIlB,KAAK40C,aAAa5O,EAAS5jC,EAAQlB,IAAK,CAEtB,WADpB0N,EAASxM,EAAQlB,IACN2B,MAAoB+L,EAAOomC,iBACpCF,EAAoB90C,KAAK0tC,kBAAkB9+B,EAAQo3B,IACnD+O,EAAY/0C,KAAKo0C,uBAAuBxlC,EAAOlN,SAAUozC,KAC5C90C,KAAKm0C,QAAQvzC,KAAKm0C,IAEjC,MAGJ,OAAOnmC,GAQTm/B,kBAAmB,SAAS/H,GAC1B,OAAO7nC,OAAOiC,KAAKyG,eACjBm/B,EACA7nC,OAAOiC,KAAKyH,gBAAgB7H,KAAK67B,qBAoBrClgB,WAAY,SAAUxB,EAAG86B,EAAYvW,GAC9BA,IACHA,EAAgB1+B,KAAK0+B,eAEvB,IAIIwW,EAJAlP,EAAUrqB,EAAWxB,GACrBjF,EAASwpB,EAAche,wBACvBy0B,EAAcjgC,EAAO5N,OAAS,EAC9B8tC,EAAelgC,EAAOtN,QAAU,EA+BpC,OA5BKutC,GAAgBC,IACf,QAASlgC,GAAU,WAAYA,IACjCkgC,EAAerwC,KAAKG,IAAKgQ,EAAOvN,IAAMuN,EAAOmgC,SAE3C,UAAWngC,GAAU,SAAUA,IACjCigC,EAAcpwC,KAAKG,IAAKgQ,EAAOogC,MAAQpgC,EAAOxN,QAIlD1H,KAAK88B,aAELkJ,EAAQz/B,EAAIy/B,EAAQz/B,EAAIvG,KAAKo9B,QAAQ11B,KACrCs+B,EAAQx/B,EAAIw/B,EAAQx/B,EAAIxG,KAAKo9B,QAAQz1B,IAChCstC,IACHjP,EAAUhmC,KAAK+tC,kBAAkB/H,IAKjCkP,EAFkB,IAAhBC,GAAsC,IAAjBC,EAEZ,CAAE9tC,MAAO,EAAGM,OAAQ,GAGpB,CACTN,MAAOo3B,EAAcp3B,MAAQ6tC,EAC7BvtC,OAAQ82B,EAAc92B,OAASwtC,GAI5B,CACL7uC,EAAGy/B,EAAQz/B,EAAI2uC,EAAS5tC,MACxBd,EAAGw/B,EAAQx/B,EAAI0uC,EAASttC,SAQ5BykC,mBAAoB,WAClB,IAAIkJ,EAAmBv1C,KAAKi9B,cAActf,UAAUjG,QAAQ,qBAAsB,IAE9E1X,KAAK0+B,cACP1+B,KAAK0+B,cAAc/gB,UAAY,GAG/B3d,KAAK0+B,cAAgB1+B,KAAK69B,uBAE5B1/B,OAAOiC,KAAKqf,SAASzf,KAAK0+B,cAAe,gBAAkB6W,GAE3Dv1C,KAAK4+B,UAAUvf,YAAYrf,KAAK0+B,eAEhC1+B,KAAKw1C,iBAAiBx1C,KAAKi9B,cAAej9B,KAAK0+B,eAC/C1+B,KAAK89B,kBAAkB99B,KAAK0+B,eAC5B1+B,KAAKklC,WAAallC,KAAK0+B,cAAc9xB,WAAW,OAMlDw9B,mBAAoB,WAClBpqC,KAAK2+B,cAAgB3+B,KAAK69B,uBAC1B79B,KAAK2+B,cAAc9gB,aAAa,QAAS7d,KAAKsH,OAC9CtH,KAAK2+B,cAAc9gB,aAAa,SAAU7d,KAAK4H,QAC/C5H,KAAKmuC,aAAenuC,KAAK2+B,cAAc/xB,WAAW,OAMpDw/B,oBAAqB,WACnBpsC,KAAK4+B,UAAYzgC,OAAOiC,KAAKsf,YAAY1f,KAAKi9B,cAAe,MAAO,CAClEwY,MAASz1C,KAAKurC,iBAEhBptC,OAAOiC,KAAKsc,SAAS1c,KAAK4+B,UAAW,CACnCt3B,MAAOtH,KAAK+9B,WAAa,KACzBn2B,OAAQ5H,KAAKg+B,YAAc,KAC3B5F,SAAU,aAEZj6B,OAAOiC,KAAKse,wBAAwB1e,KAAK4+B,YAO3Cd,kBAAmB,SAAU/jB,GAC3B,IAAIzS,EAAQtH,KAAK+9B,YAAchkB,EAAQzS,MACnCM,EAAS5H,KAAKg+B,aAAejkB,EAAQnS,OAEzCzJ,OAAOiC,KAAKsc,SAAS3C,EAAS,CAC5Bqe,SAAU,WACV9wB,MAAOA,EAAQ,KACfM,OAAQA,EAAS,KACjBF,KAAM,EACNC,IAAK,EACL+tC,eAAgB,SAElB37B,EAAQzS,MAAQA,EAChByS,EAAQnS,OAASA,EACjBzJ,OAAOiC,KAAKse,wBAAwB3E,IAStCy7B,iBAAkB,SAAUG,EAAQC,GAClCA,EAAK35B,MAAMY,QAAU84B,EAAO15B,MAAMY,SAOpCg5B,oBAAqB,WACnB,OAAO71C,KAAKklC,YAOd4Q,oBAAqB,WACnB,OAAO91C,KAAK0+B,eAOdqX,iBAAkB,SAAS9zC,GACzB,IAAIuC,EAAMxE,KAAKg2C,cACXxxC,IACFA,EAAIf,IAAI,UAAU,GACdxB,IAAWuC,GAAOA,EAAIyxC,YAAwC,mBAAnBzxC,EAAIyxC,YACjDzxC,EAAIyxC,eAGRj2C,KAAKg2C,cAAgB/zC,GACdwB,IAAI,UAAU,IAUvByyC,gBAAiB,SAAUj0C,EAAQkY,GACjC,IAAIg8B,EAAsBn2C,KAAK2sC,kBAQ/B,OAPIwJ,GAAuBA,IAAwBl0C,GACjDk0C,EAAoBp1C,KAAK,aAAc,CAAEoZ,EAAGA,IAE9Cna,KAAK+1C,iBAAiB9zC,GACtBjC,KAAKe,KAAK,kBAAmB,CAAE6N,OAAQ3M,EAAQkY,EAAGA,IAClDlY,EAAOlB,KAAK,WAAY,CAAEoZ,EAAGA,IAC7Bna,KAAK+B,YACE/B,MAOT2sC,gBAAiB,WACf,OAAO3sC,KAAKg2C,eAOdvzC,iBAAkB,SAAS+B,GAErBxE,KAAK2sC,oBAAsBnoC,IAC7BxE,KAAKe,KAAK,2BAA4B,CAAE6N,OAAQpK,IAChDxE,KAAKo2C,uBACLp2C,KAAKe,KAAK,oBAAqB,CAAE6N,OAAQpK,IACzCA,EAAIzD,KAAK,eAEPf,KAAKy0C,iBAAmBjwC,IAC1BxE,KAAKy0C,eAAiB,MAExBz0C,KAAK8Y,UAAU,mBAAoBtU,IAMrC4xC,qBAAsB,WACpB,IAAI5xC,EAAMxE,KAAKg2C,cACXxxC,IACFA,EAAIf,IAAI,UAAU,GACde,EAAIyxC,YAAwC,mBAAnBzxC,EAAIyxC,YAC/BzxC,EAAIyxC,cAGRj2C,KAAKg2C,cAAgB,MAYvBK,oBAAqB,SAAUl8B,GAC7B,IAAIuyB,EAAe1sC,KAAKg2C,cAOxB,OANItJ,IACF1sC,KAAKe,KAAK,2BAA4B,CAAE6N,OAAQ89B,EAAcvyB,EAAGA,IACjEna,KAAKo2C,uBACLp2C,KAAKe,KAAK,oBAAqB,CAAEoZ,EAAGA,IACpCuyB,EAAa3rC,KAAK,aAAc,CAAEoZ,EAAGA,KAEhCna,MAOTs2C,gBAAiB,SAAS1d,IACxB54B,KAAKi/B,aAAerG,IAElBA,EAAMn1B,IAAI,UAAU,IAcxB8yC,eAAgB,SAAU3d,EAAOze,GAM/B,OALAna,KAAKs2C,gBAAgB1d,GACjBA,IACF54B,KAAKe,KAAK,kBAAmB,CAAE6N,OAAQgqB,EAAOze,EAAGA,IACjDye,EAAM73B,KAAK,WAAY,CAAEoZ,EAAGA,KAEvBna,MAOTysC,eAAgB,WACd,OAAOzsC,KAAKi/B,cAMduX,oBAAqB,WACnB,IAAIpiB,EAAIp0B,KAAKysC,iBACTrY,GACFA,EAAEqiB,UAEJz2C,KAAKu2C,eAAe,OAWtBG,mBAAoB,SAAUv8B,GAC5B,IAAIia,EAAIp0B,KAAKysC,iBAMb,OALIrY,IACFp0B,KAAKe,KAAK,2BAA4B,CAAEoZ,EAAGA,EAAGvL,OAAQwlB,IACtDp0B,KAAKw2C,sBACLx2C,KAAKe,KAAK,oBAAqB,CAAEoZ,EAAGA,KAE/Bna,MAQT22C,cAAe,WAKb,IAJA,IAGInyC,EAHAoyC,EAAa52C,KAAKqC,aAClBnB,EAAI,EACJC,EAAMy1C,EAAWn2C,OAEbS,EAAIC,EAAKD,KACfsD,EAAMoyC,EAAW11C,KACVsD,EAAIf,IAAI,UAAU,GAI3B,OAFAzD,KAAKw2C,sBACLx2C,KAAKo2C,uBACEp2C,MAWT62C,0BAA2B,SAAU18B,GAKnC,IAJA,IAGI3V,EAHAoyC,EAAa52C,KAAKqC,aAClBnB,EAAI,EACJC,EAAMy1C,EAAWn2C,OAEbS,EAAIC,EAAKD,KACfsD,EAAMoyC,EAAW11C,KACVsD,EAAIf,IAAI,UAAU,GAI3B,OAFAzD,KAAK02C,mBAAmBv8B,GACxBna,KAAKq2C,oBAAoBl8B,GAClBna,MAQTskC,QAAS,WACPnmC,OAAO88B,aAAa1vB,UAAU+4B,QAAQxjC,KAAKd,MAC3C,IAAI2f,EAAU3f,KAAK4+B,UASnB,OARA5+B,KAAK82C,kBACLn3B,EAAQo3B,YAAY/2C,KAAK0+B,eACzB/e,EAAQo3B,YAAY/2C,KAAKi9B,sBAClBj9B,KAAK0+B,cACR/e,EAAQzB,YACVyB,EAAQzB,WAAW0B,aAAa5f,KAAKi9B,cAAej9B,KAAK4+B,kBAEpD5+B,KAAK4+B,UACL5+B,MAQT8/B,MAAO,WAIL,OAHA9/B,KAAK02C,qBACL12C,KAAKq2C,sBACLr2C,KAAK4/B,aAAa5/B,KAAKklC,YAChBllC,KAAK8Y,UAAU,UAOxB6nB,aAAc,SAASj1B,GACrB,IAAIszB,EAAch/B,KAAKysC,iBAEnBzN,EACFA,EAAYuP,gBAAgB7iC,GAG5B1L,KAAKg3C,qBAAqBtrC,IAO9BsrC,qBAAsB,SAAStrC,GAC7B,IAAK,IAAIxK,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,IAAOD,EAChDlB,KAAK0B,SAASR,IAAOlB,KAAK0B,SAASR,GAAGotC,QAG3CtuC,KAAK0B,SAASR,GAAGqtC,gBAAgB7iC,IAOrC02B,UAAW,SAAS/I,EAAUtgB,EAAYuf,GAKxC,IAAI2e,EAAqBj3C,KAAKk3C,+BAA+B7d,GACzDp3B,EAASjC,KAAK8Y,UAAU,YAAaugB,EAAUtgB,EAAYuf,GAG/D,OADAt4B,KAAKm3C,8BAA8B9d,EAAU4d,GACtCh1C,GASTi1C,+BAAgC,SAAS7d,GACvC,GAAIA,EAAST,OAASS,EAAST,QAAU54B,KAAKysC,iBAAkB,CAE9D,IAAI2K,EAAiB,GAMrB,MALkB,CAAC,QAAS,QAAS,QAAS,OAAQ,SAAU,SAAU,QAAS,QAAS,OAChF/sC,QAAQ,SAAS3J,GAC3B02C,EAAe12C,GAAQ24B,EAAS34B,KAElCV,KAAKysC,iBAAiB4K,iBAAiBhe,GAChC+d,EAGP,OAAO,MAUXD,8BAA+B,SAAS9d,EAAU+d,GAC5CA,GACF/d,EAAS51B,IAAI2zC,IAOjB5T,cAAe,SAAShL,EAAQa,EAAUrvB,GACxC,IAAIitC,EAGJA,EAAqBj3C,KAAKk3C,+BAA+B7d,GACzDr5B,KAAK8Y,UAAU,gBAAiB0f,EAAQa,EAAUrvB,GAClDhK,KAAKm3C,8BAA8B9d,EAAU4d,MAMhC94C,OAAO88B,aACT,cAATv6B,IACFvC,OAAO+rC,OAAOxpC,GAAQvC,OAAO88B,aAAav6B,IAI1CvC,OAAOU,mBAETV,OAAO+rC,OAAO3+B,UAAU+rC,oBAAsB,cAUhDn5C,OAAOmZ,QAAUnZ,OAAO+rC,OAjrD1B,GAqrDA,WAEE,IAAIqN,EAAe,CACbpiC,GAAI,EACJorB,GAAI,EACJiX,GAAI,EACJlX,GAAI,EACJmX,GAAI,EACJjX,GAAI,EACJkX,GAAI,EACJrX,GAAI,GAENhmB,EAAclc,OAAOiC,KAAKia,YAC1BC,EAAiBnc,OAAOiC,KAAKka,eAGjC,SAASq9B,EAAWx9B,EAAG9Y,GACrB,MAAO,UAAW8Y,EAAIA,EAAEy9B,QAAUv2C,EAAQ8Y,EAAE09B,SAAWx2C,EAAQ,EAGjElD,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+rC,OAAO3+B,UAAiD,CAMvFusC,UAAW,CACT,WACA,YACA,WACA,YACA,WACA,YACA,WACA,aAOFxL,oBAAqB,WAInBtsC,KAAK82C,kBACL92C,KAAK+3C,cAEL19B,EAAYlc,OAAOI,OAAQ,SAAUyB,KAAKg4C,WAG1C39B,EAAYra,KAAK0+B,cAAe,YAAa1+B,KAAKi4C,cAClD59B,EAAYra,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cAClD79B,EAAYra,KAAK0+B,cAAe,WAAY1+B,KAAKm4C,aACjD99B,EAAYra,KAAK0+B,cAAe,aAAc1+B,KAAKo4C,eACnD/9B,EAAYra,KAAK0+B,cAAe,QAAS1+B,KAAKq4C,eAC9Ch+B,EAAYra,KAAK0+B,cAAe,cAAe1+B,KAAKs4C,gBAGpDj+B,EAAYra,KAAK0+B,cAAe,aAAc1+B,KAAKi4C,aAAc,CAAEM,SAAS,IAC5El+B,EAAYra,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,aAAc,CAAEK,SAAS,IAEpD,oBAAZC,SAA2B,QAASA,UAC7CA,QAAQ72C,IAAI3B,KAAK0+B,cAAe,UAAW1+B,KAAKy4C,YAChDD,QAAQ72C,IAAI3B,KAAK0+B,cAAe,OAAQ1+B,KAAK04C,SAC7CF,QAAQ72C,IAAI3B,KAAK0+B,cAAe,cAAe1+B,KAAK24C,sBACpDH,QAAQ72C,IAAI3B,KAAK0+B,cAAe,QAAS1+B,KAAK44C,UAC9CJ,QAAQ72C,IAAI3B,KAAK0+B,cAAe,YAAa1+B,KAAK64C,gBAOtDd,YAAa,WACP/3C,KAAK84C,eAIT94C,KAAKi4C,aAAej4C,KAAKi4C,aAAahgC,KAAKjY,MAC3CA,KAAKk4C,aAAel4C,KAAKk4C,aAAajgC,KAAKjY,MAC3CA,KAAK+4C,WAAa/4C,KAAK+4C,WAAW9gC,KAAKjY,MACvCA,KAAKg4C,UAAYh4C,KAAKg4C,UAAU//B,KAAKjY,MACrCA,KAAKy4C,WAAaz4C,KAAKy4C,WAAWxgC,KAAKjY,MACvCA,KAAK04C,QAAU14C,KAAK04C,QAAQzgC,KAAKjY,MACjCA,KAAK44C,SAAW54C,KAAK44C,SAAS3gC,KAAKjY,MACnCA,KAAK64C,aAAe74C,KAAK64C,aAAa5gC,KAAKjY,MAC3CA,KAAK24C,qBAAuB34C,KAAK24C,qBAAqB1gC,KAAKjY,MAC3DA,KAAKq4C,cAAgBr4C,KAAKq4C,cAAcpgC,KAAKjY,MAC7CA,KAAKm4C,YAAcn4C,KAAKm4C,YAAYlgC,KAAKjY,MACzCA,KAAKo4C,cAAgBp4C,KAAKo4C,cAAcngC,KAAKjY,MAC7CA,KAAKs4C,eAAiBt4C,KAAKs4C,eAAergC,KAAKjY,MAC/CA,KAAK84C,cAAe,IAMtBhC,gBAAiB,WACfx8B,EAAenc,OAAOI,OAAQ,SAAUyB,KAAKg4C,WAE7C19B,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKi4C,cACrD39B,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cACrD59B,EAAeta,KAAK0+B,cAAe,WAAY1+B,KAAKm4C,aACpD79B,EAAeta,KAAK0+B,cAAe,aAAc1+B,KAAKo4C,eACtD99B,EAAeta,KAAK0+B,cAAe,QAAS1+B,KAAKq4C,eACjD/9B,EAAeta,KAAK0+B,cAAe,cAAe1+B,KAAKs4C,gBAEvDh+B,EAAeta,KAAK0+B,cAAe,aAAc1+B,KAAKi4C,cACtD39B,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cAE9B,oBAAZM,SAA2B,WAAYA,UAChDA,QAAQj2C,OAAOvC,KAAK0+B,cAAe,UAAW1+B,KAAKy4C,YACnDD,QAAQj2C,OAAOvC,KAAK0+B,cAAe,OAAQ1+B,KAAK04C,SAChDF,QAAQj2C,OAAOvC,KAAK0+B,cAAe,cAAe1+B,KAAK24C,sBACvDH,QAAQj2C,OAAOvC,KAAK0+B,cAAe,QAAS1+B,KAAK44C,UACjDJ,QAAQj2C,OAAOvC,KAAK0+B,cAAe,YAAa1+B,KAAK64C,gBASzDJ,WAAY,SAASt+B,EAAG6+B,GACtBh5C,KAAKi5C,sBAAwBj5C,KAAKi5C,qBAAqB9+B,EAAG6+B,IAQ5DN,QAAS,SAASv+B,EAAG6+B,GACnBh5C,KAAKk5C,UAAYl5C,KAAKk5C,SAAS/+B,EAAG6+B,IAOpCX,cAAe,SAASl+B,GACtBna,KAAKm5C,eAAeh/B,IAOtBg+B,YAAa,SAASh+B,GACpB,IAAIvL,EAAS5O,KAAKy0C,eAClBz0C,KAAKe,KAAK,YAAa,CAAE6N,OAAQA,EAAQuL,EAAGA,IAC5Cna,KAAKy0C,eAAiB,KACtB7lC,GAAUA,EAAO7N,KAAK,WAAY,CAAEoZ,EAAGA,IACnCna,KAAKigC,iBACPjgC,KAAKigC,gBAAgB51B,QAAQ,SAAS7F,GAChCA,EAAIqwC,WACNrwC,EAAI40C,eAAeC,WAU3BjB,cAAe,SAASj+B,GACjBna,KAAK+zC,WAAW55B,KACnBna,KAAKe,KAAK,aAAc,CAAE6N,OAAQ,KAAMuL,EAAGA,IAC3Cna,KAAKy0C,eAAiB,OAS1BkE,qBAAsB,SAASx+B,EAAG6+B,GAChCh5C,KAAKs5C,uBAAyBt5C,KAAKs5C,sBAAsBn/B,EAAG6+B,IAQ9DJ,SAAU,SAASz+B,EAAG6+B,GACpBh5C,KAAKu5C,WAAav5C,KAAKu5C,UAAUp/B,EAAG6+B,IAQtCH,aAAc,SAAS1+B,EAAG6+B,GACxBh5C,KAAKw5C,eAAiBx5C,KAAKw5C,cAAcr/B,EAAG6+B,IAO9CV,eAAgB,SAAUn+B,GAKxB,OAJIna,KAAK+rC,kBACP5xB,EAAEs/B,kBACFt/B,EAAEu/B,mBAEG,GAOTzB,aAAc,SAAU99B,GACtBna,KAAK25C,cAAcx/B,GAEnBE,EAAYlc,OAAOG,SAAU,WAAY0B,KAAK+4C,WAAY,CAAER,SAAS,IACrEl+B,EAAYlc,OAAOG,SAAU,YAAa0B,KAAKk4C,aAAc,CAAEK,SAAS,IAExEj+B,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cACrD59B,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cAEtC,eAAX/9B,EAAEtX,KAEJyX,EAAeta,KAAK0+B,cAAe,YAAa1+B,KAAKi4C,eAGrD59B,EAAYlc,OAAOG,SAAU,UAAW0B,KAAK+4C,YAC7C1+B,EAAYlc,OAAOG,SAAU,YAAa0B,KAAKk4C,gBAQnDa,WAAY,SAAU5+B,GAYpB,GAXAna,KAAK45C,YAAYz/B,GAEjBG,EAAenc,OAAOG,SAAU,UAAW0B,KAAK+4C,YAChDz+B,EAAenc,OAAOG,SAAU,WAAY0B,KAAK+4C,YAEjDz+B,EAAenc,OAAOG,SAAU,YAAa0B,KAAKk4C,cAClD59B,EAAenc,OAAOG,SAAU,YAAa0B,KAAKk4C,cAElD79B,EAAYra,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,cAClD79B,EAAYra,KAAK0+B,cAAe,YAAa1+B,KAAKk4C,aAAc,CAAEK,SAAS,IAE5D,aAAXp+B,EAAEtX,KAAqB,CAGzB,IAAIsV,EAAQnY,KACZkiB,WAAW,WACT7H,EAAYlC,EAAMumB,cAAe,YAAavmB,EAAM8/B,eACnD,OAQPC,aAAc,SAAU/9B,IACrBna,KAAK27B,qBAAuBxhB,EAAEu/B,gBAAkBv/B,EAAEu/B,iBACnD15C,KAAK65C,cAAc1/B,IAMrB69B,UAAW,WACTh4C,KAAK88B,cASPgd,cAAe,SAASlrC,EAAQo3B,GAC9B,IAAI0G,EAAe1sC,KAAKysC,kBAAoBzsC,KAAK2sC,kBAEjD,QAAID,IAAgBA,EAAamI,WAAajmC,IAAW89B,OAMtD99B,IACCA,EAAOmrC,UACPnrC,IAAW89B,KAEX99B,GAAY89B,IAEZ99B,IAAW89B,IAAiB1sC,KAAKmsC,gBAElCnG,GACChmC,KAAKg6C,kBACLh6C,KAAK2qC,YACL3E,EAAQz/B,IAAMvG,KAAKg6C,iBAAiBzzC,GACpCy/B,EAAQx/B,IAAMxG,KAAKg6C,iBAAiBxzC,KAW1CozC,YAAa,SAAUz/B,GAErB,IAAIvL,EAGJ,GAAI+oC,EAAWx9B,EApTD,GAqTRna,KAAKgsC,gBACPhsC,KAAKi6C,aAAa9/B,EAAG,KAAMvL,EAtTjB,QA2Td,GAAI+oC,EAAWx9B,EA3TiB,GA4T1Bna,KAAKisC,iBACPjsC,KAAKi6C,aAAa9/B,EAAG,KAAMvL,EA7TC,QAkUhC,GAAI5O,KAAK2rC,eAAiB3rC,KAAKk6C,oBAC7Bl6C,KAAKm6C,wBAAwBhgC,OAD/B,CAKA,IAAIigC,GAAe,EAAMrzB,EAAY/mB,KAAKksC,kBACtCwH,EAAgB1zC,KAAKmsC,eACrBkO,GAAY3G,GAAyC,IAAvBA,EAAchsC,MAAoC,IAAtBgsC,EAAc/rC,IAExEof,IACF/mB,KAAKs6C,0BAA0BngC,GAC/BigC,GAAgBrzB,EAAUwzB,iBAG5B3rC,EAASwrC,EAAep6C,KAAK+zC,WAAW55B,GAAG,GAAQ4M,EAAUnY,OAE7D,IAAI4rC,EAAex6C,KAAK85C,cAAclrC,EAAQ5O,KAAK2b,WAAWxB,IAE1DvL,IAAWyrC,EACbr6C,KAAKy6C,mBAAmBtgC,IAKxBna,KAAKmsC,eAAiB,KACtBnsC,KAAKksC,kBAAoB,MAGvBt9B,IACFA,EAAOmrC,UAAW,GAEpB/5C,KAAKs3C,oBAAoBn9B,EAAGvL,GAC5B5O,KAAKi6C,aAAa9/B,EAAG,KAAMvL,GAAkB,KAlWG,EAkWeyrC,GAC/DzrC,IAAWA,EAAO8rC,SAAW,GAC7BF,GAAgBx6C,KAAK+B,cAYvBk4C,aAAc,SAAS9/B,EAAGwgC,EAAWC,EAAW/C,EAAQwC,GACtD,IAAIzrC,OAA8B,IAAdgsC,EAA4B56C,KAAK+zC,WAAW55B,GAAKygC,EACjEzG,EAAUn0C,KAAKm0C,SAAW,GAC1BnzC,EAAU,CACRmZ,EAAGA,EACHvL,OAAQA,EACRisC,WAAY1G,EACZ0D,OAAQA,GAvXkC,EAwX1CwC,QAASA,IAAW,GAE1Br6C,KAAKe,KAAK,SAAW45C,EAAW35C,GAChC4N,GAAUA,EAAO7N,KAAK,QAAU45C,EAAW35C,GAC3C,IAAK,IAAIE,EAAI,EAAGA,EAAIizC,EAAQ1zC,OAAQS,IAClCizC,EAAQjzC,GAAGH,KAAK,QAAU45C,EAAW35C,IAQzCs5C,0BAA2B,SAASngC,GAElC,IAAI4M,EAAY/mB,KAAKksC,kBACjBt9B,EAASmY,EAAUnY,OAEnBA,EAAOksC,WACTlsC,EAAOksC,UAAW,GAGpBlsC,EAAOswB,YACPl/B,KAAK+6C,iBAAiBnsC,IAElBmY,EAAUwzB,iBAAoBv6C,KAAKy7B,UAAY7sB,EAAOosC,qBACxDh7C,KAAKe,KAAK,kBAAmB,CAAE6N,OAAQA,EAAQuL,EAAGA,IAClDvL,EAAO7N,KAAK,WAAY,CAAEoZ,EAAGA,MAQjC4gC,iBAAkB,SAASnsC,GACzB,GAAI5O,KAAKi7C,kBAAoBj7C,KAAKk7C,iBAAkB,CAElD,IAAIC,EAAcvsC,EAAOqiC,uBACvBriC,EAAOwyB,iBACPphC,KAAKi7C,iBACLj7C,KAAKk7C,kBAEPtsC,EAAO24B,QAAUvnC,KAAKi7C,iBACtBrsC,EAAO44B,QAAUxnC,KAAKk7C,iBAEtBtsC,EAAOlH,KAAOyzC,EAAY50C,EAC1BqI,EAAOjH,IAAMwzC,EAAY30C,EAEzBxG,KAAKi7C,iBAAmB,KACxBj7C,KAAKk7C,iBAAmB,OAQ5BE,0BAA2B,SAASjhC,GAClCna,KAAKk6C,qBAAsB,EAC3Bl6C,KAAKq2C,oBAAoBl8B,GAAGpY,YACxB/B,KAAKmE,QACPhG,OAAOiC,KAAKmN,YAAYvN,KAAMA,KAAKklC,YAErC,IAAIc,EAAUhmC,KAAK2b,WAAWxB,GAC9Bna,KAAKusC,iBAAiBxG,YAAYC,GAClChmC,KAAKi6C,aAAa9/B,EAAG,SAOvBkhC,0BAA2B,SAASlhC,GAClC,GAAIna,KAAKk6C,oBAAqB,CAC5B,IAAIlU,EAAUhmC,KAAK2b,WAAWxB,GAC9Bna,KAAKusC,iBAAiBnG,YAAYJ,GAEpChmC,KAAKuzC,UAAUvzC,KAAKqrC,mBACpBrrC,KAAKi6C,aAAa9/B,EAAG,SAOvBggC,wBAAyB,SAAShgC,GAChCna,KAAKk6C,qBAAsB,EACvBl6C,KAAKmE,QACPnE,KAAKklC,WAAW14B,UAElBxM,KAAKusC,iBAAiBlG,YACtBrmC,KAAKi6C,aAAa9/B,EAAG,OAWvBw/B,cAAe,SAAUx/B,GAEvB,IAAIvL,EAAS5O,KAAK+zC,WAAW55B,GAG7B,GAAIw9B,EAAWx9B,EApeD,GAqeRna,KAAKgsC,gBACPhsC,KAAKi6C,aAAa9/B,EAAG,OAAQvL,GAAkB,KAterC,QA2ed,GAAI+oC,EAAWx9B,EA3eiB,GA4e1Bna,KAAKisC,iBACPjsC,KAAKi6C,aAAa9/B,EAAG,OAAQvL,GAAkB,KA7enB,QAkfhC,GAAI5O,KAAK2rC,cACP3rC,KAAKo7C,0BAA0BjhC,QAKjC,IAAIna,KAAKksC,kBAAT,CAKA,IAAIlG,EAAUhmC,KAAK2b,WAAWxB,GAAG,GACjCna,KAAKg6C,iBAAmBhU,EAExB,IAAIwU,EAAex6C,KAAK85C,cAAclrC,EAAQo3B,GAC1CsV,EAAct7C,KAAKu7C,aAAaphC,EAAGvL,GAmBvC,GAjBI5O,KAAKwuC,sBAAsBr0B,EAAGvL,GAChC5O,KAAK62C,0BAA0B18B,GAExBmhC,IACPt7C,KAAKw7C,gBAAgBrhC,EAAGvL,GACxBA,EAAS5O,KAAKysC,mBAGZzsC,KAAK2qC,WAAe/7B,IAAYA,EAAO8/B,YAAe9/B,EAAOimC,aAC/D70C,KAAKmsC,eAAiB,CACpB8C,GAAIjJ,EAAQz/B,EACZ2oC,GAAIlJ,EAAQx/B,EACZmB,IAAK,EACLD,KAAM,IAINkH,EAAQ,EACNA,EAAO8/B,aAAe9/B,EAAO8rC,UAAaY,IAC5Ct7C,KAAKy7C,iBAAiBthC,EAAGvL,GACzB5O,KAAKgvC,uBAAuB70B,EAAGvL,IAEjC,IAAI89B,EAAe1sC,KAAK2sC,kBACpB/9B,IAAW5O,KAAKysC,kBAAoB79B,IAAW89B,IACjD1sC,KAAK22C,gBACD/nC,EAAO8/B,aACThC,GAAgBA,EAAa3rC,KAAK,aAAc,CAAEoZ,EAAGA,IACrDna,KAAKk2C,gBAAgBtnC,EAAQuL,KAInCna,KAAKi6C,aAAa9/B,EAAG,OAAQvL,GAAkB,MAE/C4rC,GAAgBx6C,KAAK+B,cAMvB05C,iBAAkB,SAASthC,EAAGvL,GAC5B5O,KAAKy7B,UAAY7sB,EAAO8sC,YAGpB9sC,EAAO++B,kBAAkB3tC,KAAK2b,WAAWxB,KAC3Cna,KAAKg8B,oBAAoBptB,IAS7By+B,mBAAoB,SAASz+B,GAC3B5O,KAAKi7C,iBAAmBj7C,KAAKksC,kBAAkBt9B,OAAO24B,QACtDvnC,KAAKk7C,iBAAmBl7C,KAAKksC,kBAAkBt9B,OAAO44B,QAEtD,IAAIjG,EAAS3yB,EAAOwyB,iBAEpBxyB,EAAO24B,QAAU,SACjB34B,EAAO44B,QAAU,SAEjB54B,EAAOlH,KAAO65B,EAAOh7B,EACrBqI,EAAOjH,IAAM45B,EAAO/6B,EAEpBxG,KAAKksC,kBAAkBxkC,KAAOkH,EAAOlH,KACrC1H,KAAKksC,kBAAkBvkC,IAAMiH,EAAOjH,KAOtCg0C,mBAAoB,SAAS/sC,GAC3B,IAAIusC,EAAcvsC,EAAOqiC,uBACvBriC,EAAOwyB,iBACPphC,KAAKi7C,iBACLj7C,KAAKk7C,kBAEPtsC,EAAO24B,QAAUvnC,KAAKi7C,iBACtBrsC,EAAO44B,QAAUxnC,KAAKk7C,iBAEtBtsC,EAAOlH,KAAOyzC,EAAY50C,EAC1BqI,EAAOjH,IAAMwzC,EAAY30C,EAEzBxG,KAAKi7C,iBAAmB,KACxBj7C,KAAKk7C,iBAAmB,MAY1BrB,cAAe,SAAU1/B,GAEvB,IAAIvL,EAAQo3B,EAEZ,GAAIhmC,KAAK2rC,cACP3rC,KAAKq7C,0BAA0BlhC,QAGjC,UAAyB,IAAdA,EAAEyhC,SAA8C,EAAnBzhC,EAAEyhC,QAAQn7C,QAAlD,CAIA,IAAIizC,EAAgB1zC,KAAKmsC,eAGrBuH,GACF1N,EAAUhmC,KAAK2b,WAAWxB,GAAG,GAE7Bu5B,EAAchsC,KAAOs+B,EAAQz/B,EAAImtC,EAAczE,GAC/CyE,EAAc/rC,IAAMq+B,EAAQx/B,EAAIktC,EAAcxE,GAE9ClvC,KAAK+sC,aAEG/sC,KAAKksC,kBAKblsC,KAAK67C,iBAAiB1hC,IAJtBvL,EAAS5O,KAAK+zC,WAAW55B,GACzBna,KAAKs3C,oBAAoBn9B,EAAGvL,IAK9B5O,KAAKi6C,aAAa9/B,EAAG,OAAQvL,GAAkB,QAOjDuqC,eAAgB,SAASh/B,GACvBna,KAAKi6C,aAAa9/B,EAAG,UAOvB0hC,iBAAkB,SAAS1hC,GACzB,IAAI6rB,EAAUhmC,KAAK2b,WAAWxB,GAC1B4M,EAAY/mB,KAAKksC,kBAErBnlB,EAAU+0B,OAAQ,EAClB/0B,EAAUnY,OAAOmrC,UAAW,EAC5BhzB,EAAUuoB,SAAWn1B,EAAEm1B,SACvBvoB,EAAU6nB,OAASz0B,EAAEna,KAAKyqC,aAE1BzqC,KAAK+7C,sBAAsB5hC,EAAG4M,GAC9B/mB,KAAKg8C,wBAAwB7hC,EAAG4M,EAAWif,GAE3Cjf,EAAUwzB,iBAAmBv6C,KAAK+B,aAMpCi6C,wBAAyB,SAAS7hC,EAAG4M,EAAWif,GAC9C,IAAIz/B,EAAIy/B,EAAQz/B,EACZC,EAAIw/B,EAAQx/B,EACZoI,EAASmY,EAAUnY,OACnBw+B,EAASrmB,EAAUqmB,OACnBmN,GAAkB,EAEP,WAAXnN,GACDmN,EAAkBv6C,KAAKizC,cAAc1sC,EAAGC,KAAOxG,KAAKi8C,MAAM,WAAYrtC,EAAQuL,GAE7D,UAAXizB,GACNmN,EAAkBv6C,KAAKk8C,SAAS/hC,EAAG4M,EAAWxgB,EAAGC,KAAOxG,KAAKi8C,MAAM,UAAWrtC,EAAQuL,GAErE,WAAXizB,GACNmN,EAAkBv6C,KAAK6xC,aAAatrC,EAAGC,EAAG,OAASxG,KAAKi8C,MAAM,UAAWrtC,EAAQuL,GAEhE,WAAXizB,GACNmN,EAAkBv6C,KAAK6xC,aAAatrC,EAAGC,EAAG,OAASxG,KAAKi8C,MAAM,UAAWrtC,EAAQuL,GAEhE,UAAXizB,GACNmN,EAAkBv6C,KAAKswC,YAAY/pC,EAAGC,EAAG,OAASxG,KAAKi8C,MAAM,UAAWrtC,EAAQuL,GAE/D,UAAXizB,GACNmN,EAAkBv6C,KAAKswC,YAAY/pC,EAAGC,EAAG,OAASxG,KAAKi8C,MAAM,UAAWrtC,EAAQuL,IAGjFogC,EAAkBv6C,KAAKuvC,iBAAiBhpC,EAAGC,MAEzCxG,KAAKi8C,MAAM,SAAUrtC,EAAQuL,GAC7Bna,KAAKuzC,UAAU3kC,EAAOu8B,YAAcnrC,KAAKmrC,aAG7CpkB,EAAUwzB,gBAAkBxzB,EAAUwzB,iBAAmBA,GAM3D0B,MAAO,SAASn8C,EAAW8O,EAAQuL,GACjCna,KAAKe,KAAK,UAAYjB,EAAW,CAAE8O,OAAQA,EAAQuL,EAAGA,IACtDvL,EAAO7N,KAAKjB,EAAW,CAAEqa,EAAGA,KAM9B4hC,sBAAuB,SAAS5hC,EAAG4M,GACjC,GAAyB,UAArBA,EAAUqmB,QAA2C,WAArBrmB,EAAUqmB,QAA4C,WAArBrmB,EAAUqmB,OAAqB,CAClG,IAAIuB,EAAkB3uC,KAAKmtC,uBAAuBpmB,EAAUnY,SAGvD+/B,IAA0C,WAAtB5nB,EAAUwgB,SAA8C,WAAtBxgB,EAAUygB,WAEhEmH,GAAyC,WAAtB5nB,EAAUwgB,SAA8C,WAAtBxgB,EAAUygB,WAElExnC,KAAKitC,yBACLlmB,EAAU+0B,OAAQ,KAaxBI,SAAU,SAAS/hC,EAAG4M,EAAWxgB,EAAGC,GAClC,OAAK2T,EAAEna,KAAKsqC,eAAgBtqC,KAAKqqC,mBAAuBtjB,EAAUnY,OAAOjK,IAAI,mBAMtEoiB,EAAU+0B,OAAqC,UAA5B/0B,EAAUo1B,eAChCn8C,KAAKitC,yBAGPlmB,EAAUo1B,cAAgB,eACnBn8C,KAAK6xC,aAAatrC,EAAGC,EAAG,aAV/BugB,EAAUo1B,cAAgB,QACnBn8C,KAAK6xC,aAAatrC,EAAGC,KAmBhC8wC,oBAAqB,SAAUn9B,EAAGvL,GAChC,IAAKA,EAEH,OADA5O,KAAKuzC,UAAUvzC,KAAKorC,gBACb,EAGT,IAAIF,EAAct8B,EAAOs8B,aAAelrC,KAAKkrC,YACzClM,EAAch/B,KAAKysC,iBAEnBqC,EAASlgC,EAAO++B,qBACD3O,IAAgBA,EAAY97B,SAAS0L,KACvCA,EAAO++B,kBAAkB3tC,KAAK2b,WAAWxB,GAAG,IAU7D,OARK20B,EAIH9uC,KAAKo8C,iBAAiBtN,EAAQlgC,EAAQuL,GAHtCna,KAAKuzC,UAAUrI,IAOV,GAMTkR,iBAAkB,SAAStN,EAAQlgC,EAAQuL,GACzC,GAAI20B,KAAUyI,EACZv3C,KAAKuzC,UAAUvzC,KAAKq8C,wBAAwBvN,EAAQlgC,EAAQuL,QAEzD,CAAA,GAAe,QAAX20B,IAAoBlgC,EAAO0tC,iBAKlC,OADAt8C,KAAKuzC,UAAUvzC,KAAKorC,gBACb,EAJPprC,KAAKuzC,UAAUvzC,KAAKsrC,kBAWxB+Q,wBAAyB,SAASvN,EAAQlgC,EAAQuL,GAChD,IAAI7D,EAAIvR,KAAKuvB,MAAO1lB,EAAO2tC,WAAa,IAAO,IAa/C,OAXIjmC,EAAI,IACNA,GAAK,GAEPA,GAAKihC,EAAazI,GACd30B,EAAEna,KAAK0qC,eAAiB6M,EAAazI,GAAU,GAAM,IAEvDx4B,GAAK,GAGPA,GAAK,EAEEtW,KAAK83C,UAAUxhC,MAt0B5B,GA40BA,WAEE,IAAI9Q,EAAMT,KAAKS,IACXC,EAAMV,KAAKU,IAEftH,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+rC,OAAO3+B,UAAiD,CAQvFgwC,aAAc,SAASphC,EAAGvL,GACxB,IAAI89B,EAAe1sC,KAAK2sC,kBACxB,OAAOxyB,EAAEna,KAAK4qC,eAAiBh8B,GAAUA,EAAO8/B,aACzC1uC,KAAKysC,kBAAqBC,GAAgBA,IAAiB99B,IACzD5O,KAAK2qC,WAQhB6Q,gBAAiB,SAAUrhC,EAAGvL,GAC5B,IAAIowB,EAAch/B,KAAKysC,kBAEnB79B,IAAWowB,IAEbpwB,EAAS5O,KAAK+zC,WAAW55B,GAAG,OAM1B6kB,EACFh/B,KAAKw8C,mBAAmB5tC,EAAQuL,GAGhCna,KAAKy8C,mBAAmB7tC,EAAQuL,GAG9Bna,KAAKi/B,cACPj/B,KAAKi/B,aAAayd,eAOtBF,mBAAoB,SAAS5tC,EAAQuL,GACnC,IAAI6kB,EAAch/B,KAAKysC,iBAEvB,GAAIzN,EAAY97B,SAAS0L,IAKvB,GAHAowB,EAAY2d,iBAAiB/tC,GAC7BA,EAAOnL,IAAI,UAAU,GAEM,IAAvBu7B,EAAY/7B,OAKd,OAHAjD,KAAK02C,mBAAmBv8B,QAExBna,KAAKk2C,gBAAgBlX,EAAYj8B,KAAK,GAAIoX,QAK5C6kB,EAAY4d,cAAchuC,GAE5B5O,KAAKe,KAAK,oBAAqB,CAAE6N,OAAQowB,EAAa7kB,EAAGA,IACzD6kB,EAAYv7B,IAAI,UAAU,IAM5Bg5C,mBAAoB,SAAS7tC,EAAQuL,GAEnC,GAAIna,KAAKg2C,eAAiBpnC,IAAW5O,KAAKg2C,cAAe,CAEvD,IAAIpd,EAAQ54B,KAAK68C,aAAajuC,GAC9BgqB,EAAMgkB,gBAEN58C,KAAKu2C,eAAe3d,EAAOze,GAC3Bna,KAAKg2C,cAAgB,KAErBh2C,KAAKe,KAAK,oBAAqB,CAAE6N,OAAQgqB,EAAOze,EAAGA,IAGrDvL,EAAOnL,IAAI,UAAU,IAOvBo5C,aAAc,SAASjuC,GAErB,IAAIxM,EAAUpC,KAAKqC,aAEfy6C,EADgB16C,EAAQjC,QAAQH,KAAKg2C,eAAiB5zC,EAAQjC,QAAQyO,GAElE,CAAC5O,KAAKg2C,cAAepnC,GACrB,CAACA,EAAQ5O,KAAKg2C,eAEtB,OADAh2C,KAAKg2C,cAAcnB,WAAa70C,KAAKg2C,cAAc+G,cAC5C,IAAI5+C,OAAOiqC,MAAM0U,EAAc,CACpCnd,OAAQ3/B,QAQZg9C,sBAAuB,SAAU7iC,GAE/B,IAAIye,EAAQ54B,KAAKi9C,kBAGI,IAAjBrkB,EAAMn4B,OACRT,KAAKk2C,gBAAgBtd,EAAM,GAAIze,GAET,EAAfye,EAAMn4B,UACbm4B,EAAQ,IAAIz6B,OAAOiqC,MAAMxP,EAAMC,UAAW,CACxC8G,OAAQ3/B,QAEJ48C,gBACN58C,KAAKu2C,eAAe3d,EAAOze,GAC3Bye,EAAM8jB,aACN18C,KAAKe,KAAK,oBAAqB,CAAE6N,OAAQgqB,EAAOze,EAAGA,IACnDna,KAAK+B,cAOTk7C,gBAAiB,WAWf,IAVA,IACIC,EADAtkB,EAAQ,GAERpkB,EAAKxU,KAAKmsC,eAAe8C,GACzBx6B,EAAKzU,KAAKmsC,eAAe+C,GACzBvjC,EAAK6I,EAAKxU,KAAKmsC,eAAezkC,KAC9BkE,EAAK6I,EAAKzU,KAAKmsC,eAAexkC,IAC9Bw1C,EAAgB,IAAIh/C,OAAOmI,MAAMd,EAAIgP,EAAI7I,GAAKnG,EAAIiP,EAAI7I,IACtDwxC,EAAgB,IAAIj/C,OAAOmI,MAAMb,EAAI+O,EAAI7I,GAAKlG,EAAIgP,EAAI7I,IACtDyuC,EAAU7lC,IAAO7I,GAAM8I,IAAO7I,EAEzB1K,EAAIlB,KAAK0B,SAASjB,OAAQS,QACjCg8C,EAAgBl9C,KAAK0B,SAASR,KAEPg8C,EAAcxO,YAAewO,EAAcvvB,UAI9DuvB,EAAcG,mBAAmBF,EAAeC,IAChDF,EAAcI,sBAAsBH,EAAeC,IACnDF,EAAc1P,cAAc2P,IAC5BD,EAAc1P,cAAc4P,MAE9BF,EAAcz5C,IAAI,UAAU,GAC5Bm1B,EAAMh4B,KAAKs8C,GAGP7C,MAMR,OAAOzhB,GAMT6hB,mBAAoB,SAAStgC,GACvBna,KAAK2qC,WAAa3qC,KAAKmsC,gBACzBnsC,KAAKg9C,sBAAsB7iC,GAG7B,IAAI6kB,EAAch/B,KAAKysC,iBACnBzN,IACFA,EAAYue,mBAAmBre,YAC/BF,EAAY+a,UAAW,EACvB/5C,KAAKuzC,UAAUvzC,KAAKorC,gBAItBprC,KAAKmsC,eAAiB,KACtBnsC,KAAKksC,kBAAoB,QA9L/B,GAqMA,WAEE,IAAIsR,EAAiBr/C,OAAO88B,aAAawJ,SAAS,wBAElDtmC,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO88B,aAAa1vB,UAAuD,CAiCnGouB,UAAW,SAAU34B,GACnBA,IAAYA,EAAU,IAEtB,IAAIy8C,EAASz8C,EAAQy8C,QAAU,MAC3BC,EAAU18C,EAAQ08C,SAAW,EAC7BC,EAAa38C,EAAQ28C,YAAc,EACnCC,EAAW,CACTl2C,KAAM1G,EAAQ0G,MAAQ,EACtBC,IAAK3G,EAAQ2G,KAAO,EACpBL,MAAOtG,EAAQsG,OAAS,EACxBM,OAAQ5G,EAAQ4G,QAAU,GAEhC,OAAO5H,KAAK69C,0BAA0BJ,EAAQC,EAASE,EAAUD,IAMnEE,0BAA2B,SAASJ,EAAQC,EAASE,EAAUD,GAE7D,IAAIG,EAAY99C,KAAK+9B,WACjBggB,EAAa/9C,KAAKg+B,YAClBggB,GAAeJ,EAASt2C,OAAStH,KAAK+9B,YAAc4f,EACpDM,GAAgBL,EAASh2C,QAAU5H,KAAKg+B,aAAe2f,EAEvDO,EADOl+C,KAAK6+B,UACK8e,EACjBQ,EAAKn+C,KAAK67B,kBAGVuiB,EAAQ,CAACF,EAAS,EAAG,EAAGA,GAFVC,EAAG,GAAKP,EAASl2C,MAAQi2C,GACzBQ,EAAG,GAAKP,EAASj2C,KAAOg2C,GAEtCU,EAAsBr+C,KAAKw8B,YAE/Bx8B,KAAK67B,kBAAoBuiB,EAEzBp+C,KAAKw8B,cAAgBx8B,KAAKw8B,aAAc,GACpCshB,IAAcE,GAAeD,IAAeE,EAE9Cj+C,KAAKk+B,cAAc,CAAE52B,MAAO02C,EAAap2C,OAAQq2C,GAAgB,CAAEzf,eAAe,IAGlFx+B,KAAK+B,YAEP,IAAI0N,EAAOzP,KAAKs+C,YAAYb,EAAQC,EAASE,GAM7C,OALAS,IAAwBr+C,KAAKw8B,YAAc6hB,GAC3Cr+C,KAAK67B,kBAAoBsiB,EAGzBn+C,KAAKk+B,cAAc,CAAE52B,MAAOw2C,EAAWl2C,OAAQm2C,GAAc,CAAEvf,eAAe,IACvE/uB,GAMT6uC,YAAa,SAASb,EAAQC,GAE5B,IAAIhxC,EAAW1M,KAAKk9B,iBAAiByC,OAUrC,MARe,QAAX8d,IACFA,EAAS,QAGAD,EACC9wC,EAASitB,UAAU,SAAW8jB,EAAQC,GACtChxC,EAASitB,UAAU,SAAW8jB,IAa5Cc,wBAAyB,SAAUd,EAAQE,EAAYD,GACrD,OAAO19C,KAAK25B,UAAU,CACpB8jB,OAAQA,EACRE,WAAYA,EACZD,QAASA,OAtHjB,GA8HAv/C,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO88B,aAAa1vB,UAAuD,CAenGizC,qBAAsB,SAAUC,EAAM97C,EAAUqH,GAC9C,OAAOhK,KAAK0+C,aAAaD,EAAM97C,EAAUqH,IAwB3C00C,aAAc,SAAUD,EAAM97C,EAAUqH,GACtC,GAAKy0C,EAAL,CAKA,IAAIE,EAA8B,iBAATF,EACrBG,KAAKzwB,MAAMswB,GACXtgD,OAAOiC,KAAK6B,OAAOuV,MAAMinC,GAEzBtmC,EAAQnY,KACR8B,EAAoB9B,KAAK8B,kBA2B7B,OA1BA9B,KAAK8B,mBAAoB,EAEzB9B,KAAK6+C,gBAAgBF,EAAWv8C,QAAS,SAAUgI,GACjD+N,EAAM2nB,QACN3nB,EAAM2mC,cAAcH,EAAY,WAC9Bv0C,EAAiBC,QAAQ,SAAS7F,EAAKtC,GAGrCiW,EAAMnW,SAASwC,EAAKtC,KAEtBiW,EAAMrW,kBAAoBA,SAEnB68C,EAAWv8C,eACXu8C,EAAWrjB,uBACXqjB,EAAWnjB,oBACXmjB,EAAWnc,kBACXmc,EAAWpc,QAKlBpqB,EAAM3U,YAAYm7C,GAClBxmC,EAAMpW,YACNY,GAAYA,OAEbqH,GACIhK,OAQT8+C,cAAe,SAASH,EAAYh8C,GAClC,IAAIo8C,EAAS,CACX1jB,iBAAiB,EACjBE,cAAc,EACdD,iBAAiB,EACjBE,cAAc,GAGhB,GAAKmjB,EAAWrjB,iBAAoBqjB,EAAWnjB,cAAiBmjB,EAAWnc,YAAemc,EAAWpc,QAArG,CAKA,IAAIyc,EAAa,WACXD,EAAOzjB,iBAAmByjB,EAAOvjB,cAAgBujB,EAAO1jB,iBAAmB0jB,EAAOxjB,cACpF54B,GAAYA,KAIhB3C,KAAKi/C,eAAe,kBAAmBN,EAAWrjB,gBAAiByjB,EAAQC,GAC3Eh/C,KAAKi/C,eAAe,eAAgBN,EAAWnjB,aAAcujB,EAAQC,GACrEh/C,KAAKi/C,eAAe,kBAAmBN,EAAWnc,WAAYuc,EAAQC,GACtEh/C,KAAKi/C,eAAe,eAAgBN,EAAWpc,QAASwc,EAAQC,QAb9Dr8C,GAAYA,KAuBhBs8C,eAAgB,SAASr7C,EAAUvC,EAAO09C,EAAQp8C,GAChD,IAAIwV,EAAQnY,KAEZ,IAAKqB,EAGH,OAFA09C,EAAOn7C,IAAY,OACnBjB,GAAYA,KAIG,oBAAbiB,GAA+C,iBAAbA,EACpCzF,OAAOiC,KAAK2J,eAAe,CAAC1I,GAAQ,SAAS69C,GAC3C/mC,EAAMvU,GAAYs7C,EAAc,GAChCH,EAAOn7C,IAAY,EACnBjB,GAAYA,MAId3C,KAAK,MAAQ7B,OAAOiC,KAAK0I,OAAO8O,WAAWhU,GAAU,IAAOvC,EAAO,WACjE09C,EAAOn7C,IAAY,EACnBjB,GAAYA,OAWlBk8C,gBAAiB,SAAUz8C,EAASO,EAAUqH,GACvC5H,GAA8B,IAAnBA,EAAQ3B,OAKxBtC,OAAOiC,KAAK2J,eAAe3H,EAAS,SAASgI,GAC3CzH,GAAYA,EAASyH,IACpB,KAAMJ,GANPrH,GAAYA,EAAS,KAczBw8C,WAAY,SAAU1B,EAAQ96C,GAC5B3C,KAAKwX,MAAM,SAAUA,GACnB7U,EAAS6U,EAAMmiB,UAAU8jB,OAU7B2B,yBAA0B,SAAU3B,EAAQE,EAAYh7C,GACtD3C,KAAKwX,MAAM,SAAUA,GACnB7U,EAAS6U,EAAM+mC,wBAAwBd,EAAQE,OASnDnmC,MAAO,SAAU7U,EAAU0I,GACzB,IAAIoE,EAAOmvC,KAAKS,UAAUr/C,KAAK2kC,OAAOt5B,IACtCrL,KAAKs/C,iBAAiB,SAAS9nC,GAC7BA,EAAMknC,aAAajvC,EAAM,WACvB9M,GAAYA,EAAS6U,QAW3B8nC,iBAAkB,SAAS38C,GACzB,IAAI+a,EAAKvf,OAAOG,SAASqO,cAAc,UAEvC+Q,EAAGpW,MAAQtH,KAAK+9B,WAChBrgB,EAAG9V,OAAS5H,KAAKg+B,YAEjB,IAAIxmB,EAAQ,IAAIrZ,OAAO+rC,OAAOxsB,GAC9BlG,EAAMrT,OAASnE,KAAKmE,OAChBnE,KAAKs7B,iBACP9jB,EAAMmlB,mBAAmB38B,KAAKs7B,gBAAgBxxB,IAAK,WACjD0N,EAAMzV,YACNY,GAAYA,EAAS6U,KAEvBA,EAAM+nC,uBAAyBv/C,KAAKu/C,uBACpC/nC,EAAMgoC,uBAAyBx/C,KAAKw/C,wBAGpC78C,GAAYA,EAAS6U,MAM3B,SAAU3S,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5BI,EAAQrZ,EAAOiC,KAAK6B,OAAOuV,MAC3BxP,EAAU7J,EAAOiC,KAAK4H,QACtB4P,EAAazZ,EAAOiC,KAAK0I,OAAO8O,WAChChS,EAAmBzH,EAAOiC,KAAKwF,iBAC/B65C,EAAmBthD,EAAO88B,aAAawJ,SAAS,eAChDib,GAAiBvhD,EAAOW,aAGxBX,EAAOmN,SA2BXnN,EAAOmN,OAASnN,EAAOiC,KAAK+Y,YAAYhb,EAAOoF,cAAqD,CAuQlGV,KAA0B,SAQ1B0kC,QAA0B,OAQ1BC,QAA0B,MAO1B7/B,IAA0B,EAO1BD,KAA0B,EAO1BJ,MAA0B,EAO1BM,OAA0B,EAO1BqG,OAA0B,EAO1BC,OAA0B,EAO1BW,OAA0B,EAO1BC,OAA0B,EAO1BoN,QAA0B,EAO1BnO,MAA0B,EAO1BI,MAA0B,EAO1BC,MAA0B,EAO1BuxC,WAA0B,GAO1BzR,oBAA0B,EAO1BhD,YAA0B,KAO1BC,WAA0B,KAO1B6H,QAA0B,EAO1B4M,YAA0B,yBAO1BC,gBAA0B,KAO1BC,YAA0B,wBAQ1BC,kBAA0B,KAO1BC,YAAsB,OAOtBC,gBAA0B,KAU1B1V,iBAA0B,EAU1BC,kBAA0B,EAO1BlqC,KAA0B,aAS1B4/C,SAA0B,UAO1BC,yBAA0B,cAO1B9kB,gBAA0B,GAQ1BgT,yBAAmC,GAOnCtmB,OAA0B,KAO1Buf,YAA0B,EAM1BvC,gBAA0B,KAO1BF,cAA0B,OAO1BC,eAA0B,QAO1Bsb,iBAA0B,GAO1BzlB,OAA0B,KAO1B0lB,wBAA0B,GAO1BC,kBAA0B,EAM1B5yB,gBAA0B,KAO1B6yB,cAA0B,IAQ1B7R,YAA0B,EAO1BD,SAA0B,EAO1B9gB,SAA0B,EAO1B6yB,aAA0B,EAO1BvS,YAA0B,EAO1BqO,kBAA0B,EAO1BmE,oBAA0B,GAO1BjV,oBAA0B,EAO1B/Q,sBAA0B,EAO1Bt2B,OAA0B,KAO1Bu8C,eAA0B,EAO1BC,eAA0B,EAO1BC,cAA0B,EAO1B9O,cAA0B,EAO1BC,cAA0B,EAO1B8O,gBAA0B,EAO1BrQ,cAA0B,EAO1BC,cAA0B,EAO1BuB,iBAA0B,EAQ1B7P,mBAA0B,EAS1Bud,cAA0BA,EAY1BoB,gBAA2B,EAW3BC,cAA2B,EAQ3BC,OAAsB,EAQtB1zC,gBAAiB,0QAKfjE,MAAM,KAMR43C,gBAAiB,qHAGf53C,MAAM,KAMR+P,WAAY,SAASpY,IACnBA,EAAUA,GAAW,KAEnBhB,KAAKy5B,WAAWz4B,IAQpBopC,mBAAoB,WAClBpqC,KAAKkhD,iBAAmB,GACxBlhD,KAAKmhD,aAAehjD,EAAOG,SAASqO,cAAc,UAClD3M,KAAKohD,cAAgBphD,KAAKmhD,aAAav0C,WAAW,MAClD5M,KAAKqhD,sBAkBPC,gBAAiB,SAASC,GACxB,IAAIjiD,EAAqBnB,EAAOmB,mBAC5BgI,EAAQi6C,EAAKj6C,MAAOM,EAAS25C,EAAK35C,OAClCnC,EAAMtH,EAAOoB,kBAAmBiG,EAAMrH,EAAOqB,kBACjD,GAAI8H,GAAS7B,GAAOmC,GAAUnC,GAAO6B,EAAQM,GAAUtI,EAOrD,OANIgI,EAAQ9B,IACV+7C,EAAKj6C,MAAQ9B,GAEXoC,EAASpC,IACX+7C,EAAK35C,OAASpC,GAET+7C,EAET,IAAIlxC,EAAK/I,EAAQM,EAAQ45C,EAAcrjD,EAAOiC,KAAKgQ,gBAAgBC,EAAI/Q,GACnEmR,EAAWtS,EAAOiC,KAAKqQ,SACvBlK,EAAIkK,EAASjL,EAAKg8C,EAAYj7C,EAAGd,GACjCe,EAAIiK,EAASjL,EAAKg8C,EAAYh7C,EAAGf,GAWrC,OAVYc,EAARe,IACFi6C,EAAKE,OAASn6C,EAAQf,EACtBg7C,EAAKj6C,MAAQf,EACbg7C,EAAKG,QAAS,GAEHl7C,EAAToB,IACF25C,EAAKI,OAAS/5C,EAASpB,EACvB+6C,EAAK35C,OAASpB,EACd+6C,EAAKG,QAAS,GAETH,GAcTK,0BAA2B,WACzB,IAAInlC,EAAOzc,KAAK2/B,QAAU3/B,KAAK2/B,OAAOd,WAAa,EAC/CgjB,EAAc7hD,KAAK8hD,mBACnBC,EAAS/hD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO5C,mBAAqB5+B,EAAOuB,iBAAmB,EACnFqxC,EAAM/wC,KAAKgiD,+BACXP,EAAQI,EAAY5zC,OAASwO,EAAOslC,EACpCJ,EAAQE,EAAY3zC,OAASuO,EAAOslC,EAGxC,MAAO,CACLz6C,MAHUypC,EAAIxqC,EAAIk7C,EA93BH,EAk4Bf75C,OAHWmpC,EAAIvqC,EAAIm7C,EA/3BJ,EAm4BfF,MAAOA,EACPE,MAAOA,EACPp7C,EAAGwqC,EAAIxqC,EACPC,EAAGuqC,EAAIvqC,IAUX66C,mBAAoB,WAClB,GAAIrhD,KAAK+gD,cAAgB/gD,KAAK2/B,QAAU3/B,KAAK2/B,OAAOuM,kBAAmB,CACrE,IAAIt9B,EAAS5O,KAAK2/B,OAAOuM,kBAAkBt9B,OACvCw+B,EAASptC,KAAK2/B,OAAOuM,kBAAkBkB,OAC3C,GAAIptC,OAAS4O,GAAUw+B,EAAOlkC,OAAgC,UAAvBkkC,EAAOlkC,MAAM,EAAG,GACrD,OAAO,EAGX,IAG8C+4C,EAAcC,EAHxDviB,EAAS3/B,KAAKmhD,aACdI,EAAOvhD,KAAKshD,gBAAgBthD,KAAK4hD,6BACjCO,EAAehkD,EAAOqB,kBACtB8H,EAAQi6C,EAAKj6C,MAAOM,EAAS25C,EAAK35C,OAClC65C,EAAQF,EAAKE,MAAOE,EAAQJ,EAAKI,MACjCS,EAAoB96C,IAAUtH,KAAKqiD,YAAcz6C,IAAW5H,KAAKsiD,YACjEC,EAAcviD,KAAKyhD,QAAUA,GAASzhD,KAAK2hD,QAAUA,EACrDa,EAAeJ,GAAqBG,EACpCE,EAAkB,EAAGC,EAAmB,EAAGC,GAAqB,EACpE,GAAIP,EAAmB,CACrB,IAAIQ,EAAc5iD,KAAKmhD,aAAa75C,MAChCu7C,EAAe7iD,KAAKmhD,aAAav5C,OACjCk7C,EAAsBF,EAARt7C,GAAgCu7C,EAATj7C,EAGzC+6C,EAAqBG,IAFAx7C,EAAsB,GAAds7C,GAAqBh7C,EAAwB,GAAfi7C,IACvCV,EAAdS,GAA6CT,EAAfU,EAEhCC,IAAgBvB,EAAKG,SAAmBS,EAAR76C,GAAiC66C,EAATv6C,KAC1D66C,EAA0B,GAARn7C,EAClBo7C,EAA4B,GAAT96C,GAGvB,QAAI46C,IACEG,GACFhjB,EAAOr4B,MAAQvC,KAAKgO,KAAKzL,EAAQm7C,GACjC9iB,EAAO/3B,OAAS7C,KAAKgO,KAAKnL,EAAS86C,KAGnC1iD,KAAKohD,cAAc2B,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GAC/C/iD,KAAKohD,cAAcvhB,UAAU,EAAG,EAAGF,EAAOr4B,MAAOq4B,EAAO/3B,SAE1Dq6C,EAAeV,EAAKh7C,EAAIk7C,EAAQ,EAChCS,EAAgBX,EAAK/6C,EAAIm7C,EAAQ,EACjC3hD,KAAKgjD,kBAAoBj+C,KAAKuvB,MAAMqL,EAAOr4B,MAAQ,EAAI26C,GAAgBA,EACvEjiD,KAAKijD,kBAAoBl+C,KAAKuvB,MAAMqL,EAAO/3B,OAAS,EAAIs6C,GAAiBA,EACzEliD,KAAKqiD,WAAa/6C,EAClBtH,KAAKsiD,YAAc16C,EACnB5H,KAAKohD,cAAc/0C,UAAUrM,KAAKgjD,kBAAmBhjD,KAAKijD,mBAC1DjjD,KAAKohD,cAAcjkB,MAAMskB,EAAOE,GAChC3hD,KAAKyhD,MAAQA,EACbzhD,KAAK2hD,MAAQA,GACN,IASXloB,WAAY,SAASz4B,GACnBhB,KAAKwD,YAAYxC,GACjBhB,KAAK0D,cAAc1C,EAAQV,KAAM,QACjCN,KAAK0D,cAAc1C,EAAQ+mB,OAAQ,UACnC/nB,KAAKkE,cAAclD,GACnBhB,KAAK+D,aAAa/C,EAAQV,KAAM,QAChCN,KAAK+D,aAAa/C,EAAQ+mB,OAAQ,WAQpChB,UAAW,SAASrb,EAAKw3C,GACnBljD,KAAK44B,QAAU54B,KAAK44B,MAAMuqB,gBAAkBnjD,KAAK44B,QAAU54B,KAAK2/B,OAAOV,cACzEj/B,KAAK44B,MAAM7R,UAAUrb,GAEvB,IAAI61B,EAAS2hB,EAAWljD,KAAKgqC,oBAAsBhqC,KAAKohC,iBACxD11B,EAAIW,UAAUk1B,EAAOh7B,EAAGg7B,EAAO/6B,GAC/BxG,KAAK+N,OAASrC,EAAIa,OAAO3G,EAAiB5F,KAAK+N,QAC/CrC,EAAIyxB,MACFn9B,KAAKiO,QAAUjO,KAAK6O,OAAS,EAAI,GACjC7O,KAAKkO,QAAUlO,KAAK8O,OAAS,EAAI,IAEnC9O,KAAKmO,OAASzC,EAAIqb,UAAU,EAAG,EAAGhiB,KAAK0J,IAAI7I,EAAiB5F,KAAKmO,QAAS,EAAG,EAAG,GAChFnO,KAAKoO,OAAS1C,EAAIqb,UAAU,EAAGhiB,KAAK0J,IAAI7I,EAAiB5F,KAAKoO,QAAS,EAAG,EAAG,EAAG,IAQlFiqB,SAAU,SAASC,GACjB,IAAIoB,EAAsBv7B,EAAOmN,OAAOouB,oBAEpCz3B,EAAS,CACPY,KAA0B7C,KAAK6C,KAC/B0kC,QAA0BvnC,KAAKunC,QAC/BC,QAA0BxnC,KAAKwnC,QAC/B9/B,KAA0BM,EAAQhI,KAAK0H,KAAMgyB,GAC7C/xB,IAA0BK,EAAQhI,KAAK2H,IAAK+xB,GAC5CpyB,MAA0BU,EAAQhI,KAAKsH,MAAOoyB,GAC9C9xB,OAA0BI,EAAQhI,KAAK4H,OAAQ8xB,GAC/Cp5B,KAA2BN,KAAKM,MAAQN,KAAKM,KAAK+3B,SAAYr4B,KAAKM,KAAK+3B,WAAar4B,KAAKM,KAC1FynB,OAA2B/nB,KAAK+nB,QAAU/nB,KAAK+nB,OAAOsQ,SAAYr4B,KAAK+nB,OAAOsQ,WAAar4B,KAAK+nB,OAChGuf,YAA0Bt/B,EAAQhI,KAAKsnC,YAAa5N,GACpDqL,gBAA0B/kC,KAAK+kC,gBAAkB/kC,KAAK+kC,gBAAgB3sB,SAAWpY,KAAK+kC,gBACtFF,cAA0B7kC,KAAK6kC,cAC/BC,eAA0B9kC,KAAK8kC,eAC/Bsb,iBAA0Bp4C,EAAQhI,KAAKogD,iBAAkB1mB,GACzDzrB,OAA0BjG,EAAQhI,KAAKiO,OAAQyrB,GAC/CxrB,OAA0BlG,EAAQhI,KAAKkO,OAAQwrB,GAC/C3rB,MAA0B/F,EAAQhI,KAAKu8C,WAAY7iB,GACnD7qB,MAA0B7O,KAAK6O,MAC/BC,MAA0B9O,KAAK8O,MAC/BoN,QAA0BlU,EAAQhI,KAAKkc,QAASwd,GAChDiB,OAA2B36B,KAAK26B,QAAU36B,KAAK26B,OAAOtC,SAAYr4B,KAAK26B,OAAOtC,WAAar4B,KAAK26B,OAChGhN,QAA0B3tB,KAAK2tB,QAC/BxpB,OAA0BnE,KAAKmE,QAAU8K,OAAOjP,KAAKmE,QACrDk3B,gBAA0Br7B,KAAKq7B,gBAC/B6kB,SAA0BlgD,KAAKkgD,SAC/BC,yBAA0BngD,KAAKmgD,yBAC/BzyB,gBAA0B1tB,KAAK0tB,gBAAkB1tB,KAAK0tB,gBAAgBtV,SAAW,KACjFjK,MAA0BnG,EAAQhI,KAAKmO,MAAOurB,GAC9CtrB,MAA0BpG,EAAQhI,KAAKoO,MAAOsrB,IASpD,OANAv7B,EAAOiC,KAAK+K,uBAAuBnL,KAAMiC,EAAQq2B,GAE5Ct4B,KAAKy6B,uBACRx4B,EAASjC,KAAKojD,qBAAqBnhD,IAG9BA,GAQT8/B,iBAAkB,SAASzJ,GAEzB,OAAOt4B,KAAKq4B,SAASC,IAOvB8qB,qBAAsB,SAASnhD,GAC7B,IAAIsJ,EAAYpN,EAAOiC,KAAKwI,SAAS3G,EAAOY,MAAM0I,UAelD,OAdsBA,EAAU+B,gBAChBjD,QAAQ,SAAS3J,GAC3BuB,EAAOvB,KAAU6K,EAAU7K,WACtBuB,EAAOvB,GAE+C,mBAAjD4K,OAAOC,UAAUC,SAAS1K,KAAKmB,EAAOvB,KACc,mBAApD4K,OAAOC,UAAUC,SAAS1K,KAAKyK,EAAU7K,KAGhB,IAAxBuB,EAAOvB,GAAMD,QAA2C,IAA3B8K,EAAU7K,GAAMD,eACnDwB,EAAOvB,KAIXuB,GAOTuJ,SAAU,WACR,MAAO,YAAcoM,EAAW5X,KAAK6C,MAAQ,KAO/Ci/C,iBAAkB,WAChB,IAAI7zC,EAASjO,KAAKiO,OAAQC,EAASlO,KAAKkO,OACxC,GAAIlO,KAAK44B,MAAO,CACd,IAAIyqB,EAAUrjD,KAAK44B,MAAMkpB,mBACzB7zC,GAAUo1C,EAAQp1C,OAClBC,GAAUm1C,EAAQn1C,OAEpB,MAAO,CAAED,OAAQA,EAAQC,OAAQA,IASnCzJ,KAAM,SAASC,EAAKrD,GAClB,IAAIiiD,EAAgC,WAAR5+C,GAA4B,WAARA,EAC5C6+C,EAAYvjD,KAAK0E,KAASrD,EAqC9B,OAnCIiiD,IACFjiD,EAAQrB,KAAKwjD,gBAAgBniD,IAEnB,WAARqD,GAAoBrD,EAAQ,GAC9BrB,KAAK6O,OAAS7O,KAAK6O,MACnBxN,IAAU,GAEK,WAARqD,GAAoBrD,EAAQ,GACnCrB,KAAK8O,OAAS9O,KAAK8O,MACnBzN,IAAU,GAEK,WAARqD,IAAoBrD,GAAWA,aAAiBlD,EAAOm8B,OAG/C,UAAR51B,GAAmB1E,KAAK44B,OAC/B54B,KAAK44B,MAAMn1B,IAAI,QAASpC,GAHxBA,EAAQ,IAAIlD,EAAOm8B,OAAOj5B,GAM5BrB,KAAK0E,GAAOrD,EAERkiD,IAAkD,EAArCvjD,KAAKihD,gBAAgB9gD,QAAQuE,KACxC1E,KAAK44B,OACP54B,KAAK44B,MAAMn1B,IAAI,SAAS,GAE1BzD,KAAKghD,OAAQ,GAGXuC,GAAavjD,KAAK44B,QAA8C,EAArC54B,KAAKsN,gBAAgBnN,QAAQuE,IAC1D1E,KAAK44B,MAAMn1B,IAAI,SAAS,GAGd,UAARiB,GAA2B,WAARA,IACrB1E,KAAKugD,cAAgBx7C,KAAKS,IAAI,GAAK,EAAIT,KAAKU,IAAIzF,KAAKsH,MAAOtH,KAAK4H,UAG5D5H,MASTyjD,WAAY,aAUZC,cAAe,SAASriD,GAEtB,OADArB,KAAKkL,WAAa7J,EACXrB,MAST2jD,qBAAsB,WACpB,OAAI3jD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO9D,kBACtB77B,KAAK2/B,OAAO9D,kBAEd19B,EAAOiB,QAAQgZ,UASxBwrC,aAAc,WACZ,OAAwB,IAAjB5jD,KAAKkc,SAAiC,IAAflc,KAAKsH,OAA+B,IAAhBtH,KAAK4H,SAAkB5H,KAAK2tB,SAQhFkT,OAAQ,SAASn1B,EAAKm4C,GAEhB7jD,KAAK4jD,gBAGL5jD,KAAK2/B,QAAU3/B,KAAK2/B,OAAOxD,gBAAkBn8B,KAAK44B,QAAU54B,KAAK8jD,eAGrEp4C,EAAIU,OAEJpM,KAAK+jD,yBAAyBr4C,GAC9B1L,KAAKgkD,wBAAwBt4C,GACxBm4C,GACH7jD,KAAK+mB,UAAUrb,GAEjB1L,KAAKikD,YAAYv4C,GACjB1L,KAAKulC,WAAW75B,GACZ1L,KAAK0tB,iBACPhiB,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK0tB,iBAEhC1tB,KAAKmE,QAAUhG,EAAOiC,KAAKmN,YAAYvN,KAAM0L,GACzC1L,KAAKkkD,YAAYL,IACd7jD,KAAKmhD,cACRnhD,KAAKoqC,qBAEHpqC,KAAKmkD,aAAaN,KACpB7jD,KAAK8gD,gBAAkB9gD,KAAK07C,UAAU,CAAE0I,YAAa,oBACrDpkD,KAAKqkD,WAAWrkD,KAAKohD,cAAeyC,GACpC7jD,KAAKghD,OAAQ,GAEfhhD,KAAKskD,kBAAkB54C,KAGvB1L,KAAKukD,qBACLvkD,KAAKghD,OAAQ,EACbhhD,KAAKqkD,WAAW34C,EAAKm4C,GACjBA,GAAe7jD,KAAK0/C,eAAiB1/C,KAAK8gD,gBAC5C9gD,KAAK07C,UAAU,CAAE0I,YAAa,qBAGlCpkD,KAAKmE,QAAUuH,EAAIc,UACnBd,EAAIc,YAMN+3C,mBAAoB,WAClBvkD,KAAKmhD,aAAe,KACpBnhD,KAAKqiD,WAAa,EAClBriD,KAAKsiD,YAAc,GAYrBkC,iBAAkB,WAChB,OAAO,GAYTN,YAAa,SAASL,GACpB,OAAQA,GAAe7jD,KAAK0/C,iBAC1B1/C,KAAK44B,OAAS54B,KAAKwkD,qBAAuBxkD,KAAK44B,MAAM6rB,cAQzDC,eAAgB,WACd,QAAS1kD,KAAK26B,SAAmC,IAAxB36B,KAAK26B,OAAO3C,SAAyC,IAAxBh4B,KAAK26B,OAAO1C,UAQpEosB,WAAY,SAAS34C,EAAKm4C,GACxB7jD,KAAKygC,kBAAkB/0B,GACvB1L,KAAK2kD,iBAAiBj5C,GACtB1L,KAAK4kD,eAAel5C,GACpB1L,KAAKmmC,QAAQz6B,EAAKm4C,IAOpBS,kBAAmB,SAAS54C,GAC1BA,EAAIyxB,MAAM,EAAIn9B,KAAKyhD,MAAO,EAAIzhD,KAAK2hD,OACnCj2C,EAAIm5C,UAAU7kD,KAAKmhD,cAAenhD,KAAKgjD,mBAAoBhjD,KAAKijD,oBAQlEkB,aAAc,SAASW,GACrB,GAAI9kD,KAAK4jD,eACP,OAAO,EAET,GAAI5jD,KAAKmhD,eAAiB2D,GAAc9kD,KAAKqhD,qBAE3C,OAAO,EAGP,GAAIrhD,KAAKghD,OAAUhhD,KAAK8gD,gBAAkB9gD,KAAKg7C,gBAAgB,mBAAqB,CAClF,GAAIh7C,KAAKmhD,eAAiB2D,EAAY,CACpC,IAAIx9C,EAAQtH,KAAKqiD,WAAariD,KAAKyhD,MAC/B75C,EAAS5H,KAAKsiD,YAActiD,KAAK2hD,MACrC3hD,KAAKohD,cAAcvhB,WAAWv4B,EAAQ,GAAIM,EAAS,EAAGN,EAAOM,GAE/D,OAAO,EAGX,OAAO,GAQT64B,kBAAmB,SAAS/0B,GAC1B,GAAK1L,KAAKq7B,gBAAV,CAGA,IAAI0V,EAAM/wC,KAAKgiD,+BACft2C,EAAIq1B,UAAY/gC,KAAKq7B,gBAErB3vB,EAAIs1B,UACD+P,EAAIxqC,EAAI,GACRwqC,EAAIvqC,EAAI,EACTuqC,EAAIxqC,EACJwqC,EAAIvqC,GAINxG,KAAK+kD,cAAcr5C,KAOrBu4C,YAAa,SAASv4C,GACpBA,EAAI89B,aAAexpC,KAAKkc,SAG1ByoC,iBAAkB,SAASj5C,GACrB1L,KAAK+nB,SACPrc,EAAI05B,UAAYplC,KAAKsnC,YACrB57B,EAAI25B,QAAUrlC,KAAK6kC,cACnBn5B,EAAI45B,SAAWtlC,KAAK8kC,eACpBp5B,EAAIs5C,WAAahlD,KAAKogD,iBACtB10C,EAAIy5B,YAAcnlC,KAAK+nB,OAAOkR,OAC1Bj5B,KAAK+nB,OAAOkR,OAAOvtB,EAAK1L,MACxBA,KAAK+nB,SAIb68B,eAAgB,SAASl5C,GACnB1L,KAAKM,OACPoL,EAAIq1B,UAAY/gC,KAAKM,KAAK24B,OACtBj5B,KAAKM,KAAK24B,OAAOvtB,EAAK1L,MACtBA,KAAKM,OAWbuzC,aAAc,SAASnoC,EAAKu5C,EAAWC,GAChCD,IAID,EAAIA,EAAUxkD,QAChBwkD,EAAUrkD,KAAKgB,MAAMqjD,EAAWA,GAE9BxF,EACF/zC,EAAIg5B,YAAYugB,GAGhBC,GAAeA,EAAYx5C,KAQ/B6iC,gBAAiB,SAAS7iC,GACxB,GAAK1L,KAAKsuC,UAAWtuC,KAAK44B,OAAS54B,KAAK44B,QAAU54B,KAAK2/B,OAAO8M,kBAA9D,CAIA,IAEIzrC,EAFA+9B,EAAM/+B,KAAK2jD,uBACXp6B,EAASvpB,KAAK4tC,sBAElBrkB,EAASprB,EAAOiC,KAAKuN,0BAA0BoxB,EAAKxV,GACpDvoB,EAAU7C,EAAOiC,KAAK0N,YAAYyb,GAElC7d,EAAIU,OACJV,EAAIW,UAAUrL,EAAQqN,WAAYrN,EAAQsN,YAC1C5C,EAAI05B,UAAY,EAAIplC,KAAKsgD,kBACpBtgD,KAAK44B,QACRltB,EAAI89B,YAAcxpC,KAAK+5C,SAAW/5C,KAAKqgD,wBAA0B,GAE/DrgD,KAAK44B,OAAS54B,KAAK44B,QAAU54B,KAAK2/B,OAAO8M,kBAC3C/gC,EAAIa,OAAO3G,EAAiB5E,EAAQ+M,QACpC/N,KAAKmlD,mBAAmBz5C,EAAK1K,KAG7B0K,EAAIa,OAAO3G,EAAiB5F,KAAK+N,QACjC/N,KAAKolD,YAAY15C,IAEnB1L,KAAK2gC,aAAaj1B,GAClBA,EAAIc,YAON+4B,WAAY,SAAS75B,GACnB,GAAK1L,KAAK26B,OAAV,CAIA,IAAI0qB,EAASrlD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO9D,kBAAkB,IAAO,EAC7DypB,EAAStlD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO9D,kBAAkB,IAAO,EAC7DwnB,EAAUrjD,KAAK8hD,mBACf9hD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO5C,qBAC7BsoB,GAASlnD,EAAOuB,iBAChB4lD,GAASnnD,EAAOuB,kBAElBgM,EAAI85B,YAAcxlC,KAAK26B,OAAOzW,MAC9BxY,EAAI+5B,WAAazlC,KAAK26B,OAAOJ,MAAQ8qB,EAAQC,IAAUjC,EAAQp1C,OAASo1C,EAAQn1C,QAAU,EAC1FxC,EAAIg6B,cAAgB1lC,KAAK26B,OAAO3C,QAAUqtB,EAAQhC,EAAQp1C,OAC1DvC,EAAIi6B,cAAgB3lC,KAAK26B,OAAO1C,QAAUqtB,EAAQjC,EAAQn1C,SAO5D62C,cAAe,SAASr5C,GACjB1L,KAAK26B,SAIVjvB,EAAI85B,YAAc,GAClB95B,EAAI+5B,WAAa/5B,EAAIg6B,cAAgBh6B,EAAIi6B,cAAgB,IAQ3D4f,+BAAgC,SAAS75C,EAAK/H,GAC5C,GAAKA,EAAOs1B,OAAZ,CAGA,IAAIlS,EAAYpjB,EAAOu0B,mBAAqBv0B,EAAO6hD,iBAC/Cz+B,GACFrb,EAAIqb,UAAUnlB,MAAM8J,EAAKqb,GAE3B,IAAIiR,GAAWh4B,KAAKsH,MAAQ,EAAI3D,EAAOq0B,SAAW,EAC9CC,GAAWj4B,KAAK4H,OAAS,EAAIjE,EAAOs0B,SAAW,EACnDvsB,EAAIW,UAAU2rB,EAASC,KAOzBwtB,YAAa,SAAS/5C,GACf1L,KAAKM,OAIVoL,EAAIU,OACJpM,KAAKulD,+BAA+B75C,EAAK1L,KAAKM,MACxB,YAAlBN,KAAKkgD,SACPx0C,EAAIpL,KAAK,WAGToL,EAAIpL,OAENoL,EAAIc,YAONk5C,cAAe,SAASh6C,GACjB1L,KAAK+nB,QAA+B,IAArB/nB,KAAKsnC,cAIrBtnC,KAAK26B,SAAW36B,KAAK26B,OAAOH,cAC9Bx6B,KAAK+kD,cAAcr5C,GAGrBA,EAAIU,OACJpM,KAAK6zC,aAAanoC,EAAK1L,KAAK+kC,gBAAiB/kC,KAAK2lD,qBAClD3lD,KAAKulD,+BAA+B75C,EAAK1L,KAAK+nB,QAC9Crc,EAAIqc,SACJrc,EAAIc,YAUNgL,MAAO,SAAS7U,EAAU21B,GACxB,OAAIt4B,KAAK0Y,YAAYpO,WACZtK,KAAK0Y,YAAYpO,WAAWtK,KAAKq4B,SAASC,GAAsB31B,GAElE,IAAIxE,EAAOmN,OAAOtL,KAAKq4B,SAASC,KAUzCstB,aAAc,SAASjjD,EAAU3B,GAC/B,IAAI6kD,EAAU7lD,KAAK25B,UAAU34B,GAM7B,OALA7C,EAAOiC,KAAKkJ,UAAUu8C,EAAS,SAASp8C,GAClC9G,GACFA,EAAS,IAAIxE,EAAOy/B,MAAMn0B,MAGvBzJ,MAgBT25B,UAAW,SAAS34B,GAClBA,IAAYA,EAAU,IAEtB,IAAI0c,EAAKvf,EAAOiC,KAAKqM,sBACjBq5C,EAAe9lD,KAAK+lD,kBAExBroC,EAAGpW,MAAQw+C,EAAax+C,MACxBoW,EAAG9V,OAASk+C,EAAal+C,OACzBzJ,EAAOiC,KAAKsf,YAAYhC,EAAI,OAC5B,IAAIiiB,EAAS,IAAIxhC,EAAO88B,aAAavd,EAAI,CAAEue,oBAAqBj7B,EAAQi7B,sBAEjD,QAAnBj7B,EAAQy8C,SACVz8C,EAAQy8C,OAAS,QAGI,SAAnBz8C,EAAQy8C,SACV9d,EAAOtE,gBAAkB,QAG3B,IAAI2qB,EAAa,CACf1X,OAAQtuC,KAAK2E,IAAI,UACjB+C,KAAM1H,KAAKimD,UACXt+C,IAAK3H,KAAKkmD,UAGZlmD,KAAKyD,IAAI,UAAU,GACnBzD,KAAK6hC,oBAAoB,IAAI1jC,EAAOmI,MAAMq5B,EAAO5B,WAAa,EAAG4B,EAAO3B,YAAc,GAAI,SAAU,UAEpG,IAAImoB,EAAiBnmD,KAAK2/B,OAC1BA,EAAOh+B,IAAI3B,MACX,IAAIyP,EAAOkwB,EAAOhG,UAAU34B,GAQ5B,OANAhB,KAAKyD,IAAIuiD,GAAY9mB,YACrBl/B,KAAK2/B,OAASwmB,EAEdxmB,EAAO2E,UACP3E,EAAS,KAEFlwB,GAQT22C,OAAQ,SAASvjD,GACf,OAAO7C,KAAK6C,OAASA,GAOvBM,WAAY,WACV,OAAO,GAQTwhC,OAAQ,SAASrM,GAEf,OAAOt4B,KAAKq4B,SAASC,IAmDvB+tB,YAAa,SAASziD,EAAU5C,GAC9BA,IAAYA,EAAU,IAEtB,IAAIk4B,EAAW,CAAEr1B,WAAY,IAkB7B,OAhBAq1B,EAASr2B,KAAO7B,EAAQ6B,OAAS7B,EAAQmyB,IAAMnyB,EAAQoyB,GAAK,SAAW,UACvE8F,EAASzjB,OAAS,CAChBjB,GAAIxT,EAAQwT,GACZC,GAAIzT,EAAQyT,GACZ9I,GAAI3K,EAAQ2K,GACZC,GAAI5K,EAAQ4K,KAGV5K,EAAQmyB,IAAMnyB,EAAQoyB,MACxB8F,EAASzjB,OAAO0d,GAAKnyB,EAAQmyB,GAC7B+F,EAASzjB,OAAO2d,GAAKpyB,EAAQoyB,IAG/B8F,EAAShB,kBAAoBl3B,EAAQk3B,kBACrC/5B,EAAO2F,SAASyH,UAAU4sB,aAAar3B,KAAKo4B,EAAUl4B,EAAQ6C,YAEvD7D,KAAKyD,IAAIG,EAAUzF,EAAO2F,SAASy1B,UAAUv5B,KAAMk5B,KAsB5DotB,eAAgB,SAAStlD,GACvB,OAAOhB,KAAKyD,IAAI,OAAQ,IAAItF,EAAO8F,QAAQjD,KAyB7CgkC,UAAW,SAAShkC,GAClB,OAAOhB,KAAKyD,IAAI,SAAUzC,EAAU,IAAI7C,EAAOm8B,OAAOt5B,GAAW,OASnEulD,SAAU,SAASriC,GAEjB,OADAlkB,KAAKyD,IAAI,OAAQygB,GACVlkB,MAST+O,SAAU,SAAShB,GACjB,IAAIy4C,GAAuC,WAAjBxmD,KAAKunC,SAAyC,WAAjBvnC,KAAKwnC,UAAyBxnC,KAAKwqC,iBAY1F,OAVIgc,GACFxmD,KAAKqtC,qBAGPrtC,KAAKyD,IAAI,QAASsK,GAEdy4C,GACFxmD,KAAKymD,eAGAzmD,MAST0mD,QAAS,WAEP,OADA1mD,KAAK2/B,QAAU3/B,KAAK2/B,OAAOuB,cAAclhC,MAClCA,MAST2mD,gBAAiB,WAEf,OADA3mD,KAAK2/B,QAAU3/B,KAAK2/B,OAAOgC,sBAAsB3hC,MAC1CA,MAST4mD,QAAS,WAEP,OADA5mD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO0B,cAAcrhC,MAClCA,MAST6mD,gBAAiB,WAEf,OADA7mD,KAAK2/B,QAAU3/B,KAAK2/B,OAAOiC,sBAAsB5hC,MAC1CA,MASTuhC,OAAQ,WAEN,OADAvhC,KAAK2/B,QAAU3/B,KAAK2/B,OAAO2B,aAAathC,MACjCA,MAST8mD,eAAgB,WAEd,OADA9mD,KAAK2/B,QAAU3/B,KAAK2/B,OAAO6B,qBAAqBxhC,MACzCA,MAQTuC,OAAQ,WAON,OANIvC,KAAK2/B,SACH3/B,KAAK44B,OAAS54B,KAAK44B,QAAU54B,KAAK2/B,OAAOV,cAC3Cj/B,KAAK44B,MAAMr2B,OAAOvC,MAEpBA,KAAK2/B,OAAOp9B,OAAOvC,OAEdA,MAST+mD,gBAAiB,SAAS5sC,EAAG6rB,GAC3BA,EAAUA,GAAWhmC,KAAK2/B,OAAOhkB,WAAWxB,GAC5C,IAAI6sC,EAAW,IAAI7oD,EAAOmI,MAAM0/B,EAAQz/B,EAAGy/B,EAAQx/B,GAC/CygD,EAAgBjnD,KAAKgqC,oBAKzB,OAJIhqC,KAAK+N,QACPi5C,EAAW7oD,EAAOiC,KAAK4F,YACrBghD,EAAUC,EAAerhD,GAAkB5F,KAAK+N,SAE7C,CACLxH,EAAGygD,EAASzgD,EAAI0gD,EAAc1gD,EAC9BC,EAAGwgD,EAASxgD,EAAIygD,EAAczgD,IASlCu9C,yBAA0B,SAAUr4C,GAC9B1L,KAAKmgD,2BACPz0C,EAAIy0C,yBAA2BngD,KAAKmgD,6BAK1ChiD,EAAOiC,KAAK2M,gBAAgB5O,EAAOmN,QAOnCnN,EAAOmN,OAAOC,UAAUgB,OAASpO,EAAOmN,OAAOC,UAAUwD,SAEzDqI,EAAOjZ,EAAOmN,OAAOC,UAAWpN,EAAOmD,YAUvCnD,EAAOmN,OAAOouB,oBAAsB,EAEpCv7B,EAAOmN,OAAO47C,YAAc,SAASvpC,EAAW1b,EAAQU,EAAUwkD,EAAYC,GAC5E,IAAIp6C,EAAQ7O,EAAOwf,GAEnB,GADA1b,EAASuV,EAAMvV,GAAQ,IACnBklD,EAYC,CACH,IAAI9tB,EAAW+tB,EAAa,IAAIp6C,EAAM/K,EAAOmlD,GAAanlD,GAAU,IAAI+K,EAAM/K,GAE9E,OADAU,GAAYA,EAAS02B,GACdA,EAdPl7B,EAAOiC,KAAKoK,gBAAgB,CAACvI,EAAO3B,KAAM2B,EAAO8lB,QAAS,SAAStd,QACtC,IAAhBA,EAAS,KAClBxI,EAAO3B,KAAOmK,EAAS,SAEE,IAAhBA,EAAS,KAClBxI,EAAO8lB,OAAStd,EAAS,IAE3B,IAAI4uB,EAAW+tB,EAAa,IAAIp6C,EAAM/K,EAAOmlD,GAAanlD,GAAU,IAAI+K,EAAM/K,GAC9EU,GAAYA,EAAS02B,MAgB3Bl7B,EAAOmN,OAAOwgB,MAAQ,GAv7DxB,CAy7DsB,oBAAZztB,QAA0BA,QAAU2B,MAG9C,WAEE,IAAI4F,EAAmBzH,OAAOiC,KAAKwF,iBAC/ByhD,EAAgB,CACd3/C,MAAO,GACP65B,OAAQ,EACR+T,MAAO,IAETgS,EAAgB,CACd3/C,KAAM,GACN45B,OAAQ,EACR8T,OAAQ,IAGdl3C,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAWvFk8B,uBAAwB,SAASxhC,EAAOshD,EAAaC,EAAaC,EAAWC,GAC3E,IAEI1vB,EAASC,EAAS8Y,EAFlBxqC,EAAIN,EAAMM,EACVC,EAAIP,EAAMO,EAyCd,MAtC2B,iBAAhB+gD,EACTA,EAAcF,EAAcE,GAG5BA,GAAe,GAGQ,iBAAdE,EACTA,EAAYJ,EAAcI,GAG1BA,GAAa,GAKY,iBAAhBD,EACTA,EAAcF,EAAcE,GAG5BA,GAAe,GAGQ,iBAAdE,EACTA,EAAYJ,EAAcI,GAG1BA,GAAa,GAGfzvB,EAAUyvB,EAAYF,IAhBtBxvB,EAAUyvB,EAAYF,IAkBPtvB,KACb8Y,EAAM/wC,KAAKgxC,4BACXzqC,EAAIN,EAAMM,EAAIyxB,EAAU+Y,EAAIxqC,EAC5BC,EAAIP,EAAMO,EAAIyxB,EAAU8Y,EAAIvqC,GAGvB,IAAIrI,OAAOmI,MAAMC,EAAGC,IAU7BmhD,uBAAwB,SAAS1hD,EAAOshC,EAASC,GAC/C,IAAI1gC,EAAI9G,KAAKynC,uBAAuBxhC,EAAOshC,EAASC,EAAS,SAAU,UACvE,OAAIxnC,KAAK+N,MACA5P,OAAOiC,KAAK4F,YAAYc,EAAGb,EAAOL,EAAiB5F,KAAK+N,QAE1DjH,GAUTmqC,uBAAwB,SAAS1P,EAAQgG,EAASC,GAChD,IAAI1gC,EAAI9G,KAAKynC,uBAAuBlG,EAAQ,SAAU,SAAUgG,EAASC,GACzE,OAAIxnC,KAAK+N,MACA5P,OAAOiC,KAAK4F,YAAYc,EAAGy6B,EAAQ37B,EAAiB5F,KAAK+N,QAE3DjH,GAOTs6B,eAAgB,WACd,IAAIwmB,EAAU,IAAIzpD,OAAOmI,MAAMtG,KAAK0H,KAAM1H,KAAK2H,KAC/C,OAAO3H,KAAK2nD,uBAAuBC,EAAS5nD,KAAKunC,QAASvnC,KAAKwnC,UAkBjEqgB,iBAAkB,SAAStgB,EAASC,GAClC,IAAIjG,EAASvhC,KAAKohC,iBAClB,OAAOphC,KAAKixC,uBAAuB1P,EAAQgG,EAASC,IAUtDqJ,aAAc,SAAS5qC,EAAOshC,EAASC,GACrC,IACI1gC,EAAG6/B,EADHpF,EAASvhC,KAAKohC,iBAclB,OAVEt6B,OADqB,IAAZygC,QAA8C,IAAZC,EACvCxnC,KAAKynC,uBAAuBlG,EAAQ,SAAU,SAAUgG,EAASC,GAGjE,IAAIrpC,OAAOmI,MAAMtG,KAAK0H,KAAM1H,KAAK2H,KAGvCg/B,EAAK,IAAIxoC,OAAOmI,MAAML,EAAMM,EAAGN,EAAMO,GACjCxG,KAAK+N,QACP44B,EAAKxoC,OAAOiC,KAAK4F,YAAY2gC,EAAIpF,GAAS37B,EAAiB5F,KAAK+N,SAE3D44B,EAAGxgC,eAAeW,IAmB3B+6B,oBAAqB,SAAS5d,EAAKsjB,EAASC,GAC1C,IAAIjG,EAASvhC,KAAK2nD,uBAAuB1jC,EAAKsjB,EAASC,GACnDpP,EAAWp4B,KAAKixC,uBAAuB1P,EAAQvhC,KAAKunC,QAASvnC,KAAKwnC,SAEtExnC,KAAKyD,IAAI,OAAQ20B,EAAS7xB,GAC1BvG,KAAKyD,IAAI,MAAO20B,EAAS5xB,IAM3BshD,eAAgB,SAASC,GACvB,IAIIC,EAAYC,EAJZl6C,EAAQnI,EAAiB5F,KAAK+N,OAC9Bm6C,EAAYloD,KAAK+9B,WACjBoqB,EAAQpjD,KAAK6B,IAAImH,GAASm6C,EAC1BE,EAAQrjD,KAAK4B,IAAIoH,GAASm6C,EAK5BF,EAD0B,iBAAjBhoD,KAAKunC,QACD8f,EAAcrnD,KAAKunC,SAGnBvnC,KAAKunC,QAAU,GAG5B0gB,EADgB,iBAAPF,EACEV,EAAcU,GAGdA,EAAK,GAElB/nD,KAAK0H,MAAQygD,GAASF,EAAWD,GACjChoD,KAAK2H,KAAOygD,GAASH,EAAWD,GAChChoD,KAAKk/B,YACLl/B,KAAKunC,QAAUwgB,GAQjB1a,mBAAoB,WAClBrtC,KAAKqoD,iBAAmBroD,KAAKunC,QAC7BvnC,KAAKsoD,iBAAmBtoD,KAAKwnC,QAE7B,IAAIjG,EAASvhC,KAAKohC,iBAElBphC,KAAKunC,QAAU,SACfvnC,KAAKwnC,QAAU,SAEfxnC,KAAK0H,KAAO65B,EAAOh7B,EACnBvG,KAAK2H,IAAM45B,EAAO/6B,GAQpBigD,aAAc,WACZ,IAAItL,EAAcn7C,KAAKixC,uBACrBjxC,KAAKohC,iBACLphC,KAAKqoD,iBACLroD,KAAKsoD,kBAEPtoD,KAAKunC,QAAUvnC,KAAKqoD,iBACpBroD,KAAKwnC,QAAUxnC,KAAKsoD,iBAEpBtoD,KAAK0H,KAAOyzC,EAAY50C,EACxBvG,KAAK2H,IAAMwzC,EAAY30C,EAEvBxG,KAAKqoD,iBAAmB,KACxBroD,KAAKsoD,iBAAmB,MAM1Bte,kBAAmB,WACjB,OAAOhqC,KAAKixC,uBAAuBjxC,KAAKohC,iBAAkB,OAAQ,QAMpE6U,WAAY,eAjQhB,GAyQA,WAWE,IAAIrwC,EAAmBzH,OAAOiC,KAAKwF,iBAC/B2iD,EAAmBpqD,OAAOiC,KAAKuN,0BAEnCxP,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAcvFi9C,QAAS,KAcTC,QAAS,KAKTC,UAAW,SAASC,EAAUC,GACvB5oD,KAAKwoD,SACRxoD,KAAKk/B,YAEP,IAjDezpB,EAiDXA,EAASkzC,EAAW3oD,KAAKyoD,QAAUzoD,KAAKwoD,QAC5C,OAlDe/yC,EAkDEmzC,EAAY5oD,KAAK6oD,WAAWF,GAAYlzC,EAjDpD,CACL,IAAItX,OAAOmI,MAAMmP,EAAO4qB,GAAG95B,EAAGkP,EAAO4qB,GAAG75B,GACxC,IAAIrI,OAAOmI,MAAMmP,EAAO8qB,GAAGh6B,EAAGkP,EAAO8qB,GAAG/5B,GACxC,IAAIrI,OAAOmI,MAAMmP,EAAO6qB,GAAG/5B,EAAGkP,EAAO6qB,GAAG95B,GACxC,IAAIrI,OAAOmI,MAAMmP,EAAO+qB,GAAGj6B,EAAGkP,EAAO+qB,GAAGh6B,KAwD1C62C,mBAAoB,SAASyL,EAASC,EAASJ,EAAUC,GACvD,IAAInzC,EAASzV,KAAK0oD,UAAUC,EAAUC,GAMtC,MAA+B,iBALZzqD,OAAO4zB,aAAamB,0BACjCzd,EACAqzC,EACAC,GAEc/2B,QAUtBkS,qBAAsB,SAAS8kB,EAAOL,EAAUC,GAM9C,MAA+B,iBALZzqD,OAAO4zB,aAAagB,wBACjC/yB,KAAK0oD,UAAUC,EAAUC,GACzBI,EAAMN,UAAUC,EAAUC,IAGZ52B,QACfg3B,EAAM7kB,wBAAwBnkC,KAAM2oD,EAAUC,IAC9C5oD,KAAKmkC,wBAAwB6kB,EAAOL,EAAUC,IAUrDzkB,wBAAyB,SAAS6kB,EAAOL,EAAUC,GAKjD,IAJA,IAAI1hD,EAASlH,KAAK0oD,UAAUC,EAAUC,GAClC1nD,EAAI,EAAG+nD,EAAQD,EAAME,eACnBN,EAAYI,EAAMH,WAAWF,GAAYA,EAAWK,EAAMP,QAAUO,EAAMR,SAEzEtnD,EAAI,EAAGA,IACZ,IAAK8nD,EAAMxb,cAActmC,EAAOhG,GAAI+nD,GAClC,OAAO,EAGX,OAAO,GAWT3L,sBAAuB,SAASwL,EAASC,EAASJ,EAAUC,GAC1D,IAAI9C,EAAe9lD,KAAK+lD,gBAAgB4C,EAAUC,GAElD,OACE9C,EAAap+C,MAAQohD,EAAQviD,GAC7Bu/C,EAAap+C,KAAOo+C,EAAax+C,OAASyhD,EAAQxiD,GAClDu/C,EAAan+C,KAAOmhD,EAAQtiD,GAC5Bs/C,EAAan+C,IAAMm+C,EAAal+C,QAAUmhD,EAAQviD,GAYtDgnC,cAAe,SAASvnC,EAAOgjD,EAAON,EAAUC,GAC1CK,EAAQA,GAASjpD,KAAKkpD,eACxBN,EAAY5oD,KAAK6oD,WAAWF,GAAYA,EAAW3oD,KAAKyoD,QAAUzoD,KAAKwoD,SADzE,IAGIrhD,EAAUnH,KAAKmpD,iBAAiBljD,EAAOgjD,GAG3C,OAAoB,IAAZ9hD,GAAiBA,EAAU,GAAM,GAS3C28C,WAAY,SAAS8E,GACnB,IAAK5oD,KAAK2/B,OACR,OAAO,EAIT,IAFA,IAC8C15B,EAD1C6iD,EAAU9oD,KAAK2/B,OAAOzD,UAAUmE,GAAI0oB,EAAU/oD,KAAK2/B,OAAOzD,UAAUoE,GACpEp5B,EAASlH,KAAK0oD,WAAU,EAAME,GACzB1nD,EAAI,EAAGA,EAAI,EAAGA,IAErB,IADA+E,EAAQiB,EAAOhG,IACLqF,GAAKwiD,EAAQxiD,GAAKN,EAAMM,GAAKuiD,EAAQviD,GAAKN,EAAMO,GAAKuiD,EAAQviD,GAAKP,EAAMO,GAAKsiD,EAAQtiD,EAC7F,OAAO,EAIX,GAAIxG,KAAKq9C,mBAAmByL,EAASC,GAAS,GAC5C,OAAO,EAGT,IAAIK,EAAc,CAAE7iD,GAAIuiD,EAAQviD,EAAIwiD,EAAQxiD,GAAK,EAAGC,GAAIsiD,EAAQtiD,EAAIuiD,EAAQviD,GAAK,GACjF,QAAIxG,KAAKwtC,cAAc4b,EAAa,MAAM,IAW5CF,eAAgB,SAASV,GACvB,MAAO,CACLa,QAAS,CACPvmD,EAAG0lD,EAAQnoB,GACXvd,EAAG0lC,EAAQjoB,IAEb+oB,UAAW,CACTxmD,EAAG0lD,EAAQjoB,GACXzd,EAAG0lC,EAAQloB,IAEbipB,WAAY,CACVzmD,EAAG0lD,EAAQloB,GACXxd,EAAG0lC,EAAQhoB,IAEbgpB,SAAU,CACR1mD,EAAG0lD,EAAQhoB,GACX1d,EAAG0lC,EAAQnoB,MAajB8oB,iBAAkB,SAASljD,EAAOgjD,GAChC,IAAQ12B,EAEJk3B,EADAC,EAAS,EAGb,IAAK,IAAIC,KAAWV,EAGlB,MAFAQ,EAAQR,EAAMU,IAEH7mD,EAAE0D,EAAIP,EAAMO,GAAOijD,EAAM3mC,EAAEtc,EAAIP,EAAMO,GAI3CijD,EAAM3mD,EAAE0D,GAAKP,EAAMO,GAAOijD,EAAM3mC,EAAEtc,GAAKP,EAAMO,KAI7CijD,EAAM3mD,EAAEyD,IAAMkjD,EAAM3mC,EAAEvc,GAAOkjD,EAAM3mD,EAAEyD,GAAKN,EAAMM,EAC9CkjD,EAAM3mD,EAAEyD,GAKR,EACLgsB,GAAMk3B,EAAM3mC,EAAEtc,EAAIijD,EAAM3mD,EAAE0D,IAAMijD,EAAM3mC,EAAEvc,EAAIkjD,EAAM3mD,EAAEyD,KAC/CN,EAAMO,EAFN,EAEeP,EAAMM,GACrBkjD,EAAM3mD,EAAE0D,EAAI+rB,EAAKk3B,EAAM3mD,EAAEyD,KAHzB,EAKmBgsB,MAIhBtsB,EAAMM,IACdmjD,GAAU,GAGG,IAAXA,IACF,MAGJ,OAAOA,GAQTE,qBAAsB,WACpB,OAAO5pD,KAAK+lD,kBAAkBz+C,OAQhCuiD,sBAAuB,WACrB,OAAO7pD,KAAK+lD,kBAAkBn+C,QAUhCm+C,gBAAiB,SAAS4C,EAAUC,GAClC,IAAInzC,EAASzV,KAAK0oD,UAAUC,EAAUC,GACtC,OAAOzqD,OAAOiC,KAAK6G,0BAA0BwO,IAO/CsoB,SAAU,WACR,OAAO/9B,KAAKgxC,4BAA4BzqC,GAQ1Cy3B,UAAW,WACT,OAAOh+B,KAAKgxC,4BAA4BxqC,GAS1Cg9C,gBAAiB,SAASniD,GACxB,OAAI0D,KAAKG,IAAI7D,GAASrB,KAAKugD,cACrBl/C,EAAQ,GACFrB,KAAKugD,cAGNvgD,KAAKugD,cAGTl/C,GAST87B,MAAO,SAAS97B,GAWd,OAVAA,EAAQrB,KAAKwjD,gBAAgBniD,IAEjB,IACVrB,KAAK6O,OAAS7O,KAAK6O,MACnB7O,KAAK8O,OAAS9O,KAAK8O,MACnBzN,IAAU,GAGZrB,KAAKiO,OAAS5M,EACdrB,KAAKkO,OAAS7M,EACPrB,KAAKk/B,aASd4qB,aAAc,SAASzoD,GAErB,IAAI0oD,EAAqB/pD,KAAK+lD,kBAAkBz+C,MAAQtH,KAAK+9B,WAC7D,OAAO/9B,KAAKm9B,MAAM97B,EAAQrB,KAAKsH,MAAQyiD,IASzCC,cAAe,SAAS3oD,GAEtB,IAAI0oD,EAAqB/pD,KAAK+lD,kBAAkBn+C,OAAS5H,KAAKg+B,YAC9D,OAAOh+B,KAAKm9B,MAAM97B,EAAQrB,KAAK4H,OAASmiD,IAQ1ClB,WAAY,SAASF,GACnB,IAAItZ,EAAQzpC,EAAiB5F,KAAK+N,OAC9BgxB,EAAM/+B,KAAK2jD,uBACX5S,EAAM4X,EAAW3oD,KAAKgxC,4BAA8BhxC,KAAKiqD,8BACzDC,EAAenZ,EAAIxqC,EAAG4jD,EAAgBpZ,EAAIvqC,EAC1CkL,EAAQ3M,KAAK4B,IAAI0oC,GACjB19B,EAAQ5M,KAAK6B,IAAIyoC,GACjB+a,EAAwB,EAAfF,EAAmBnlD,KAAK6sC,KAAKuY,EAAgBD,GAAgB,EACtEG,EAAeH,EAAenlD,KAAK6B,IAAIwjD,GAAW,EAClDpyB,EAAUjzB,KAAK6B,IAAIwjD,EAAS/a,GAASgb,EACrCpyB,EAAUlzB,KAAK4B,IAAIyjD,EAAS/a,GAASgb,EACrC9oB,EAASvhC,KAAKohC,iBAEd3rB,EAASkzC,EAAWpnB,EAASpjC,OAAOiC,KAAKyG,eAAe06B,EAAQxC,GAChEsB,EAAM,IAAIliC,OAAOmI,MAAMmP,EAAOlP,EAAIyxB,EAASviB,EAAOjP,EAAIyxB,GACtDsI,EAAM,IAAIpiC,OAAOmI,MAAM+5B,EAAG95B,EAAK2jD,EAAev4C,EAAQ0uB,EAAG75B,EAAK0jD,EAAex4C,GAC7E8uB,EAAM,IAAIriC,OAAOmI,MAAM+5B,EAAG95B,EAAK4jD,EAAgBz4C,EAAQ2uB,EAAG75B,EAAK2jD,EAAgBx4C,GAC/E2uB,EAAM,IAAIniC,OAAOmI,MAAMmP,EAAOlP,EAAIyxB,EAASviB,EAAOjP,EAAIyxB,GAC1D,IAAK0wB,EACH,IAAIjR,EAAM,IAAIv5C,OAAOmI,OAAO+5B,EAAG95B,EAAIi6B,EAAGj6B,GAAK,GAAI85B,EAAG75B,EAAIg6B,EAAGh6B,GAAK,GAC1D2O,EAAM,IAAIhX,OAAOmI,OAAOi6B,EAAGh6B,EAAI85B,EAAG95B,GAAK,GAAIg6B,EAAG/5B,EAAI65B,EAAG75B,GAAK,GAC1DgxC,EAAM,IAAIr5C,OAAOmI,OAAOg6B,EAAG/5B,EAAIg6B,EAAGh6B,GAAK,GAAI+5B,EAAG95B,EAAI+5B,EAAG/5B,GAAK,GAC1DixC,EAAM,IAAIt5C,OAAOmI,OAAOg6B,EAAG/5B,EAAIi6B,EAAGj6B,GAAK,GAAI+5B,EAAG95B,EAAIg6B,EAAGh6B,GAAK,GAC1D8jD,EAAM,IAAInsD,OAAOmI,MAAM6O,EAAG5O,EAAImL,EAAQ1R,KAAKygD,oBAAqBtrC,EAAG3O,EAAImL,EAAQ3R,KAAKygD,qBAkBtFhrC,EAAS,CAEX4qB,GAAIA,EAAIE,GAAIA,EAAID,GAAIA,EAAIE,GAAIA,GAW9B,OATKmoB,IAEHlzC,EAAOiiC,GAAKA,EACZjiC,EAAON,GAAKA,EACZM,EAAO+hC,GAAKA,EACZ/hC,EAAOgiC,GAAKA,EAEZhiC,EAAO60C,IAAMA,GAER70C,GAWTypB,UAAW,SAAS+V,EAAYsV,GAS9B,OARAvqD,KAAKwoD,QAAUxoD,KAAK6oD,WAAW5T,GAC1BsV,IACHvqD,KAAKyoD,QAAUzoD,KAAK6oD,YAAW,IAIjC5T,GAAej1C,KAAKwqD,kBAAoBxqD,KAAKwqD,mBAEtCxqD,MAOTyqD,kBAAmB,WACjB,GAAIzqD,KAAK+N,MAAO,CACd,IAAIshC,EAAQzpC,EAAiB5F,KAAK+N,OAAQnH,EAAM7B,KAAK6B,IAAIyoC,GAAQ1oC,EAAM5B,KAAK4B,IAAI0oC,GAKhF,OAHY,uBAARzoC,IAA0C,wBAATA,IACnCA,EAAM,GAED,CAACA,EAAKD,GAAMA,EAAKC,EAAK,EAAG,GAElC,OAAOzI,OAAOiB,QAAQgZ,UASxBw1B,oBAAqB,SAASoG,GAC5B,IAEI0W,EAEAnhC,EAJAgY,EAASvhC,KAAKohC,iBACdtW,EAAkB,CAAC,EAAG,EAAG,EAAG,EAAGyW,EAAOh7B,EAAGg7B,EAAO/6B,GAEhDmkD,EAAkB3qD,KAAK4qD,+BAA+B5qD,KAAKmO,MAAOnO,KAAKoO,OAAO,GAalF,OAVEmb,EADEvpB,KAAK44B,QAAUob,EACRuU,EAAiBvoD,KAAK44B,MAAMgV,sBAAuB9iB,GAGnDA,EAEP9qB,KAAK+N,QACP28C,EAAe1qD,KAAKyqD,oBACpBlhC,EAASg/B,EAAiBh/B,EAAQmhC,IAEpCnhC,EAASg/B,EAAiBh/B,EAAQohC,IAIpCC,+BAAgC,SAASz8C,EAAOC,EAAOy8C,GACrD,IAAIvhC,EAGA5a,EAAc,CAFL1O,KAAKiO,QAAU48C,GAAY7qD,KAAK6O,OAAS,EAAI,GAE/B,EAAG,EADjB7O,KAAKkO,QAAU28C,GAAY7qD,KAAK8O,OAAS,EAAI,GACjB,EAAG,GAS5C,OARIX,IACFmb,EAAa,CAAC,EAAG,EAAGvkB,KAAK0J,IAAI7I,EAAiBuI,IAAS,GACvDO,EAAc65C,EAAiB75C,EAAa4a,GAAY,IAEtDlb,IACFkb,EAAa,CAAC,EAAGvkB,KAAK0J,IAAI7I,EAAiBwI,IAAS,EAAG,GACvDM,EAAc65C,EAAiB75C,EAAa4a,GAAY,IAEnD5a,GASTszC,6BAA8B,WAC5B,IAAI1a,EAActnC,KAAKsnC,YAGvB,MAAO,CAAE/gC,EAFDvG,KAAKsH,MAAQggC,EAEN9gC,EADPxG,KAAK4H,OAAS0/B,IAUxB0J,0BAA2B,SAAS7iC,EAAOC,QACpB,IAAVD,IACTA,EAAQnO,KAAKmO,YAEM,IAAVC,IACTA,EAAQpO,KAAKoO,OAEf,IAmBIlN,EACA4pD,EApBA1sB,EAAap+B,KAAKgiD,+BAClB+I,EAAO3sB,EAAW73B,EAAI,EAAGykD,EAAO5sB,EAAW53B,EAAI,EAC/CU,EAAS,CACP,CACEX,GAAIwkD,EACJvkD,GAAIwkD,GAEN,CACEzkD,EAAGwkD,EACHvkD,GAAIwkD,GAEN,CACEzkD,GAAIwkD,EACJvkD,EAAGwkD,GAEL,CACEzkD,EAAGwkD,EACHvkD,EAAGwkD,IAEJt9B,EAAkB1tB,KAAK4qD,+BAA+Bz8C,EAAOC,GAAO,GAE3E,IAAKlN,EAAI,EAAGA,EAAIgG,EAAOzG,OAAQS,IAC7BgG,EAAOhG,GAAK/C,OAAOiC,KAAKyG,eAAeK,EAAOhG,GAAIwsB,GAGpD,MAAO,CAAEnnB,GADTukD,EAAO3sD,OAAOiC,KAAK6G,0BAA0BC,IAC5BI,MAAOd,EAAGskD,EAAKljD,SAOlCqiD,4BAA6B,WAC3B,IAAIlrB,EAAM/+B,KAAK2jD,uBACX5S,EAAM/wC,KAAKgxC,4BAGf,OAFQ7yC,OAAOiC,KAAKyG,eAAekqC,EAAKhS,GAAK,GAEpCvO,UAAU,EAAIxwB,KAAKgzC,YAtjBlC,GA4jBA70C,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAOvFk4B,WAAY,WAOV,OANIzjC,KAAK44B,MACPz6B,OAAO88B,aAAa1vB,UAAUk4B,WAAW3iC,KAAKd,KAAK44B,MAAO54B,MAG1DA,KAAK2/B,OAAO8D,WAAWzjC,MAElBA,MAQT4jC,aAAc,WAOZ,OANI5jC,KAAK44B,MACPz6B,OAAO88B,aAAa1vB,UAAUq4B,aAAa9iC,KAAKd,KAAK44B,MAAO54B,MAG5DA,KAAK2/B,OAAOiE,aAAa5jC,MAEpBA,MAST6jC,cAAe,SAASC,GAOtB,OANI9jC,KAAK44B,MACPz6B,OAAO88B,aAAa1vB,UAAUs4B,cAAc/iC,KAAKd,KAAK44B,MAAO54B,KAAM8jC,GAGnE9jC,KAAK2/B,OAAOkE,cAAc7jC,KAAM8jC,GAE3B9jC,MASTokC,aAAc,SAASN,GAOrB,OANI9jC,KAAK44B,MACPz6B,OAAO88B,aAAa1vB,UAAU64B,aAAatjC,KAAKd,KAAK44B,MAAO54B,KAAM8jC,GAGlE9jC,KAAK2/B,OAAOyE,aAAapkC,KAAM8jC,GAE1B9jC,MASTsM,OAAQ,SAASpK,GAOf,OANIlC,KAAK44B,MACPz6B,OAAO88B,aAAa1vB,UAAUe,OAAOxL,KAAKd,KAAK44B,MAAO54B,KAAMkC,GAG5DlC,KAAK2/B,OAAOrzB,OAAOtM,KAAMkC,GAEpBlC,QAMX,WAEE,SAASirD,EAAkBvqD,EAAMW,GAC/B,GAAKA,EAGA,CAAA,GAAIA,EAAM43B,OACb,OAAOv4B,EAAO,gBAAkBW,EAAMke,GAAK,MAG3C,IAAI2E,EAAQ,IAAI/lB,OAAOylB,MAAMviB,GACzB6pD,EAAMxqD,EAAO,KAAOwjB,EAAMsQ,QAAU,KACpCtY,EAAUgI,EAAM6J,WAKpB,OAJgB,IAAZ7R,IAEFgvC,GAAOxqD,EAAO,aAAewb,EAAQ1Q,WAAa,MAE7C0/C,EAbP,OAAOxqD,EAAO,WAiBlBvC,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAMvF4/C,aAAc,SAASC,GAErB,IAAIlL,EAAWlgD,KAAKkgD,SAChB5Y,EAActnC,KAAKsnC,YAActnC,KAAKsnC,YAAc,IACpDvC,EAAkB/kC,KAAK+kC,gBAAkB/kC,KAAK+kC,gBAAgBh0B,KAAK,KAAO,OAC1E8zB,EAAgB7kC,KAAK6kC,cAAgB7kC,KAAK6kC,cAAgB,OAC1DC,EAAiB9kC,KAAK8kC,eAAiB9kC,KAAK8kC,eAAiB,QAC7Dsb,EAAmBpgD,KAAKogD,iBAAmBpgD,KAAKogD,iBAAmB,IACnElkC,OAAkC,IAAjBlc,KAAKkc,QAA0Blc,KAAKkc,QAAU,IAC/D4K,EAAa9mB,KAAK2tB,QAAU,GAAK,uBACjCvsB,EAASgqD,EAAa,GAAKprD,KAAKqrD,eAChC/qD,EAAO2qD,EAAkB,OAAQjrD,KAAKM,MAG1C,MAAO,CAFM2qD,EAAkB,SAAUjrD,KAAK+nB,QAI5C,iBAAkBuf,EAAa,KAC/B,qBAAsBvC,EAAiB,KACvC,mBAAoBF,EAAe,KACnC,oBAAqBC,EAAgB,KACrC,sBAAuBsb,EAAkB,KACzC9/C,EACA,cAAe4/C,EAAU,KACzB,YAAahkC,EAAS,IACtB9a,EACA0lB,GACA/V,KAAK,KAOTs6C,aAAc,WACZ,OAAOrrD,KAAK26B,OAAS,sBAAwB36B,KAAK26B,OAAOpb,GAAK,KAAO,IAOvE+rC,SAAU,WACR,OAAOtrD,KAAKuf,GAAK,OAASvf,KAAKuf,GAAK,KAAO,IAO7CgsC,gBAAiB,WACf,GAAIvrD,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,KAC3B,MAAO,GAET,IAAImF,EAAU7J,OAAOiC,KAAK4H,QACtB+F,EAAQ/N,KAAKu8C,WACbpuC,EAASnO,KAAKwrD,WAAa,IAC3Bp9C,EAASpO,KAAKyrD,WAAa,IAC3BlqB,EAASvhC,KAAKohC,iBAEd1H,EAAsBv7B,OAAOmN,OAAOouB,oBAEpCgyB,EAA8B,eAAd1rD,KAAK6C,KAAwB,GAAK,aAChCmF,EAAQu5B,EAAOh7B,EAAGmzB,GAClB,IACA1xB,EAAQu5B,EAAO/6B,EAAGkzB,GACpB,IAEhBiyB,EAAsB,IAAV59C,EACP,WAAa/F,EAAQ+F,EAAO2rB,GAAuB,IACpD,GAEJkyB,EAA6B,IAAhB5rD,KAAKiO,QAAgC,IAAhBjO,KAAKkO,OACnC,GACD,UACClG,EAAQhI,KAAKiO,OAAQyrB,GACrB,IACA1xB,EAAQhI,KAAKkO,OAAQwrB,GACvB,IAEFmyB,EAAsB,IAAV19C,EAAc,UAAYnG,EAAQmG,EAAOurB,GAAuB,IAAM,GAElFoyB,EAAsB,IAAV19C,EAAc,UAAYpG,EAAQoG,EAAOsrB,GAAuB,IAAM,GAElFqyB,EAA8B,eAAd/rD,KAAK6C,KAAwB7C,KAAKsH,MAAQ,EAE1D0kD,EAAYhsD,KAAK6O,MAAQ,oBAAsBk9C,EAAgB,OAAS,GAExEE,EAA8B,eAAdjsD,KAAK6C,KAAwB7C,KAAK4H,OAAS,EAI/D,MAAO,CACL8jD,EAAeC,EAAWC,EAAWI,EAHvBhsD,KAAK8O,MAAQ,sBAAwBm9C,EAAgB,IAAM,GAGdJ,EAAWC,GACtE/6C,KAAK,KAOTm7C,sBAAuB,WACrB,OAAOlsD,KAAK0tB,gBAAkB,WAAa1tB,KAAK0tB,gBAAgB3c,KAAK,KAAO,KAAO,IAMrFo7C,qBAAsB,WACpB,IAAI3zB,EAAS,GAWb,OATIx4B,KAAKM,MAAQN,KAAKM,KAAK24B,QACzBT,EAAO53B,KAAKZ,KAAKM,KAAKi4B,MAAMv4B,MAAM,IAEhCA,KAAK+nB,QAAU/nB,KAAK+nB,OAAOkR,QAC7BT,EAAO53B,KAAKZ,KAAK+nB,OAAOwQ,MAAMv4B,MAAM,IAElCA,KAAK26B,QACPnC,EAAO53B,KAAKZ,KAAK26B,OAAOpC,MAAMv4B,OAEzBw4B,KAlJb,GAyJA,WAEE,IAAIphB,EAASjZ,OAAOiC,KAAK6B,OAAOmV,OAC5Bg1C,EAAc,kBAKlB,SAASC,EAAUnmD,EAAQkF,EAAakhD,GACtC,IAAIC,EAAS,GACbD,EAAMjiD,QAAQ,SAAS3J,GACrB6rD,EAAO7rD,GAAQwF,EAAOxF,KAExB0W,EAAOlR,EAAOkF,GAAcmhD,GAJH,GAuC3BpuD,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAOvFyvC,gBAAiB,SAASoJ,GAExB,IAAIoI,EAAoB,KADxBpI,EAAcA,GAAegI,GAE7B,OAAI9gD,OAAOmhD,KAAKzsD,KAAKwsD,IAAoB/rD,OAAST,KAAKokD,GAAa3jD,SA1CxE,SAASisD,EAASC,EAAWC,EAAcC,GACzC,GAAIF,IAAcC,EAEhB,OAAO,EAEJ,GAAI97C,MAAM0c,QAAQm/B,GAAY,CACjC,GAAIA,EAAUlsD,SAAWmsD,EAAansD,OACpC,OAAO,EAET,IAAK,IAAIS,EAAI,EAAGC,EAAMwrD,EAAUlsD,OAAQS,EAAIC,EAAKD,IAC/C,IAAKwrD,EAASC,EAAUzrD,GAAI0rD,EAAa1rD,IACvC,OAAO,EAGX,OAAO,EAEJ,GAAIyrD,GAAkC,iBAAdA,EAAwB,CACnD,IAAmCjoD,EAA/B+nD,EAAOnhD,OAAOmhD,KAAKE,GACvB,IAAKE,GAAaJ,EAAKhsD,SAAW6K,OAAOmhD,KAAKG,GAAcnsD,OAC1D,OAAO,EAET,IAASS,EAAI,EAAGC,EAAMsrD,EAAKhsD,OAAQS,EAAIC,EAAKD,IAE1C,IAAKwrD,EAASC,EADdjoD,EAAM+nD,EAAKvrD,IACmB0rD,EAAaloD,IACzC,OAAO,EAGX,OAAO,GAkBCgoD,CAAS1sD,KAAKwsD,GAAoBxsD,MAAM,IAQlD07C,UAAW,SAAS16C,GAClB,IAAIojD,EAAcpjD,GAAWA,EAAQojD,aAAegI,EAChDhhD,EAAc,IAAMg5C,EACxB,OAAKpkD,KAAKoL,IAGVihD,EAAUrsD,KAAMoL,EAAapL,KAAKokD,IAC9BpjD,GAAWA,EAAQsM,iBACrB++C,EAAUrsD,KAAMoL,EAAapK,EAAQsM,iBAEhCtN,MANEA,KAAK0/B,WAAW1+B,IAc3B0+B,WAAY,SAAS1+B,GAEnB,IAAIojD,GADJpjD,EAAUA,GAAW,IACKojD,aAAegI,EAIzC,OAFApsD,KAAK,KADLgB,EAAQojD,YAAcA,IACI,GAC1BpkD,KAAK07C,UAAU16C,GACRhB,QA7Fb,GAmGA,WAEE,IAAI4F,EAAmBzH,OAAOiC,KAAKwF,iBAInCzH,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAMvFuhD,oBAAqB,KAQrBnf,kBAAmB,SAAS3H,GAC1B,IAAKhmC,KAAKwgD,cAAgBxgD,KAAKsuC,OAC7B,OAAO,EAGT,IAEInnC,EACA8hD,EAHAha,EAAKjJ,EAAQz/B,EACb2oC,EAAKlJ,EAAQx/B,EAIjB,IAAK,IAAItF,KADTlB,KAAK06C,SAAW,EACF16C,KAAKwoD,QAEjB,GAAKxoD,KAAK+sD,iBAAiB7rD,KAIjB,QAANA,GAAgBlB,KAAKs8C,qBAIrBt8C,KAAK2E,IAAI,mBACH,OAANzD,GAAoB,OAANA,GAAoB,OAANA,GAAoB,OAANA,KAI9C+nD,EAAQjpD,KAAKkpD,eAAelpD,KAAKwoD,QAAQtnD,GAAG4tC,QAiB5B,KADhB3nC,EAAUnH,KAAKmpD,iBAAiB,CAAE5iD,EAAG0oC,EAAIzoC,EAAG0oC,GAAM+Z,KAC7B9hD,EAAU,GAAM,GAEnC,OADAnH,KAAK06C,SAAWx5C,EAIpB,OAAO,GAQTspD,iBAAkB,WAChB,IAOIjkD,EAAGC,EAPHiP,EAASzV,KAAKwoD,QACdwE,EAAWpnD,EAAiB,GAAK5F,KAAK+N,OAGtCk/C,EAAqC,QAAlBjtD,KAAK2/C,WACxBuN,EAAgBD,EAAmBloD,KAAK6B,IAAIomD,GAC5CG,EAAgBF,EAAmBloD,KAAK4B,IAAIqmD,GAGhD,IAAK,IAAI/mD,KAASwP,EAChBlP,EAAIkP,EAAOxP,GAAOM,EAClBC,EAAIiP,EAAOxP,GAAOO,EAClBiP,EAAOxP,GAAO6oC,OAAS,CACrBzO,GAAI,CACF95B,EAAGA,EAAI4mD,EACP3mD,EAAGA,EAAI0mD,GAET3sB,GAAI,CACFh6B,EAAGA,EAAI2mD,EACP1mD,EAAGA,EAAI2mD,GAET3sB,GAAI,CACFj6B,EAAGA,EAAI2mD,EACP1mD,EAAGA,EAAI2mD,GAET7sB,GAAI,CACF/5B,EAAGA,EAAI4mD,EACP3mD,EAAGA,EAAI0mD,KAeflJ,wBAAyB,SAASt4C,GAChC,IAAK1L,KAAKquC,0BAA4BruC,KAAK44B,QAAU54B,KAAKsuC,QACvDtuC,KAAK2/B,SAAW3/B,KAAK2/B,OAAOnD,YAC7B,OAAOx8B,KAET0L,EAAIU,OACJ,IAAIm1B,EAASvhC,KAAKohC,iBAAkBgsB,EAAKptD,KAAKiqD,8BAC1ClrB,EAAM/+B,KAAK2/B,OAAO9D,kBAOtB,OANAnwB,EAAIW,UAAUk1B,EAAOh7B,EAAGg7B,EAAO/6B,GAC/BkF,EAAIyxB,MAAM,EAAI4B,EAAI,GAAI,EAAIA,EAAI,IAC9BrzB,EAAIa,OAAO3G,EAAiB5F,KAAK+N,QACjCrC,EAAIq1B,UAAY/gC,KAAKquC,yBACrB3iC,EAAIs1B,UAAUosB,EAAG7mD,EAAI,GAAI6mD,EAAG5mD,EAAI,EAAG4mD,EAAG7mD,EAAG6mD,EAAG5mD,GAC5CkF,EAAIc,UACGxM,MAWTolD,YAAa,SAAS15C,GACpB,IAAK1L,KAAKiuC,WACR,OAAOjuC,KAGT,IAAIotD,EAAKptD,KAAKiqD,8BACV3iB,EAAc,EAAItnC,KAAKsgD,kBACvBh5C,EAAQ8lD,EAAG7mD,EAAI+gC,EACf1/B,EAASwlD,EAAG5mD,EAAI8gC,EAapB,GAXA57B,EAAIU,OACJV,EAAIy5B,YAAcnlC,KAAK4/C,YACvB5/C,KAAK6zC,aAAanoC,EAAK1L,KAAK6/C,gBAAiB,MAE7Cn0C,EAAIooC,YACDxsC,EAAQ,GACRM,EAAS,EACVN,EACAM,GAGE5H,KAAKs8C,kBAAoBt8C,KAAK+sD,iBAAiB,SAAW/sD,KAAK2E,IAAI,iBAAmB3E,KAAKwgD,YAAa,CAE1G,IAAI6M,GAAgBzlD,EAAS,EAE7B8D,EAAI+B,YACJ/B,EAAIY,OAAO,EAAG+gD,GACd3hD,EAAIo7B,OAAO,EAAGumB,EAAertD,KAAKygD,qBAClC/0C,EAAIg8B,YACJh8B,EAAIqc,SAIN,OADArc,EAAIc,UACGxM,MAYTmlD,mBAAoB,SAASz5C,EAAK1K,GAChC,IAAKhB,KAAKiuC,WACR,OAAOjuC,KAGT,IAAI8G,EAAI9G,KAAKgiD,+BACTz4B,EAASprB,OAAOiC,KAAKmO,sBAAsBvN,EAAQiN,OAAQjN,EAAQkN,OAAQlN,EAAQmN,OACnFi/C,EAAKjvD,OAAOiC,KAAKyG,eAAeC,EAAGyiB,GACnC+d,EAAc,EAAItnC,KAAKsgD,kBACvBh5C,EAAQ8lD,EAAG7mD,EAAI+gC,EACf1/B,EAASwlD,EAAG5mD,EAAI8gC,EAcpB,OAZA57B,EAAIU,OACJpM,KAAK6zC,aAAanoC,EAAK1L,KAAK6/C,gBAAiB,MAC7Cn0C,EAAIy5B,YAAcnlC,KAAK4/C,YAEvBl0C,EAAIooC,YACDxsC,EAAQ,GACRM,EAAS,EACVN,EACAM,GAGF8D,EAAIc,UACGxM,MAWT2gC,aAAc,SAASj1B,GACrB,IAAK1L,KAAKwgD,YACR,OAAOxgD,KAGT,IAAIotD,EAAKptD,KAAKiqD,8BACV3iD,EAAQ8lD,EAAG7mD,EACXqB,EAASwlD,EAAG5mD,EACZ8mD,EAActtD,KAAK2/C,WACnBj4C,IAASJ,EAAQgmD,GAAe,EAChC3lD,IAAQC,EAAS0lD,GAAe,EAChCv0C,EAAa/Y,KAAKkuC,mBAAqB,SAAW,OA6DtD,OA3DAxiC,EAAIU,OACJV,EAAIy5B,YAAcz5B,EAAIq1B,UAAY/gC,KAAK8/C,YAClC9/C,KAAKkuC,qBACRxiC,EAAIy5B,YAAcnlC,KAAK+/C,mBAEzB//C,KAAK6zC,aAAanoC,EAAK1L,KAAKigD,gBAAiB,MAG7CjgD,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EACAC,GAGF3H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EAAOJ,EACPK,GAGF3H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EACAC,EAAMC,GAGR5H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EAAOJ,EACPK,EAAMC,GAEH5H,KAAK2E,IAAI,oBAGZ3E,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EAAOJ,EAAQ,EACfK,GAGF3H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EAAOJ,EAAQ,EACfK,EAAMC,GAGR5H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EAAOJ,EACPK,EAAMC,EAAS,GAGjB5H,KAAKutD,aAAa,KAAM7hD,EAAKqN,EAC3BrR,EACAC,EAAMC,EAAS,IAIf5H,KAAKs8C,kBACPt8C,KAAKutD,aAAa,MAAO7hD,EAAKqN,EAC5BrR,EAAOJ,EAAQ,EACfK,EAAM3H,KAAKygD,qBAGf/0C,EAAIc,UAEGxM,MAMTutD,aAAc,SAASC,EAAS9hD,EAAKqN,EAAYrR,EAAMC,GACrD,GAAK3H,KAAK+sD,iBAAiBS,GAA3B,CAGA,IAAIvqD,EAAOjD,KAAK2/C,WAAY53B,GAAU/nB,KAAKkuC,oBAAsBluC,KAAK+/C,kBACtE,OAAQ//C,KAAKggD,aACX,IAAK,SACHt0C,EAAI+B,YACJ/B,EAAIo8B,IAAIpgC,EAAOzE,EAAO,EAAG0E,EAAM1E,EAAO,EAAGA,EAAO,EAAG,EAAG,EAAI8B,KAAKK,IAAI,GACnEsG,EAAIqN,KACAgP,GACFrc,EAAIqc,SAEN,MACF,QAvTwD,oBAAvBlb,oBAwTpB7M,KAAKkuC,oBAAsBxiC,EAAIm0B,UAAUn4B,EAAMC,EAAK1E,EAAMA,GACrEyI,EAAIqN,EAAa,QAAQrR,EAAMC,EAAK1E,EAAMA,GACtC8kB,GACFrc,EAAIooC,WAAWpsC,EAAMC,EAAK1E,EAAMA,MAUxC8pD,iBAAkB,SAASU,GACzB,OAAOztD,KAAK0tD,yBAAyBD,IAUvCE,kBAAmB,SAASF,EAAa9/B,GAEvC,OADA3tB,KAAK0tD,yBAAyBD,GAAe9/B,EACtC3tB,MAkBT4tD,sBAAuB,SAAS5sD,GAG9B,IAAK,IAAI8F,KAFT9F,IAAYA,EAAU,IAERA,EACZhB,KAAK2tD,kBAAkB7mD,EAAG9F,EAAQ8F,IAEpC,OAAO9G,MAQT0tD,uBAAwB,WActB,OAbK1tD,KAAK8sD,sBACR9sD,KAAK8sD,oBAAsB,CACzBzsB,IAAI,EACJE,IAAI,EACJD,IAAI,EACJE,IAAI,EACJkX,IAAI,EACJviC,IAAI,EACJqiC,IAAI,EACJC,IAAI,EACJ6S,KAAK,IAGFtqD,KAAK8sD,uBApYlB,GA0YA3uD,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO88B,aAAa1vB,UAAuD,CAOnGsiD,YAAa,IAWbC,gBAAiB,SAAU7rD,EAAQ8rD,GAGjC,IAAIC,EAAQ,aACR5sC,GAHJ2sC,EAAYA,GAAa,IAGE3sC,YAAc4sC,EACrCrrC,EAAWorC,EAAUprC,UAAYqrC,EACjC71C,EAAQnY,KAiBZ,OAfA7B,OAAOiC,KAAKgiB,QAAQ,CAClBW,WAAY9gB,EAAO0C,IAAI,QACvBqe,SAAUhjB,KAAKihC,YAAYv5B,KAC3B+a,SAAUziB,KAAK6tD,YACflrC,SAAU,SAASthB,GACjBY,EAAOwB,IAAI,OAAQpC,GACnB8W,EAAMpW,YACN4gB,KAEFvB,WAAY,WACVnf,EAAOi9B,YACP9d,OAIGphB,MAYTiuD,gBAAiB,SAAUhsD,EAAQ8rD,GAGjC,IAAIC,EAAQ,aACR5sC,GAHJ2sC,EAAYA,GAAa,IAGE3sC,YAAc4sC,EACrCrrC,EAAWorC,EAAUprC,UAAYqrC,EACjC71C,EAAQnY,KAiBZ,OAfA7B,OAAOiC,KAAKgiB,QAAQ,CAClBW,WAAY9gB,EAAO0C,IAAI,OACvBqe,SAAUhjB,KAAKihC,YAAYt5B,IAC3B8a,SAAUziB,KAAK6tD,YACflrC,SAAU,SAASthB,GACjBY,EAAOwB,IAAI,MAAOpC,GAClB8W,EAAMpW,YACN4gB,KAEFvB,WAAY,WACVnf,EAAOi9B,YACP9d,OAIGphB,MAYTkuD,SAAU,SAAUjsD,EAAQ8rD,GAG1B,IAAIC,EAAQ,aACR5sC,GAHJ2sC,EAAYA,GAAa,IAGE3sC,YAAc4sC,EACrCrrC,EAAWorC,EAAUprC,UAAYqrC,EACjC71C,EAAQnY,KAoBZ,OAlBA7B,OAAOiC,KAAKgiB,QAAQ,CAClBW,WAAY9gB,EAAO0C,IAAI,WACvBqe,SAAU,EACVP,SAAUziB,KAAK6tD,YACf3qC,QAAS,WACPjhB,EAAOwB,IAAI,UAAU,IAEvBkf,SAAU,SAASthB,GACjBY,EAAOwB,IAAI,UAAWpC,GACtB8W,EAAMpW,YACN4gB,KAEFvB,WAAY,WACVjJ,EAAM5V,OAAON,GACbmf,OAIGphB,QAIX7B,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAoBvF6W,QAAS,WACP,GAAI5hB,UAAU,IAA8B,iBAAjBA,UAAU,GAAiB,CACpD,IAAyBE,EAAMytD,EAA3BC,EAAiB,GACrB,IAAK1tD,KAAQF,UAAU,GACrB4tD,EAAextD,KAAKF,GAEtB,IAAK,IAAIQ,EAAI,EAAGC,EAAMitD,EAAe3tD,OAAQS,EAAIC,EAAKD,IACpDR,EAAO0tD,EAAeltD,GACtBitD,EAAgBjtD,IAAMC,EAAM,EAC5BnB,KAAKquD,SAAS3tD,EAAMF,UAAU,GAAGE,GAAOF,UAAU,GAAI2tD,QAIxDnuD,KAAKquD,SAASzsD,MAAM5B,KAAMQ,WAE5B,OAAOR,MAUTquD,SAAU,SAASzqD,EAAUmkD,EAAI/mD,EAASmtD,GACxC,IAAkBG,EAAdn2C,EAAQnY,KAEZ+nD,EAAKA,EAAGv8C,WAMNxK,EAJGA,EAIO7C,OAAOiC,KAAK6B,OAAOuV,MAAMxW,GAHzB,IAMP4C,EAASzD,QAAQ,OACpBmuD,EAAW1qD,EAASyF,MAAM,MAG5B,IAAIujD,EAAe0B,EACftuD,KAAK2E,IAAI2pD,EAAS,IAAIA,EAAS,IAC/BtuD,KAAK2E,IAAIf,GAEP,SAAU5C,IACdA,EAAQutD,KAAO3B,GAIf7E,GADGA,EAAG5nD,QAAQ,KACTysD,EAAezkD,WAAW4/C,EAAGrwC,QAAQ,IAAK,KAG1CvP,WAAW4/C,GAGlB5pD,OAAOiC,KAAKgiB,QAAQ,CAClBW,WAAY/hB,EAAQutD,KACpBvrC,SAAU+kC,EACV9kC,QAASjiB,EAAQ8uC,GACjBjtB,OAAQ7hB,EAAQ6hB,OAChBJ,SAAUzhB,EAAQyhB,SAClBG,MAAO5hB,EAAQ4hB,OAAS,WACtB,OAAO5hB,EAAQ4hB,MAAM9hB,KAAKqX,IAE5BwK,SAAU,SAASthB,EAAOmtD,EAAeC,GACnCH,EACFn2C,EAAMm2C,EAAS,IAAIA,EAAS,IAAMjtD,EAGlC8W,EAAM1U,IAAIG,EAAUvC,GAElB8sD,GAGJntD,EAAQ2hB,UAAY3hB,EAAQ2hB,SAASthB,EAAOmtD,EAAeC,IAE7DrtC,WAAY,SAAS/f,EAAOmtD,EAAeC,GACrCN,IAIJh2C,EAAM+mB,YACNl+B,EAAQogB,YAAcpgB,EAAQogB,WAAW/f,EAAOmtD,EAAeC,UAOvE,SAAU5pD,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5BI,EAAQrZ,EAAOiC,KAAK6B,OAAOuV,MAC3Bk3C,EAAa,CAAEl6C,GAAI,EAAG7I,GAAI,EAAG8I,GAAI,EAAG7I,GAAI,GACxC6zC,EAAmBthD,EAAO88B,aAAawJ,SAAS,eAuUpD,SAASkqB,EAAuBC,EAAeC,GAC7C,IAAI3oD,EAAS0oD,EAAc1oD,OACvB4oD,EAAQF,EAAcE,MACtBC,EAAQH,EAAcG,MACtBC,EAAYJ,EAAcI,UAC1BC,EAAUJ,EAAaI,QACvB1tB,EAASstB,EAAattB,OACtB2tB,EAAWL,EAAaK,SAE5B,OAAO,WACL,OAAQlvD,KAAK2E,IAAIuB,IACf,KAAK+oD,EACH,OAAOlqD,KAAKS,IAAIxF,KAAK2E,IAAImqD,GAAQ9uD,KAAK2E,IAAIoqD,IAC5C,KAAKxtB,EACH,OAAOx8B,KAAKS,IAAIxF,KAAK2E,IAAImqD,GAAQ9uD,KAAK2E,IAAIoqD,IAAW,GAAM/uD,KAAK2E,IAAIqqD,GACtE,KAAKE,EACH,OAAOnqD,KAAKU,IAAIzF,KAAK2E,IAAImqD,GAAQ9uD,KAAK2E,IAAIoqD,MArV9C5wD,EAAOgxD,KACThxD,EAAOujB,KAAK,mCAUdvjB,EAAOgxD,KAAOhxD,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA4C,CAOvFzI,KAAM,OAON2R,GAAI,EAOJC,GAAI,EAOJ9I,GAAI,EAOJC,GAAI,EAEJq1C,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,KAAM,KAAM,KAAM,MAQlFgB,WAAY,SAASlS,EAAQlG,GACtBkG,IACHA,EAAS,CAAC,EAAG,EAAG,EAAG,IAGrBlH,KAAK8Y,UAAU,aAAc9X,GAE7BhB,KAAKyD,IAAI,KAAMyD,EAAO,IACtBlH,KAAKyD,IAAI,KAAMyD,EAAO,IACtBlH,KAAKyD,IAAI,KAAMyD,EAAO,IACtBlH,KAAKyD,IAAI,KAAMyD,EAAO,IAEtBlH,KAAKovD,gBAAgBpuD,IAOvBouD,gBAAiB,SAASpuD,GACxBA,IAAYA,EAAU,IAEtBhB,KAAKsH,MAAQvC,KAAKG,IAAIlF,KAAK2L,GAAK3L,KAAKwU,IACrCxU,KAAK4H,OAAS7C,KAAKG,IAAIlF,KAAK4L,GAAK5L,KAAKyU,IAEtCzU,KAAK0H,KAAO,SAAU1G,EAClBA,EAAQ0G,KACR1H,KAAKqvD,oBAETrvD,KAAK2H,IAAM,QAAS3G,EAChBA,EAAQ2G,IACR3H,KAAKsvD,oBAQX7qD,KAAM,SAASC,EAAKrD,GAKlB,OAJArB,KAAK8Y,UAAU,OAAQpU,EAAKrD,QACG,IAApBqtD,EAAWhqD,IACpB1E,KAAKovD,kBAEApvD,MAOTqvD,kBAAmBV,EACjB,CACEzoD,OAAQ,UACR4oD,MAAO,KACPC,MAAO,KACPC,UAAW,SAEb,CACEC,QAAS,OACT1tB,OAAQ,SACR2tB,SAAU,UAQdI,iBAAkBX,EAChB,CACEzoD,OAAQ,UACR4oD,MAAO,KACPC,MAAO,KACPC,UAAW,UAEb,CACEC,QAAS,MACT1tB,OAAQ,SACR2tB,SAAU,WASd/oB,QAAS,SAASz6B,EAAKm4C,GAGrB,GAFAn4C,EAAI+B,YAEAo2C,EAAa,CAIf,IAAI0L,EAAKvvD,KAAKohC,iBACVjhB,EAASngB,KAAKsnC,YAAc,EAChC57B,EAAIW,UACFkjD,EAAGhpD,GAA4B,SAAvBvG,KAAK6kC,eAA4C,IAAhB7kC,KAAK4H,OAAe,EAAIuY,GACjEovC,EAAG/oD,GAA4B,SAAvBxG,KAAK6kC,eAA2C,IAAf7kC,KAAKsH,MAAc,EAAI6Y,IAIpE,IAAKngB,KAAK+kC,iBAAmB/kC,KAAK+kC,iBAAmB0a,EAAkB,CAGrE,IAAI34C,EAAI9G,KAAKwvD,iBACb9jD,EAAIY,OAAOxF,EAAE0N,GAAI1N,EAAE2N,IACnB/I,EAAIo7B,OAAOhgC,EAAE6E,GAAI7E,EAAE8E,IAGrBF,EAAI05B,UAAYplC,KAAKsnC,YAKrB,IAAImoB,EAAkB/jD,EAAIy5B,YAC1Bz5B,EAAIy5B,YAAcnlC,KAAK+nB,QAAUrc,EAAIq1B,UACrC/gC,KAAK+nB,QAAU/nB,KAAK0lD,cAAch6C,GAClCA,EAAIy5B,YAAcsqB,GAOpB9J,oBAAqB,SAASj6C,GAC5B,IAAI5E,EAAI9G,KAAKwvD,iBAEb9jD,EAAI+B,YACJtP,EAAOiC,KAAKqL,eAAeC,EAAK5E,EAAE0N,GAAI1N,EAAE2N,GAAI3N,EAAE6E,GAAI7E,EAAE8E,GAAI5L,KAAK+kC,iBAC7Dr5B,EAAIg8B,aASNrP,SAAU,SAASC,GACjB,OAAOlhB,EAAOpX,KAAK8Y,UAAU,WAAYwf,GAAsBt4B,KAAKwvD,mBAOtExN,6BAA8B,WAC5B,IAAIjR,EAAM/wC,KAAK8Y,UAAU,gCASzB,MAR2B,SAAvB9Y,KAAK6kC,gBACY,IAAf7kC,KAAKsH,QACPypC,EAAIvqC,GAAKxG,KAAKsnC,aAEI,IAAhBtnC,KAAK4H,SACPmpC,EAAIxqC,GAAKvG,KAAKsnC,cAGXyJ,GAOTye,eAAgB,WACd,IAAIE,EAAQ1vD,KAAKwU,IAAMxU,KAAK2L,IAAM,EAAI,EAClCgkD,EAAQ3vD,KAAKyU,IAAMzU,KAAK4L,IAAM,EAAI,EAClC4I,EAAMk7C,EAAQ1vD,KAAKsH,MAAQ,GAC3BmN,EAAMk7C,EAAQ3vD,KAAK4H,OAAS,GAIhC,MAAO,CACL4M,GAAIA,EACJ7I,GALQ+jD,EAAQ1vD,KAAKsH,OAAS,GAM9BmN,GAAIA,EACJ7I,GANQ+jD,EAAQ3vD,KAAK4H,QAAU,KAgBnC2wB,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBACdrlD,EAAI,CAAE0N,GAAIxU,KAAKwU,GAAI7I,GAAI3L,KAAK2L,GAAI8I,GAAIzU,KAAKyU,GAAI7I,GAAI5L,KAAK4L,IAiB1D,OAfM5L,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC7BiE,EAAI9G,KAAKwvD,kBAEXh3B,EAAO53B,KACL,SAAUZ,KAAKsrD,WACb,OAAQxkD,EAAE0N,GACV,SAAU1N,EAAE2N,GACZ,SAAU3N,EAAE6E,GACZ,SAAU7E,EAAE8E,GACZ,YAAa5L,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtBvrD,KAAKksD,wBACP,SAGKliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,OAY5D5S,EAAOgxD,KAAKS,gBAAkBzxD,EAAOa,kBAAkBoZ,OAAO,cAAc/O,MAAM,MAUlFlL,EAAOgxD,KAAKn/B,YAAc,SAASjW,EAAS/Y,GAC1CA,EAAUA,GAAW,GACrB,IAAI6uD,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOgxD,KAAKS,iBAC/D1oD,EAAS,CACP2oD,EAAiBr7C,IAAM,EACvBq7C,EAAiBp7C,IAAM,EACvBo7C,EAAiBlkD,IAAM,EACvBkkD,EAAiBjkD,IAAM,GAI7B,OAFA5K,EAAQumC,QAAU,OAClBvmC,EAAQwmC,QAAU,MACX,IAAIrpC,EAAOgxD,KAAKjoD,EAAQkQ,EAAOy4C,EAAkB7uD,KAa1D7C,EAAOgxD,KAAK7kD,WAAa,SAASrI,EAAQU,EAAUwkD,GAKlD,IAAInmD,EAAUwW,EAAMvV,GAAQ,GAC5BjB,EAAQkG,OAAS,CAACjF,EAAOuS,GAAIvS,EAAOwS,GAAIxS,EAAO0J,GAAI1J,EAAO2J,IAC1D,IAAIkkD,EAAO3xD,EAAOmN,OAAO47C,YAAY,OAAQlmD,EAN7C,SAAmBq4B,UACVA,EAASnyB,OAChBvE,GAAYA,EAAS02B,IAI0C8tB,EAAY,UAI7E,OAHI2I,UACKA,EAAK5oD,OAEP4oD,IAzUX,CAqWsB,oBAAZzxD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3C4xD,EAAKhrD,KAAKK,GACVgS,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAE5BjZ,EAAOgqC,OACThqC,EAAOujB,KAAK,sCAUdvjB,EAAOgqC,OAAShqC,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA8C,CAO3FzI,KAAM,SAONklC,OAAQ,EAORioB,WAAY,EAOZC,SAAe,EAALF,EAEV9O,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,UAOhEgB,WAAY,SAASpY,GACnBhB,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKyD,IAAI,SAAUzC,GAAWA,EAAQ+mC,QAAU,IASlDtjC,KAAM,SAASC,EAAKrD,GAOlB,OANArB,KAAK8Y,UAAU,OAAQpU,EAAKrD,GAEhB,WAARqD,GACF1E,KAAKkwD,UAAU7uD,GAGVrB,MAQTq4B,SAAU,SAASC,GACjB,OAAOt4B,KAAK8Y,UAAU,WAAY,CAAC,SAAU,aAAc,YAAYV,OAAOkgB,KAShFC,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBAAwB5lD,EAAI,EAAGC,EAAI,EACjDuH,GAAS/N,KAAKiwD,SAAWjwD,KAAKgwD,aAAgB,EAAID,GAEtD,GAAc,IAAVhiD,EACE/N,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC3B0D,EAAIvG,KAAK0H,KAAO1H,KAAK+nC,OACrBvhC,EAAIxG,KAAK2H,IAAM3H,KAAK+nC,QAEtBvP,EAAO53B,KACL,WAAYZ,KAAKsrD,WACf,OAAS/kD,EAAI,SAAWC,EAAI,KAC5B,MAAOxG,KAAK+nC,OACZ,YAAa/nC,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtB,IAAKvrD,KAAKksD,wBACZ,aAGC,CACH,IAAIiE,EAASprD,KAAK6B,IAAI5G,KAAKgwD,YAAchwD,KAAK+nC,OAC1CqoB,EAASrrD,KAAK4B,IAAI3G,KAAKgwD,YAAchwD,KAAK+nC,OAC1CsoB,EAAOtrD,KAAK6B,IAAI5G,KAAKiwD,UAAYjwD,KAAK+nC,OACtCuoB,EAAOvrD,KAAK4B,IAAI3G,KAAKiwD,UAAYjwD,KAAK+nC,OACtCwoB,EAAoBR,EAARhiD,EAAa,IAAM,IAEnCyqB,EAAO53B,KACL,cAAgBuvD,EAAS,IAAMC,EAC/B,MAAQpwD,KAAK+nC,OAAS,IAAM/nC,KAAK+nC,OACjC,OAAQwoB,EAAY,KAAM,IAAMF,EAAO,IAAMC,EAC7C,YAAatwD,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtB,IAAKvrD,KAAKksD,wBACV,SAIJ,OAAOliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAS1Do1B,QAAS,SAASz6B,EAAKm4C,GACrBn4C,EAAI+B,YACJ/B,EAAIo8B,IAAI+b,EAAc7jD,KAAK0H,KAAO1H,KAAK+nC,OAAS,EACxC8b,EAAc7jD,KAAK2H,IAAM3H,KAAK+nC,OAAS,EACvC/nC,KAAK+nC,OACL/nC,KAAKgwD,WACLhwD,KAAKiwD,UAAU,GACvBjwD,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,IAOrB8kD,WAAY,WACV,OAAOxwD,KAAK2E,IAAI,UAAY3E,KAAK2E,IAAI,WAOvC8rD,WAAY,WACV,OAAOzwD,KAAK2E,IAAI,UAAY3E,KAAK2E,IAAI,WAOvCurD,UAAW,SAAS7uD,GAElB,OADArB,KAAK+nC,OAAS1mC,EACPrB,KAAKyD,IAAI,QAAiB,EAARpC,GAAWoC,IAAI,SAAkB,EAARpC,MAWtDlD,EAAOgqC,OAAOynB,gBAAkBzxD,EAAOa,kBAAkBoZ,OAAO,UAAU/O,MAAM,MAWhFlL,EAAOgqC,OAAOnY,YAAc,SAASjW,EAAS/Y,GAC5CA,IAAYA,EAAU,IAEtB,IAmBqByc,EAnBjBoyC,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOgqC,OAAOynB,iBAErE,KAkBS,WADYnyC,EAjBFoyC,IAkBuC,GAArBpyC,EAAWsqB,QAjB9C,MAAM,IAAI5M,MAAM,8DAGlB00B,EAAiBnoD,KAAOmoD,EAAiBnoD,MAAQ,EACjDmoD,EAAiBloD,IAAMkoD,EAAiBloD,KAAO,EAE/C,IAAInD,EAAM,IAAIrG,EAAOgqC,OAAO/wB,EAAOy4C,EAAkB7uD,IAIrD,OAFAwD,EAAIkD,MAAQlD,EAAIujC,OAChBvjC,EAAImD,KAAOnD,EAAIujC,OACRvjC,GAoBTrG,EAAOgqC,OAAO79B,WAAa,SAASrI,EAAQU,EAAUwkD,GACpD,OAAOhpD,EAAOmN,OAAO47C,YAAY,SAAUjlD,EAAQU,EAAUwkD,KAtOjE,CAyOsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAE3CA,EAAOuyD,SACTvyD,EAAOujB,KAAK,uCAWdvjB,EAAOuyD,SAAWvyD,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAAgD,CAO/FzI,KAAM,WAONuW,WAAY,SAASpY,GACnBhB,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKyD,IAAI,QAASzC,GAAWA,EAAQsG,OAAS,KACzC7D,IAAI,SAAUzC,GAAWA,EAAQ4G,QAAU,MAOlDu+B,QAAS,SAASz6B,GAChB,IAAIilD,EAAW3wD,KAAKsH,MAAQ,EACxBspD,EAAY5wD,KAAK4H,OAAS,EAE9B8D,EAAI+B,YACJ/B,EAAIY,QAAQqkD,EAAUC,GACtBllD,EAAIo7B,OAAO,GAAI8pB,GACfllD,EAAIo7B,OAAO6pB,EAAUC,GACrBllD,EAAIg8B,YAEJ1nC,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,IAOrBi6C,oBAAqB,SAASj6C,GAC5B,IAAIilD,EAAW3wD,KAAKsH,MAAQ,EACxBspD,EAAY5wD,KAAK4H,OAAS,EAE9B8D,EAAI+B,YACJtP,EAAOiC,KAAKqL,eAAeC,GAAMilD,EAAUC,EAAW,GAAIA,EAAW5wD,KAAK+kC,iBAC1E5mC,EAAOiC,KAAKqL,eAAeC,EAAK,GAAIklD,EAAWD,EAAUC,EAAW5wD,KAAK+kC,iBACzE5mC,EAAOiC,KAAKqL,eAAeC,EAAKilD,EAAUC,GAAYD,EAAUC,EAAW5wD,KAAK+kC,iBAChFr5B,EAAIg8B,aASNnP,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBACdwE,EAAW3wD,KAAKsH,MAAQ,EACxBspD,EAAY5wD,KAAK4H,OAAS,EAC1BV,EAAS,EACNypD,EAAW,IAAMC,EAClB,MAAQA,EACRD,EAAW,IAAMC,GAElB7/C,KAAK,KAUV,OARAynB,EAAO53B,KACL,YAAaZ,KAAKsrD,WAChB,WAAYpkD,EACZ,YAAalH,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACxB,OAGKvhD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,OAc5D5S,EAAOuyD,SAASpmD,WAAa,SAASrI,EAAQU,EAAUwkD,GACtD,OAAOhpD,EAAOmN,OAAO47C,YAAY,WAAYjlD,EAAQU,EAAUwkD,KA/GnE,CAkHsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3C0yD,EAAoB,EAAV9rD,KAAKK,GACfgS,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAE5BjZ,EAAO2yD,QACT3yD,EAAOujB,KAAK,uCAWdvjB,EAAO2yD,QAAU3yD,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA+C,CAO7FzI,KAAM,UAONsO,GAAM,EAONC,GAAM,EAEN6vC,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,KAAM,MAOtEgB,WAAY,SAASpY,GACnBhB,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKyD,IAAI,KAAMzC,GAAWA,EAAQmQ,IAAM,GACxCnR,KAAKyD,IAAI,KAAMzC,GAAWA,EAAQoQ,IAAM,IAS1C3M,KAAM,SAASC,EAAKrD,GAElB,OADArB,KAAK8Y,UAAU,OAAQpU,EAAKrD,GACpBqD,GAEN,IAAK,KACH1E,KAAKmR,GAAK9P,EACVrB,KAAKyD,IAAI,QAAiB,EAARpC,GAClB,MAEF,IAAK,KACHrB,KAAKoR,GAAK/P,EACVrB,KAAKyD,IAAI,SAAkB,EAARpC,GAIvB,OAAOrB,MAOT+wD,MAAO,WACL,OAAO/wD,KAAK2E,IAAI,MAAQ3E,KAAK2E,IAAI,WAOnCqsD,MAAO,WACL,OAAOhxD,KAAK2E,IAAI,MAAQ3E,KAAK2E,IAAI,WAQnC0zB,SAAU,SAASC,GACjB,OAAOt4B,KAAK8Y,UAAU,WAAY,CAAC,KAAM,MAAMV,OAAOkgB,KASxDC,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBAAwB5lD,EAAI,EAAGC,EAAI,EAgBrD,OAfIxG,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC3B0D,EAAIvG,KAAK0H,KAAO1H,KAAKmR,GACrB3K,EAAIxG,KAAK2H,IAAM3H,KAAKoR,IAEtBonB,EAAO53B,KACL,YAAaZ,KAAKsrD,WAChB,OAAQ/kD,EAAG,SAAUC,EAAG,KACxB,OAAQxG,KAAKmR,GACb,SAAUnR,KAAKoR,GACf,YAAapR,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtBvrD,KAAKksD,wBACP,SAGKliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAS1Do1B,QAAS,SAASz6B,EAAKm4C,GACrBn4C,EAAI+B,YACJ/B,EAAIU,OACJV,EAAIqb,UAAU,EAAG,EAAG,EAAG/mB,KAAKoR,GAAKpR,KAAKmR,GAAI,EAAG,GAC7CzF,EAAIo8B,IACF+b,EAAc7jD,KAAK0H,KAAO1H,KAAKmR,GAAK,EACpC0yC,GAAe7jD,KAAK2H,IAAM3H,KAAKoR,IAAMpR,KAAKmR,GAAKnR,KAAKoR,GAAK,EACzDpR,KAAKmR,GACL,EACA0/C,GACA,GACFnlD,EAAIc,UACJxM,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,MAWvBvN,EAAO2yD,QAAQlB,gBAAkBzxD,EAAOa,kBAAkBoZ,OAAO,cAAc/O,MAAM,MAUrFlL,EAAO2yD,QAAQ9gC,YAAc,SAASjW,EAAS/Y,GAC7CA,IAAYA,EAAU,IAEtB,IAAI6uD,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAO2yD,QAAQlB,iBAEtEC,EAAiBnoD,KAAOmoD,EAAiBnoD,MAAQ,EACjDmoD,EAAiBloD,IAAMkoD,EAAiBloD,KAAO,EAE/C,IAAIspD,EAAU,IAAI9yD,EAAO2yD,QAAQ15C,EAAOy4C,EAAkB7uD,IAI1D,OAFAiwD,EAAQtpD,KAAOspD,EAAQ7/C,GACvB6/C,EAAQvpD,MAAQupD,EAAQ9/C,GACjB8/C,GAaT9yD,EAAO2yD,QAAQxmD,WAAa,SAASrI,EAAQU,EAAUwkD,GACrD,OAAOhpD,EAAOmN,OAAO47C,YAAY,UAAWjlD,EAAQU,EAAUwkD,KArMlE,CAwMsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAE5BjZ,EAAOgrC,KACThrC,EAAOujB,KAAK,mCAWdvjB,EAAOgrC,KAAOhrC,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA4C,CAOvFgC,gBAAiBnP,EAAOmN,OAAOC,UAAU+B,gBAAgB8K,OAAO,KAAM,MAOtEvV,KAAM,OAONsO,GAAM,EAONC,GAAM,EAEN6vC,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,KAAM,MAOtEgB,WAAY,SAASpY,GACnBhB,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKkxD,aAOPA,UAAW,WACLlxD,KAAKmR,KAAOnR,KAAKoR,GACnBpR,KAAKoR,GAAKpR,KAAKmR,GAERnR,KAAKoR,KAAOpR,KAAKmR,KACxBnR,KAAKmR,GAAKnR,KAAKoR,KASnB+0B,QAAS,SAASz6B,EAAKm4C,GAGrB,GAAmB,IAAf7jD,KAAKsH,OAA+B,IAAhBtH,KAAK4H,OAA7B,CAKA,IAAIuJ,EAAKnR,KAAKmR,GAAKpM,KAAKS,IAAIxF,KAAKmR,GAAInR,KAAKsH,MAAQ,GAAK,EACnD8J,EAAKpR,KAAKoR,GAAKrM,KAAKS,IAAIxF,KAAKoR,GAAIpR,KAAK4H,OAAS,GAAK,EACpDupD,EAAInxD,KAAKsH,MACT+sB,EAAIr0B,KAAK4H,OACTrB,EAAIs9C,EAAc7jD,KAAK0H,MAAQ1H,KAAKsH,MAAQ,EAC5Cd,EAAIq9C,EAAc7jD,KAAK2H,KAAO3H,KAAK4H,OAAS,EAC5CwpD,EAAmB,IAAPjgD,GAAmB,IAAPC,EAExBqF,EAAI,YACR/K,EAAI+B,YAEJ/B,EAAIY,OAAO/F,EAAI4K,EAAI3K,GAEnBkF,EAAIo7B,OAAOvgC,EAAI4qD,EAAIhgD,EAAI3K,GACvB4qD,GAAa1lD,EAAIkK,cAAcrP,EAAI4qD,EAAI16C,EAAItF,EAAI3K,EAAGD,EAAI4qD,EAAG3qD,EAAIiQ,EAAIrF,EAAI7K,EAAI4qD,EAAG3qD,EAAI4K,GAEhF1F,EAAIo7B,OAAOvgC,EAAI4qD,EAAG3qD,EAAI6tB,EAAIjjB,GAC1BggD,GAAa1lD,EAAIkK,cAAcrP,EAAI4qD,EAAG3qD,EAAI6tB,EAAI5d,EAAIrF,EAAI7K,EAAI4qD,EAAI16C,EAAItF,EAAI3K,EAAI6tB,EAAG9tB,EAAI4qD,EAAIhgD,EAAI3K,EAAI6tB,GAE7F3oB,EAAIo7B,OAAOvgC,EAAI4K,EAAI3K,EAAI6tB,GACvB+8B,GAAa1lD,EAAIkK,cAAcrP,EAAIkQ,EAAItF,EAAI3K,EAAI6tB,EAAG9tB,EAAGC,EAAI6tB,EAAI5d,EAAIrF,EAAI7K,EAAGC,EAAI6tB,EAAIjjB,GAEhF1F,EAAIo7B,OAAOvgC,EAAGC,EAAI4K,GAClBggD,GAAa1lD,EAAIkK,cAAcrP,EAAGC,EAAIiQ,EAAIrF,EAAI7K,EAAIkQ,EAAItF,EAAI3K,EAAGD,EAAI4K,EAAI3K,GAErEkF,EAAIg8B,YAEJ1nC,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,QAhCjBA,EAAIs1B,UAAU,IAAM,GAAK,EAAG,IAuChC2kB,oBAAqB,SAASj6C,GAC5B,IAAInF,GAAKvG,KAAKsH,MAAQ,EAClBd,GAAKxG,KAAK4H,OAAS,EACnBupD,EAAInxD,KAAKsH,MACT+sB,EAAIr0B,KAAK4H,OAEb8D,EAAI+B,YACJtP,EAAOiC,KAAKqL,eAAeC,EAAKnF,EAAGC,EAAGD,EAAI4qD,EAAG3qD,EAAGxG,KAAK+kC,iBACrD5mC,EAAOiC,KAAKqL,eAAeC,EAAKnF,EAAI4qD,EAAG3qD,EAAGD,EAAI4qD,EAAG3qD,EAAI6tB,EAAGr0B,KAAK+kC,iBAC7D5mC,EAAOiC,KAAKqL,eAAeC,EAAKnF,EAAI4qD,EAAG3qD,EAAI6tB,EAAG9tB,EAAGC,EAAI6tB,EAAGr0B,KAAK+kC,iBAC7D5mC,EAAOiC,KAAKqL,eAAeC,EAAKnF,EAAGC,EAAI6tB,EAAG9tB,EAAGC,EAAGxG,KAAK+kC,iBACrDr5B,EAAIg8B,aAQNrP,SAAU,SAASC,GACjB,OAAOt4B,KAAK8Y,UAAU,WAAY,CAAC,KAAM,MAAMV,OAAOkgB,KASxDC,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBAAwB5lD,EAAIvG,KAAK0H,KAAMlB,EAAIxG,KAAK2H,IAelE,OAdM3H,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC7B0D,GAAKvG,KAAKsH,MAAQ,EAClBd,GAAKxG,KAAK4H,OAAS,GAErB4wB,EAAO53B,KACL,SAAUZ,KAAKsrD,WACb,MAAO/kD,EAAG,QAASC,EACnB,SAAUxG,KAAK2E,IAAI,MAAO,SAAU3E,KAAK2E,IAAI,MAC7C,YAAa3E,KAAKsH,MAAO,aAActH,KAAK4H,OAC5C,YAAa5H,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtBvrD,KAAKksD,wBACP,SAEKliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,OAY5D5S,EAAOgrC,KAAKymB,gBAAkBzxD,EAAOa,kBAAkBoZ,OAAO,yBAAyB/O,MAAM,MAU7FlL,EAAOgrC,KAAKnZ,YAAc,SAASjW,EAAS/Y,GAC1C,IAAK+Y,EACH,OAAO,KAET/Y,EAAUA,GAAW,GAErB,IAAI6uD,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOgrC,KAAKymB,iBAEnEC,EAAiBnoD,KAAOmoD,EAAiBnoD,MAAQ,EACjDmoD,EAAiBloD,IAAOkoD,EAAiBloD,KAAQ,EACjD,IAAIuhC,EAAO,IAAI/qC,EAAOgrC,KAAK/xB,EAAQpW,EAAU7C,EAAOiC,KAAK6B,OAAOuV,MAAMxW,GAAW,GAAM6uD,IAEvF,OADA3mB,EAAKvb,QAAUub,EAAKvb,SAAwB,EAAbub,EAAK5hC,OAA2B,EAAd4hC,EAAKthC,OAC/CshC,GAaT/qC,EAAOgrC,KAAK7+B,WAAa,SAASrI,EAAQU,EAAUwkD,GAClD,OAAOhpD,EAAOmN,OAAO47C,YAAY,OAAQjlD,EAAQU,EAAUwkD,KAvN/D,CA0NsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5B5R,EAAMrH,EAAOiC,KAAKC,MAAMmF,IACxBC,EAAMtH,EAAOiC,KAAKC,MAAMoF,IACxBuC,EAAU7J,EAAOiC,KAAK4H,QACtB0xB,EAAsBv7B,EAAOmN,OAAOouB,oBAEpCv7B,EAAOkzD,SACTlzD,EAAOujB,KAAK,uCAUdvjB,EAAOkzD,SAAWlzD,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAAgD,CAO/FzI,KAAM,WAONqE,OAAQ,KAORE,KAAM,EAONI,KAAM,EAENy5C,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,UAqBhEgB,WAAY,SAASlS,EAAQlG,GAC3BA,EAAUA,GAAW,GACrBhB,KAAKkH,OAASA,GAAU,GACxBlH,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKsxD,kBACC,QAAStwD,IACbhB,KAAK2H,IAAM3H,KAAKwH,MAEZ,SAAUxG,IACdhB,KAAK0H,KAAO1H,KAAKoH,MAEnBpH,KAAKuxD,WAAa,CAChBhrD,EAAGvG,KAAKoH,KAAOpH,KAAKsH,MAAQ,EAC5Bd,EAAGxG,KAAKwH,KAAOxH,KAAK4H,OAAS,IAOjC0pD,gBAAiB,WAEf,IAAIpqD,EAASlH,KAAKkH,OACdE,EAAO5B,EAAI0B,EAAQ,KACnBM,EAAOhC,EAAI0B,EAAQ,KACnBG,EAAO5B,EAAIyB,EAAQ,KACnBO,EAAOhC,EAAIyB,EAAQ,KAEvBlH,KAAKsH,MAASD,EAAOD,GAAS,EAC9BpH,KAAK4H,OAAUH,EAAOD,GAAS,EAC/BxH,KAAKoH,KAAOA,GAAQ,EACpBpH,KAAKwH,KAAOA,GAAQ,GAQtB6wB,SAAU,SAASC,GACjB,OAAOlhB,EAAOpX,KAAK8Y,UAAU,WAAYwf,GAAsB,CAC7DpxB,OAAQlH,KAAKkH,OAAOkR,YAUxBmgB,MAAO,SAASvuB,GACd,IAAI9C,EAAS,GACTsqD,EAAQ,EACRC,EAAQ,EACRj5B,EAASx4B,KAAKmsD,uBAEZnsD,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC7B2uD,EAAQxxD,KAAKuxD,WAAWhrD,EACxBkrD,EAAQzxD,KAAKuxD,WAAW/qD,GAG1B,IAAK,IAAItF,EAAI,EAAGC,EAAMnB,KAAKkH,OAAOzG,OAAQS,EAAIC,EAAKD,IACjDgG,EAAOtG,KACLoH,EAAQhI,KAAKkH,OAAOhG,GAAGqF,EAAIirD,EAAO93B,GAAsB,IACxD1xB,EAAQhI,KAAKkH,OAAOhG,GAAGsF,EAAIirD,EAAO/3B,GAAsB,KAY5D,OATAlB,EAAO53B,KACL,IAAKZ,KAAK6C,KAAM,IAAK7C,KAAKsrD,WACxB,WAAYpkD,EAAO6J,KAAK,IACxB,YAAa/Q,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBACtB,IAAKvrD,KAAKksD,wBACZ,SAGKliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAU1D2gD,aAAc,SAAShmD,EAAKm4C,GAC1B,IAAI59C,EAAO9E,EAAMnB,KAAKkH,OAAOzG,OACzB8F,EAAIs9C,EAAc,EAAI7jD,KAAKuxD,WAAWhrD,EACtCC,EAAIq9C,EAAc,EAAI7jD,KAAKuxD,WAAW/qD,EAE1C,IAAKrF,GAAOyrB,MAAM5sB,KAAKkH,OAAO/F,EAAM,GAAGqF,GAGrC,OAAO,EAETkF,EAAI+B,YACJ/B,EAAIY,OAAOtM,KAAKkH,OAAO,GAAGX,EAAIA,EAAGvG,KAAKkH,OAAO,GAAGV,EAAIA,GACpD,IAAK,IAAItF,EAAI,EAAGA,EAAIC,EAAKD,IACvB+E,EAAQjG,KAAKkH,OAAOhG,GACpBwK,EAAIo7B,OAAO7gC,EAAMM,EAAIA,EAAGN,EAAMO,EAAIA,GAEpC,OAAO,GAQT2/B,QAAS,SAASz6B,EAAKm4C,GAChB7jD,KAAK0xD,aAAahmD,EAAKm4C,KAG5B7jD,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,KAOrBi6C,oBAAqB,SAASj6C,GAC5B,IAAIg7B,EAAIC,EAERj7B,EAAI+B,YACJ,IAAK,IAAIvM,EAAI,EAAGC,EAAMnB,KAAKkH,OAAOzG,OAAQS,EAAIC,EAAKD,IACjDwlC,EAAK1mC,KAAKkH,OAAOhG,GACjBylC,EAAK3mC,KAAKkH,OAAOhG,EAAI,IAAMwlC,EAC3BvoC,EAAOiC,KAAKqL,eAAeC,EAAKg7B,EAAGngC,EAAGmgC,EAAGlgC,EAAGmgC,EAAGpgC,EAAGogC,EAAGngC,EAAGxG,KAAK+kC,kBAQjE5hC,WAAY,WACV,OAAOnD,KAAK2E,IAAI,UAAUlE,UAW9BtC,EAAOkzD,SAASzB,gBAAkBzxD,EAAOa,kBAAkBoZ,SAU3Dja,EAAOkzD,SAASrhC,YAAc,SAASjW,EAAS/Y,GAC9C,IAAK+Y,EACH,OAAO,KAET/Y,IAAYA,EAAU,IAEtB,IAAIkG,EAAS/I,EAAOowB,qBAAqBxU,EAAQ+O,aAAa,WAC1D+mC,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOkzD,SAASzB,iBAEvE,OAAO,IAAIzxD,EAAOkzD,SAASnqD,EAAQ/I,EAAOiC,KAAK6B,OAAOmV,OAAOy4C,EAAkB7uD,KAajF7C,EAAOkzD,SAAS/mD,WAAa,SAASrI,EAAQU,EAAUwkD,GACtD,OAAOhpD,EAAOmN,OAAO47C,YAAY,WAAYjlD,EAAQU,EAAUwkD,EAAY,YAhQ/E,CAmQsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAE5BjZ,EAAOwzD,QACTxzD,EAAOujB,KAAK,sCAUdvjB,EAAOwzD,QAAUxzD,EAAOiC,KAAK+Y,YAAYhb,EAAOkzD,SAAiD,CAO/FxuD,KAAM,UAONsjC,QAAS,SAASz6B,EAAKm4C,GAChB7jD,KAAK0xD,aAAahmD,EAAKm4C,KAG5Bn4C,EAAIg8B,YACJ1nC,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,KAOrBi6C,oBAAqB,SAASj6C,GAC5B1L,KAAK8Y,UAAU,sBAAuBpN,GACtCA,EAAIg8B,eAWRvpC,EAAOwzD,QAAQ/B,gBAAkBzxD,EAAOa,kBAAkBoZ,SAU1Dja,EAAOwzD,QAAQ3hC,YAAc,SAASjW,EAAS/Y,GAC7C,IAAK+Y,EACH,OAAO,KAGT/Y,IAAYA,EAAU,IAEtB,IAAIkG,EAAS/I,EAAOowB,qBAAqBxU,EAAQ+O,aAAa,WAC1D+mC,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOwzD,QAAQ/B,iBAEtE,OAAO,IAAIzxD,EAAOwzD,QAAQzqD,EAAQkQ,EAAOy4C,EAAkB7uD,KAa7D7C,EAAOwzD,QAAQrnD,WAAa,SAASrI,EAAQU,EAAUwkD,GACrD,OAAOhpD,EAAOmN,OAAO47C,YAAY,UAAWjlD,EAAQU,EAAUwkD,EAAY,YA5F9E,CA+FsB,oBAAZ9oD,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CqH,EAAMrH,EAAOiC,KAAKC,MAAMmF,IACxBC,EAAMtH,EAAOiC,KAAKC,MAAMoF,IACxB2R,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bw6C,EAAYtmD,OAAOC,UAAUC,SAC7B8J,EAAUnX,EAAOiC,KAAKkV,QACtBu8C,EAAiB,CACf9nC,EAAG,EACHva,EAAG,EACH6kB,EAAG,EACHjuB,EAAG,EACHwO,EAAG,EACHtC,EAAG,EACHwhB,EAAG,EACH/sB,EAAG,EACHe,EAAG,GAELgqD,EAAmB,CACjB/nC,EAAG,IACHgoC,EAAG,KAGL5zD,EAAOkpC,KACTlpC,EAAOujB,KAAK,mCAWdvjB,EAAOkpC,KAAOlpC,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA4C,CAOvFzI,KAAM,OAONmI,KAAM,KAON5D,KAAM,EAONI,KAAM,EAENy5C,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OAAO,OAAQ,YAExE9K,gBAAiBnP,EAAOmN,OAAOC,UAAU+B,gBAAgB8K,OAAO,QAQhEgB,WAAY,SAASpO,EAAMhK,GACzBA,EAAUA,GAAW,GACrBhB,KAAK8Y,UAAU,aAAc9X,GAExBgK,IACHA,EAAO,IAGT,IAAIgnD,EAAqC,mBAAzBJ,EAAU9wD,KAAKkK,GAE/BhL,KAAKgL,KAAOgnD,EACRhnD,EAEAA,EAAKkE,OAASlE,EAAKkE,MAAM,gCAExBlP,KAAKgL,OAILgnD,IACHhyD,KAAKgL,KAAOhL,KAAKiyD,cAGnBjyD,KAAKkyD,uBAAuBlxD,KAO9BkxD,uBAAwB,SAASlxD,GAC/B,IAAImxD,EAAUnyD,KAAKoyD,mBAEnBpyD,KAAKoH,KAAO+qD,EAAQzqD,KACpB1H,KAAKwH,KAAO2qD,EAAQxqD,IACpB3H,KAAKsH,MAAQ6qD,EAAQ7qD,MACrBtH,KAAK4H,OAASuqD,EAAQvqD,YAEM,IAAjB5G,EAAQ0G,OACjB1H,KAAK0H,KAAOyqD,EAAQzqD,MAAyB,WAAjB1H,KAAKunC,QAC7BvnC,KAAKsH,MAAQ,EACI,UAAjBtH,KAAKunC,QACHvnC,KAAKsH,MACL,SAGmB,IAAhBtG,EAAQ2G,MACjB3H,KAAK2H,IAAMwqD,EAAQxqD,KAAwB,WAAjB3H,KAAKwnC,QAC3BxnC,KAAK4H,OAAS,EACG,WAAjB5H,KAAKwnC,QACHxnC,KAAK4H,OACL,IAGR5H,KAAKuxD,WAAavxD,KAAKuxD,YAAc,CACnChrD,EAAGvG,KAAKoH,KAAOpH,KAAKsH,MAAQ,EAC5Bd,EAAGxG,KAAKwH,KAAOxH,KAAK4H,OAAS,IAQjCyqD,oBAAqB,SAAS3mD,GAC5B,IAAIpI,EAQAgvD,EACAC,EARAC,EAAW,KACXC,EAAgB,EAChBC,EAAgB,EAChBnsD,EAAI,EACJC,EAAI,EACJmsD,EAAW,EACXC,EAAW,EAGXpjD,GAAKxP,KAAKuxD,WAAWhrD,EACrBQ,GAAK/G,KAAKuxD,WAAW/qD,EAErBxG,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAE3BkE,EADAyI,EAAI,GAIN9D,EAAI+B,YAEJ,IAAK,IAAIvM,EAAI,EAAGC,EAAMnB,KAAKgL,KAAKvK,OAAQS,EAAIC,IAAOD,EAAG,CAIpD,QAFAoC,EAAUtD,KAAKgL,KAAK9J,IAEJ,IAEd,IAAK,IACHqF,GAAKjD,EAAQ,GACbkD,GAAKlD,EAAQ,GACboI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHR,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZoI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHR,GAAKjD,EAAQ,GACboI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHR,EAAIjD,EAAQ,GACZoI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHP,GAAKlD,EAAQ,GACboI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHP,EAAIlD,EAAQ,GACZoI,EAAIo7B,OAAOvgC,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IAGH0rD,EAFAlsD,GAAKjD,EAAQ,GAGbovD,EAFAlsD,GAAKlD,EAAQ,GAGboI,EAAIY,OAAO/F,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IAGH0rD,EAFAlsD,EAAIjD,EAAQ,GAGZovD,EAFAlsD,EAAIlD,EAAQ,GAGZoI,EAAIY,OAAO/F,EAAIiJ,EAAGhJ,EAAIO,GACtB,MAEF,IAAK,IACHurD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GACpBqvD,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GACvBoI,EAAIkK,cACFrP,EAAIjD,EAAQ,GAAKkM,EACjBhJ,EAAIlD,EAAQ,GAAKyD,EACjB4rD,EAAWnjD,EACXojD,EAAW7rD,EACXurD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHhsD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZqvD,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GACnBoI,EAAIkK,cACFtS,EAAQ,GAAKkM,EACblM,EAAQ,GAAKyD,EACb4rD,EAAWnjD,EACXojD,EAAW7rD,EACXR,EAAIiJ,EACJhJ,EAAIO,GAEN,MAEF,IAAK,IAGHurD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GAMlBsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAGrBlnD,EAAIkK,cACF+8C,EAAWnjD,EACXojD,EAAW7rD,EACXR,EAAIjD,EAAQ,GAAKkM,EACjBhJ,EAAIlD,EAAQ,GAAKyD,EACjBurD,EAAQ9iD,EACR+iD,EAAQxrD,GAMV4rD,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GAEvBiD,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHD,EAAQhvD,EAAQ,GAChBivD,EAAQjvD,EAAQ,GAKdsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAErBlnD,EAAIkK,cACF+8C,EAAWnjD,EACXojD,EAAW7rD,EACXzD,EAAQ,GAAKkM,EACblM,EAAQ,GAAKyD,EACburD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EAMJI,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GAEnB,MAEF,IAAK,IAEHgvD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GAEpBqvD,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GAEvBoI,EAAIm7B,iBACF8rB,EAAWnjD,EACXojD,EAAW7rD,EACXurD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHD,EAAQhvD,EAAQ,GAChBivD,EAAQjvD,EAAQ,GAEhBoI,EAAIm7B,iBACFvjC,EAAQ,GAAKkM,EACblM,EAAQ,GAAKyD,EACburD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EACJI,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GACnB,MAEF,IAAK,IAGHgvD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GAMlBsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAGrBlnD,EAAIm7B,iBACF8rB,EAAWnjD,EACXojD,EAAW7rD,EACXurD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EAEJ,MAEF,IAAK,IACHD,EAAQhvD,EAAQ,GAChBivD,EAAQjvD,EAAQ,GAMdsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAErBlnD,EAAIm7B,iBACF8rB,EAAWnjD,EACXojD,EAAW7rD,EACXurD,EAAQ9iD,EACR+iD,EAAQxrD,GAEVR,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IAEHj9C,EAAQ5J,EAAKnF,EAAIiJ,EAAGhJ,EAAIO,EAAG,CACzBzD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GAAKiD,EAAIiJ,EACjBlM,EAAQ,GAAKkD,EAAIO,IAEnBR,GAAKjD,EAAQ,GACbkD,GAAKlD,EAAQ,GACb,MAEF,IAAK,IAEHgS,EAAQ5J,EAAKnF,EAAIiJ,EAAGhJ,EAAIO,EAAG,CACzBzD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GAAKkM,EACblM,EAAQ,GAAKyD,IAEfR,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZ,MAEF,IAAK,IACL,IAAK,IACHiD,EAAIksD,EACJjsD,EAAIksD,EACJhnD,EAAIg8B,YAGR8qB,EAAWlvD,IAQf6iC,QAAS,SAASz6B,GAChB1L,KAAKqyD,oBAAoB3mD,GACzB1L,KAAKylD,YAAY/5C,GACjB1L,KAAK0lD,cAAch6C,IAOrBF,SAAU,WACR,MAAO,kBAAoBxL,KAAKmD,aAC9B,eAAiBnD,KAAK2H,IAAM,aAAe3H,KAAK0H,KAAO,OAQ3D2wB,SAAU,SAASC,GAMjB,OALQlhB,EAAOpX,KAAK8Y,UAAU,WAAY,CAAC,aAAc,cAAcV,OAAOkgB,IAAuB,CACnGttB,KAAMhL,KAAKgL,KAAK0L,IAAI,SAAS3T,GAAQ,OAAOA,EAAKmG,UACjDvB,IAAK3H,KAAK2H,IACVD,KAAM1H,KAAK0H,QAUfq6B,iBAAkB,SAASzJ,GACzB,IAAIx1B,EAAI9C,KAAKq4B,SAASC,GAKtB,OAJIt4B,KAAKkL,aACPpI,EAAEkI,KAAOhL,KAAKkL,mBAETpI,EAAEoI,WACFpI,GASTy1B,MAAO,SAASvuB,GAId,IAHA,IAAI6oD,EAAS,GACTr6B,EAASx4B,KAAKmsD,uBAAwB2G,EAAe,GAEhD5xD,EAAI,EAAGC,EAAMnB,KAAKgL,KAAKvK,OAAQS,EAAIC,EAAKD,IAC/C2xD,EAAOjyD,KAAKZ,KAAKgL,KAAK9J,GAAG6P,KAAK,MAEhC,IAAI/F,EAAO6nD,EAAO9hD,KAAK,KAavB,OAZM/Q,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC7BiwD,EAAe,eAAkB9yD,KAAKuxD,WAAWhrD,EAAK,MAASvG,KAAKuxD,WAAW/qD,EAAK,MAEtFgyB,EAAO53B,KACL,SAAUZ,KAAKsrD,WACb,MAAOtgD,EACP,YAAahL,KAAKmrD,eAClB,gBAAiBnrD,KAAKurD,kBAAmBuH,EACzC9yD,KAAKksD,wBAAyB,4BAChC,QAGKliD,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAQ1D5N,WAAY,WACV,OAAOnD,KAAKgL,KAAKvK,QAMnBwxD,WAAY,WASV,IARA,IAEIc,EACAxlC,EAEAre,EACA8jD,EAEYC,EARZjgD,EAAS,GACTyC,EAAS,GAGTy9C,EAAK,sDAIAhyD,EAAI,EAAiBC,EAAMnB,KAAKgL,KAAKvK,OAAQS,EAAIC,EAAKD,IAAK,CAMlE,IAHA8xD,GAFAD,EAAc/yD,KAAKgL,KAAK9J,IAEAgI,MAAM,GAAGuO,OACjChC,EAAOhV,OAAS,EAERyO,EAAQgkD,EAAG1qD,KAAKwqD,IACtBv9C,EAAO7U,KAAKsO,EAAM,IAGpB+jD,EAAe,CAACF,EAAY/pD,OAAO,IAEnC,IAAK,IAAIoM,EAAI,EAAGC,EAAOI,EAAOhV,OAAQ2U,EAAIC,EAAMD,IAC9CmY,EAASplB,WAAWsN,EAAOL,IACtBwX,MAAMW,IACT0lC,EAAaryD,KAAK2sB,GAItB,IAAI4lC,EAAUF,EAAa,GACvBG,EAAgBvB,EAAesB,EAAQr7C,eACvCu7C,EAAkBvB,EAAiBqB,IAAYA,EAEnD,GAAIF,EAAaxyD,OAAS,EAAI2yD,EAC5B,IAAK,IAAI38C,EAAI,EAAG68C,EAAOL,EAAaxyD,OAAQgW,EAAI68C,EAAM78C,GAAK28C,EACzDpgD,EAAOpS,KAAK,CAACuyD,GAAS/6C,OAAO66C,EAAa/pD,MAAMuN,EAAGA,EAAI28C,KACvDD,EAAUE,OAIZrgD,EAAOpS,KAAKqyD,GAIhB,OAAOjgD,GAMTo/C,iBAAkB,WAgBhB,IAdA,IAEI9uD,EAQAgvD,EACAC,EACAr9C,EAZAq+C,EAAK,GACLC,EAAK,GAELhB,EAAW,KACXC,EAAgB,EAChBC,EAAgB,EAChBnsD,EAAI,EACJC,EAAI,EACJmsD,EAAW,EACXC,EAAW,EAKN1xD,EAAI,EAAGC,EAAMnB,KAAKgL,KAAKvK,OAAQS,EAAIC,IAAOD,EAAG,CAIpD,QAFAoC,EAAUtD,KAAKgL,KAAK9J,IAEJ,IAEd,IAAK,IACHqF,GAAKjD,EAAQ,GACbkD,GAAKlD,EAAQ,GACb4R,EAAS,GACT,MAEF,IAAK,IACH3O,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZ4R,EAAS,GACT,MAEF,IAAK,IACH3O,GAAKjD,EAAQ,GACb4R,EAAS,GACT,MAEF,IAAK,IACH3O,EAAIjD,EAAQ,GACZ4R,EAAS,GACT,MAEF,IAAK,IACH1O,GAAKlD,EAAQ,GACb4R,EAAS,GACT,MAEF,IAAK,IACH1O,EAAIlD,EAAQ,GACZ4R,EAAS,GACT,MAEF,IAAK,IAGHu9C,EAFAlsD,GAAKjD,EAAQ,GAGbovD,EAFAlsD,GAAKlD,EAAQ,GAGb4R,EAAS,GACT,MAEF,IAAK,IAGHu9C,EAFAlsD,EAAIjD,EAAQ,GAGZovD,EAFAlsD,EAAIlD,EAAQ,GAGZ4R,EAAS,GACT,MAEF,IAAK,IACHo9C,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GACpBqvD,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GACvB4R,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZqvD,EACAC,EACAN,EACAC,GAEFhsD,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHI,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GACnB4R,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvClD,EAAQ,GACRA,EAAQ,GACRqvD,EACAC,EACAtvD,EAAQ,GACRA,EAAQ,IAEViD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZ,MAEF,IAAK,IAGHgvD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GAMlBsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAGrB19C,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACArsD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZgvD,EACAC,GAMFI,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GACvBiD,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHD,EAAQhvD,EAAQ,GAChBivD,EAAQjvD,EAAQ,GAKdsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAErB19C,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACAtvD,EAAQ,GACRA,EAAQ,GACRgvD,EACAC,GAEFhsD,EAAI+rD,EACJ9rD,EAAI+rD,EAKJI,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GACnB,MAEF,IAAK,IAEHgvD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GACpBqvD,EAAWpsD,EAAIjD,EAAQ,GACvBsvD,EAAWpsD,EAAIlD,EAAQ,GACvB4R,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACAD,EACAC,EACAN,EACAC,GAEFhsD,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IACHI,EAAWrvD,EAAQ,GACnBsvD,EAAWtvD,EAAQ,GACnB4R,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACAD,EACAC,EACAtvD,EAAQ,GACRA,EAAQ,IAEViD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZ,MAEF,IAAK,IAEHgvD,EAAQ/rD,EAAIjD,EAAQ,GACpBivD,EAAQ/rD,EAAIlD,EAAQ,GAKlBsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAGrB19C,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACAD,EACAC,EACAN,EACAC,GAEFhsD,EAAI+rD,EACJ9rD,EAAI+rD,EAEJ,MAEF,IAAK,IACHD,EAAQhvD,EAAQ,GAChBivD,EAAQjvD,EAAQ,GAMdsvD,EAJkC,OAAhCJ,EAAS,GAAGtjD,MAAM,WAGpByjD,EAAWpsD,EACAC,IAIXmsD,EAAW,EAAIpsD,EAAIosD,EACR,EAAInsD,EAAIosD,GAErB19C,EAAS/W,EAAOiC,KAAKiU,iBAAiB9N,EAAGC,EACvCmsD,EACAC,EACAD,EACAC,EACAN,EACAC,GAEFhsD,EAAI+rD,EACJ9rD,EAAI+rD,EACJ,MAEF,IAAK,IAEHr9C,EAAS/W,EAAOiC,KAAKyV,eAAetP,EAAGC,EACrClD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GAAKiD,EACbjD,EAAQ,GAAKkD,GAEfD,GAAKjD,EAAQ,GACbkD,GAAKlD,EAAQ,GACb,MAEF,IAAK,IAEH4R,EAAS/W,EAAOiC,KAAKyV,eAAetP,EAAGC,EACrClD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IAEViD,EAAIjD,EAAQ,GACZkD,EAAIlD,EAAQ,GACZ,MAEF,IAAK,IACL,IAAK,IACHiD,EAAIksD,EACJjsD,EAAIksD,EAGRF,EAAWlvD,EACX4R,EAAO7K,QAAQ,SAAUpE,GACvBstD,EAAG3yD,KAAKqF,EAAMM,GACditD,EAAG5yD,KAAKqF,EAAMO,KAEhB+sD,EAAG3yD,KAAK2F,GACRitD,EAAG5yD,KAAK4F,GAGV,IAAIY,EAAO5B,EAAI+tD,IAAO,EAClB/rD,EAAOhC,EAAIguD,IAAO,EAatB,MAPQ,CACF9rD,KAAMN,EACNO,IAAKH,EACLF,OARK7B,EAAI8tD,IAAO,GAEFnsD,EAOdQ,QARKnC,EAAI+tD,IAAO,GAEFhsD,MAqBxBrJ,EAAOkpC,KAAK/8B,WAAa,SAASrI,EAAQU,EAAUwkD,GAElD,IAAIn8C,EACJ,GAA2B,iBAAhB/I,EAAO+I,KAahB,OAAO7M,EAAOmN,OAAO47C,YAAY,OAAQjlD,EAAQU,EAAUwkD,EAAY,QAZvEhpD,EAAO6wB,eAAe/sB,EAAO+I,KAAM,SAAUD,GAC3C,IAAI0oD,EAAUxxD,EAAO+I,KACrBA,EAAOD,EAAS,UACT9I,EAAO+I,KAEdA,EAAKyuB,WAAWx3B,GAChB+I,EAAK04C,cAAc+P,GAEnB9wD,GAAYA,EAASqI,MAe3B7M,EAAOkpC,KAAKuoB,gBAAkBzxD,EAAOa,kBAAkBoZ,OAAO,CAAC,MAU/Dja,EAAOkpC,KAAKrX,YAAc,SAASjW,EAASpX,EAAU3B,GACpD,IAAI6uD,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOkpC,KAAKuoB,iBACnEjtD,GAAYA,EAAS,IAAIxE,EAAOkpC,KAAKwoB,EAAiB/sC,EAAG1L,EAAOy4C,EAAkB7uD,MAWpF7C,EAAOkpC,KAAKjY,OAAQ,GAt8BtB,CAw8BsB,oBAAZ/wB,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAE5BjZ,EAAO8M,UACT9M,EAAOujB,KAAK,wCAWdvjB,EAAO8M,UAAY9M,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAAiD,CAOjGzI,KAAM,aAONvC,KAAM,GAON2gD,gBAAiB,GAQjB7nC,WAAY,SAASs6C,EAAO1yD,GAE1BA,EAAUA,GAAW,GACrBhB,KAAK0zD,MAAQA,GAAS,GAEtB,IAAK,IAAIxyD,EAAIlB,KAAK0zD,MAAMjzD,OAAQS,KAC9BlB,KAAK0zD,MAAMxyD,GAAG03B,MAAQ54B,KAGpBgB,EAAQ4pB,aACV5qB,KAAK2zD,yBAAyB3yD,UACvBA,EAAQ4pB,YAEjB5qB,KAAKy5B,WAAWz4B,GAChBhB,KAAKk/B,aAMPy0B,yBAA0B,SAAS3yD,GAGjC,IAFA,IAAIkG,EAAQJ,EAAqBkE,EAAMpD,EAAQN,EAC3CyiB,EADW6pC,EAAK,GAAIC,EAAK,GAEpBz+C,EAAIpV,KAAK0zD,MAAMjzD,OAAQ2U,KAAM,CAEpCxN,GADAoD,EAAOhL,KAAK0zD,MAAMt+C,IACJxN,OAASoD,EAAKs8B,YAC5BhgC,EAAQ0D,EAAK1D,MAAQ0D,EAAKs8B,YAC1BpgC,EAAS,CACP,CAAEX,EAAGyE,EAAKtD,KAAMlB,EAAGwE,EAAKrD,KACxB,CAAEpB,EAAGyE,EAAKtD,KAAOJ,EAAOd,EAAGwE,EAAKrD,KAChC,CAAEpB,EAAGyE,EAAKtD,KAAMlB,EAAGwE,EAAKrD,IAAMC,GAC9B,CAAErB,EAAGyE,EAAKtD,KAAOJ,EAAOd,EAAGwE,EAAKrD,IAAMC,IAExCmiB,EAAI/pB,KAAK0zD,MAAMt+C,GAAGsY,gBAClB,IAAK,IAAIxsB,EAAI,EAAGA,EAAIgG,EAAOzG,OAAQS,IACjC4F,EAAII,EAAOhG,GACP6oB,IACFjjB,EAAI3I,EAAOiC,KAAKyG,eAAeC,EAAGijB,GAAG,IAEvC6pC,EAAGhzD,KAAKkG,EAAEP,GACVstD,EAAGjzD,KAAKkG,EAAEN,GAGdxF,EAAQsG,MAAQvC,KAAKU,IAAI7D,MAAM,KAAMgyD,GACrC5yD,EAAQ4G,OAAS7C,KAAKU,IAAI7D,MAAM,KAAMiyD,IAQxCxP,WAAY,SAAS34C,GACnBA,EAAIU,OACJV,EAAIW,WAAWrM,KAAKsH,MAAQ,GAAItH,KAAK4H,OAAS,GAC9C,IAAK,IAAI1G,EAAI,EAAGsO,EAAIxP,KAAK0zD,MAAMjzD,OAAQS,EAAIsO,IAAKtO,EAC9ClB,KAAK0zD,MAAMxyD,GAAG2/B,OAAOn1B,GAAK,GAE5BA,EAAIc,WAWN03C,YAAa,WACX,IAAI4P,EAAc9zD,KAAK0/C,iBAAmB1/C,KAAK44B,OAAS54B,KAAKwkD,qBAAuBxkD,KAAK44B,MAAM6rB,aAE/F,GADAzkD,KAAK+zD,QAAUD,EAEb,IAAK,IAAI5yD,EAAI,EAAGC,EAAMnB,KAAK0zD,MAAMjzD,OAAQS,EAAIC,EAAKD,IAChD,GAAIlB,KAAK0zD,MAAMxyD,GAAGwjD,iBAEhB,OADA1kD,KAAK+zD,SAAU,EAKrB,OAAOD,GAOTpP,eAAgB,WACd,GAAI1kD,KAAK26B,OACP,OAAO,EAET,IAAK,IAAIz5B,EAAI,EAAGC,EAAMnB,KAAK0zD,MAAMjzD,OAAQS,EAAIC,EAAKD,IAChD,GAAIlB,KAAK0zD,MAAMxyD,GAAGwjD,iBAChB,OAAO,EAGX,OAAO,GAOTD,UAAW,WACT,OAAOzkD,KAAK+zD,SAAW/zD,KAAK44B,OAAS54B,KAAK44B,MAAM6rB,aAMlDN,aAAc,WACZ,GAAInkD,KAAK8Y,UAAU,gBACjB,OAAO,EAET,IAAK9Y,KAAK8gD,eACR,OAAO,EAET,IAAK,IAAI5/C,EAAI,EAAGC,EAAMnB,KAAK0zD,MAAMjzD,OAAQS,EAAIC,EAAKD,IAChD,GAAIlB,KAAK0zD,MAAMxyD,GAAGijD,cAAa,GAAO,CACpC,GAAInkD,KAAKmhD,aAAc,CACrB,IAAI56C,EAAIvG,KAAKqiD,WAAariD,KAAKyhD,MAAOj7C,EAAIxG,KAAKsiD,YAActiD,KAAK2hD,MAClE3hD,KAAKohD,cAAcvhB,WAAWt5B,EAAI,GAAIC,EAAI,EAAGD,EAAGC,GAElD,OAAO,EAGX,OAAO,GAST/B,KAAM,SAAS/D,EAAMW,GAEnB,GAAa,SAATX,GAAmBW,GAASrB,KAAKg0D,cAEnC,IADA,IAAI9yD,EAAIlB,KAAK0zD,MAAMjzD,OACZS,KACLlB,KAAK0zD,MAAMxyD,GAAGuD,KAAK/D,EAAMW,GAI7B,OAAOrB,KAAK8Y,UAAU,OAAQpY,EAAMW,IAQtCg3B,SAAU,SAASC,GACjB,IAAI27B,EAAgBj0D,KAAK0zD,MAAMh9C,IAAI,SAAS1L,GAC1C,IAAIkpD,EAAmBlpD,EAAKyvB,qBAC5BzvB,EAAKyvB,qBAAuBzvB,EAAK4tB,MAAM6B,qBACvC,IAAIj2B,EAAMwG,EAAKqtB,SAASC,GAExB,OADAttB,EAAKyvB,qBAAuBy5B,EACrB1vD,IAKT,OAHQ4S,EAAOpX,KAAK8Y,UAAU,WAAY,CAAC,cAAcV,OAAOkgB,IAAuB,CACrFo7B,MAAOO,KAUXlyB,iBAAkB,SAASzJ,GACzB,IAAIx1B,EAAI9C,KAAKq4B,SAASC,GAItB,OAHIt4B,KAAKkL,aACPpI,EAAE4wD,MAAQ1zD,KAAKkL,YAEVpI,GASTy1B,MAAO,SAASvuB,GACd,IAAI5H,EAAUpC,KAAKqC,aACfyE,EAAI9G,KAAK6nD,iBAAiB,OAAQ,OAClC6D,EAAgB,aAAe5kD,EAAEP,EAAI,IAAMO,EAAEN,EAAI,IACjDgyB,EAASx4B,KAAKmsD,uBAClB3zB,EAAO53B,KACL,MAAOZ,KAAKsrD,WACZ,UAAWtrD,KAAKmrD,eAAgB,KAChC,cAAenrD,KAAKksD,wBAAyBR,EAAe1rD,KAAKurD,kBAAmB,KACpF,OAGF,IAAK,IAAIrqD,EAAI,EAAGC,EAAMiB,EAAQ3B,OAAQS,EAAIC,EAAKD,IAC7Cs3B,EAAO53B,KAAK,KAAMwB,EAAQlB,GAAGq3B,MAAMvuB,IAIrC,OAFAwuB,EAAO53B,KAAK,UAELoJ,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAQ1DvF,SAAU,WACR,MAAO,uBAAyBxL,KAAKmD,aACnC,aAAenD,KAAK2H,IAAM,WAAa3H,KAAK0H,KAAO,OAOvDssD,YAAa,WACX,IAAIG,EAAgBn0D,KAAKqC,aAAa,GAAGsC,IAAI,SAAW,GACxD,MAA6B,iBAAlBwvD,IAGXA,EAAgBA,EAAcr8C,cACvB9X,KAAKqC,aAAasU,MAAM,SAAS3L,GACtC,IAAIopD,EAAWppD,EAAKrG,IAAI,SAAW,GACnC,MAA2B,iBAAbyvD,GAAyB,EAAWt8C,gBAAkBq8C,MAQxEhxD,WAAY,WACV,OAAOnD,KAAK0zD,MAAMtwD,OAAO,SAASixD,EAAOrpD,GACvC,OAAOqpD,GAAUrpD,GAAQA,EAAK7H,WAAc6H,EAAK7H,aAAe,IAC/D,IAOLd,WAAY,WACV,OAAOrC,KAAK0zD,SAWhBv1D,EAAO8M,UAAUX,WAAa,SAASrI,EAAQU,GAC7C,IAAI2xD,EAAgBryD,EAAOyxD,aACpBzxD,EAAOyxD,MACe,iBAAlBY,EACTn2D,EAAO6wB,eAAeslC,EAAe,SAAUvpD,GAC7C,IAAI0oD,EAAUa,EACVC,EAAYp2D,EAAOiC,KAAK0K,iBAAiBC,EAAU9I,EAAQwxD,GAC/DxxD,EAAOyxD,MAAQY,EACf3xD,EAAS4xD,KAIXp2D,EAAOiC,KAAK2J,eAAeuqD,EAAe,SAASlqD,GACjD,IAAImqD,EAAY,IAAIp2D,EAAO8M,UAAUb,EAAkBnI,GACvDA,EAAOyxD,MAAQY,EACf3xD,EAAS4xD,MAYfp2D,EAAO8M,UAAUmkB,OAAQ,GA5U3B,CA8UsB,oBAAZ/wB,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5B5R,EAAMrH,EAAOiC,KAAKC,MAAMmF,IACxBC,EAAMtH,EAAOiC,KAAKC,MAAMoF,IAE5B,IAAItH,EAAOiqC,MAAX,CAOA,IAAIosB,EAAkB,CACpB9T,eAAgB,EAChBC,eAAgB,EAChBC,cAAgB,EAChB9O,cAAgB,EAChBC,cAAgB,EAChB8O,gBAAgB,GAWlB1iD,EAAOiqC,MAAQjqC,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAAQnN,EAAOsD,WAAiD,CAO5GoB,KAAM,QAONykC,YAAa,EAOb0N,gBAAgB,EAOhBiM,gBAAiB,GASjB7nC,WAAY,SAAShX,EAASpB,EAASyzD,GACrCzzD,EAAUA,GAAW,GAErBhB,KAAK0B,SAAW,GAKhB+yD,GAAoBz0D,KAAK8Y,UAAU,aAAc9X,GAEjDhB,KAAK0B,SAAWU,GAAW,GAC3B,IAAK,IAAIlB,EAAIlB,KAAK0B,SAASjB,OAAQS,KACjClB,KAAK0B,SAASR,GAAG03B,MAAQ54B,KAGvBgB,EAAQumC,UACVvnC,KAAKunC,QAAUvmC,EAAQumC,SAErBvmC,EAAQwmC,UACVxnC,KAAKwnC,QAAUxmC,EAAQwmC,SAGrBitB,GAGFz0D,KAAK00D,sBAAqB,GAC1B10D,KAAK20D,0BAGL30D,KAAK40D,cACL50D,KAAK00D,uBACL10D,KAAK8Y,UAAU,aAAc9X,IAG/BhB,KAAKk/B,YACLl/B,KAAK08C,cAGPiY,sBAAuB,WAErB,IADA,IACSzzD,EAAIlB,KAAK0B,SAASjB,OAAQS,KACjClB,KAAK0B,SAASR,GAAGg+B,WAFF,GAAqB,IAUxCw1B,qBAAsB,SAASG,GAE7B,IADA,IAAItzB,EAASvhC,KAAKohC,iBACTlgC,EAAIlB,KAAK0B,SAASjB,OAAQS,KACjClB,KAAK80D,oBAAoB90D,KAAK0B,SAASR,GAAIqgC,EAAQszB,IAUvDC,oBAAqB,SAAS7yD,EAAQs/B,EAAQszB,GAK5C,GAHA5yD,EAAO8yD,kBAAoB9yD,EAAOu+C,YAClCv+C,EAAOu+C,aAAc,GAEjBqU,EAAJ,CAIA,IAAIG,EAAa/yD,EAAOgkD,UACpBgP,EAAYhzD,EAAOikD,SAGvBjkD,EAAOwB,IAAI,CACTiE,KAAMstD,EAAazzB,EAAOh7B,EAC1BoB,IAAKstD,EAAY1zB,EAAO/6B,IAE1BvE,EAAOi9B,WANU,GAAqB,KAaxC1zB,SAAU,WACR,MAAO,oBAAsBxL,KAAKmD,aAAe,MASnDy5C,cAAe,SAAS36C,GActB,OAbAjC,KAAKk1D,uBACL/2D,EAAOiC,KAAKuO,qBAAqB3O,MAC7BiC,IACFjC,KAAK0B,SAASd,KAAKqB,GACnBA,EAAO22B,MAAQ54B,KACfiC,EAAOwC,KAAK,SAAUzE,KAAK2/B,SAG7B3/B,KAAK0C,cAAc1C,KAAKm1D,iBAAkBn1D,MAC1CA,KAAK40D,cACL50D,KAAK00D,uBACL10D,KAAKk/B,YACLl/B,KAAKghD,OAAQ,EACNhhD,MAMTm1D,iBAAkB,SAASlzD,GACzBA,EAAOwB,IAAI,UAAU,GACrBxB,EAAO22B,MAAQ54B,MASjB28C,iBAAkB,SAAS16C,GAWzB,OAVAjC,KAAKk1D,uBACL/2D,EAAOiC,KAAKuO,qBAAqB3O,MAEjCA,KAAK0C,cAAc1C,KAAKm1D,iBAAkBn1D,MAE1CA,KAAKuC,OAAON,GACZjC,KAAK40D,cACL50D,KAAK00D,uBACL10D,KAAKk/B,YACLl/B,KAAKghD,OAAQ,EACNhhD,MAMT6B,eAAgB,SAASI,GACvBjC,KAAKghD,OAAQ,EACb/+C,EAAO22B,MAAQ54B,KACfiC,EAAOwC,KAAK,SAAUzE,KAAK2/B,SAM7Bl9B,iBAAkB,SAASR,GACzBjC,KAAKghD,OAAQ,SACN/+C,EAAO22B,MACd32B,EAAOwB,IAAI,UAAU,IAOvB2xD,oBAAqB,CACnB90D,MAAkB,EAClBynB,QAAkB,EAClBuf,aAAkB,EAClBn3B,YAAkB,EAClBuc,YAAkB,EAClBpkB,UAAkB,EAClBmkB,WAAkB,EAClBE,YAAkB,EAClB0oC,gBAAkB,EAClBC,WAAkB,EAClBj6B,iBAAkB,GAMpB52B,KAAM,SAASC,EAAKrD,GAClB,IAAIH,EAAIlB,KAAK0B,SAASjB,OAEtB,GAAIT,KAAKo1D,oBAAoB1wD,IAAgB,WAARA,EACnC,KAAOxD,KACLlB,KAAK0B,SAASR,GAAGuC,IAAIiB,EAAKrD,QAI5B,KAAOH,KACLlB,KAAK0B,SAASR,GAAGuiD,WAAW/+C,EAAKrD,GAIrCrB,KAAK8Y,UAAU,OAAQpU,EAAKrD,IAQ9Bg3B,SAAU,SAASC,GACjB,IAAIi9B,EAAev1D,KAAKqC,aAAaqU,IAAI,SAASlS,GAChD,IAAI0vD,EAAmB1vD,EAAIi2B,qBAC3Bj2B,EAAIi2B,qBAAuBj2B,EAAIo0B,MAAM6B,qBACrC,IAAI3K,EAAOtrB,EAAI6zB,SAASC,GAExB,OADA9zB,EAAIi2B,qBAAuBy5B,EACpBpkC,IAET,OAAO1Y,EAAOpX,KAAK8Y,UAAU,WAAYwf,GAAsB,CAC7Dl2B,QAASmzD,KASbxzB,iBAAkB,SAASzJ,GACzB,IAAIi9B,EAAev1D,KAAKqC,aAAaqU,IAAI,SAASlS,GAChD,IAAI0vD,EAAmB1vD,EAAIi2B,qBAC3Bj2B,EAAIi2B,qBAAuBj2B,EAAIo0B,MAAM6B,qBACrC,IAAI3K,EAAOtrB,EAAIu9B,iBAAiBzJ,GAEhC,OADA9zB,EAAIi2B,qBAAuBy5B,EACpBpkC,IAET,OAAO1Y,EAAOpX,KAAK8Y,UAAU,mBAAoBwf,GAAsB,CACrEl2B,QAASmzD,KAQb10B,OAAQ,SAASn1B,GACf1L,KAAKmjD,gBAAiB,EACtBnjD,KAAK8Y,UAAU,SAAUpN,GACzB1L,KAAKmjD,gBAAiB,GAWxBe,YAAa,WACX,IAAI4P,EAAc9zD,KAAK0/C,iBAAmB1/C,KAAK44B,OAAS54B,KAAKwkD,qBAAuBxkD,KAAK44B,MAAM6rB,aAE/F,GADAzkD,KAAK+zD,QAAUD,EAEb,IAAK,IAAI5yD,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnD,GAAIlB,KAAK0B,SAASR,GAAGwjD,iBAEnB,OADA1kD,KAAK+zD,SAAU,EAKrB,OAAOD,GAOTpP,eAAgB,WACd,GAAI1kD,KAAK8Y,UAAU,kBACjB,OAAO,EAET,IAAK,IAAI5X,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnD,GAAIlB,KAAK0B,SAASR,GAAGwjD,iBACnB,OAAO,EAGX,OAAO,GAOTD,UAAW,WACT,OAAOzkD,KAAK+zD,SAAW/zD,KAAK44B,OAAS54B,KAAK44B,MAAM6rB,aAQlDJ,WAAY,SAAS34C,GACnB,IAAK,IAAIxK,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnDlB,KAAKw1D,cAAcx1D,KAAK0B,SAASR,GAAIwK,IAOzCy4C,aAAc,WACZ,GAAInkD,KAAK8Y,UAAU,gBACjB,OAAO,EAET,IAAK9Y,KAAK8gD,eACR,OAAO,EAET,IAAK,IAAI5/C,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnD,GAAIlB,KAAK0B,SAASR,GAAGijD,cAAa,GAAO,CACvC,GAAInkD,KAAKmhD,aAAc,CAErB,IAAI56C,EAAIvG,KAAKqiD,WAAariD,KAAKyhD,MAAOj7C,EAAIxG,KAAKsiD,YAActiD,KAAK2hD,MAClE3hD,KAAKohD,cAAcvhB,WAAWt5B,EAAI,GAAIC,EAAI,EAAGD,EAAGC,GAElD,OAAO,EAGX,OAAO,GAQT+nC,gBAAiB,SAAS7iC,EAAKm4C,GAC7Bn4C,EAAIU,OACJV,EAAI89B,YAAcxpC,KAAK+5C,SAAW/5C,KAAKqgD,wBAA0B,EACjErgD,KAAK8Y,UAAU,kBAAmBpN,EAAKm4C,GACvC,IAAK,IAAI3iD,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnDlB,KAAK0B,SAASR,GAAGqtC,gBAAgB7iC,GAEnCA,EAAIc,WAMNgpD,cAAe,SAASvzD,EAAQyJ,GAE9B,GAAKzJ,EAAO0rB,QAAZ,CAIA,IAAI8nC,EAA2BxzD,EAAOq6C,iBACtCr6C,EAAOq6C,kBAAmB,EAC1Br6C,EAAO4+B,OAAOn1B,GACdzJ,EAAOq6C,iBAAmBmZ,IAS5BP,qBAAsB,WAEpB,OADAl1D,KAAK0B,SAAS2I,QAAQrK,KAAK01D,oBAAqB11D,MACzCA,MAWTq3C,iBAAkB,SAASp1C,GACzB,IAAIsnB,EAAStnB,EAAO2rC,sBAChB5sC,EAAU7C,EAAOiC,KAAK0N,YAAYyb,GAClCgY,EAAS,IAAIpjC,EAAOmI,MAAMtF,EAAQqN,WAAYrN,EAAQsN,YAS1D,OARArM,EAAO4M,OAAQ,EACf5M,EAAO6M,OAAQ,EACf7M,EAAOwB,IAAI,SAAUzC,EAAQiN,QAC7BhM,EAAOwB,IAAI,SAAUzC,EAAQkN,QAC7BjM,EAAOkM,MAAQnN,EAAQmN,MACvBlM,EAAOmM,MAAQpN,EAAQoN,MACvBnM,EAAO8L,MAAQ/M,EAAQ+M,MACvB9L,EAAO4/B,oBAAoBN,EAAQ,SAAU,UACtCt/B,GASTyzD,oBAAqB,SAASzzD,GAQ5B,OAPAjC,KAAKq3C,iBAAiBp1C,GACtBA,EAAOi9B,YACPj9B,EAAOu+C,YAAcv+C,EAAO8yD,yBACrB9yD,EAAO8yD,kBACd9yD,EAAOwB,IAAI,UAAU,UACdxB,EAAO22B,MAEP54B,MAQTy2C,QAAS,WAMP,OAHAz2C,KAAK0B,SAAS2I,QAAQ,SAASpI,GAC7BA,EAAOwB,IAAI,SAAS,KAEfzD,KAAKk1D,wBASdxY,WAAY,WAGV,OAFA18C,KAAK21D,cAAgB31D,KAAK2E,IAAI,QAC9B3E,KAAK41D,aAAe51D,KAAK2E,IAAI,OACtB3E,MAOT61D,SAAU,WACR,OAAO71D,KAAK21D,gBAAkB31D,KAAK2E,IAAI,SAChC3E,KAAK41D,eAAiB51D,KAAK2E,IAAI,QAQxC44C,iBAAkB,WAKhB,OAHAv9C,KAAK0C,cAAc,SAAST,GAC1BA,EAAOi9B,WAFQ,GAAqB,KAI/Bl/B,MAMT40D,YAAa,SAASkB,GASpB,IARA,IAEIhzD,EAAGpC,EAGH0U,EALAm+C,EAAK,GACLC,EAAK,GAELlH,EAAQ,CAAC,KAAM,KAAM,KAAM,MAC3BprD,EAAI,EAAG60D,EAAO/1D,KAAK0B,SAASjB,OACzBu1D,EAAO1J,EAAM7rD,OAGZS,EAAI60D,IAAQ70D,EAGlB,KAFA4B,EAAI9C,KAAK0B,SAASR,IAChBg+B,WAJa,GAKV9pB,EAAI,EAAGA,EAAI4gD,EAAM5gD,IACpB1U,EAAO4rD,EAAMl3C,GACbm+C,EAAG3yD,KAAKkC,EAAE0lD,QAAQ9nD,GAAM6F,GACxBitD,EAAG5yD,KAAKkC,EAAE0lD,QAAQ9nD,GAAM8F,GAI5BxG,KAAKyD,IAAIzD,KAAKi2D,WAAW1C,EAAIC,EAAIsC,KAMnCG,WAAY,SAAS1C,EAAIC,EAAIsC,GAC3B,IAAII,EAAQ,IAAI/3D,EAAOmI,MAAMd,EAAI+tD,GAAK/tD,EAAIguD,IACtC2C,EAAQ,IAAIh4D,EAAOmI,MAAMb,EAAI8tD,GAAK9tD,EAAI+tD,IACtChvD,EAAM,CACJ8C,MAAQ6uD,EAAM5vD,EAAI2vD,EAAM3vD,GAAM,EAC9BqB,OAASuuD,EAAM3vD,EAAI0vD,EAAM1vD,GAAM,GAmBrC,OAhBKsvD,IACHtxD,EAAIkD,KAAOwuD,EAAM3vD,GAAK,EACtB/B,EAAImD,IAAMuuD,EAAM1vD,GAAK,EACA,WAAjBxG,KAAKunC,UACP/iC,EAAIkD,MAAQlD,EAAI8C,MAAQ,GAEL,UAAjBtH,KAAKunC,UACP/iC,EAAIkD,MAAQlD,EAAI8C,OAEG,WAAjBtH,KAAKwnC,UACPhjC,EAAImD,KAAOnD,EAAIoD,OAAS,GAEL,WAAjB5H,KAAKwnC,UACPhjC,EAAImD,KAAOnD,EAAIoD,SAGZpD,GAST+zB,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBAClB3zB,EAAO53B,KACL,MAAOZ,KAAKsrD,WAAY,cAExBtrD,KAAKurD,kBACLvrD,KAAKksD,wBACL,YACAlsD,KAAKqrD,eACL,QAGF,IAAK,IAAInqD,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnDs3B,EAAO53B,KAAK,KAAMZ,KAAK0B,SAASR,GAAGq3B,MAAMvuB,IAK3C,OAFAwuB,EAAO53B,KAAK,UAELoJ,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAS1DpM,IAAK,SAASjE,GACZ,GAAIA,KAAQ8zD,EAAiB,CAC3B,GAAIx0D,KAAKU,GACP,OAAOV,KAAKU,GAGZ,IAAK,IAAIQ,EAAI,EAAGC,EAAMnB,KAAK0B,SAASjB,OAAQS,EAAIC,EAAKD,IACnD,GAAIlB,KAAK0B,SAASR,GAAGR,GACnB,OAAO,EAGX,OAAO,EAIT,OAAIA,KAAQV,KAAKo1D,oBACRp1D,KAAK0B,SAAS,IAAM1B,KAAK0B,SAAS,GAAGiD,IAAIjE,GAE3CV,KAAKU,MAYlBvC,EAAOiqC,MAAM99B,WAAa,SAASrI,EAAQU,GACzCxE,EAAOiC,KAAK2J,eAAe9H,EAAOG,QAAS,SAASgI,GAClD,IAAIpJ,EAAU7C,EAAOiC,KAAK6B,OAAOuV,MAAMvV,GAAQ,UACxCjB,EAAQoB,QACfO,GAAYA,EAAS,IAAIxE,EAAOiqC,MAAMh+B,EAAkBpJ,GAAS,OAWrE7C,EAAOiqC,MAAMhZ,OAAQ,GA/oBvB,CAipBsB,oBAAZ/wB,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAIuS,EAASjZ,OAAOiC,KAAK6B,OAAOmV,OAE3BvS,EAAO1G,SACV0G,EAAO1G,OAAS,IAGd0G,EAAO1G,OAAOy/B,MAChBz/B,OAAOujB,KAAK,qCAWdvjB,OAAOy/B,MAAQz/B,OAAOiC,KAAK+Y,YAAYhb,OAAOmN,OAA6C,CAOzFzI,KAAM,QAQN2G,YAAa,GASbwG,OAAQ,OASRC,OAAQ,OASRJ,YAAa,OAQby3B,YAAa,EAQb8uB,YAAa,EAQbC,YAAa,EASbC,oBAAqB,GAQrBhpD,gBAAiBnP,OAAOmN,OAAOC,UAAU+B,gBAAgB8K,OACvD,SACA,SACA,eASFsnC,eAAe,EASftmC,WAAY,SAASW,EAAS/Y,EAAS2B,GACrC3B,IAAYA,EAAU,IACtBhB,KAAKu2D,QAAU,GACfv2D,KAAKw2D,cAAgB,GACrBx2D,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAKy2D,aAAa18C,EAAS/Y,EAAS2B,IAOtCgX,WAAY,WACV,OAAO3Z,KAAK02D,UAad98C,WAAY,SAASG,EAASpX,EAAU3B,GAEtC,IAAI21D,EAAWx+C,EAuBf,OArBAnY,KAAK02D,SAAW38C,EAChB/Z,KAAK42D,iBAAmB78C,EACxB/Z,KAAK62D,YAAY71D,GAGf21D,EADgC,IAA9B32D,KAAKw2D,cAAc/1D,OACTkC,GAGZwV,EAAQnY,KACI,WACVmY,EAAM2+C,aAAan0D,EAAUwV,EAAMq+C,cAAer+C,EAAM4+C,aAAe5+C,EAAMy+C,kBAAkB,KAIvE,IAAxB52D,KAAKu2D,QAAQ91D,OACfT,KAAK82D,aAAaH,GAEXA,GACPA,EAAU32D,MAGLA,MAQTg3D,eAAgB,SAAS31D,GAIvB,OAHArB,KAAKwJ,YAAcnI,EACnBrB,KAAK02D,SAASltD,YAAcnI,EAErBrB,MAOTi3D,gBAAiB,WACf,IAAIl9C,EAAU/Z,KAAK2Z,aACnB,MAAO,CACLrS,MAAOyS,EAAQzS,MACfM,OAAQmS,EAAQnS,SAQpBsvD,QAAS,SAASxrD,GAChB,GAAK1L,KAAK+nB,QAA+B,IAArB/nB,KAAKsnC,YAAzB,CAGA,IAAI6pB,EAAInxD,KAAKsH,MAAQ,EAAG+sB,EAAIr0B,KAAK4H,OAAS,EAC1C8D,EAAI+B,YACJ/B,EAAIY,QAAQ6kD,GAAI98B,GAChB3oB,EAAIo7B,OAAOqqB,GAAI98B,GACf3oB,EAAIo7B,OAAOqqB,EAAG98B,GACd3oB,EAAIo7B,QAAQqqB,EAAG98B,GACf3oB,EAAIo7B,QAAQqqB,GAAI98B,GAChB3oB,EAAIg8B,cAONie,oBAAqB,SAASj6C,GAC5B,IAAInF,GAAKvG,KAAKsH,MAAQ,EAClBd,GAAKxG,KAAK4H,OAAS,EACnBupD,EAAInxD,KAAKsH,MACT+sB,EAAIr0B,KAAK4H,OAEb8D,EAAIU,OACJpM,KAAK2kD,iBAAiBj5C,GAEtBA,EAAI+B,YACJtP,OAAOiC,KAAKqL,eAAeC,EAAKnF,EAAGC,EAAGD,EAAI4qD,EAAG3qD,EAAGxG,KAAK+kC,iBACrD5mC,OAAOiC,KAAKqL,eAAeC,EAAKnF,EAAI4qD,EAAG3qD,EAAGD,EAAI4qD,EAAG3qD,EAAI6tB,EAAGr0B,KAAK+kC,iBAC7D5mC,OAAOiC,KAAKqL,eAAeC,EAAKnF,EAAI4qD,EAAG3qD,EAAI6tB,EAAG9tB,EAAGC,EAAI6tB,EAAGr0B,KAAK+kC,iBAC7D5mC,OAAOiC,KAAKqL,eAAeC,EAAKnF,EAAGC,EAAI6tB,EAAG9tB,EAAGC,EAAGxG,KAAK+kC,iBACrDr5B,EAAIg8B,YACJh8B,EAAIc,WAQN6rB,SAAU,SAASC,GACjB,IAAIi+B,EAAU,GAAIC,EAAgB,GAC9BvoD,EAAS,EAAGC,EAAS,EAEzBlO,KAAKu2D,QAAQlsD,QAAQ,SAAS8sD,GACxBA,IACqB,WAAnBA,EAAUt0D,OACZoL,GAAUkpD,EAAUlpD,OACpBC,GAAUipD,EAAUjpD,QAEtBqoD,EAAQ31D,KAAKu2D,EAAU9+B,eAI3Br4B,KAAKw2D,cAAcnsD,QAAQ,SAAS8sD,GAClCA,GAAaX,EAAc51D,KAAKu2D,EAAU9+B,cAE5C,IAAIp2B,EAASmV,EACXpX,KAAK8Y,UACH,WACA,CAAC,cAAe,SAAU,SAAU,eAAeV,OAAOkgB,IACzD,CACDxuB,IAAK9J,KAAKo3D,SACVb,QAASA,EACTC,cAAeA,IAMnB,OAHAv0D,EAAOqF,OAAS2G,EAChBhM,EAAO2F,QAAUsG,EAEVjM,GASTs2B,MAAO,SAASvuB,GACd,IAAIwuB,EAASx4B,KAAKmsD,uBAAwB5lD,GAAKvG,KAAKsH,MAAQ,EAAGd,GAAKxG,KAAK4H,OAAS,EAC9E6iB,EAAsB,OAsB1B,GArBIzqB,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,OAC3B0D,EAAIvG,KAAK0H,KACTlB,EAAIxG,KAAK2H,KAES,SAAhB3H,KAAKgQ,QAAqC,SAAhBhQ,KAAKiQ,SACjCwa,EAAsB,IAAMzqB,KAAKgQ,OAAS,IAAMhQ,KAAKiQ,OAAS,IAAMjQ,KAAK6P,aAE3E2oB,EAAO53B,KACL,iBAAkBZ,KAAKurD,kBAAmBvrD,KAAKksD,wBAAyB,OACtE,UAAWlsD,KAAKsrD,WAAY,eAAgBtrD,KAAKq3D,WAVR,GAWvC,QAAS9wD,EAAG,QAASC,EACrB,YAAaxG,KAAKmrD,eAIlB,YAAanrD,KAAKsH,MAClB,aAActH,KAAK4H,OACnB,0BAA2B6iB,EAAqB,IAClD,eAGAzqB,KAAK+nB,QAAU/nB,KAAK+kC,gBAAiB,CACvC,IAAIuyB,EAAWt3D,KAAKM,KACpBN,KAAKM,KAAO,KACZk4B,EAAO53B,KACL,SACE,MAAO2F,EAAG,QAASC,EACnB,YAAaxG,KAAKsH,MAAO,aAActH,KAAK4H,OAC5C,YAAa5H,KAAKmrD,eACpB,SAEFnrD,KAAKM,KAAOg3D,EAKd,OAFA9+B,EAAO53B,KAAK,UAELoJ,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAS1DqmD,OAAQ,SAASG,GACf,IAAIx9C,EAAUw9C,EAAWv3D,KAAK02D,SAAW12D,KAAK42D,iBAC9C,OAAI78C,EACK5b,OAAOW,aAAeib,EAAQy9C,KAAOz9C,EAAQjQ,IAG7C9J,KAAK8J,KAAO,IAYvB2tD,OAAQ,SAAS3tD,EAAKnH,EAAU3B,GAC9B7C,OAAOiC,KAAKkJ,UAAUQ,EAAK,SAASL,GAClC,OAAOzJ,KAAK4Z,WAAWnQ,EAAK9G,EAAU3B,IACrChB,KAAMgB,GAAWA,EAAQwI,cAO9BgC,SAAU,WACR,MAAO,2BAA6BxL,KAAKo3D,SAAW,QAatDN,aAAc,SAASn0D,EAAU4zD,EAASmB,EAAYC,GAKpD,GAHApB,EAAUA,GAAWv2D,KAAKu2D,QAC1BmB,EAAaA,GAAc13D,KAAK42D,iBAEhC,CAIA,IAGkB3oD,EAAQC,EAHtB0pD,EAAcz5D,OAAOiC,KAAKsJ,cAC1BmuD,EAAgB73D,KAAK2/B,OAAS3/B,KAAK2/B,OAAO3C,mBAAqB7+B,OAAOuB,iBACtEo4D,EAAe93D,KAAKs2D,oBAAsBuB,EAC1C1/C,EAAQnY,KAEZ,GAAuB,IAAnBu2D,EAAQ91D,OAGV,OAFAT,KAAK02D,SAAWgB,EAChB/0D,GAAYA,EAAS3C,MACd03D,EAGT,IAAIhrD,EAAWvO,OAAOiC,KAAKqM,sBAiD3B,OAhDAC,EAASpF,MAAQowD,EAAWpwD,MAC5BoF,EAAS9E,OAAS8vD,EAAW9vD,OAC7B8E,EAASE,WAAW,MAAMi4C,UAAU6S,EAAY,EAAG,EAAGA,EAAWpwD,MAAOowD,EAAW9vD,QAEnF2uD,EAAQlsD,QAAQ,SAASjJ,GAClBA,IAGDu2D,GACF1pD,EAASkK,EAAMlK,OAAS6pD,EAAe3/C,EAAMlK,OAAS,EACtDC,EAASiK,EAAMjK,OAAS4pD,EAAe3/C,EAAMjK,OAAS,EAClDD,EAAS4pD,EAAgB,IAC3B5pD,GAAU4pD,GAER3pD,EAAS2pD,EAAgB,IAC3B3pD,GAAU2pD,KAIZ5pD,EAAS7M,EAAO6M,OAChBC,EAAS9M,EAAO8M,QAElB9M,EAAO22D,QAAQrrD,EAAUuB,EAAQC,GAC5BypD,GAA+B,WAAhBv2D,EAAOyB,OACzBsV,EAAM7Q,OAASlG,EAAO6M,OACtBkK,EAAMvQ,QAAUxG,EAAO8M,WAK3B0pD,EAAYtwD,MAAQoF,EAASpF,MAC7BswD,EAAYhwD,OAAS8E,EAAS9E,OAC1BzJ,OAAOW,cACT84D,EAAY9tD,IAAM4C,EAASsrD,cAASv5C,EAAWtgB,OAAOy/B,MAAMq6B,gBAE5D9/C,EAAMu+C,SAAWkB,GAChBD,IAAgBx/C,EAAM4+C,YAAca,GACrCj1D,GAAYA,EAASwV,KAGrBy/C,EAAYjuD,OAAS,WACnBwO,EAAMu+C,SAAWkB,GAChBD,IAAgBx/C,EAAM4+C,YAAca,GACrCj1D,GAAYA,EAASwV,GACrBy/C,EAAYjuD,OAAS+C,EAAW,MAElCkrD,EAAY9tD,IAAM4C,EAASitB,UAAU,cAEhCjtB,IAQTy5B,QAAS,SAASz6B,EAAKm4C,GACrB,IAAIt9C,EAAGC,EAAuC0xD,EAApCC,EAAen4D,KAAKo4D,eAE9B7xD,EAAKs9C,EAAc7jD,KAAK0H,MAAQ1H,KAAKsH,MAAQ,EAC7Cd,EAAKq9C,EAAc7jD,KAAK2H,KAAO3H,KAAK4H,OAAS,EAEpB,UAArB5H,KAAK6P,cACPnE,EAAI+B,YACJ/B,EAAIw9B,KAAK3iC,EAAGC,EAAGxG,KAAKsH,MAAOtH,KAAK4H,QAChC8D,EAAIgC,SAMJwqD,GAHoB,IAAlBl4D,KAAK+5C,UAAsB/5C,KAAKw2D,cAAc/1D,QAAUT,KAAKq4D,gBAC/Dr4D,KAAKo2D,YAAcp2D,KAAKiO,OACxBjO,KAAKq2D,YAAcr2D,KAAKkO,OACRlO,KAAK82D,aAAa,KAAM92D,KAAKw2D,cAAex2D,KAAK+2D,aAAe/2D,KAAK42D,kBAAkB,IAGvF52D,KAAK02D,WAENhrD,EAAIm5C,UAAUqT,EACA3xD,EAAI4xD,EAAaG,QACjB9xD,EAAI2xD,EAAaI,QACjBJ,EAAa7wD,MACb6wD,EAAavwD,QAG5C5H,KAAKk3D,QAAQxrD,GACb1L,KAAK0lD,cAAch6C,IAMrB2sD,aAAc,WACZ,OAAQr4D,KAAKiO,SAAWjO,KAAKo2D,aAAep2D,KAAKkO,SAAWlO,KAAKq2D,aAMnE+B,aAAc,WACZ,IAA8CI,EAC1Cr7B,EADA71B,EAAQtH,KAAKsH,MAAOM,EAAS5H,KAAK4H,OAC3B0wD,EAAU,EAAGC,EAAU,EAqBlC,MAnBoB,SAAhBv4D,KAAKgQ,QAAqC,SAAhBhQ,KAAKiQ,SACjCuoD,EAAS,CAACx4D,KAAKsH,MAAQtH,KAAK02D,SAASpvD,MAAOtH,KAAK4H,OAAS5H,KAAK02D,SAAS9uD,QACxEu1B,EAA6B,SAArBn9B,KAAK6P,YACH9K,KAAKS,IAAI5D,MAAM,KAAM42D,GAAUzzD,KAAKU,IAAI7D,MAAM,KAAM42D,GAC9DlxD,EAAQtH,KAAK02D,SAASpvD,MAAQ61B,EAC9Bv1B,EAAS5H,KAAK02D,SAAS9uD,OAASu1B,EACZ,QAAhBn9B,KAAKgQ,SACPsoD,GAAWt4D,KAAKsH,MAAQA,GAAS,GAEf,QAAhBtH,KAAKgQ,SACPsoD,EAAUt4D,KAAKsH,MAAQA,GAEL,QAAhBtH,KAAKiQ,SACPsoD,GAAWv4D,KAAK4H,OAASA,GAAU,GAEjB,QAAhB5H,KAAKiQ,SACPsoD,EAAUv4D,KAAK4H,OAASA,IAGrB,CACLN,MAAQA,EACRM,OAAQA,EACR0wD,QAASA,EACTC,QAASA,IAObE,kBAAmB,WACjB,IAAI1+C,EAAU/Z,KAAK2Z,aAEnB3Z,KAAKyD,IAAI,QAASsW,EAAQzS,OAC1BtH,KAAKyD,IAAI,SAAUsW,EAAQnS,SAU7B6uD,aAAc,SAAS18C,EAAS/Y,EAAS2B,GACvC3C,KAAK4Z,WAAWzb,OAAOiC,KAAKkf,QAAQvF,GAAUpX,EAAU3B,GACxD7C,OAAOiC,KAAKqf,SAASzf,KAAK2Z,aAAcxb,OAAOy/B,MAAM86B,aAOvD7B,YAAa,SAAS71D,GACpBA,IAAYA,EAAU,IACtBhB,KAAKy5B,WAAWz4B,GAChBhB,KAAKovD,gBAAgBpuD,GACjBhB,KAAK02D,UAAY12D,KAAKwJ,cACxBxJ,KAAK02D,SAASltD,YAAcxJ,KAAKwJ,cASrCmvD,aAAc,SAASpC,EAAS5zD,GAC1B4zD,GAAWA,EAAQ91D,OACrBtC,OAAOiC,KAAK2J,eAAewsD,EAAS,SAASnsD,GAC3CzH,GAAYA,EAASyH,IACpB,wBAGHzH,GAAYA,KAQhBysD,gBAAiB,SAASpuD,GACxBhB,KAAKsH,MAAQ,UAAWtG,EACpBA,EAAQsG,MACPtH,KAAK2Z,cACF3Z,KAAK2Z,aAAarS,OAClB,EAERtH,KAAK4H,OAAS,WAAY5G,EACtBA,EAAQ4G,OACP5H,KAAK2Z,cACF3Z,KAAK2Z,aAAa/R,QAClB,KAUZzJ,OAAOy/B,MAAM86B,WAAa,aAM1Bv6D,OAAOy/B,MAAMryB,UAAU8rD,UAAYl5D,OAAOy/B,MAAMryB,UAAU6rD,OAQ1Dj5D,OAAOy/B,MAAMtzB,WAAa,SAASrI,EAAQU,GACzCxE,OAAOiC,KAAKkJ,UAAUrH,EAAO6H,IAAK,SAASL,EAAKc,GAC1CA,EACF5H,GAAYA,EAAS,KAAM4H,GAG7BpM,OAAOy/B,MAAMryB,UAAUotD,aAAa73D,KAAKmB,EAAQA,EAAOs0D,QAAS,SAASA,GACxEt0D,EAAOs0D,QAAUA,GAAW,GAC5Bp4D,OAAOy/B,MAAMryB,UAAUotD,aAAa73D,KAAKmB,EAAQA,EAAOu0D,cAAe,SAASA,GAE9E,OADAv0D,EAAOu0D,cAAgBA,GAAiB,GACjC,IAAIr4D,OAAOy/B,MAAMn0B,EAAKxH,EAAQU,QAGxC,KAAMV,EAAOuH,cAUlBrL,OAAOy/B,MAAMg7B,QAAU,SAASrvD,EAAK5G,EAAUk2D,GAC7C16D,OAAOiC,KAAKkJ,UAAUC,EAAK,SAASE,GAClC9G,GAAYA,EAAS,IAAIxE,OAAOy/B,MAAMn0B,EAAKovD,KAC1C,KAAMA,GAAcA,EAAWrvD,cASpCrL,OAAOy/B,MAAMgyB,gBACXzxD,OAAOa,kBAAkBoZ,OAAO,8DAA8D/O,MAAM,MAUtGlL,OAAOy/B,MAAM5N,YAAc,SAASjW,EAASpX,EAAU3B,GACrD,IACI83D,EADAjJ,EAAmB1xD,OAAO4uB,gBAAgBhT,EAAS5b,OAAOy/B,MAAMgyB,iBAGhEC,EAAiBplC,sBACnBquC,EAAa36D,OAAOiC,KAAKsP,kCAAkCmgD,EAAiBplC,qBAC5ErT,EAAOy4C,EAAkBiJ,IAG3B36D,OAAOy/B,MAAMg7B,QAAQ/I,EAAiB,cAAeltD,EACnDyU,EAAQpW,EAAU7C,OAAOiC,KAAK6B,OAAOuV,MAAMxW,GAAW,GAAM6uD,KAUhE1xD,OAAOy/B,MAAMxO,OAAQ,EAQrBjxB,OAAOy/B,MAAMq6B,eAAiB,GAnrBhC,CAqrBsB,oBAAZ55D,QAA0BA,QAAU2B,MAG9C7B,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOmN,OAAOC,UAAiD,CAMvFwtD,4BAA6B,WAC3B,IAAIhrD,EAAQ/N,KAAKu8C,WAAa,IAC9B,OAAY,EAARxuC,EACoC,GAA/BhJ,KAAKuvB,OAAOvmB,EAAQ,GAAK,IAEF,GAAzBhJ,KAAKuvB,MAAMvmB,EAAQ,KAQ5BirD,WAAY,WAEV,OADAh5D,KAAK+O,SAAS/O,KAAK+4D,+BACZ/4D,MAWTi5D,aAAc,SAASlL,GAGrB,IAAIC,EAAQ,aACR5sC,GAHJ2sC,EAAYA,GAAa,IAGE3sC,YAAc4sC,EACrCrrC,EAAWorC,EAAUprC,UAAYqrC,EACjC71C,EAAQnY,KAmBZ,OAjBA7B,OAAOiC,KAAKgiB,QAAQ,CAClBW,WAAY/iB,KAAK2E,IAAI,SACrBqe,SAAUhjB,KAAK+4D,8BACft2C,SAAUziB,KAAK6tD,YACflrC,SAAU,SAASthB,GACjB8W,EAAMpJ,SAAS1N,GACfshB,KAEFvB,WAAY,WACVjJ,EAAM+mB,YACN9d,KAEF8B,QAAS,WACP/K,EAAM1U,IAAI,UAAU,MAIjBzD,QAIX7B,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO88B,aAAa1vB,UAAuD,CAQnG2tD,iBAAkB,SAAUj3D,GAG1B,OAFAA,EAAO+2D,aACPh5D,KAAK+B,YACE/B,MASTm5D,mBAAoB,SAAUl3D,GAI5B,OAHAA,EAAOg3D,aAAa,CAClBt2C,SAAU3iB,KAAK+B,UAAUkW,KAAKjY,QAEzBA,QAWX7B,OAAOy/B,MAAM24B,QAAUp4D,OAAOy/B,MAAM24B,SAAW,GAO/Cp4D,OAAOy/B,MAAM24B,QAAQ6C,WAAaj7D,OAAOiC,KAAK+Y,YAAoE,CAOhHtW,KAAM,aAMNuW,WAAY,SAASpY,GACfA,GACFhB,KAAKy5B,WAAWz4B,IAQpBy4B,WAAY,SAASz4B,GACnB,IAAK,IAAIN,KAAQM,EACfhB,KAAKU,GAAQM,EAAQN,IAQzB23B,SAAU,WACR,MAAO,CAAEx1B,KAAM7C,KAAK6C,OAOtB8hC,OAAQ,WAEN,OAAO3kC,KAAKq4B,cAIhBl6B,OAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAa,SAASrI,EAAQU,GAC5D,IAAIvB,EAAS,IAAIjD,OAAOy/B,MAAM24B,QAAQt0D,EAAOY,MAAMZ,GAEnD,OADAU,GAAYA,EAASvB,GACdA,GAIT,SAAUyD,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAgB9Bo9C,EAAQ8C,WAAalgD,EAAYo9C,EAAQ6C,WAAoE,CAO3Gv2D,KAAM,aAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKs5D,WAAat4D,EAAQs4D,YAAc,GAO1CvB,QAAS,SAASrrD,GAMhB,IALA,IAAI9J,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjB6pD,EAAat5D,KAAKs5D,WAEbp4D,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAC/CuO,EAAKvO,IAAMo4D,EACX7pD,EAAKvO,EAAI,IAAMo4D,EACf7pD,EAAKvO,EAAI,IAAMo4D,EAGjB12D,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCwgD,WAAYt5D,KAAKs5D,gBAYvBn7D,EAAOy/B,MAAM24B,QAAQ8C,WAAW/uD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAhF/E,CAkFsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YA2C9Bo9C,EAAQiD,UAAYrgD,EAAYo9C,EAAQ6C,WAAmE,CAOzGv2D,KAAM,YASNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GAErBhB,KAAKy5D,OAASz4D,EAAQy4D,OACtBz5D,KAAKupB,OAASvoB,EAAQuoB,QAAU,CAC9B,EAAG,EAAG,EACN,EAAG,EAAG,EACN,EAAG,EAAG,IAQVwuC,QAAS,SAASrrD,GAkBhB,IAhBA,IAaI3E,EAAGqsB,EAAGxmB,EAAG9F,EAAG4xD,EACZC,EAAKC,EAAKC,EAAQC,EAdlBC,EAAU/5D,KAAKupB,OACf3mB,EAAU8J,EAASE,WAAW,MAC9BotD,EAASp3D,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAE7DqyD,EAAOl1D,KAAKuvB,MAAMvvB,KAAKD,KAAKi1D,EAAQt5D,SACpCy5D,EAAWn1D,KAAKW,MAAMu0D,EAAO,GAC7BnwD,EAAMkwD,EAAOvqD,KACb0qD,EAAKH,EAAO1yD,MACZ8yD,EAAKJ,EAAOpyD,OACZyyD,EAASz3D,EAAQ03D,gBAAgBH,EAAIC,GACrCG,EAAMF,EAAO5qD,KAEb+qD,EAAWx6D,KAAKy5D,OAAS,EAAI,EAIxBjzD,EAAI,EAAGA,EAAI4zD,EAAI5zD,IACtB,IAAK,IAAID,EAAI,EAAGA,EAAI4zD,EAAI5zD,IAAK,CAC3BmzD,EAAwB,GAAdlzD,EAAI2zD,EAAK5zD,GAKnB,IAAK,IAAIiM,EAFY1K,EAAP8F,EAAPwmB,EAAPrsB,EAAI,EAEayK,EAAKynD,EAAMznD,IAC1B,IAAK,IAAID,EAAK,EAAGA,EAAK0nD,EAAM1nD,IAE1BonD,EAAMpzD,EAAIgM,EAAK2nD,GADfN,EAAMpzD,EAAIgM,EAAK0nD,GAIL,GAAWE,EAANR,GAAYD,EAAM,GAAWQ,EAANR,IAItCE,EAA4B,GAAlBD,EAAMO,EAAKR,GACrBG,EAAKC,EAAQvnD,EAAKynD,EAAO1nD,GAEzBxK,GAAK+B,EAAI+vD,GAAUC,EACnB1lC,GAAKtqB,EAAI+vD,EAAS,GAAKC,EACvBlsD,GAAK9D,EAAI+vD,EAAS,GAAKC,EACvBhyD,GAAKgC,EAAI+vD,EAAS,GAAKC,GAG3BS,EAAIb,GAAU3xD,EACdwyD,EAAIb,EAAS,GAAKtlC,EAClBmmC,EAAIb,EAAS,GAAK9rD,EAClB2sD,EAAIb,EAAS,GAAK5xD,EAAI0yD,GAAY,IAAM1yD,GAI5ClF,EAAQ22D,aAAac,EAAQ,EAAG,IAOlChiC,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxC2gD,OAAQz5D,KAAKy5D,OACblwC,OAAQvpB,KAAKupB,YAYnBprB,EAAOy/B,MAAM24B,QAAQiD,UAAUlvD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WA1J9E,CA4JsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAiB9Bo9C,EAAQkE,qBAAuBthD,EAAYo9C,EAAQ6C,WAA8E,CAO/Hv2D,KAAM,uBAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKm1B,UAAYn0B,EAAQm0B,WAAa,KAOxC4iC,QAAS,SAASrrD,GAOhB,IANA,IAAI9J,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjB0lB,EAAYn1B,KAAKm1B,UACjBk/B,EAAQ5kD,EAAKhP,OAERS,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAC/CuO,EAAKvO,EAAI,GAAKi0B,EAAY,KAAOk/B,EAAQnzD,GAAKmzD,EAGhDzxD,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCqc,UAAWn1B,KAAKm1B,eAYtBh3B,EAAOy/B,MAAM24B,QAAQkE,qBAAqBnwD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAhFzF,CAkFsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5Co4D,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAa9Bo9C,EAAQmE,UAAYvhD,EAAYo9C,EAAQ6C,WAAmE,CAOzGv2D,KAAM,YAONk1D,QAAS,SAASrrD,GAQhB,IAPA,IAKIsoB,EALApyB,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBtO,EAAMmO,EAAUhI,MAAQgI,EAAU1H,OAAS,EAC3C1F,EAAQ,EAGLA,EAAQf,GACb6zB,GAAWvlB,EAAKvN,GAASuN,EAAKvN,EAAQ,GAAKuN,EAAKvN,EAAQ,IAAM,EAC9DuN,EAAKvN,GAAa8yB,EAClBvlB,EAAKvN,EAAQ,GAAK8yB,EAClBvlB,EAAKvN,EAAQ,GAAK8yB,EAClB9yB,GAAS,EAGXU,EAAQ22D,aAAajqD,EAAW,EAAG,MAWvCnR,EAAOy/B,MAAM24B,QAAQmE,UAAUpwD,WAAa,SAASrI,EAAQU,GAG3D,OAFAV,EAASA,GAAU,IACZY,KAAO,YACP1E,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAWrI,EAAQU,IA/D9D,CAkEsB,oBAAZtE,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5Co4D,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAa9Bo9C,EAAQoE,OAASxhD,EAAYo9C,EAAQ6C,WAAgE,CAOnGv2D,KAAM,SAONk1D,QAAS,SAASrrD,GAChB,IAGwBxL,EAHpB0B,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAEhB,IAAKS,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzBuO,EAAKvO,GAAK,IAAMuO,EAAKvO,GACrBuO,EAAKvO,EAAI,GAAK,IAAMuO,EAAKvO,EAAI,GAC7BuO,EAAKvO,EAAI,GAAK,IAAMuO,EAAKvO,EAAI,GAG/B0B,EAAQ22D,aAAajqD,EAAW,EAAG,MAWvCnR,EAAOy/B,MAAM24B,QAAQoE,OAAOrwD,WAAa,SAASrI,EAAQU,GAGxD,OAFAV,EAASA,GAAU,IACZY,KAAO,SACP1E,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAWrI,EAAQU,IA3D9D,CA8DsB,oBAAZtE,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAU9Bo9C,EAAQqE,KAAOzhD,EAAYo9C,EAAQ6C,WAA8D,CAO/Fv2D,KAAM,OASNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GAErBhB,KAAK66D,KAAO75D,EAAQ65D,KACpB76D,KAAK86D,SAAmD,EAAzC,CAAC,EAAG,EAAG,EAAG,GAAG36D,QAAQa,EAAQ85D,SAAgB95D,EAAQ85D,QAAU,GAOhF/C,QAAS,SAASrrD,GAChB,GAAK1M,KAAK66D,KAAV,CAIA,IAMI35D,EANA0B,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsrD,EAAS/6D,KAAK66D,KAAKlhD,aACnBqhD,EAAe78D,EAAOiC,KAAKqM,sBAC3BquD,EAAU96D,KAAK86D,QAEf/E,EAAOzmD,EAAUhI,MAAQgI,EAAU1H,OAAS,EAEhDozD,EAAa1zD,MAAQoF,EAASpF,MAC9B0zD,EAAapzD,OAAS8E,EAAS9E,OAE/BozD,EAAapuD,WAAW,MAAMi4C,UAAUkW,EAAQ,EAAG,EAAGruD,EAASpF,MAAOoF,EAAS9E,QAE/E,IACIqzD,EADgBD,EAAapuD,WAAW,MAAM2C,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QACjE6H,KAE7B,IAAKvO,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzBuO,EAAKvO,EAAI,GAAK+5D,EAAS/5D,EAAI45D,GAG7Bl4D,EAAQ22D,aAAajqD,EAAW,EAAG,KAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxC+hD,KAAM76D,KAAK66D,KAAKxiC,WAChByiC,QAAS96D,KAAK86D,aAWpB38D,EAAOy/B,MAAM24B,QAAQqE,KAAKtwD,WAAa,SAASrI,EAAQU,GACtDxE,EAAOiC,KAAKkJ,UAAUrH,EAAO44D,KAAK/wD,IAAK,SAASL,GAE9C,OADAxH,EAAO44D,KAAO,IAAI18D,EAAOy/B,MAAMn0B,EAAKxH,EAAO44D,MACpC18D,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAWrI,EAAQU,MAU9DxE,EAAOy/B,MAAM24B,QAAQqE,KAAKxrC,OAAQ,EAxGpC,CA0GsB,oBAAZ/wB,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAgB9Bo9C,EAAQ2E,MAAQ/hD,EAAYo9C,EAAQ6C,WAA+D,CAOjGv2D,KAAM,QAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKm7D,MAAQn6D,EAAQm6D,OAAS,GAOhCpD,QAAS,SAASrrD,GAMhB,IALA,IAGwB0uD,EAHpBx4D,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjB0rD,EAAQn7D,KAAKm7D,MAERj6D,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAE/Ck6D,GAAQ,GAAMr2D,KAAKY,UAAYw1D,EAE/B1rD,EAAKvO,IAAMk6D,EACX3rD,EAAKvO,EAAI,IAAMk6D,EACf3rD,EAAKvO,EAAI,IAAMk6D,EAGjBx4D,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCqiD,MAAOn7D,KAAKm7D,WAYlBh9D,EAAOy/B,MAAM24B,QAAQ2E,MAAM5wD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAnF1E,CAqFsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAgB9Bo9C,EAAQ8E,SAAWliD,EAAYo9C,EAAQ6C,WAAkE,CAOvGv2D,KAAM,WAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKs7D,UAAYt6D,EAAQs6D,WAAa,GAOxCvD,QAAS,SAASrrD,GAChB,IAKIxK,EAAOhB,EAAGkU,EAAGrN,EAAGqsB,EAAGxmB,EAAG9F,EALtBlF,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOzmD,EAAU1H,OACjBouD,EAAO1mD,EAAUhI,MAGrB,IAAKpG,EAAI,EAAGA,EAAI60D,EAAM70D,GAAKlB,KAAKs7D,UAC9B,IAAKlmD,EAAI,EAAGA,EAAI4gD,EAAM5gD,GAAKpV,KAAKs7D,UAAW,CAIzCvzD,EAAI0H,EAFJvN,EAAa,EAAJhB,EAAS80D,EAAY,EAAJ5gD,GAG1Bgf,EAAI3kB,EAAKvN,EAAQ,GACjB0L,EAAI6B,EAAKvN,EAAQ,GACjB4F,EAAI2H,EAAKvN,EAAQ,GAYjB,IAAK,IAAIq5D,EAAKr6D,EAAGs6D,EAAQt6D,EAAIlB,KAAKs7D,UAAWC,EAAKC,EAAOD,IACvD,IAAK,IAAIE,EAAKrmD,EAAGsmD,EAAQtmD,EAAIpV,KAAKs7D,UAAWG,EAAKC,EAAOD,IAEvDhsD,EADAvN,EAAc,EAALq5D,EAAUvF,EAAa,EAALyF,GACb1zD,EACd0H,EAAKvN,EAAQ,GAAKkyB,EAClB3kB,EAAKvN,EAAQ,GAAK0L,EAClB6B,EAAKvN,EAAQ,GAAK4F,EAM1BlF,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCwiD,UAAWt7D,KAAKs7D,eAYtBn9D,EAAOy/B,MAAM24B,QAAQ8E,SAAS/wD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WA5G7E,CA8GsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAiB9Bo9C,EAAQoF,YAAcxiD,EAAYo9C,EAAQ6C,WAAqE,CAO7Gv2D,KAAM,cASNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKm1B,UAAYn0B,EAAQm0B,WAAa,GACtCn1B,KAAK47D,SAAW56D,EAAQ46D,UAAY,IAOtC7D,QAAS,SAASrrD,GAUhB,IATA,IAOI3E,EAAGqsB,EAAGxmB,EAPNhL,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjB0lB,EAAYn1B,KAAKm1B,UACjBymC,EAAW57D,KAAK47D,SAChBC,EAAQ,IAAM1mC,EACdjwB,EAAMH,KAAKG,IAGNhE,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAC/C6G,EAAI0H,EAAKvO,GACTkzB,EAAI3kB,EAAKvO,EAAI,GACb0M,EAAI6B,EAAKvO,EAAI,GAEL26D,EAAJ9zD,GACI8zD,EAAJznC,GACIynC,EAAJjuD,GACA1I,EAAI6C,EAAIqsB,GAAKwnC,GACb12D,EAAI6C,EAAI6F,GAAKguD,GACb12D,EAAIkvB,EAAIxmB,GAAKguD,IAEfnsD,EAAKvO,EAAI,GAAK,GAIlB0B,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCqc,UAAWn1B,KAAKm1B,UAChBymC,SAAU57D,KAAK47D,cAYrBz9D,EAAOy/B,MAAM24B,QAAQoF,YAAYrxD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAlGhF,CAoGsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5Co4D,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAa9Bo9C,EAAQuF,MAAQ3iD,EAAYo9C,EAAQ6C,WAA+D,CAOjGv2D,KAAM,QAONk1D,QAAS,SAASrrD,GAChB,IAGwBxL,EAAG66D,EAHvBn5D,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAEhB,IAAKS,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzB66D,EAAM,GAAOtsD,EAAKvO,GAAK,IAAOuO,EAAKvO,EAAI,GAAK,IAAOuO,EAAKvO,EAAI,GAC5DuO,EAAKvO,GAAK66D,EAAM,IAChBtsD,EAAKvO,EAAI,GAAK66D,EAAM,GACpBtsD,EAAKvO,EAAI,GAAK66D,EAAM,IAGtBn5D,EAAQ22D,aAAajqD,EAAW,EAAG,MAWvCnR,EAAOy/B,MAAM24B,QAAQuF,MAAMxxD,WAAa,SAASrI,EAAQU,GAGvD,OAFAV,EAASA,GAAU,IACZY,KAAO,QACP,IAAI1E,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAWrI,EAAQU,IA5DlE,CA+DsB,oBAAZtE,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5Co4D,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAa9Bo9C,EAAQyF,OAAS7iD,EAAYo9C,EAAQ6C,WAAgE,CAOnGv2D,KAAM,SAONk1D,QAAS,SAASrrD,GAChB,IAGwBxL,EAAG6G,EAAGqsB,EAAGxmB,EAH7BhL,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAEhB,IAAKS,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzB6G,EAAI0H,EAAKvO,GACTkzB,EAAI3kB,EAAKvO,EAAI,GACb0M,EAAI6B,EAAKvO,EAAI,GAEbuO,EAAKvO,IAAU,KAAJ6G,EAAgB,KAAJqsB,EAAgB,KAAJxmB,GAAc,MACjD6B,EAAKvO,EAAI,IAAU,KAAJ6G,EAAgB,KAAJqsB,EAAgB,KAAJxmB,GAAc,MACrD6B,EAAKvO,EAAI,IAAU,KAAJ6G,EAAgB,KAAJqsB,EAAgB,KAAJxmB,GAAc,KAGvDhL,EAAQ22D,aAAajqD,EAAW,EAAG,MAWvCnR,EAAOy/B,MAAM24B,QAAQyF,OAAO1xD,WAAa,SAASrI,EAAQU,GAGxD,OAFAV,EAASA,GAAU,IACZY,KAAO,SACP,IAAI1E,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAAWrI,EAAQU,IA/DlE,CAkEsB,oBAAZtE,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAwB9Bo9C,EAAQ0F,KAAO9iD,EAAYo9C,EAAQ6C,WAA8D,CAO/Fv2D,KAAM,OASNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GAErBhB,KAAKkkB,MAAQljB,EAAQkjB,OAAS,UAC9BlkB,KAAKkc,aAAqC,IAApBlb,EAAQkb,QACZlb,EAAQkb,QACR,IAAI/d,EAAOylB,MAAM5jB,KAAKkkB,OAAO6J,YAOjDgqC,QAAS,SAASrrD,GAChB,IAGwBxL,EACpBg7D,EAAOC,EAAOC,EACdr0D,EAAGqsB,EAAGxmB,EAAGyuD,EACTr4D,EANApB,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAahB,IANAy7D,GAFAl4D,EAAS,IAAI7F,EAAOylB,MAAM5jB,KAAKkkB,OAAOL,aAEvB,GAAK7jB,KAAKkc,QACzBigD,EAAQn4D,EAAO,GAAKhE,KAAKkc,QACzBkgD,EAAQp4D,EAAO,GAAKhE,KAAKkc,QAEzBmgD,EAAS,EAAIr8D,KAAKkc,QAEbhb,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzB6G,EAAI0H,EAAKvO,GACTkzB,EAAI3kB,EAAKvO,EAAI,GACb0M,EAAI6B,EAAKvO,EAAI,GAGbuO,EAAKvO,GAAKg7D,EAAQn0D,EAAIs0D,EACtB5sD,EAAKvO,EAAI,GAAKi7D,EAAQ/nC,EAAIioC,EAC1B5sD,EAAKvO,EAAI,GAAKk7D,EAAQxuD,EAAIyuD,EAG5Bz5D,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCoL,MAAOlkB,KAAKkkB,MACZhI,QAASlc,KAAKkc,aAYpB/d,EAAOy/B,MAAM24B,QAAQ0F,KAAK3xD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WA9GzE,CAgHsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAqB9Bo9C,EAAQ+F,SAAWnjD,EAAYo9C,EAAQ6C,WAAkE,CAOvGv2D,KAAM,WAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GAErBhB,KAAKkkB,MAAQljB,EAAQkjB,OAAS,WAOhC6zC,QAAS,SAASrrD,GAChB,IAGwBxL,EACpB8C,EAJApB,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAKhB,IAFAuD,EAAS,IAAI7F,EAAOylB,MAAM5jB,KAAKkkB,OAAOL,YAEjC3iB,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EACzBuO,EAAKvO,IAAM8C,EAAO,GAAK,IACvByL,EAAKvO,EAAI,IAAM8C,EAAO,GAAK,IAC3ByL,EAAKvO,EAAI,IAAM8C,EAAO,GAAK,IAG7BpB,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCoL,MAAOlkB,KAAKkkB,WAYlB/lB,EAAOy/B,MAAM24B,QAAQ+F,SAAShyD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAzF7E,CA2FsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GACR,aAEA,IAAI1G,EAAS0G,EAAO1G,OAChBo4D,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAuB9Bo9C,EAAQgG,MAAQpjD,EAAYo9C,EAAQ6C,WAA+D,CACjGv2D,KAAM,QAENuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKkkB,MAAQljB,EAAQkjB,OAAS,OAC9BlkB,KAAKq9B,MAAQr8B,EAAQq8B,QAAS,EAC9Br9B,KAAKw8D,KAAOx7D,EAAQw7D,MAAQ,WAC5Bx8D,KAAK80B,MAAQ9zB,EAAQ8zB,OAAS,GAGhCijC,QAAS,SAASrrD,GAChB,IAGI6zB,EAAIk8B,EAAIroD,EACRrM,EAAGqsB,EAAGxmB,EACN8uD,EAAIC,EAAIC,EACR54D,EANApB,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KAKjBotD,GAAU,EAEd,GAAI78D,KAAKq9B,MAAO,CAEdw/B,GAAU,EAEV,IAAIC,EAAM3+D,EAAOiC,KAAKqM,sBACtBqwD,EAAIx1D,MAAQtH,KAAKq9B,MAAM/1B,MACvBw1D,EAAIl1D,OAAS5H,KAAKq9B,MAAMz1B,OAExB,IAAIm1D,EAAY,IAAI5+D,EAAO88B,aAAa6hC,GACxCC,EAAUp7D,IAAI3B,KAAKq9B,OAEnBr5B,EADgB+4D,EAAUnwD,WAAW,MACnB2C,aAAa,EAAG,EAAGwtD,EAAUz1D,MAAOy1D,EAAUn1D,QAAQ6H,UAMxE8wB,GAFAv8B,EAAS,IAAI7F,EAAOylB,MAAM5jB,KAAKkkB,OAAOL,aAE1B,GAAK7jB,KAAK80B,MACtB2nC,EAAKz4D,EAAO,GAAKhE,KAAK80B,MACtB1gB,EAAKpQ,EAAO,GAAKhE,KAAK80B,MAGxB,IAAK,IAAI5zB,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAY/C,OAVA6G,EAAI0H,EAAKvO,GACTkzB,EAAI3kB,EAAKvO,EAAI,GACb0M,EAAI6B,EAAKvO,EAAI,GAET27D,IACFt8B,EAAKv8B,EAAO9C,GAAKlB,KAAK80B,MACtB2nC,EAAKz4D,EAAO9C,EAAI,GAAKlB,KAAK80B,MAC1B1gB,EAAKpQ,EAAO9C,EAAI,GAAKlB,KAAK80B,OAGpB90B,KAAKw8D,MACX,IAAK,WACH/sD,EAAKvO,GAAK6G,EAAIw4B,EAAK,IACnB9wB,EAAKvO,EAAI,GAAKkzB,EAAIqoC,EAAK,IACvBhtD,EAAKvO,EAAI,GAAK0M,EAAIwG,EAAK,IACvB,MACF,IAAK,SACH3E,EAAKvO,GAAK,GAAK,EAAI6G,IAAM,EAAIw4B,GAC7B9wB,EAAKvO,EAAI,GAAK,GAAK,EAAIkzB,IAAM,EAAIqoC,GACjChtD,EAAKvO,EAAI,GAAK,GAAK,EAAI0M,IAAM,EAAIwG,GACjC,MACF,IAAK,MACH3E,EAAKvO,GAAK6D,KAAKS,IAAI,IAAKuC,EAAIw4B,GAC5B9wB,EAAKvO,EAAI,GAAK6D,KAAKS,IAAI,IAAK4uB,EAAIqoC,GAChChtD,EAAKvO,EAAI,GAAK6D,KAAKS,IAAI,IAAKoI,EAAIwG,GAChC,MACF,IAAK,OACL,IAAK,aACH3E,EAAKvO,GAAK6D,KAAKG,IAAI6C,EAAIw4B,GACvB9wB,EAAKvO,EAAI,GAAK6D,KAAKG,IAAIkvB,EAAIqoC,GAC3BhtD,EAAKvO,EAAI,GAAK6D,KAAKG,IAAI0I,EAAIwG,GAC3B,MACF,IAAK,WACHsoD,EAAK30D,EAAIw4B,EACTo8B,EAAKvoC,EAAIqoC,EACTG,EAAKhvD,EAAIwG,EAET3E,EAAKvO,GAAMw7D,EAAK,EAAK,EAAIA,EACzBjtD,EAAKvO,EAAI,GAAMy7D,EAAK,EAAK,EAAIA,EAC7BltD,EAAKvO,EAAI,GAAM07D,EAAK,EAAK,EAAIA,EAC7B,MACF,IAAK,SACHntD,EAAKvO,GAAK6D,KAAKS,IAAIuC,EAAGw4B,GACtB9wB,EAAKvO,EAAI,GAAK6D,KAAKS,IAAI4uB,EAAGqoC,GAC1BhtD,EAAKvO,EAAI,GAAK6D,KAAKS,IAAIoI,EAAGwG,GAC1B,MACF,IAAK,UACH3E,EAAKvO,GAAK6D,KAAKU,IAAIsC,EAAGw4B,GACtB9wB,EAAKvO,EAAI,GAAK6D,KAAKU,IAAI2uB,EAAGqoC,GAC1BhtD,EAAKvO,EAAI,GAAK6D,KAAKU,IAAImI,EAAGwG,GAKhCxR,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,MAAO,CACLnU,MAAOlkB,KAAKkkB,MACZmZ,MAAOr9B,KAAKq9B,MACZm/B,KAAMx8D,KAAKw8D,KACX1nC,MAAO90B,KAAK80B,UAYlB32B,EAAOy/B,MAAM24B,QAAQgG,MAAMjyD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAvJ1E,CAyJsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAAM8G,EAAMF,KAAKE,IAAKS,EAAQX,KAAKW,MAC/EZ,EAAOC,KAAKD,KAAMI,EAAMH,KAAKG,IAAKO,EAAMV,KAAKU,IAAK6uB,EAAQvvB,KAAKuvB,MAAO3tB,EAAM5B,KAAK4B,IACjFoM,EAAOhO,KAAKgO,KACZwjD,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAa9Bo9C,EAAQyG,OAAS7jD,EAAYo9C,EAAQ6C,WAAgE,CAOnGv2D,KAAM,SAONo6D,WAAY,UAOZhvD,OAAQ,EAORC,OAAQ,EAORgvD,aAAc,EASdnF,QAAS,SAASrrD,EAAUuB,EAAQC,GAClC,GAAe,IAAXD,GAA2B,IAAXC,EAApB,CAIAlO,KAAKm9D,UAAY,EAAIlvD,EACrBjO,KAAKo9D,UAAY,EAAIlvD,EAErB,IAEIoB,EAFA+tD,EAAK3wD,EAASpF,MAAOg2D,EAAK5wD,EAAS9E,OACnC21D,EAAKjpC,EAAM+oC,EAAKpvD,GAASuvD,EAAKlpC,EAAMgpC,EAAKpvD,GAGrB,cAApBlO,KAAKi9D,aACP3tD,EAAYtP,KAAKy9D,WAAW/wD,EAAU2wD,EAAIC,EAAIC,EAAIC,IAE5B,YAApBx9D,KAAKi9D,aACP3tD,EAAYtP,KAAK09D,kBAAkBhxD,EAAU2wD,EAAIC,EAAIC,EAAIC,IAEnC,aAApBx9D,KAAKi9D,aACP3tD,EAAYtP,KAAK29D,kBAAkBjxD,EAAU2wD,EAAIC,EAAIC,EAAIC,IAEnC,YAApBx9D,KAAKi9D,aACP3tD,EAAYtP,KAAK49D,cAAclxD,EAAU2wD,EAAIC,EAAIC,EAAIC,IAEvD9wD,EAASpF,MAAQi2D,EACjB7wD,EAAS9E,OAAS41D,EAClB9wD,EAASE,WAAW,MAAM2sD,aAAajqD,EAAW,EAAG,KAYvDmuD,WAAY,SAAS/wD,EAAU2wD,EAAIC,EAAIC,EAAIC,GACzC,IAAyCluD,EAArC1M,EAAU8J,EAASE,WAAW,MAC9BixD,EAAQ,GAAKC,EAAQ,GAAKC,EAAQ,EAAGC,EAAQ,EAC7CC,GAAQ,EAAOC,GAAQ,EAAOC,EAAQd,EAAIe,EAAQd,EAClDP,EAAY5+D,EAAOiC,KAAKqM,sBACxB4xD,EAAStB,EAAUnwD,WAAW,MAmBlC,IAlBA2wD,EAAK73D,EAAM63D,GACXC,EAAK93D,EAAM83D,GACXT,EAAUz1D,MAAQ7B,EAAI83D,EAAIF,GAC1BN,EAAUn1D,OAASnC,EAAI+3D,EAAIF,GAElBD,EAALE,IACFM,EAAQ,EACRE,GAAS,GAEFT,EAALE,IACFM,EAAQ,EACRE,GAAS,GAEX1uD,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG8tD,EAAIC,GAC3C5wD,EAASpF,MAAQ7B,EAAI83D,EAAIF,GACzB3wD,EAAS9E,OAASnC,EAAI+3D,EAAIF,GAC1B16D,EAAQ22D,aAAajqD,EAAW,EAAG,IAE3B2uD,IAAUC,GAEhBZ,EAAKc,EACDb,EAAKQ,EAAQr4D,GAFjB23D,EAAKc,GAE0BN,EAAQE,GACrCI,EAAQz4D,EAAMy4D,EAAQN,IAGtBM,EAAQZ,EACRU,GAAQ,GAENT,EAAKQ,EAAQt4D,EAAM04D,EAAQN,EAAQE,GACrCI,EAAQ14D,EAAM04D,EAAQN,IAGtBM,EAAQZ,EACRU,GAAQ,GAEV5uD,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG8tD,EAAIC,GAC3Ce,EAAO9E,aAAajqD,EAAW,EAAG,GAClC1M,EAAQi9B,UAAU,EAAG,EAAGs+B,EAAOC,GAC/Bx7D,EAAQiiD,UAAUkY,EAAW,EAAG,EAAGM,EAAIC,EAAI,EAAG,EAAGa,EAAOC,GAE1D,OAAOx7D,EAAQ2M,aAAa,EAAG,EAAGguD,EAAIC,IAYxCI,cAAe,SAASlxD,EAAU2wD,EAAIC,EAAIC,EAAIC,GAmE5C,IAjEuBc,EAiEnB17D,EAAU8J,EAASE,WAAW,MAC9B2xD,EAAS37D,EAAQ2M,aAAa,EAAG,EAAG8tD,EAAIC,GACxCkB,EAAU57D,EAAQ2M,aAAa,EAAG,EAAGguD,EAAIC,GACzCiB,EAAUF,EAAO9uD,KAAMivD,EAAWF,EAAQ/uD,KAC1CkvD,GArEmBL,EAqEKt+D,KAAKk9D,aApExB,SAAS32D,GACd,GAAQ+3D,EAAJ/3D,EACF,OAAO,EAGT,GADAA,GAAKxB,KAAKK,GACNF,EAAIqB,GAAK,MACX,OAAO,EAET,IAAIq4D,EAAKr4D,EAAI+3D,EACb,OAAO33D,EAAIJ,GAAKI,EAAIi4D,GAAMr4D,EAAIq4D,IA4D9BC,EAAS7+D,KAAKm9D,UAAW2B,EAAS9+D,KAAKo9D,UACvC2B,EAAY,EAAI/+D,KAAKm9D,UAAW6B,EAAY,EAAIh/D,KAAKo9D,UACrD6B,EAAUlsD,EAAK8rD,EAAS7+D,KAAKk9D,aAAe,GAC5CgC,EAAUnsD,EAAK+rD,EAAS9+D,KAAKk9D,aAAe,GAC5CiC,EAAY,GAAK59B,EAAS,GAAK69B,EAAU,GAE7C,OA9DA,SAASC,EAAQC,GACf,IAAIl5D,EAAGlF,EAAGq+D,EAAQj6D,EAAKwC,EAAGyuB,EAAKP,EAC3BJ,EAAMd,EAAO0qC,EAAIC,EAGrB,IAFAl+B,EAAOh7B,GAAK+4D,EAAI,IAAOT,EACvBO,EAAQ74D,EAAIb,EAAM67B,EAAOh7B,GACpBH,EAAI,EAAGA,EAAIo3D,EAAIp3D,IAAK,CAIvB,IAHAm7B,EAAO/6B,GAAKJ,EAAI,IAAO04D,EACvBM,EAAQ54D,EAAId,EAAM67B,EAAO/6B,GACYsuB,EAAVc,EAAXI,EAATO,EAAPzuB,EAAI,EACC5G,EAAIk+D,EAAQ74D,EAAI04D,EAAS/9D,GAAKk+D,EAAQ74D,EAAI04D,EAAS/9D,IACtD,KAAIA,EAAI,GAAUm8D,GAALn8D,GAAb,CAGAs+D,EAAK95D,EAAM,IAAOR,EAAIhE,EAAIqgC,EAAOh7B,IAC5B44D,EAAUK,KACbL,EAAUK,GAAM,IAElB,IAAK,IAAIpqD,EAAIgqD,EAAQ54D,EAAI04D,EAAS9pD,GAAKgqD,EAAQ54D,EAAI04D,EAAS9pD,IACtDA,EAAI,GAAUkoD,GAALloD,IAGbqqD,EAAK/5D,EAAM,IAAOR,EAAIkQ,EAAImsB,EAAO/6B,IAC5B24D,EAAUK,GAAIC,KACjBN,EAAUK,GAAIC,GAAMd,EAAQ75D,EAAKG,EAAIu6D,EAAKT,EAAW,GAAK95D,EAAIw6D,EAAKT,EAAW,IAAM,MAGzE,GADbO,EAASJ,EAAUK,GAAIC,MAGrB33D,GAAKy3D,EACLhpC,GAAOgpC,EAASd,EAFhBn5D,EAAqB,GAAd8P,EAAIioD,EAAKn8D,IAGhB80B,GAASupC,EAASd,EAAQn5D,EAAM,GAChCswB,GAAQ2pC,EAASd,EAAQn5D,EAAM,GAC/BwvB,GAASyqC,EAASd,EAAQn5D,EAAM,KAKtCo5D,EADAp5D,EAAqB,GAAdc,EAAIm3D,EAAK+B,IACA/oC,EAAMzuB,EACtB42D,EAASp5D,EAAM,GAAK0wB,EAAQluB,EAC5B42D,EAASp5D,EAAM,GAAKswB,EAAO9tB,EAC3B42D,EAASp5D,EAAM,GAAKwvB,EAAQhtB,EAG9B,QAAMw3D,EAAI/B,EACD8B,EAAQC,GAGRd,EAeJa,CAAQ,IAYjB1B,kBAAmB,SAASjxD,EAAU2wD,EAAIC,EAAIC,EAAIC,GAChD,IAAgBj3D,EAAGC,EAAGtF,EAAGkU,EAAGsqD,EAAOC,EAAOC,EACtC17C,EAAmB27C,EAAZ1/C,EAAS,EAAY0+C,EAAS7+D,KAAKm9D,UAC1C2B,EAAS9+D,KAAKo9D,UAAWx6D,EAAU8J,EAASE,WAAW,MACvDkzD,EAAK,GAAKzC,EAAK,GACfrD,EADyBp3D,EAAQ2M,aAAa,EAAG,EAAG8tD,EAAIC,GAC3C7tD,KAAMswD,EAAYn9D,EAAQ2M,aAAa,EAAG,EAAGguD,EAAIC,GAC9DwC,EAAaD,EAAUtwD,KAC3B,IAAKvO,EAAI,EAAGA,EAAIs8D,EAAIt8D,IAClB,IAAKkU,EAAI,EAAGA,EAAImoD,EAAInoD,IAOlB,IAJAsqD,EAAQb,EAASzpD,GAFjB7O,EAAIb,EAAMm5D,EAASzpD,IAGnBuqD,EAAQb,EAAS59D,GAFjBsF,EAAId,EAAMo5D,EAAS59D,IAGnB2+D,EAAU,GAAKr5D,EAAI62D,EAAK92D,GAEnBq5D,EAAO,EAAGA,EAAO,EAAGA,IAKvB17C,EAJI81C,EAAO6F,EAAUD,IAIR,EAAIF,IAAU,EAAIC,GAH3B3F,EAAO6F,EAAU,EAAID,GAGmBF,GAAS,EAAIC,GAFrD3F,EAAO6F,EAAUC,EAAKF,GAGdD,GAAS,EAAID,GAFrB1F,EAAO6F,EAAUC,EAAK,EAAIF,GAEQF,EAAQC,EAC9CK,EAAW7/C,KAAY+D,EAI7B,OAAO67C,GAYTrC,kBAAmB,SAAShxD,EAAU2wD,EAAIC,EAAIC,EAAIC,GAOhD,IANA,IAAIyC,EAASjgE,KAAKm9D,UAAW+C,EAASlgE,KAAKo9D,UACvC+C,EAAaptD,EAAKktD,EAAS,GAC3BG,EAAartD,EAAKmtD,EAAS,GAC3Bt9D,EAAU8J,EAASE,WAAW,MACY6C,EAApC7M,EAAQ2M,aAAa,EAAG,EAAG8tD,EAAIC,GAAgB7tD,KACrD4wD,EAAOz9D,EAAQ2M,aAAa,EAAG,EAAGguD,EAAIC,GAAK8C,EAAQD,EAAK5wD,KACnD2F,EAAI,EAAGA,EAAIooD,EAAIpoD,IACtB,IAAK,IAAIlU,EAAI,EAAGA,EAAIq8D,EAAIr8D,IAAK,CAG3B,IAFA,IAAIyK,EAAoB,GAAdzK,EAAIkU,EAAImoD,GAASgC,EAAS,EAAGxF,EAAU,EAAGwG,EAAe,EAC/DC,EAAM,EAAGC,EAAM,EAAGC,EAAM,EAAGC,EAAM,EAAGC,GAAWxrD,EAAI,IAAO8qD,EACrDW,EAAKn7D,EAAM0P,EAAI8qD,GAASW,GAAMzrD,EAAI,GAAK8qD,EAAQW,IAGtD,IAFA,IAAI90D,EAAK7G,EAAI07D,GAAWC,EAAK,KAAQT,EACjCU,GAAW5/D,EAAI,IAAO++D,EAAQc,EAAKh1D,EAAKA,EACnC6yD,EAAKl5D,EAAMxE,EAAI++D,GAASrB,GAAM19D,EAAI,GAAK++D,EAAQrB,IAAM,CAC5D,IAAI9yD,EAAK5G,EAAI47D,GAAWlC,EAAK,KAAQuB,EACjChP,EAAIrsD,EAAKi8D,EAAKj1D,EAAKA,GAEf,EAAJqlD,GAASA,GAAK,GAKL,GADboO,EAAS,EAAIpO,EAAIA,EAAIA,EAAI,EAAIA,EAAIA,EAAI,KAInCwP,GAAOpB,EAAS9vD,GAFhB3D,EAAK,GAAK8yD,EAAKiC,EAAKxD,IAEM,GAC1BkD,GAAgBhB,EAEZ9vD,EAAK3D,EAAK,GAAK,MACjByzD,EAASA,EAAS9vD,EAAK3D,EAAK,GAAK,KAEnC00D,GAAOjB,EAAS9vD,EAAK3D,GACrB20D,GAAOlB,EAAS9vD,EAAK3D,EAAK,GAC1B40D,GAAOnB,EAAS9vD,EAAK3D,EAAK,GAC1BiuD,GAAWwF,GAKjBe,EAAM30D,GAAM60D,EAAMzG,EAClBuG,EAAM30D,EAAK,GAAK80D,EAAM1G,EACtBuG,EAAM30D,EAAK,GAAK+0D,EAAM3G,EACtBuG,EAAM30D,EAAK,GAAKg1D,EAAMJ,EAG1B,OAAOF,GAOThoC,SAAU,WACR,MAAO,CACLx1B,KAAM7C,KAAK6C,KACXoL,OAAQjO,KAAKiO,OACbC,OAAQlO,KAAKkO,OACb+uD,WAAYj9D,KAAKi9D,WACjBC,aAAcl9D,KAAKk9D,iBAYzB/+D,EAAOy/B,MAAM24B,QAAQyG,OAAO1yD,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAxW3E,CA0WsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAuB9Bo9C,EAAQyK,YAAc7nD,EAAYo9C,EAAQ6C,WAAqE,CAO7Gv2D,KAAM,cAQNuW,WAAY,SAAUpY,GACpBA,IAAaA,EAAU,IACvBhB,KAAKupB,OAASvoB,EAAQuoB,QAAU,CAC9B,EAAG,EAAG,EAAG,EAAG,EACZ,EAAG,EAAG,EAAG,EAAG,EACZ,EAAG,EAAG,EAAG,EAAG,EACZ,EAAG,EAAG,EAAG,EAAG,IAQhBwuC,QAAS,SAAUrrD,GACjB,IAIIxL,EACA6G,EACAqsB,EACAxmB,EACA9F,EARAlF,EAAU8J,EAASE,WAAY,MAC/B0C,EAAY1M,EAAQ2M,aAAc,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QACjE6H,EAAOH,EAAUG,KACjBsmD,EAAOtmD,EAAKhP,OAMZspB,EAAI/pB,KAAKupB,OAEb,IAAMroB,EAAI,EAAGA,EAAI60D,EAAM70D,GAAK,EAC1B6G,EAAI0H,EAAMvO,GACVkzB,EAAI3kB,EAAMvO,EAAI,GACd0M,EAAI6B,EAAMvO,EAAI,GACd4G,EAAI2H,EAAMvO,EAAI,GAEduO,EAAMvO,GAAM6G,EAAIgiB,EAAG,GAAMqK,EAAIrK,EAAG,GAAMnc,EAAImc,EAAG,GAAMjiB,EAAIiiB,EAAG,GAAMA,EAAG,GACnEta,EAAMvO,EAAI,GAAM6G,EAAIgiB,EAAG,GAAMqK,EAAIrK,EAAG,GAAMnc,EAAImc,EAAG,GAAMjiB,EAAIiiB,EAAG,GAAMA,EAAG,GACvEta,EAAMvO,EAAI,GAAM6G,EAAIgiB,EAAG,IAAOqK,EAAIrK,EAAG,IAAOnc,EAAImc,EAAG,IAAOjiB,EAAIiiB,EAAG,IAAOA,EAAG,IAC3Eta,EAAMvO,EAAI,GAAM6G,EAAIgiB,EAAG,IAAOqK,EAAIrK,EAAG,IAAOnc,EAAImc,EAAG,IAAOjiB,EAAIiiB,EAAG,IAAOA,EAAG,IAG7EnnB,EAAQ22D,aAAcjqD,EAAW,EAAG,IAOtC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCjW,KAAM7C,KAAK6C,KACX0mB,OAAQvpB,KAAKupB,YAYnBprB,EAAOy/B,MAAM24B,QAAQyK,YAAY12D,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAzGhF,CA0GsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAgB9Bo9C,EAAQ0K,SAAW9nD,EAAYo9C,EAAQ6C,WAAkE,CAOvGv2D,KAAM,WAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKkhE,SAAWlgE,EAAQkgE,UAAY,GAOtCnJ,QAAS,SAASrrD,GAMhB,IALA,IAAI9J,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACjB0xD,EAAY,KAAOnhE,KAAKkhE,SAAW,MAAQ,KAAO,IAAMlhE,KAAKkhE,WAExDhgE,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAC/CuO,EAAKvO,GAAKigE,GAAa1xD,EAAKvO,GAAK,KAAO,IACxCuO,EAAKvO,EAAI,GAAKigE,GAAa1xD,EAAKvO,EAAI,GAAK,KAAO,IAChDuO,EAAKvO,EAAI,GAAKigE,GAAa1xD,EAAKvO,EAAI,GAAK,KAAO,IAGlD0B,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCooD,SAAUlhE,KAAKkhE,cAYrB/iE,EAAOy/B,MAAM24B,QAAQ0K,SAAS32D,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAhF7E,CAkFsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAU0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC5CiZ,EAASjZ,EAAOiC,KAAK6B,OAAOmV,OAC5Bm/C,EAAUp4D,EAAOy/B,MAAM24B,QACvBp9C,EAAchb,EAAOiC,KAAK+Y,YAgB9Bo9C,EAAQ6K,SAAWjoD,EAAYo9C,EAAQ6C,WAAkE,CAOvGv2D,KAAM,WAQNuW,WAAY,SAASpY,GACnBA,EAAUA,GAAW,GACrBhB,KAAKqhE,SAAWrgE,EAAQqgE,UAAY,GAOtCtJ,QAAS,SAASrrD,GAMhB,IALA,IAGIjH,EAHA7C,EAAU8J,EAASE,WAAW,MAC9B0C,EAAY1M,EAAQ2M,aAAa,EAAG,EAAG7C,EAASpF,MAAOoF,EAAS9E,QAChE6H,EAAOH,EAAUG,KACZ6xD,EAA0B,KAAhBthE,KAAKqhE,SAEfngE,EAAI,EAAGC,EAAMsO,EAAKhP,OAAQS,EAAIC,EAAKD,GAAK,EAC/CuE,EAAMV,KAAKU,IAAIgK,EAAKvO,GAAIuO,EAAKvO,EAAI,GAAIuO,EAAKvO,EAAI,IAC9CuO,EAAKvO,IAAMuE,IAAQgK,EAAKvO,IAAMuE,EAAMgK,EAAKvO,IAAMogE,EAAS,EACxD7xD,EAAKvO,EAAI,IAAMuE,IAAQgK,EAAKvO,EAAI,IAAMuE,EAAMgK,EAAKvO,EAAI,IAAMogE,EAAS,EACpE7xD,EAAKvO,EAAI,IAAMuE,IAAQgK,EAAKvO,EAAI,IAAMuE,EAAMgK,EAAKvO,EAAI,IAAMogE,EAAS,EAGtE1+D,EAAQ22D,aAAajqD,EAAW,EAAG,IAOrC+oB,SAAU,WACR,OAAOjhB,EAAOpX,KAAK8Y,UAAU,YAAa,CACxCuoD,SAAUrhE,KAAKqhE,cAYrBljE,EAAOy/B,MAAM24B,QAAQ6K,SAAS92D,WAAanM,EAAOy/B,MAAM24B,QAAQ6C,WAAW9uD,WAjF7E,CAmFsB,oBAAZjM,QAA0BA,QAAU2B,MAG9C,SAAU6E,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAC3C6J,EAAU7J,EAAOiC,KAAK4H,QACtB0xB,EAAsBv7B,EAAOmN,OAAOouB,oBAGpCv7B,EAAOsK,KACTtK,EAAOujB,KAAK,mCAYdvjB,EAAOsK,KAAOtK,EAAOiC,KAAK+Y,YAAYhb,EAAOmN,OAA4C,CAOvFi2D,yBAA0B,CACxB,WACA,aACA,aACA,YACA,aACA,OACA,cACA,aAMFC,WAAY,QAOZC,iBAAkB,YAiKlB5+D,KAAsB,OAOtByF,SAAsB,GAOtBokB,WAAsB,SAOtBvc,WAAsB,kBAOtBklD,eAAsB,GAOtBC,UAAsB,OAOtB7oC,UAAsB,GAOtBE,WAAsB,KAOtB+0C,oBAAsB,GAQtBp0D,gBAAiBnP,EAAOmN,OAAOC,UAAU+B,gBAAgB8K,OACvD,aACA,aACA,WACA,OACA,iBACA,YACA,YACA,aACA,sBACA,eAMF6oC,gBAAiB9iD,EAAOmN,OAAOC,UAAU01C,gBAAgB7oC,OACvD,aACA,aACA,WACA,OACA,iBACA,YACA,YACA,aACA,sBACA,cACA,UAQF2P,OAAsB,KAQtB4S,OAAsB,KAKtBgnC,kBAAmB,IAOnBC,cAA2B,KAQ3BC,YAAyB,EAQzBzoD,WAAY,SAASwV,EAAM5tB,GACzBA,EAAUA,GAAW,GACrBhB,KAAK4uB,KAAOA,EACZ5uB,KAAK8hE,iBAAkB,EACvB9hE,KAAK8Y,UAAU,aAAc9X,GAC7BhB,KAAK8hE,iBAAkB,EACvB9hE,KAAK+hE,kBACL/hE,KAAKk/B,YACLl/B,KAAK0/B,WAAW,CAAE0kB,YAAa,8BAWjC2d,gBAAiB,SAASr2D,GACpB1L,KAAK8hE,kBAGJp2D,IACHA,EAAMvN,EAAOiC,KAAKqM,sBAAsBG,WAAW,MACnD5M,KAAKgiE,eAAet2D,IAEtB1L,KAAKiiE,WAAajiE,KAAKkiE,sBACvBliE,KAAKmiE,cACLniE,KAAKsH,MAAQtH,KAAKoiE,cAAc12D,IAAQ1L,KAAKqiE,aAhX5B,EAiXjBriE,KAAK4H,OAAS5H,KAAKsiE,eAAe52D,GAClC1L,KAAKk/B,cAOP1zB,SAAU,WACR,MAAO,kBAAoBxL,KAAKmD,aAC9B,iBAAmBnD,KAAK4uB,KAAO,qBAAuB5uB,KAAKmQ,WAAa,QAc5EyxC,0BAA2B,WACzB,IAAIL,EAAOvhD,KAAK8Y,UAAU,6BACtBxQ,EAAWtI,KAAKsI,SAGpB,OAFAi5C,EAAKj6C,OAASgB,EAAWi5C,EAAKE,MAC9BF,EAAK35C,QAAUU,EAAWi5C,EAAKI,MACxBJ,GAOTpb,QAAS,SAASz6B,GAChB1L,KAAKgiE,eAAet2D,GAChB1L,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,MAC3B6I,EAAIW,UAAUrM,KAAK0H,KAAM1H,KAAK2H,KAEhC3H,KAAKuiE,2BAA2B72D,GAChC1L,KAAKwiE,YAAY92D,GACjB1L,KAAKyiE,sBAAsB/2D,IAO7B82D,YAAa,SAAS92D,GACpB1L,KAAK0iE,gBAAgBh3D,GACrB1L,KAAK2iE,kBAAkBj3D,IAOzBs2D,eAAgB,SAASt2D,GACvBA,EAAIk3D,aAAe,aACnBl3D,EAAIkiB,KAAO5tB,KAAK6iE,uBAOlBP,eAAgB,WACd,OAAOtiE,KAAK8iE,0BAA4B9iE,KAAKiiE,WAAWxhE,OAAS,GAAKT,KAAK+iE,oBAQ7EX,cAAe,SAAS12D,GAGtB,IAFA,IAAIs3D,EAAWhjE,KAAKijE,cAAcv3D,EAAK,GAE9BxK,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IAAK,CAC1D,IAAIgiE,EAAmBljE,KAAKijE,cAAcv3D,EAAKxK,GACxB8hE,EAAnBE,IACFF,EAAWE,GAGf,OAAOF,GAWTG,aAAc,SAASnsD,EAAQtL,EAAK03D,EAAO17D,EAAMC,GAE/C,IAAkC07D,EAAO/7D,EAArCg8D,EAAStsD,EAAO9N,MAAM,GAAI,GAC9B,GAAIlJ,KAAKsjE,GAAQrqC,OAAQ,CACvB,IAAIjB,GAAWh4B,KAAKsH,MAAQ,EAAItH,KAAKsjE,GAAQtrC,SAAW,EACpDC,GAAWj4B,KAAK4H,OAAS,EAAI5H,KAAKsjE,GAAQrrC,SAAW,EACzDvsB,EAAIU,OACJV,EAAIW,UAAU2rB,EAASC,GACvBvwB,GAAQswB,EACRrwB,GAAOswB,EAET,GAAyB,IAArBj4B,KAAK6hE,YAGP,IAFA,IAAI0B,EAAkBvjE,KAAKwjE,yBAElBtiE,EAAI,EAAGC,GADhBiiE,EAAQA,EAAM/5D,MAAM,KACQ5I,OAAQS,EAAIC,EAAKD,IAC3CmiE,EAAQD,EAAMliE,GACdoG,EAAQoE,EAAI+3D,YAAYJ,GAAO/7D,MAAQi8D,EACvC73D,EAAIsL,GAAQqsD,EAAO37D,EAAMC,GACzBD,GAAgB,EAARJ,EAAYA,EAAQ,OAI9BoE,EAAIsL,GAAQosD,EAAO17D,EAAMC,GAE3B3H,KAAKsjE,GAAQrqC,QAAUvtB,EAAIc,WAY7Bk3D,gBAAiB,SAAS1sD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,EAAKg8D,GAEtDh8D,GAAO3H,KAAKsI,SAAWtI,KAAK2hE,kBAG5B,IAAIv8B,EAAYplC,KAAKijE,cAAcv3D,EAAKi4D,GACxC,GAAuB,YAAnB3jE,KAAKs1D,WAA2Bt1D,KAAKsH,MAAQ89B,EAC/CplC,KAAKmjE,aAAansD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,EAAKg8D,QAalD,IARA,IAMoBC,EANhBC,EAAQ/T,EAAKzmD,MAAM,OACnBy6D,EAAa,EACbC,EAAa/jE,KAAKgkE,iBAAiBt4D,EAAKm4D,EAAM9yD,KAAK,KAAM4yD,EAAW,GACpEM,EAAYjkE,KAAKsH,MAAQy8D,EACzBG,EAAYL,EAAMpjE,OAAS,EAC3B0jE,EAAyB,EAAZD,EAAgBD,EAAYC,EAAY,EACrDE,EAAa,EAERljE,EAAI,EAAGC,EAAM0iE,EAAMpjE,OAAQS,EAAIC,EAAKD,IAAK,CAChD,KAA4B,MAArB4uD,EAAKgU,IAAuBA,EAAahU,EAAKrvD,QACnDqjE,IAEFF,EAAOC,EAAM3iE,GACblB,KAAKmjE,aAAansD,EAAQtL,EAAKk4D,EAAMl8D,EAAO08D,EAAYz8D,EAAKg8D,EAAWG,GACxEM,GAAcpkE,KAAKgkE,iBAAiBt4D,EAAKk4D,EAAMD,EAAWG,GAAcK,EACxEL,GAAcF,EAAKnjE,SASvBujE,iBAAkB,SAAUt4D,EAAKk4D,GAC/B,IAAIt8D,EAAQoE,EAAI+3D,YAAYG,GAAMt8D,MAMlC,OALyB,IAArBtH,KAAK6hE,cAGPv6D,GAFYs8D,EAAKv6D,MAAM,IAAI5I,OACGT,KAAKwjE,0BAGtB,EAARl8D,EAAYA,EAAQ,GAO7B+8D,eAAgB,WACd,OAAQrkE,KAAKsH,MAAQ,GAOvBg9D,cAAe,WACb,OAAQtkE,KAAK4H,OAAS,GAMxB28D,cAAe,WACb,OAAO,GAQTC,kBAAmB,SAAS94D,EAAKsL,GAI/B,IAFA,IAAIytD,EAAc,EAAG/8D,EAAO1H,KAAKqkE,iBAAkB18D,EAAM3H,KAAKskE,gBAErDpjE,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IAAK,CAC1D,IAAIwjE,EAAe1kE,KAAK+iE,iBAAiBr3D,EAAKxK,GAC1CyjE,EAAYD,EAAe1kE,KAAK2sB,WAChCyY,EAAYplC,KAAKijE,cAAcv3D,EAAKxK,GACpCkjE,EAAapkE,KAAK4kE,mBAAmBx/B,GACzCplC,KAAK0jE,gBACH1sD,EACAtL,EACA1L,KAAKiiE,WAAW/gE,GAChBwG,EAAO08D,EACPz8D,EAAM88D,EAAcE,EACpBzjE,GAEFujE,GAAeC,IAQnBhC,gBAAiB,SAASh3D,IACnB1L,KAAKM,MAAQN,KAAKukE,iBAIvBvkE,KAAKwkE,kBAAkB94D,EAAK,aAO9Bi3D,kBAAmB,SAASj3D,IACpB1L,KAAK+nB,QAA+B,IAArB/nB,KAAKsnC,cAAsBtnC,KAAKukE,mBAIjDvkE,KAAK26B,SAAW36B,KAAK26B,OAAOH,cAC9Bx6B,KAAK+kD,cAAcr5C,GAGrBA,EAAIU,OACJpM,KAAK6zC,aAAanoC,EAAK1L,KAAK+kC,iBAC5Br5B,EAAI+B,YACJzN,KAAKwkE,kBAAkB94D,EAAK,cAC5BA,EAAIg8B,YACJh8B,EAAIc,YAONu2D,iBAAkB,WAChB,OAAO/iE,KAAK8iE,yBAA2B9iE,KAAK2sB,YAO9Cm2C,uBAAwB,WACtB,OAAO9iE,KAAKsI,SAAWtI,KAAK4hE,eAO9BW,2BAA4B,SAAS72D,GACnC,GAAK1L,KAAK0hE,oBAAV,CAGA,IAAuBgD,EACnBt/B,EAAWy/B,EADXC,EAAgB,EACWC,EAAer5D,EAAIq1B,UAElDr1B,EAAIq1B,UAAY/gC,KAAK0hE,oBACrB,IAAK,IAAIxgE,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IACrDwjE,EAAe1kE,KAAK+iE,iBAAiBr3D,EAAKxK,GAE1B,GADhBkkC,EAAYplC,KAAKijE,cAAcv3D,EAAKxK,MAElC2jE,EAAiB7kE,KAAK4kE,mBAAmBx/B,GACzC15B,EAAIs1B,SACFhhC,KAAKqkE,iBAAmBQ,EACxB7kE,KAAKskE,gBAAkBQ,EACvB1/B,EACAs/B,EAAe1kE,KAAK2sB,aAGxBm4C,GAAiBJ,EAEnBh5D,EAAIq1B,UAAYgkC,EAGhB/kE,KAAK+kD,cAAcr5C,KAQrBk5D,mBAAoB,SAASx/B,GAC3B,MAAuB,WAAnBplC,KAAKs1D,WACCt1D,KAAKsH,MAAQ89B,GAAa,EAEb,UAAnBplC,KAAKs1D,UACAt1D,KAAKsH,MAAQ89B,EAEf,GAMT+8B,YAAa,WACXniE,KAAKglE,aAAe,GACpBhlE,KAAKilE,cAAgB,IAMvBC,2BAA4B,WAC1B,IAAIC,EAAcnlE,KAAKolE,iBAMvB,OALAD,IAAgBA,EAAcnlE,KAAKg7C,gBAAgB,6BAC/CmqB,IACFnlE,KAAK07C,UAAU,CAAE0I,YAAa,6BAC9BpkD,KAAKghD,OAAQ,GAERmkB,GASTlC,cAAe,SAASv3D,EAAKi4D,GAC3B,GAAI3jE,KAAKglE,aAAarB,GACpB,OAAyC,IAAlC3jE,KAAKglE,aAAarB,GAAoB3jE,KAAKsH,MAAQtH,KAAKglE,aAAarB,GAG9E,IAAIr8D,EAAkBwoD,EAAO9vD,KAAKiiE,WAAW0B,GAgB7C,OAbEr8D,EADW,KAATwoD,EACM,EAGA9vD,KAAKqlE,aAAa35D,EAAKi4D,IAEjC3jE,KAAKglE,aAAarB,GAAar8D,IAEC,YAAnBtH,KAAKs1D,WAEO,EADXxF,EAAKzmD,MAAM,OACT5I,SACZT,KAAKglE,aAAarB,IAAc,GAG7Br8D,GAGTk8D,uBAAwB,WACtB,OAAyB,IAArBxjE,KAAK6hE,YACA7hE,KAAKsI,SAAWtI,KAAK6hE,YAAc,IAErC,GASTwD,aAAc,SAAS35D,EAAKi4D,GAC1B,IAEoC2B,EAFhCxV,EAAO9vD,KAAKiiE,WAAW0B,GACvBr8D,EAAQoE,EAAI+3D,YAAY3T,GAAMxoD,MAC9Bi8D,EAAkB,EAMtB,OALyB,IAArBvjE,KAAK6hE,cAEP0B,GADYzT,EAAKzmD,MAAM,IAAI5I,OACI,GAAKT,KAAKwjE,0BAGvB,GADpB8B,EAAah+D,EAAQi8D,GACG+B,EAAa,GAOvC7C,sBAAuB,SAAS/2D,GAC9B,GAAK1L,KAAKq1D,eAAV,CAGA,IAAIkQ,EAAoBvlE,KAAK4H,OAAS,EAClCuQ,EAAQnY,KAAMwlE,EAAU,IAwBoB,EAA5CxlE,KAAKq1D,eAAel1D,QAAQ,cAC9BqlE,EAAQ5kE,KAAK,MAEoC,EAA/CZ,KAAKq1D,eAAel1D,QAAQ,iBAC9BqlE,EAAQ5kE,KAAK,MAEgC,EAA3CZ,KAAKq1D,eAAel1D,QAAQ,aAC9BqlE,EAAQ5kE,MAAM,KAEK,EAAjB4kE,EAAQ/kE,QA9BZ,SAA6B+kE,GAC3B,IAAItkE,EAAmBC,EAAKiU,EAAGqwD,EAAMrgC,EACjCy/B,EAAgBH,EADb/3C,EAAa,EAGpB,IAAKzrB,EAAI,EAAGC,EAAMgX,EAAM8pD,WAAWxhE,OAAQS,EAAIC,EAAKD,IAAK,CAMvD,IAJAkkC,EAAYjtB,EAAM8qD,cAAcv3D,EAAKxK,GACrC2jE,EAAiB1sD,EAAMysD,mBAAmBx/B,GAC1Cs/B,EAAevsD,EAAM4qD,iBAAiBr3D,EAAKxK,GAEtCkU,EAAI,EAAGqwD,EAAOD,EAAQ/kE,OAAQ2U,EAAIqwD,EAAMrwD,IAC3C1J,EAAIs1B,SACF7oB,EAAMksD,iBAAmBQ,EACzBl4C,GAAcxU,EAAMypD,cAAgB,EAAI4D,EAAQpwD,IAAO+C,EAAM7P,SAAWi9D,EACxEngC,EACAjtB,EAAM7P,SAAW,IAErBqkB,GAAc+3C,GAchBgB,CAAoBF,KAQxB3C,oBAAqB,WACnB,MAAO,CAEJ1kE,EAAOW,aAAekB,KAAK0sB,WAAa1sB,KAAKysB,UAC7CtuB,EAAOW,aAAekB,KAAKysB,UAAYzsB,KAAK0sB,WAC7C1sB,KAAKsI,SAAW,KACfnK,EAAOW,aAAgB,IAAMkB,KAAKmQ,WAAa,IAAOnQ,KAAKmQ,YAC5DY,KAAK,MAQT8vB,OAAQ,SAASn1B,EAAKm4C,GAEf7jD,KAAK2tB,UAGN3tB,KAAK2/B,QAAU3/B,KAAK2/B,OAAOxD,gBAAkBn8B,KAAK44B,QAAU54B,KAAK8jD,eAGjE9jD,KAAKklE,+BACPllE,KAAKgiE,eAAet2D,GACpB1L,KAAK+hE,gBAAgBr2D,IAEvB1L,KAAK8Y,UAAU,SAAUpN,EAAKm4C,MAOhCqe,oBAAqB,WACnB,OAAOliE,KAAK4uB,KAAKvlB,MAAMrJ,KAAKwhE,aAQ9BnpC,SAAU,SAASC,GACjB,IAAIqtC,EAAuB,CACzB,OACA,WACA,aACA,aACA,YACA,aACA,iBACA,YACA,sBACA,eACAvtD,OAAOkgB,GACT,OAAOt4B,KAAK8Y,UAAU,WAAY6sD,IASpCptC,MAAO,SAASvuB,GACThK,KAAK0L,MACR1L,KAAK0L,IAAMvN,EAAOiC,KAAKqM,sBAAsBG,WAAW,OAE1D,IAAI4rB,EAASx4B,KAAKmsD,uBACdqZ,EAAUxlE,KAAK4lE,sBAAsB5lE,KAAK0L,KAC1Cm6D,EAAY7lE,KAAK8lE,iBAAiBN,EAAQO,QAASP,EAAQQ,UAG/D,OAFAhmE,KAAKimE,kBAAkBztC,EAAQqtC,GAExB77D,EAAUA,EAAQwuB,EAAOznB,KAAK,KAAOynB,EAAOznB,KAAK,KAM1D60D,sBAAuB,SAASl6D,GAC9B,IAAIw6D,EAAUlmE,KAAK+iE,iBAAiBr3D,EAAK,GAIzC,MAAO,CACLs6D,UAJchmE,KAAKsH,MAAQ,GAILtH,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,KAAwB7C,KAAK0H,KAAO,GACnFq+D,QAJY,GAIQ/lE,KAAK44B,OAA6B,eAApB54B,KAAK44B,MAAM/1B,MAAyB7C,KAAK2H,IAAM,GACjFu+D,QAASA,IAObD,kBAAmB,SAASztC,EAAQqtC,GAClC,IAAqBzkE,EAASpB,KAAKqrD,eAC/BpvC,EAAmB,KAAX7a,EAAgB,GAAK,WAAaA,EAAS,IAEvDo3B,EAAO53B,KACL,QAASZ,KAAKsrD,WAAY,cAAetrD,KAAKurD,kBAAmBvrD,KAAKksD,wBAAyB,IAC7FjwC,EAAO,MACP4pD,EAAUM,YAAYp1D,KAAK,IAC3B,kCACG/Q,KAAKmQ,WAAa,gBAAkBnQ,KAAKmQ,WAAWuH,QAAQ,KAAM,KAAQ,KAAO,GACjF1X,KAAKsI,SAAW,cAAgBtI,KAAKsI,SAAW,KAAO,GACvDtI,KAAKysB,UAAY,eAAiBzsB,KAAKysB,UAAY,KAAO,GAC1DzsB,KAAK0sB,WAAa,gBAAkB1sB,KAAK0sB,WAAa,KAAO,GAC7D1sB,KAAKq1D,eAAiB,oBAAsBr1D,KAAKq1D,eAAiB,KAAO,GAC1E,UAAWr1D,KAAKmrD,cAbP,GAa+B,QACxC0a,EAAUO,UAAUr1D,KAAK,IAC3B,gBACF,aAIJo6C,aAAc,SAASC,GAErB,OADejtD,EAAOmN,OAAOC,UAAU4/C,aAAarqD,KAAKd,KAAMorD,GAC7C,sBASpB0a,iBAAkB,SAASO,EAAeC,GACxC,IAAIF,EAAY,GACZD,EAAc,GACdv+D,EAAS,EAEb5H,KAAKumE,UAAUJ,GAGf,IAAK,IAAIjlE,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IACjDlB,KAAK0hE,qBACP1hE,KAAKwmE,kBAAkBL,EAAajlE,EAAGolE,EAAgBD,EAAez+D,GAExE5H,KAAKymE,oBAAoBvlE,EAAGklE,EAAWx+D,EAAQ0+D,EAAgBD,EAAeF,GAC9Ev+D,GAAU5H,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKxK,GAG5C,MAAO,CACLklE,UAAWA,EACXD,YAAaA,IAIjBM,oBAAqB,SAASvlE,EAAGklE,EAAWx+D,EAAQ0+D,EAAgBD,GAClE,IAAIK,EAAO1mE,KAAKsI,UAAYtI,KAAK4hE,cAAgB5hE,KAAK2hE,mBAClD0E,EAAgBz+D,EAAS5H,KAAK4H,OAAS,EACpB,YAAnB5H,KAAKs1D,UAKT8Q,EAAUxlE,KACR,mBACEoH,EAAQs+D,EAAiBtmE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcjjE,KAAK0L,IAAKxK,IAAKw4B,GAAsB,KACzG,MACA1xB,EAAQ0+D,EAAMhtC,GACd,KAGA15B,KAAK2mE,mBAAmB3mE,KAAKM,MAAO,IACpCnC,EAAOiC,KAAK0I,OAAOiP,UAAU/X,KAAKiiE,WAAW/gE,IAC/C,cAbAlB,KAAK4mE,wBAAwB1lE,EAAGklE,EAAWM,EAAMJ,IAiBrDM,wBAAyB,SAAS1lE,EAAGklE,EAAWM,EAAMJ,GACpD,IAAI56D,EAAMvN,EAAOiC,KAAKqM,sBAAsBG,WAAW,MAEvD5M,KAAKgiE,eAAet2D,GAEpB,IAMIk4D,EACAziE,EANA0iE,EADO7jE,KAAKiiE,WAAW/gE,GACVmI,MAAM,OACnB06D,EAAa/jE,KAAKgkE,iBAAiBt4D,EAAKm4D,EAAM9yD,KAAK,KACnDkzD,EAAYjkE,KAAKsH,MAAQy8D,EACzBG,EAAYL,EAAMpjE,OAAS,EAC3B0jE,EAAyB,EAAZD,EAAgBD,EAAYC,EAAY,EAC/CzmD,EAAazd,KAAK2mE,mBAAmB3mE,KAAKM,MAKpD,IAFAgmE,GAAkBtmE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcv3D,EAAKxK,IAE7DA,EAAI,EAAGC,EAAM0iE,EAAMpjE,OAAQS,EAAIC,EAAKD,IACvC0iE,EAAOC,EAAM3iE,GACbklE,EAAUxlE,KACR,mBACEoH,EAAQs+D,EAAgB5sC,GAAsB,KAC9C,MACA1xB,EAAQ0+D,EAAMhtC,GACd,KAGAjc,EAAY,IACZtf,EAAOiC,KAAK0I,OAAOiP,UAAU6rD,GAC/B,cAEF0C,GAAkBtmE,KAAKgkE,iBAAiBt4D,EAAKk4D,GAAQO,GAIzDqC,kBAAmB,SAASL,EAAajlE,EAAGolE,EAAgBD,EAAez+D,GACzEu+D,EAAYvlE,KACV,aACEZ,KAAK2mE,mBAAmB3mE,KAAK0hE,qBAC7B,OACA15D,EAAQs+D,EAAiBtmE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcjjE,KAAK0L,IAAKxK,IAAKw4B,GACnF,QACA1xB,EAAQJ,EAAS5H,KAAK4H,OAAS,EAAG8xB,GAClC,YACA1xB,EAAQhI,KAAKijE,cAAcjjE,KAAK0L,IAAKxK,GAAIw4B,GACzC,aACA1xB,EAAQhI,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKxK,GAAKlB,KAAK2sB,WAAY+M,GAChE,gBAGJ6sC,UAAW,SAASJ,GACdnmE,KAAKq7B,iBACP8qC,EAAYvlE,KACV,aACEZ,KAAK2mE,mBAAmB3mE,KAAKq7B,iBAC7B,OACArzB,GAAShI,KAAKsH,MAAQ,EAAGoyB,GACzB,QACA1xB,GAAShI,KAAK4H,OAAS,EAAG8xB,GAC1B,YACA1xB,EAAQhI,KAAKsH,MAAOoyB,GACpB,aACA1xB,EAAQhI,KAAK4H,OAAQ8xB,GACvB,gBAYNitC,mBAAoB,SAAStlE,GAC3B,IAAIwlE,EAAaxlE,GAA0B,iBAAVA,EAAsB,IAAIlD,EAAOylB,MAAMviB,GAAS,GACjF,OAAKwlE,GAAcA,EAAUhjD,aAAwC,IAAzBgjD,EAAU94C,WAG/C,YAAc84C,EAAU94C,WAAa,WAAa84C,EAAU/4C,SAAS,GAAG0G,QAAU,IAFhF,SAAWnzB,EAAQ,KAa9BoD,KAAM,SAASC,EAAKrD,GAClBrB,KAAK8Y,UAAU,OAAQpU,EAAKrD,IAEsB,EAA9CrB,KAAKuhE,yBAAyBphE,QAAQuE,KACxC1E,KAAK+hE,kBACL/hE,KAAKk/B,cAQT/7B,WAAY,WACV,OAAO,KAWXhF,EAAOsK,KAAKmnD,gBAAkBzxD,EAAOa,kBAAkBoZ,OACrD,qFAAqF/O,MAAM,MAO7FlL,EAAOsK,KAAKC,sBAAwB,GAUpCvK,EAAOsK,KAAKunB,YAAc,SAASjW,EAAS/Y,GAC1C,IAAK+Y,EACH,OAAO,KAGT,IAAI81C,EAAmB1xD,EAAO4uB,gBAAgBhT,EAAS5b,EAAOsK,KAAKmnD,kBACnE5uD,EAAU7C,EAAOiC,KAAK6B,OAAOmV,OAAQpW,EAAU7C,EAAOiC,KAAK6B,OAAOuV,MAAMxW,GAAW,GAAM6uD,IAEjFloD,IAAM3G,EAAQ2G,KAAO,EAC7B3G,EAAQ0G,KAAO1G,EAAQ0G,MAAQ,EAC3B,OAAQmoD,IACV7uD,EAAQ0G,MAAQmoD,EAAiB/jD,IAE/B,OAAQ+jD,IACV7uD,EAAQ2G,KAAOkoD,EAAiB9jD,IAE5B,aAAc/K,IAClBA,EAAQsH,SAAWnK,EAAOsK,KAAKC,uBAG5B1H,EAAQumC,UACXvmC,EAAQumC,QAAU,QAGpB,IAAI5Y,EAAc,GAKZ,gBAAiB5U,EAQrB4U,EAAc5U,EAAQ4U,YAPlB,eAAgB5U,GAAkC,OAAvBA,EAAQgR,YACjC,SAAUhR,EAAQgR,YAA0C,OAA5BhR,EAAQgR,WAAWtb,OACrDkf,EAAc5U,EAAQgR,WAAWtb,MAQvCkf,EAAcA,EAAYjX,QAAQ,iBAAkB,IAAIA,QAAQ,OAAQ,KAExE,IAAIkX,EAAO,IAAIzwB,EAAOsK,KAAKkmB,EAAa3tB,GACpC8lE,EAAwBl4C,EAAKoP,YAAcpP,EAAKhnB,OAEhDm/D,IADkBn4C,EAAKhnB,OAASgnB,EAAK0Y,aAAe1Y,EAAKjC,WAAaiC,EAAKhnB,QAC7Ck/D,EAC9BE,EAAap4C,EAAKoP,YAAc+oC,EAChCE,EAAO,EAiBX,MAXqB,SAAjBr4C,EAAK2Y,UACP0/B,EAAOr4C,EAAKmP,WAAa,GAEN,UAAjBnP,EAAK2Y,UACP0/B,GAAQr4C,EAAKmP,WAAa,GAE5BnP,EAAKnrB,IAAI,CACPiE,KAAMknB,EAAKq3B,UAAYghB,EACvBt/D,IAAKinB,EAAKs3B,SAAW8gB,EAAa,EAAIp4C,EAAKtmB,UAAY,IAAOsmB,EAAK+yC,mBAAqB/yC,EAAKjC,aAGxFiC,GAaTzwB,EAAOsK,KAAK6B,WAAa,SAASrI,EAAQU,EAAUwkD,GAClD,OAAOhpD,EAAOmN,OAAO47C,YAAY,OAAQjlD,EAAQU,EAAUwkD,EAAY,SAGzEhpD,EAAOiC,KAAK2M,gBAAgB5O,EAAOsK,OA5rCrC,CA8rCsB,oBAAZpK,QAA0BA,QAAU2B,MAG9C,WAEE,IAAIwX,EAAQrZ,OAAOiC,KAAK6B,OAAOuV,MAgD/BrZ,OAAO+oE,MAAQ/oE,OAAOiC,KAAK+Y,YAAYhb,OAAOsK,KAAMtK,OAAOmD,WAAiD,CAO1GuB,KAAM,SAONskE,eAAgB,EAOhBC,aAAc,EAOdt8B,eAAgB,uBAOhB+J,WAAW,EAOXwyB,UAAU,EAOVC,mBAAoB,yBAOpBjF,YAAa,EAObkF,YAAa,OAObC,YAAa,IAObC,eAAgB,IAQhB9qD,OAAQ,KAORo3C,SAAS,EAKT2T,SAAU,QAKVC,sBAAuB,EAKvBC,oBAAqB,KAKrBC,uBAAuB,EAKvBC,eAAgB,GAQhB1uD,WAAY,SAASwV,EAAM5tB,GACzBhB,KAAK2c,OAAS3b,GAAWA,EAAQ2b,QAAiB,GAClD3c,KAAK8Y,UAAU,aAAc8V,EAAM5tB,GACnChB,KAAK+nE,gBAMP5F,YAAa,WACXniE,KAAK8Y,UAAU,eACf9Y,KAAK8nE,eAAiB,IAMxBvD,cAAe,WACb,IAAKvkE,KAAK2c,OACR,OAAO,EAET,IAAInY,EAAMxE,KAAK2c,OAEf,IAAK,IAAI+pB,KAAMliC,EACb,IAAK,IAAImiC,KAAMniC,EAAIkiC,GAEjB,IAAK,IAAIshC,KAAMxjE,EAAIkiC,GAAIC,GACrB,OAAO,EAIb,OAAO,GAOTshC,kBAAmB,SAAS/lE,GAC1BA,EAAQ6C,KAAKU,IAAIvD,EAAO,GACxBlC,KAAKkoE,eAAe,iBAAkBhmE,IAOxCimE,gBAAiB,SAASjmE,GACxBA,EAAQ6C,KAAKS,IAAItD,EAAOlC,KAAK4uB,KAAKnuB,QAClCT,KAAKkoE,eAAe,eAAgBhmE,IAQtCgmE,eAAgB,SAAStkE,EAAU1B,GAC7BlC,KAAK4D,KAAc1B,IACrBlC,KAAKooE,wBACLpoE,KAAK4D,GAAY1B,GAEnBlC,KAAKqoE,mBAOPD,sBAAuB,WACrBpoE,KAAKe,KAAK,qBACVf,KAAK2/B,QAAU3/B,KAAK2/B,OAAO5+B,KAAK,yBAA0B,CAAE6N,OAAQ5O,QAStEsoE,mBAAoB,SAASC,EAAYC,GAEvC,GAAyB,IAArBhoE,UAAUC,OAAc,CAE1B,IADA,IAAIkc,EAAS,GACJzb,EAAIqnE,EAAYrnE,EAAIsnE,EAAUtnE,IACrCyb,EAAO/b,KAAKZ,KAAKsoE,mBAAmBpnE,IAEtC,OAAOyb,EAGT,IAAI8rD,EAAMzoE,KAAK0oE,oBAAoBH,GAGnC,OAFYvoE,KAAK2oE,qBAAqBF,EAAI9E,UAAW8E,EAAInlC,YAEzC,IASlBslC,mBAAoB,SAASjsD,GAC3B,GAAI3c,KAAKmnE,iBAAmBnnE,KAAKonE,aAC/BpnE,KAAK6oE,cAAc7oE,KAAKmnE,eAAgBxqD,QAGxC,IAAK,IAAIzb,EAAIlB,KAAKmnE,eAAgBjmE,EAAIlB,KAAKonE,aAAclmE,IACvDlB,KAAK6oE,cAAc3nE,EAAGyb,GAK1B,OADA3c,KAAKolE,kBAAmB,EACjBplE,MAMT6oE,cAAe,SAAS3mE,EAAOya,GAC7B,IAAI8rD,EAAMzoE,KAAK0oE,oBAAoBxmE,GAE9BlC,KAAK8oE,cAAcL,EAAI9E,YAC1B3jE,KAAK+oE,cAAcN,EAAI9E,UAAW,IAG/B3jE,KAAK2oE,qBAAqBF,EAAI9E,UAAW8E,EAAInlC,YAChDtjC,KAAKgpE,qBAAqBP,EAAI9E,UAAW8E,EAAInlC,UAAW,IAG1DnlC,OAAOiC,KAAK6B,OAAOmV,OAAOpX,KAAK2oE,qBAAqBF,EAAI9E,UAAW8E,EAAInlC,WAAY3mB,IAWrFolD,gBAAiB,SAASr2D,GACnBA,GACH1L,KAAKipE,kBAEPjpE,KAAK8Y,UAAU,kBAAmBpN,IAQpCm1B,OAAQ,SAASn1B,EAAKm4C,GACpB7jD,KAAKipE,kBACLjpE,KAAK8Y,UAAU,SAAUpN,EAAKm4C,GAG9B7jD,KAAKkpE,kBAAoB,GACzBlpE,KAAKmpE,2BAOPhjC,QAAS,SAASz6B,GAChB1L,KAAK8Y,UAAU,UAAWpN,GAC1B1L,KAAK0L,IAAMA,GAMbu9D,gBAAiB,WACf,GAAKjpE,KAAKsuC,QAAWtuC,KAAK60C,WAGtB70C,KAAK2/B,QAAU3/B,KAAK2/B,OAAOuF,WAAY,CACzC,IAAIx5B,EAAM1L,KAAK2/B,OAAOuF,WACtBx5B,EAAIU,OACJV,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK2/B,OAAO9D,mBACrC77B,KAAK+mB,UAAUrb,GACf1L,KAAK0tB,iBAAmBhiB,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK0tB,iBACtD1tB,KAAKopE,eAAe19D,GACpBA,EAAIc,YAOR28D,wBAAyB,WACvB,GAAKnpE,KAAKsuC,QAAWtuC,KAAK60C,UAA1B,CAGA,IACIw0B,EAAY39D,EADZ03D,EAAQpjE,KAAK4uB,KAAKvlB,MAAM,IAExBrJ,KAAK2/B,QAAU3/B,KAAK2/B,OAAOuF,aAC7Bx5B,EAAM1L,KAAK2/B,OAAOuF,YACd94B,OACJV,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK2/B,OAAO9D,mBACrC77B,KAAK+mB,UAAUrb,GACf1L,KAAK0tB,iBAAmBhiB,EAAIqb,UAAUnlB,MAAM8J,EAAK1L,KAAK0tB,iBACtD1tB,KAAKopE,eAAe19D,KAGpBA,EAAM1L,KAAK0L,KACPU,OAEFpM,KAAKmnE,iBAAmBnnE,KAAKonE,cAC/BiC,EAAarpE,KAAKspE,qBAAqBlG,EAAO,UAC9CpjE,KAAKupE,aAAaF,EAAY39D,KAG9B29D,EAAarpE,KAAKspE,qBAAqBlG,EAAO,aAC9CpjE,KAAKwpE,gBAAgBpG,EAAOiG,EAAY39D,IAE1CA,EAAIc,YAGN48D,eAAgB,SAAS19D,GAEvB,IAAIpE,EAAQtH,KAAKsH,MAAQ,EAAGM,EAAS5H,KAAK4H,OAAS,EACnD8D,EAAIm0B,WAAWv4B,EAAQ,GAAIM,EAAS,EAAGN,EAAOM,IAMhD8gE,oBAAqB,SAASvB,QACE,IAAnBA,IACTA,EAAiBnnE,KAAKmnE,gBAGxB,IADA,IAAIhmE,EAAMnB,KAAKiiE,WAAWxhE,OACjBS,EAAI,EAAGA,EAAIC,EAAKD,IAAK,CAC5B,GAAIimE,GAAkBnnE,KAAKiiE,WAAW/gE,GAAGT,OACvC,MAAO,CACLkjE,UAAWziE,EACXoiC,UAAW6jC,GAGfA,GAAkBnnE,KAAKiiE,WAAW/gE,GAAGT,OAAS,EAEhD,MAAO,CACLkjE,UAAWziE,EAAI,EACfoiC,UAAWtjC,KAAKiiE,WAAW/gE,EAAI,GAAGT,OAAS0mE,EAAiBnnE,KAAKiiE,WAAW/gE,EAAI,GAAGT,OAAS0mE,IAUhGsC,oBAAqB,SAAS9F,EAAWrgC,GACvC,IAAIrnB,EAAQjc,KAAK2oE,qBAAqBhF,EAAyB,IAAdrgC,EAAkB,EAAIA,EAAY,GAEnF,MAAO,CACLh7B,SAAU2T,GAASA,EAAM3T,UAAYtI,KAAKsI,SAC1ChI,KAAM2b,GAASA,EAAM3b,MAAQN,KAAKM,KAClCohE,oBAAqBzlD,GAASA,EAAMylD,qBAAuB1hE,KAAK0hE,oBAChErM,eAAgBp5C,GAASA,EAAMo5C,gBAAkBr1D,KAAKq1D,eACtDllD,WAAY8L,GAASA,EAAM9L,YAAcnQ,KAAKmQ,WAC9Cuc,WAAYzQ,GAASA,EAAMyQ,YAAc1sB,KAAK0sB,WAC9CD,UAAWxQ,GAASA,EAAMwQ,WAAazsB,KAAKysB,UAC5C1E,OAAQ9L,GAASA,EAAM8L,QAAU/nB,KAAK+nB,OACtCuf,YAAarrB,GAASA,EAAMqrB,aAAetnC,KAAKsnC,cAUpDoiC,uBAAwB,SAAS/F,EAAWrgC,GAC1C,IAAIrnB,EAAQjc,KAAK2oE,qBAAqBhF,EAAyB,IAAdrgC,EAAkB,EAAIA,EAAY,GACnF,OAAOrnB,GAASA,EAAM3T,SAAW2T,EAAM3T,SAAWtI,KAAKsI,UASzDqhE,oBAAqB,SAAShG,EAAWrgC,GACvC,IAAIrnB,EAAQjc,KAAK2oE,qBAAqBhF,EAAyB,IAAdrgC,EAAkB,EAAIA,EAAY,GACnF,OAAOrnB,GAASA,EAAM3b,KAAO2b,EAAM3b,KAAON,KAAKunE,aASjD+B,qBAAsB,SAASlG,EAAOwG,GAKpC,IAAIliE,EAAO3C,KAAKuvB,MAAMt0B,KAAKqkE,kBACvB18D,EAAM3H,KAAKskE,gBAEXkB,EAAUxlE,KAAK6pE,4BACHzG,EAAOwG,GAEvB,MAAO,CACLliE,KAAMA,EACNC,IAAKA,EACLy8D,WAAYoB,EAAQ99D,KAAO89D,EAAQsE,SACnCC,UAAWvE,EAAQ79D,MAOvBkiE,4BAA6B,SAASzG,EAAOwG,GAC3C,GAAI5pE,KAAKkpE,mBAAqB,QAASlpE,KAAKkpE,kBAC1C,OAAOlpE,KAAKkpE,kBASd,IAPA,IAKIG,EALAxE,EAAiB,EACjBlB,EAAY,EACZrgC,EAAY,EACZymC,EAAY,EACZ3F,EAAa,EAGRljE,EAAI,EAAGA,EAAIlB,KAAKmnE,eAAgBjmE,IACtB,OAAbkiE,EAAMliE,IACRkjE,EAAa,EACb2F,GAAa/pE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKi4D,GAE7CA,IACArgC,EAAY,IAGZ8gC,GAAcpkE,KAAKgqE,gBAAgBhqE,KAAK0L,IAAK03D,EAAMliE,GAAIyiE,EAAWrgC,GAClEA,KAGFuhC,EAAiB7kE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcjjE,KAAK0L,IAAKi4D,IAexE,MAbyB,WAArBiG,IACFG,IAAc,EAAI/pE,KAAK2hE,mBAAqB3hE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKi4D,GAAa3jE,KAAK2sB,WAC1F3sB,KAAK0pE,uBAAuB/F,EAAWrgC,IAAc,EAAItjC,KAAK2hE,oBAE3C,IAArB3hE,KAAK6hE,aAAqBv+B,IAActjC,KAAKiiE,WAAW0B,GAAWljE,SACrE2jE,GAAcpkE,KAAKwjE,0BAErB6F,EAAa,CACX1hE,IAAKoiE,EACLriE,KAAmB,EAAb08D,EAAiBA,EAAa,EACpC0F,SAAUjF,GAEZ7kE,KAAKkpE,kBAAoBG,EAClBrpE,KAAKkpE,mBAQdK,aAAc,SAASF,EAAY39D,GAEjC,IAAIu+D,EAAiBjqE,KAAK0oE,sBACtB/E,EAAYsG,EAAetG,UAC3BrgC,EAAY2mC,EAAe3mC,UAC3B4mC,EAAalqE,KAAK0pE,uBAAuB/F,EAAWrgC,GACpD8gC,EAAaiF,EAAWjF,WACxBzmB,EAAa39C,KAAKiO,OAASjO,KAAK2/B,OAAOd,UACvCwjC,EAAcriE,KAAKqiE,YAAc1kB,EAErCjyC,EAAIq1B,UAAY/gC,KAAK2pE,oBAAoBhG,EAAWrgC,GACpD53B,EAAI89B,YAAcxpC,KAAKmqE,cAAgB,EAAInqE,KAAK2nE,sBAEhDj8D,EAAIs1B,SACFqoC,EAAW3hE,KAAO08D,EAAa/B,EAAc,EAC7CgH,EAAW1hE,IAAM0hE,EAAWU,UAC5B1H,EACA6H,IASJV,gBAAiB,SAASpG,EAAOiG,EAAY39D,GAE3CA,EAAIq1B,UAAY/gC,KAAK8qC,eAMrB,IAJA,IAAIvoB,EAAQviB,KAAK0oE,oBAAoB1oE,KAAKmnE,gBACtCnjD,EAAMhkB,KAAK0oE,oBAAoB1oE,KAAKonE,cACpCgD,EAAY7nD,EAAMohD,UAClB0G,EAAUrmD,EAAI2/C,UACTziE,EAAIkpE,EAAWlpE,GAAKmpE,EAASnpE,IAAK,CACzC,IAEIopE,EAFAC,EAAavqE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcv3D,EAAKxK,KAAO,EACpEyrB,EAAa3sB,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKxK,GACzBspE,EAAW,EAAG1a,EAAO9vD,KAAKiiE,WAAW/gE,GAE7D,GAAIA,IAAMkpE,EAAW,CACnB,IAAK,IAAIh1D,EAAI,EAAGjU,EAAM2uD,EAAKrvD,OAAQ2U,EAAIjU,EAAKiU,IACtCA,GAAKmN,EAAM+gB,YAAcpiC,IAAMmpE,GAAWj1D,EAAI4O,EAAIsf,aACpDknC,GAAYxqE,KAAKgqE,gBAAgBt+D,EAAKokD,EAAK16C,GAAIlU,EAAGkU,IAEhDA,EAAImN,EAAM+gB,YACZinC,GAAcvqE,KAAKgqE,gBAAgBt+D,EAAKokD,EAAK16C,GAAIlU,EAAGkU,IAGpDA,IAAM06C,EAAKrvD,SACb+pE,GAAYxqE,KAAKwjE,+BAGhB,GAAQ4G,EAAJlpE,GAAiBA,EAAImpE,EAC5BG,GAAYxqE,KAAKijE,cAAcv3D,EAAKxK,IAAM,OAEvC,GAAIA,IAAMmpE,EAAS,CACtB,IAAK,IAAII,EAAK,EAAGC,EAAQ1mD,EAAIsf,UAAWmnC,EAAKC,EAAOD,IAClDD,GAAYxqE,KAAKgqE,gBAAgBt+D,EAAKokD,EAAK2a,GAAKvpE,EAAGupE,GAEjDzmD,EAAIsf,YAAcwsB,EAAKrvD,SACzB+pE,GAAYxqE,KAAKwjE,0BAGrB8G,EAAiB39C,GACb3sB,KAAK2sB,WAAa,GAAMzrB,IAAMmpE,GAA6B,EAAlBrqE,KAAK2sB,cAChDA,GAAc3sB,KAAK2sB,YAErBjhB,EAAIs1B,SACFqoC,EAAW3hE,KAAO6iE,EAClBlB,EAAW1hE,IAAM0hE,EAAWU,UACjB,EAAXS,EAAeA,EAAW,EAC1B79C,GAEF08C,EAAWU,WAAaO,IAc5BnH,aAAc,SAASnsD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,EAAKg8D,EAAWG,GAE9D,GAAI9jE,KAAKukE,gBACP,OAAOvkE,KAAK2qE,iBAAiB3zD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,GAGxDm8D,EAAaA,GAAc,EAG3B,IACI8G,EACAC,EAFAl+C,EAAa3sB,KAAK+iE,iBAAiBr3D,EAAKi4D,GAGxCmH,EAAgB,GAEpBp/D,EAAIU,OACJzE,GAAOglB,EAAa3sB,KAAK2sB,WAAa3sB,KAAK2hE,kBAC3C,IAAK,IAAIzgE,EAAI4iE,EAAY3iE,EAAM2uD,EAAKrvD,OAASqjE,EAAY5iE,GAAKC,EAAKD,IACjE0pE,EAAYA,GAAa5qE,KAAKypE,oBAAoB9F,EAAWziE,GAC7D2pE,EAAY7qE,KAAKypE,oBAAoB9F,EAAWziE,EAAI,IAEhDlB,KAAK+qE,iBAAiBH,EAAWC,IAAc3pE,IAAMC,KACvDnB,KAAKgrE,YAAYh0D,EAAQtL,EAAKi4D,EAAWziE,EAAI,EAAG4pE,EAAepjE,EAAMC,EAAKglB,GAC1Em+C,EAAgB,GAChBF,EAAYC,GAEdC,GAAiBhb,EAAK5uD,EAAI4iE,GAE5Bp4D,EAAIc,WAWNm+D,iBAAkB,SAAS3zD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,GAEnC,aAAXqP,GAAyBhX,KAAKM,MAChCN,KAAK8Y,UAAU,eAAgB9B,EAAQtL,EAAKokD,EAAMpoD,EAAMC,GAE3C,eAAXqP,IAA6BhX,KAAK+nB,QAA6B,EAAnB/nB,KAAKsnC,aAAoBtnC,KAAKirE,sBAC5EjrE,KAAK8Y,UAAU,eAAgB9B,EAAQtL,EAAKokD,EAAMpoD,EAAMC,IAe5DqjE,YAAa,SAASh0D,EAAQtL,EAAKi4D,EAAWziE,EAAGmiE,EAAO37D,EAAMC,EAAKglB,GACjE,IAAIu+C,EAAWhB,EAAYiB,EAAYC,EAEnCjrD,EAAQk1C,EAAgB+N,EAAOG,EAAiB8H,EADhDC,EAAOtrE,KAAK2oE,qBAAqBhF,EAAWziE,GAwBhD,GArBIoqE,GACFpB,EAAalqE,KAAKurE,iBAAiB7/D,EAAK23D,EAAOM,EAAWziE,GAC1DkqE,EAAeE,EAAKvjD,OACpBojD,EAAaG,EAAKhrE,KAClB+0D,EAAiBiW,EAAKjW,gBAGtB6U,EAAalqE,KAAKsI,SAGpB8iE,GAAgBA,GAAgBprE,KAAK+nB,SAAsB,eAAX/Q,EAChDm0D,GAAcA,GAAcnrE,KAAKM,OAAoB,aAAX0W,EAE1Cs0D,GAAQ5/D,EAAIU,OAEZ8+D,EAAYlrE,KAAKwrE,yBAAyB9/D,EAAK23D,EAAOM,EAAWziE,EAAGoqE,GAAQ,MAC5EjW,EAAiBA,GAAkBr1D,KAAKq1D,eAEpCiW,GAAQA,EAAK5J,qBACf1hE,KAAK+kD,cAAcr5C,GAEI,IAArB1L,KAAK6hE,YAAmB,CAC1B0B,EAAkBvjE,KAAKwjE,yBAGvB,IAAK,IAA+BiI,EAA3Br2D,EADT81D,EAAY,EACI/pE,GAFhBiiE,EAAQC,EAAMh6D,MAAM,KAEQ5I,OAAe2U,EAAIjU,EAAKiU,IAClDq2D,EAAQrI,EAAMhuD,GACd+1D,GAAcz/D,EAAIggE,SAASD,EAAO/jE,EAAOwjE,EAAWvjE,GACpDyjE,GAAgB1/D,EAAIigE,WAAWF,EAAO/jE,EAAOwjE,EAAWvjE,GAExDujE,GAA0B,GAD1BG,EAAa3/D,EAAI+3D,YAAYgI,GAAOnkE,MAAQi8D,GACd8H,EAAa,OAI7CF,GAAcz/D,EAAIggE,SAASrI,EAAO37D,EAAMC,GACxCyjE,GAAgB1/D,EAAIigE,WAAWtI,EAAO37D,EAAMC,IAG1C0tD,GAAqC,KAAnBA,KACpBl1C,EAASngB,KAAK2hE,kBAAoBh1C,EAAa3sB,KAAK2sB,WACpD3sB,KAAK4rE,sBAAsBlgE,EAAK2pD,EAAgB3tD,EAAMC,EAAKwY,EAAQ+qD,EAAWhB,IAGhFoB,GAAQ5/D,EAAIc,UACZd,EAAIW,UAAU6+D,EAAW,IAQ3BH,iBAAkB,SAASH,EAAWC,GACpC,OAAQD,EAAUtqE,OAASuqE,EAAUvqE,MAC7BsqE,EAAUtiE,WAAauiE,EAAUviE,UACjCsiE,EAAUlJ,sBAAwBmJ,EAAUnJ,qBAC5CkJ,EAAUvV,iBAAmBwV,EAAUxV,gBACvCuV,EAAUz6D,aAAe06D,EAAU16D,YACnCy6D,EAAUl+C,aAAem+C,EAAUn+C,YACnCk+C,EAAUn+C,YAAco+C,EAAUp+C,WAClCm+C,EAAU7iD,SAAW8iD,EAAU9iD,QAC/B6iD,EAAUtjC,cAAgBujC,EAAUvjC,aAQ9CskC,sBAAuB,SAASlgE,EAAK2pD,EAAgB3tD,EAAMC,EAAKwY,EAAQ+qD,EAAWhB,GAEjF,GAAK7U,EAAL,CAIA,IAM6Dn0D,EAAG2qE,EAN5DC,EAAmB5B,EAAa,GAChC6B,EAAY,CACVC,UAAWrkE,EAAMuiE,EAAa,GAC9B+B,eAAgBtkE,EAAMuiE,GAAclqE,KAAK2hE,kBAAoB3hE,KAAK4hE,cAAgB,GAAKkK,EACvFI,SAAUvkE,GAAO3H,KAAK4hE,cAAgB5hE,KAAK2hE,mBAAqBuI,GAElEiC,EAAc,CAAC,YAAa,eAAgB,YAEhD,IAAKjrE,EAAI,EAAGA,EAAIirE,EAAY1rE,OAAQS,IAClC2qE,EAAaM,EAAYjrE,IACiB,EAAtCm0D,EAAel1D,QAAQ0rE,IACzBngE,EAAIs1B,SAASt5B,EAAMqkE,EAAUF,GAAaX,EAAYY,KAc5DpI,gBAAiB,SAAS1sD,EAAQtL,EAAKokD,EAAMpoD,EAAMC,EAAKg8D,GAGjD3jE,KAAKukE,kBACR58D,GAAO3H,KAAKsI,UAAYtI,KAAK2hE,kBAAoB,MAEnD3hE,KAAK8Y,UAAU,kBAAmB9B,EAAQtL,EAAKokD,EAAMpoD,EAAMC,EAAKg8D,IAOlElB,sBAAuB,SAAS/2D,GAC9B,GAAI1L,KAAKukE,gBACP,OAAOvkE,KAAK8Y,UAAU,wBAAyBpN,IAQnD62D,2BAA4B,SAAS72D,GACnC1L,KAAK8Y,UAAU,6BAA8BpN,GAE7C,IAAuBg5D,EACnBt/B,EAAWy/B,EAIX/U,EAAMuT,EAAOpnD,EAAOmwD,EACpBC,EAAUC,EAAYC,EANtBzH,EAAgB,EAEhBV,EAAapkE,KAAKqkE,iBAClB0F,EAAY/pE,KAAKskE,gBACjBkI,EAAa,GAGjB9gE,EAAIU,OACJ,IAAK,IAAIlL,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IAIrD,GAHAwjE,EAAe1kE,KAAK+iE,iBAAiBr3D,EAAKxK,GAG7B,MAFb4uD,EAAO9vD,KAAKiiE,WAAW/gE,KAEHlB,KAAK2c,QAAW3c,KAAK8oE,cAAc5nE,GAAvD,CAKAkkC,EAAYplC,KAAKijE,cAAcv3D,EAAKxK,GACpC2jE,EAAiB7kE,KAAK4kE,mBAAmBx/B,GACzCgnC,EAAYC,EAAWC,EAAaC,EAAc,EAClD,IAAK,IAAIn3D,EAAI,EAAGC,EAAOy6C,EAAKrvD,OAAQ2U,EAAIC,EAAMD,IAGxCo3D,KAFJvwD,EAAQjc,KAAK2oE,qBAAqBznE,EAAGkU,IAAM,IAElBssD,sBACnB6K,GAAeD,IACjB5gE,EAAIq1B,UAAYyrC,EAChB9gE,EAAIs1B,SAASorC,EAAWC,EAAUC,EAAYC,IAEhDH,EAAYC,EAAWC,EAAaC,EAAc,EAClDC,EAAavwD,EAAMylD,qBAAuB,IAGvCzlD,EAAMylD,qBAIX2B,EAAQvT,EAAK16C,GAETo3D,IAAevwD,EAAMylD,sBACvB8K,EAAavwD,EAAMylD,oBACd0K,IACHA,EAAYhI,EAAaS,EAAiB7kE,KAAKysE,mBAAmB/gE,EAAKxK,EAAGkU,IAE5Ei3D,EAAWtC,EAAYjF,EACvBwH,GAActsE,KAAKgqE,gBAAgBt+D,EAAK23D,EAAOniE,EAAGkU,GAClDm3D,EAAc7H,EAAe1kE,KAAK2sB,aAZlC6/C,EAAa,GAgBbD,GAAeD,IACjB5gE,EAAIq1B,UAAYyrC,EAChB9gE,EAAIs1B,SAASorC,EAAWC,EAAUC,EAAYC,GAC9CH,EAAYC,EAAWC,EAAaC,EAAc,GAEpDzH,GAAiBJ,OAzCfI,GAAiBJ,EA2CrBh5D,EAAIc,WAMNkgE,cAAe,SAASrJ,EAAOsJ,GAC7B,OAAOtJ,EACAsJ,EAAiBrkE,SACjBqkE,EAAiBjgD,WACjBigD,EAAiBlgD,WAQ1BmgD,cAAe,SAASz8D,GAItB,OAHKhS,OAAOsB,gBAAgB0Q,KAC1BhS,OAAOsB,gBAAgB0Q,GAAc,IAEhChS,OAAOsB,gBAAgB0Q,IAWhCq7D,yBAA0B,SAAS9/D,EAAK23D,EAAOM,EAAWrgC,EAAWgoC,GACnE,IAEIhkE,EAAOulE,EAAWptE,EAFlBqtE,EAAWxB,GAAQtrE,KAAK2oE,qBAAqBhF,EAAWrgC,GACxDqpC,EAAmBn1D,EAAMs1D,GAS7B,GANA9sE,KAAK+sE,iBAAiBJ,GACtBltE,EAAkBO,KAAK4sE,cAAcD,EAAiBx8D,YACtD08D,EAAY7sE,KAAK0sE,cAAcrJ,EAAOsJ,IAIjCG,GAAYrtE,EAAgBotE,IAAc7sE,KAAK+zD,QAClD,OAAOt0D,EAAgBotE,GAGc,iBAA5BF,EAAiBhyC,SAC1BgyC,EAAiBhyC,OAAS,IAAIx8B,OAAOm8B,OAAOqyC,EAAiBhyC,SAG/D,IAAIr6B,EAAOqsE,EAAiBrsE,MAAQN,KAAKM,KAwBzC,OAvBAoL,EAAIq1B,UAAYzgC,EAAK24B,OACjB34B,EAAK24B,OAAOvtB,EAAK1L,MACjBM,EAEAqsE,EAAiB5kD,SACnBrc,EAAIy5B,YAAewnC,EAAiB5kD,QAAU4kD,EAAiB5kD,OAAOkR,OAClE0zC,EAAiB5kD,OAAOkR,OAAOvtB,EAAK1L,MACpC2sE,EAAiB5kD,QAGvBrc,EAAI05B,UAAYunC,EAAiBrlC,aAAetnC,KAAKsnC,YACrD57B,EAAIkiB,KAAO5tB,KAAK6iE,oBAAoB/hE,KAAK6rE,GAIrCA,EAAiBhyC,SACnBgyC,EAAiB1+D,OAASjO,KAAKiO,OAC/B0+D,EAAiBz+D,OAASlO,KAAKkO,OAC/By+D,EAAiBhtC,OAAS3/B,KAAK2/B,OAC/BgtC,EAAiB7qB,iBAAmB9hD,KAAK8hD,iBACzC9hD,KAAKulC,WAAWzkC,KAAK6rE,EAAkBjhE,IAGpC1L,KAAK+zD,SAAYt0D,EAAgBotE,GAM/BptE,EAAgBotE,IALrBvlE,EAAQoE,EAAI+3D,YAAYJ,GAAO/7D,MAC/BtH,KAAK+zD,UAAYt0D,EAAgBotE,GAAavlE,GACvCA,IAUXylE,iBAAkB,SAASJ,GACpBA,EAAiBx8D,aACpBw8D,EAAiBx8D,WAAanQ,KAAKmQ,YAEhCw8D,EAAiBrkE,WACpBqkE,EAAiBrkE,SAAWtI,KAAKsI,UAE9BqkE,EAAiBjgD,aACpBigD,EAAiBjgD,WAAa1sB,KAAK0sB,YAEhCigD,EAAiBlgD,YACpBkgD,EAAiBlgD,UAAYzsB,KAAKysB,YAUtCk8C,qBAAsB,SAAShF,EAAWrgC,EAAW0pC,GACnD,OAAIA,EACMhtE,KAAK2c,OAAOgnD,IAAc3jE,KAAK2c,OAAOgnD,GAAWrgC,GACrD9rB,EAAMxX,KAAK2c,OAAOgnD,GAAWrgC,IAC7B,GAGCtjC,KAAK2c,OAAOgnD,IAAc3jE,KAAK2c,OAAOgnD,GAAWrgC,GAAatjC,KAAK2c,OAAOgnD,GAAWrgC,GAAa,MAS3G0lC,qBAAsB,SAASrF,EAAWrgC,EAAWrnB,GACnDjc,KAAK2c,OAAOgnD,GAAWrgC,GAAarnB,GAStCgxD,wBAAyB,SAAStJ,EAAWrgC,UACpCtjC,KAAK2c,OAAOgnD,GAAWrgC,IAOhCwlC,cAAe,SAASnF,GACtB,OAAO3jE,KAAK2c,OAAOgnD,IAQrBoF,cAAe,SAASpF,EAAW1nD,GACjCjc,KAAK2c,OAAOgnD,GAAa1nD,GAO3BixD,iBAAkB,SAASvJ,UAClB3jE,KAAK2c,OAAOgnD,IAOrBqG,gBAAiB,SAASt+D,EAAK23D,EAAOM,EAAWrgC,GAC/C,IAAKtjC,KAAKmtE,cAAmC,YAAnBntE,KAAKs1D,WAA2Bt1D,KAAKyhE,iBAAiB/nD,KAAK2pD,GACnF,OAAOrjE,KAAKotE,iBAAiB1hE,EAAKi4D,GAEpCj4D,EAAIU,OACJ,IAAI9E,EAAQtH,KAAKwrE,yBAAyB9/D,EAAK23D,EAAOM,EAAWrgC,GAKjE,OAJyB,IAArBtjC,KAAK6hE,cACPv6D,GAAStH,KAAKwjE,0BAEhB93D,EAAIc,UACW,EAARlF,EAAYA,EAAQ,GAS7BikE,iBAAkB,SAAS7/D,EAAKi4D,EAAWrgC,GACzC,IAAIrnB,EAAQjc,KAAK2oE,qBAAqBhF,EAAWrgC,GACjD,OAAOrnB,GAASA,EAAM3T,SAAW2T,EAAM3T,SAAWtI,KAAKsI,UASzDmkE,mBAAoB,SAAS/gE,EAAKi4D,EAAWrgC,GAC3C,IAAepiC,EAAGmiE,EAAd/7D,EAAQ,EACZ,IAAKpG,EAAI,EAAGA,EAAIoiC,EAAWpiC,IACzBmiE,EAAQrjE,KAAKiiE,WAAW0B,GAAWziE,GACnCoG,GAAStH,KAAKgqE,gBAAgBt+D,EAAK23D,EAAOM,EAAWziE,GAEvD,OAAOoG,GAST+9D,aAAc,SAAS35D,EAAKi4D,GAC1B3jE,KAAKmtE,cAAe,EACpB,IAAI7lE,EAAQtH,KAAKysE,mBAAmB/gE,EAAKi4D,EAAW3jE,KAAKiiE,WAAW0B,GAAWljE,QAK/E,OAJyB,IAArBT,KAAK6hE,cACPv6D,GAAStH,KAAKwjE,0BAEhBxjE,KAAKmtE,cAAe,EACL,EAAR7lE,EAAYA,EAAQ,GAQ7B8lE,iBAAkB,SAAU1hE,EAAKi4D,GAC/B,GAAI3jE,KAAK8nE,eAAenE,GACtB,OAAO3jE,KAAK8nE,eAAenE,GAE7B,IAAI7T,EAAO9vD,KAAKiiE,WAAW0B,GACvBI,EAAa/jE,KAAKgkE,iBAAiBt4D,EAAKokD,EAAM6T,EAAW,GACzDM,EAAYjkE,KAAKsH,MAAQy8D,EACzBG,EAAYpU,EAAKrvD,OAASqvD,EAAKp4C,QAAQ1X,KAAKyhE,iBAAkB,IAAIhhE,OAClE6G,EAAQvC,KAAKU,IAAIw+D,EAAYC,EAAWx4D,EAAI+3D,YAAY,KAAKn8D,OAEjE,OADAtH,KAAK8nE,eAAenE,GAAar8D,GAWnC08D,iBAAkB,SAAUt4D,EAAKokD,EAAM6T,EAAWG,GAGhD,IAFA,IAAIx8D,EAAQ,EAEHg8B,EAAY,EAAGA,EAAYwsB,EAAKrvD,OAAQ6iC,IAAa,CAC5D,IAAI+/B,EAAQvT,EAAKxsB,GAEZ+/B,EAAMn0D,MAAM,QACf5H,GAAStH,KAAKgqE,gBAAgBt+D,EAAK23D,EAAOM,EAAWrgC,EAAYwgC,IAIrE,OAAOx8D,GAOTy7D,iBAAkB,SAASr3D,EAAKi4D,GAC9B,GAAI3jE,KAAKilE,cAActB,GACrB,OAAO3jE,KAAKilE,cAActB,GAM5B,IAHA,IAAI7T,EAAO9vD,KAAKiiE,WAAW0B,GACvBgB,EAAY3kE,KAAKurE,iBAAiB7/D,EAAKi4D,EAAW,GAE7CziE,EAAI,EAAGC,EAAM2uD,EAAKrvD,OAAQS,EAAIC,EAAKD,IAAK,CAC/C,IAAImsE,EAAoBrtE,KAAKurE,iBAAiB7/D,EAAKi4D,EAAWziE,GACtCyjE,EAApB0I,IACF1I,EAAY0I,GAIhB,OADArtE,KAAKilE,cAActB,GAAagB,EAAY3kE,KAAK2sB,WAAa3sB,KAAK4hE,cAC5D5hE,KAAKilE,cAActB,IAO5BrB,eAAgB,SAAS52D,GAEvB,IADA,IAAIihB,EAAY/kB,EAAS,EAChB1G,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IACrDyrB,EAAa3sB,KAAK+iE,iBAAiBr3D,EAAKxK,GACxC0G,GAAW1G,IAAMC,EAAM,EAAIwrB,EAAa3sB,KAAK2sB,WAAaA,EAE5D,OAAO/kB,GASTywB,SAAU,SAASC,GACjB,OAAOn6B,OAAOiC,KAAK6B,OAAOmV,OAAOpX,KAAK8Y,UAAU,WAAYwf,GAAsB,CAChF3b,OAAQnF,EAAMxX,KAAK2c,QAAQ,QAcjCxe,OAAO+oE,MAAM58D,WAAa,SAASrI,EAAQU,EAAUwkD,GACnD,OAAOhpD,OAAOmN,OAAO47C,YAAY,QAASjlD,EAAQU,EAAUwkD,EAAY,SA9qC5E,GAmrCA,WAEE,IAAI3vC,EAAQrZ,OAAOiC,KAAK6B,OAAOuV,MAE/BrZ,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+oE,MAAM37D,UAAgD,CAKrFw8D,aAAc,WACZ/nE,KAAKstE,mBACLttE,KAAKutE,qBACLvtE,KAAKwtE,8BACLxtE,KAAKytE,4BACLztE,KAAK0tE,iBAAmB1tE,KAAK0tE,iBAAiBz1D,KAAKjY,OAGrDi2C,WAAY,WACVj2C,KAAK60C,WAAa70C,KAAK+8C,cACvB/8C,KAAK2tE,UAAW,EAChB3tE,KAAK8Y,UAAU,eAMjBw0D,iBAAkB,WAChB,IAAIn1D,EAAQnY,KACZA,KAAKW,GAAG,QAAS,WACf,IAAIg/B,EAASxnB,EAAMwnB,OACfA,IACGA,EAAOI,oBACVJ,EAAOI,mBAAoB,EAC3B5nB,EAAMy1D,oBAAoBjuC,IAE5BA,EAAOM,gBAAkBN,EAAOM,iBAAmB,GACnDN,EAAOM,gBAAgBr/B,KAAKuX,OAKlCo1D,mBAAoB,WAClB,IAAIp1D,EAAQnY,KACZA,KAAKW,GAAG,UAAW,WACjB,IAAIg/B,EAASxnB,EAAMwnB,OACfA,IACFA,EAAOM,gBAAkBN,EAAOM,iBAAmB,GACnD9hC,OAAOiC,KAAKiF,gBAAgBs6B,EAAOM,gBAAiB9nB,GACd,IAAlCwnB,EAAOM,gBAAgBx/B,SACzBk/B,EAAOI,mBAAoB,EAC3B5nB,EAAM01D,sBAAsBluC,QAUpCiuC,oBAAqB,SAASjuC,GAC5BA,EAAOK,qBAAuB,WACxBL,EAAOM,iBACTN,EAAOM,gBAAgB51B,QAAQ,SAAS7F,GACtCA,EAAI2lE,eAAgB,KAGvBlyD,KAAKjY,MACR2/B,EAAOh/B,GAAG,WAAYg/B,EAAOK,uBAO/B6tC,sBAAuB,SAASluC,GAC9BA,EAAOp+B,IAAI,WAAYo+B,EAAOK,uBAMhC8tC,MAAO,WACL9tE,KAAK+tE,kBAAoB/tE,KAAKguE,eAAehuE,KAAM,EAAGA,KAAKynE,eAAgB,oBAM7EuG,eAAgB,SAASxpE,EAAKypE,EAAexrD,EAAUyrD,GAErD,IAAIC,EA0BJ,OAxBAA,EAAY,CACVC,WAAW,EACXxrD,MAAO,WACL5iB,KAAKouE,WAAY,IAIrB5pE,EAAI4d,QAAQ,wBAAyB6rD,EAAe,CAClDxrD,SAAUA,EACVrB,WAAY,WACL+sD,EAAUC,WACb5pE,EAAI0pE,MAGRvrD,SAAU,WAEJne,EAAIm7B,QAAUn7B,EAAI2iE,iBAAmB3iE,EAAI4iE,cAC3C5iE,EAAI2kE,2BAGRvmD,MAAO,WACL,OAAOurD,EAAUC,aAGdD,GAMTE,gBAAiB,WAEf,IAAIl2D,EAAQnY,KAERA,KAAKsuE,iBACPC,aAAavuE,KAAKsuE,iBAEpBtuE,KAAKsuE,gBAAkBpsD,WAAW,WAChC/J,EAAMq2D,0BAA4Br2D,EAAM61D,eAAe71D,EAAO,EAAGnY,KAAKynE,eAAiB,EAAG,UACzF,MAMLgH,kBAAmB,SAASC,GAC1B,IAAIv2D,EAAQnY,KACR2uE,EAAQD,EAAU,EAAI1uE,KAAKwnE,YAE/BxnE,KAAK4uE,uBACL5uE,KAAK2nE,sBAAwB,EAC7B3nE,KAAK6uE,gBAAkB3sD,WAAW,WAChC/J,EAAM21D,SACLa,IAMLC,qBAAsB,WACpB,IAAIzJ,EAAcnlE,KAAK+tE,mBAAqB/tE,KAAKwuE,0BACjDxuE,KAAK+tE,mBAAqB/tE,KAAK+tE,kBAAkBnrD,QACjD5iB,KAAKwuE,2BAA6BxuE,KAAKwuE,0BAA0B5rD,QAEjE2rD,aAAavuE,KAAKsuE,iBAClBC,aAAavuE,KAAK6uE,iBAElB7uE,KAAK2nE,sBAAwB,EAGzBxC,GACFnlE,KAAK2/B,QAAU3/B,KAAK2/B,OAAOC,aAAa5/B,KAAK2/B,OAAOuF,YAAcllC,KAAK0L,MAQ3EojE,UAAW,WACT9uE,KAAKmnE,eAAiB,EACtBnnE,KAAKonE,aAAepnE,KAAK4uB,KAAKnuB,OAC9BT,KAAKooE,wBACLpoE,KAAKqoE,mBAOP0G,gBAAiB,WACf,OAAO/uE,KAAK4uB,KAAK1lB,MAAMlJ,KAAKmnE,eAAgBnnE,KAAKonE,eAQnD4H,qBAAsB,SAASC,GAC7B,IAAI9uD,EAAS,EAAGje,EAAQ+sE,EAAY,EAGpC,GAAIjvE,KAAK0nE,SAAShuD,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,IACtC,KAAOlC,KAAK0nE,SAAShuD,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,KACzCie,IACAje,IAGJ,KAAO,KAAKwX,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,MAAoB,EAATA,GAC3Cie,IACAje,IAGF,OAAO+sE,EAAY9uD,GAQrB+uD,sBAAuB,SAASD,GAC9B,IAAI9uD,EAAS,EAAGje,EAAQ+sE,EAGxB,GAAIjvE,KAAK0nE,SAAShuD,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,IACtC,KAAOlC,KAAK0nE,SAAShuD,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,KACzCie,IACAje,IAGJ,KAAO,KAAKwX,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,KAAWA,EAAQlC,KAAK4uB,KAAKnuB,QAC7D0f,IACAje,IAGF,OAAO+sE,EAAY9uD,GAQrBgvD,qBAAsB,SAASF,GAG7B,IAFA,IAAI9uD,EAAS,EAAGje,EAAQ+sE,EAAY,GAE5B,KAAKv1D,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,MAAoB,EAATA,GAC5Cie,IACAje,IAGF,OAAO+sE,EAAY9uD,GAQrBivD,sBAAuB,SAASH,GAG9B,IAFA,IAAI9uD,EAAS,EAAGje,EAAQ+sE,GAEhB,KAAKv1D,KAAK1Z,KAAK4uB,KAAK5lB,OAAO9G,KAAWA,EAAQlC,KAAK4uB,KAAKnuB,QAC9D0f,IACAje,IAGF,OAAO+sE,EAAY9uD,GAOrBkvD,6BAA8B,WAI5B,IAHA,IAAIC,EAAetvE,KAAK+uE,kBACpBQ,EAAe,EAEVruE,EAAI,EAAGC,EAAMmuE,EAAa7uE,OAAQS,EAAIC,EAAKD,IAC1B,OAApBouE,EAAapuE,IACfquE,IAGJ,OAAOA,GASTC,mBAAoB,SAASrI,EAAgBsI,GAK3C,IAJA,IAAIvtE,EAAYlC,KAAK0nE,SAAShuD,KAAK1Z,KAAK4uB,KAAK5lB,OAAOm+D,IAAmBA,EAAiB,EAAIA,EACxF9D,EAAYrjE,KAAK4uB,KAAK5lB,OAAO9G,GAC7BwtE,EAAY,kBAERA,EAAUh2D,KAAK2pD,IAAkB,EAARnhE,GAAaA,EAAQlC,KAAK4uB,KAAKnuB,QAC9DyB,GAASutE,EACTpM,EAAQrjE,KAAK4uB,KAAK5lB,OAAO9G,GAK3B,OAHIwtE,EAAUh2D,KAAK2pD,IAAoB,OAAVA,IAC3BnhE,GAAuB,IAAdutE,EAAkB,EAAI,GAE1BvtE,GAOTytE,WAAY,SAASxI,GACnBA,EAAiBA,GAAkBnnE,KAAKmnE,eACxC,IAAIyI,EAAoB5vE,KAAKwvE,mBAAmBrI,GAAiB,GAC7D0I,EAAkB7vE,KAAKwvE,mBAAmBrI,EAAgB,GAE9DnnE,KAAKmnE,eAAiByI,EACtB5vE,KAAKonE,aAAeyI,EACpB7vE,KAAKooE,wBACLpoE,KAAKqoE,kBACLroE,KAAKmpE,2BAOP2G,WAAY,SAAS3I,GACnBA,EAAiBA,GAAkBnnE,KAAKmnE,eACxC,IAAIyI,EAAoB5vE,KAAKmvE,qBAAqBhI,GAC9C0I,EAAkB7vE,KAAKovE,sBAAsBjI,GAEjDnnE,KAAKmnE,eAAiByI,EACtB5vE,KAAKonE,aAAeyI,EACpB7vE,KAAKooE,wBACLpoE,KAAKqoE,mBAQP0H,aAAc,SAAS51D,GACrB,IAAIna,KAAK60C,WAAc70C,KAAKqnE,SAoB5B,OAhBIrnE,KAAK2/B,QACP3/B,KAAKgwE,oBAAoBhwE,KAAK2/B,QAGhC3/B,KAAK60C,WAAY,EACjB70C,KAAK2tE,UAAW,EAChB3tE,KAAKiwE,mBAAmB91D,GACxBna,KAAKo5C,eAAeC,QACpBr5C,KAAKqoE,kBACLroE,KAAKkwE,oBACLlwE,KAAKmwE,mBACLnwE,KAAKowE,gBAAkBpwE,KAAK4uB,KAE5B5uB,KAAK8tE,QACL9tE,KAAKe,KAAK,mBACVf,KAAKooE,wBACApoE,KAAK2/B,SAGV3/B,KAAK2/B,OAAO5+B,KAAK,uBAAwB,CAAE6N,OAAQ5O,OACnDA,KAAKqwE,uBACLrwE,KAAK2/B,OAAO59B,aACL/B,MAGTgwE,oBAAqB,SAASrwC,GACxBA,EAAOM,iBACTN,EAAOM,gBAAgB51B,QAAQ,SAAS7F,GACtCA,EAAImpE,UAAW,EACXnpE,EAAIqwC,WACNrwC,EAAIu4C,iBASZszB,qBAAsB,WACpBrwE,KAAK2/B,OAAOh/B,GAAG,aAAcX,KAAK0tE,mBAMpCA,iBAAkB,SAAS1sE,GACzB,GAAKhB,KAAKmqE,eAAkBnqE,KAAK60C,UAAjC,CAIA,IAAI+6B,EAAoB5vE,KAAKswE,6BAA6BtvE,EAAQmZ,GAC9Do2D,EAAevwE,KAAKmnE,eACpBqJ,EAAaxwE,KAAKonE,cAEnBwI,IAAsB5vE,KAAKywE,6BAA+BF,IAAiBC,GAE3ED,IAAiBX,GAAqBY,IAAeZ,KAIpDA,EAAoB5vE,KAAKywE,6BAC3BzwE,KAAKmnE,eAAiBnnE,KAAKywE,4BAC3BzwE,KAAKonE,aAAewI,IAGpB5vE,KAAKmnE,eAAiByI,EACtB5vE,KAAKonE,aAAepnE,KAAKywE,6BAEvBzwE,KAAKmnE,iBAAmBoJ,GAAgBvwE,KAAKonE,eAAiBoJ,IAChExwE,KAAK0wE,wBACL1wE,KAAKooE,wBACLpoE,KAAKqoE,kBACLroE,KAAKmpE,8BAOTgH,iBAAkB,WAChBnwE,KAAKkrC,YAAc,OAEflrC,KAAK2/B,SACP3/B,KAAK2/B,OAAOyL,cAAgBprC,KAAK2/B,OAAOwL,WAAa,QAGvDnrC,KAAK4/C,YAAc5/C,KAAKsnE,mBAExBtnE,KAAKwgD,YAAcxgD,KAAK0uC,YAAa,EACrC1uC,KAAK0gD,cAAgB1gD,KAAK2gD,eAAgB,GAM5C0nB,gBAAiB,WACf,GAAKroE,KAAKo5C,iBAAkBp5C,KAAK2wE,oBAGjC3wE,KAAKkpE,kBAAoB,GACzBlpE,KAAKo5C,eAAe/3C,MAAQrB,KAAK4uB,KACjC5uB,KAAKo5C,eAAe+tB,eAAiBnnE,KAAKmnE,eAC1CnnE,KAAKo5C,eAAeguB,aAAepnE,KAAKonE,aACpCpnE,KAAKmnE,iBAAmBnnE,KAAKonE,cAAc,CAC7C,IAAInrD,EAAQjc,KAAK4wE,wBACjB5wE,KAAKo5C,eAAen9B,MAAMvU,KAAOuU,EAAMvU,KACvC1H,KAAKo5C,eAAen9B,MAAMtU,IAAMsU,EAAMtU,IACtC3H,KAAKo5C,eAAen9B,MAAM3T,SAAW2T,EAAM3T,WAQ/CsoE,sBAAuB,WACrB,IAAK5wE,KAAK2/B,OACR,MAAO,CAAEp5B,EAAG,EAAGC,EAAG,GAEpB,IAAI48D,EAAQpjE,KAAK4uB,KAAKvlB,MAAM,IACxBggE,EAAarpE,KAAKspE,qBAAqBlG,EAAO,UAC9C6G,EAAiBjqE,KAAK0oE,sBACtB/E,EAAYsG,EAAetG,UAC3BrgC,EAAY2mC,EAAe3mC,UAC3B4mC,EAAalqE,KAAK0pE,uBAAuB/F,EAAWrgC,GACpD8gC,EAAaiF,EAAWjF,WACxBr6C,EAAI/pB,KAAK4tC,sBACT9mC,EAAI,CACFP,EAAG8iE,EAAW3hE,KAAO08D,EACrB59D,EAAG6iE,EAAW1hE,IAAM0hE,EAAWU,UAAYG,GAE7C2G,EAAc7wE,KAAK2/B,OAAOjB,cAC1BskC,EAAW6N,EAAYvpE,MAAQ4iE,EAC/BvF,EAAYkM,EAAYjpE,OAASsiE,EAsBrC,OApBApjE,EAAI3I,OAAOiC,KAAKyG,eAAeC,EAAGijB,IAClCjjB,EAAI3I,OAAOiC,KAAKyG,eAAeC,EAAG9G,KAAK2/B,OAAO9D,oBAExCt1B,EAAI,IACRO,EAAEP,EAAI,GAEJO,EAAEP,EAAIy8D,IACRl8D,EAAEP,EAAIy8D,GAEJl8D,EAAEN,EAAI,IACRM,EAAEN,EAAI,GAEJM,EAAEN,EAAIm+D,IACR79D,EAAEN,EAAIm+D,GAIR79D,EAAEP,GAAKvG,KAAK2/B,OAAOvC,QAAQ11B,KAC3BZ,EAAEN,GAAKxG,KAAK2/B,OAAOvC,QAAQz1B,IAEpB,CAAED,KAAMZ,EAAEP,EAAI,KAAMoB,IAAKb,EAAEN,EAAI,KAAM8B,SAAU4hE,IAMxDgG,kBAAmB,WACjBlwE,KAAK8wE,YAAc,CACjBtwB,YAAaxgD,KAAKwgD,YAClBZ,YAAa5/C,KAAK4/C,YAClBc,cAAe1gD,KAAK0gD,cACpBC,cAAe3gD,KAAK2gD,cACpBzV,YAAalrC,KAAKkrC,YAClBE,cAAeprC,KAAK2/B,QAAU3/B,KAAK2/B,OAAOyL,cAC1CD,WAAYnrC,KAAK2/B,QAAU3/B,KAAK2/B,OAAOwL,aAO3C4lC,qBAAsB,WACf/wE,KAAK8wE,cAIV9wE,KAAKkrC,YAAclrC,KAAK8wE,YAAYE,WACpChxE,KAAKwgD,YAAcxgD,KAAK8wE,YAAYtwB,YACpCxgD,KAAK4/C,YAAc5/C,KAAK8wE,YAAYlxB,YACpC5/C,KAAK0gD,cAAgB1gD,KAAK8wE,YAAYpwB,cACtC1gD,KAAK2gD,cAAgB3gD,KAAK8wE,YAAYnwB,cAElC3gD,KAAK2/B,SACP3/B,KAAK2/B,OAAOyL,cAAgBprC,KAAK8wE,YAAY1lC,cAC7CprC,KAAK2/B,OAAOwL,WAAanrC,KAAK8wE,YAAY3lC,cAS9C4R,YAAa,WACX,IAAIk0B,EAAiBjxE,KAAKowE,kBAAoBpwE,KAAK4uB,KAwBnD,OAvBA5uB,KAAK2tE,UAAW,EAChB3tE,KAAK60C,WAAY,EACjB70C,KAAK0uC,YAAa,EAElB1uC,KAAKonE,aAAepnE,KAAKmnE,eAErBnnE,KAAKo5C,iBACPp5C,KAAKo5C,eAAe7e,MAAQv6B,KAAKo5C,eAAe7e,OAChDv6B,KAAK2/B,QAAU3/B,KAAKo5C,eAAel7B,WAAW64B,YAAY/2C,KAAKo5C,gBAC/Dp5C,KAAKo5C,eAAiB,MAGxBp5C,KAAK4uE,uBACL5uE,KAAK+wE,uBACL/wE,KAAK2nE,sBAAwB,EAE7B3nE,KAAKe,KAAK,kBACVkwE,GAAiBjxE,KAAKe,KAAK,YACvBf,KAAK2/B,SACP3/B,KAAK2/B,OAAOp+B,IAAI,aAAcvB,KAAK0tE,kBACnC1tE,KAAK2/B,OAAO5+B,KAAK,sBAAuB,CAAE6N,OAAQ5O,OAClDixE,GAAiBjxE,KAAK2/B,OAAO5+B,KAAK,kBAAmB,CAAE6N,OAAQ5O,QAE1DA,MAMTkxE,wBAAyB,WACvB,IAAK,IAAIxwE,KAAQV,KAAK2c,OACf3c,KAAKiiE,WAAWvhE,WACZV,KAAK2c,OAAOjc,IAQzBywE,mBAAoB,SAAS5uD,EAAOyB,GAClC,KAAOA,IAAQzB,GACbviB,KAAKoxE,0BAA0B7uD,EAAQ,GACvCyB,IAEFhkB,KAAKmnE,eAAiB5kD,EACtBviB,KAAKonE,aAAe7kD,GAGtB6uD,0BAA2B,SAASlvE,GAClC,IAAImvE,EAA6C,OAAzBrxE,KAAK4uB,KAAK1sB,EAAQ,GACtCovE,EAAoBD,EAAoBnvE,EAAQA,EAAQ,EAC5DlC,KAAKuxE,kBAAkBF,EAAmBC,GAC1CtxE,KAAK4uB,KAAO5uB,KAAK4uB,KAAK1lB,MAAM,EAAGhH,EAAQ,GACrClC,KAAK4uB,KAAK1lB,MAAMhH,GAElBlC,KAAKiiE,WAAajiE,KAAKkiE,uBAQzBsP,YAAa,SAASC,EAAQC,GAC5B,IAAIz1D,EAMJ,GAJ8C,EAA1Cjc,KAAKonE,aAAepnE,KAAKmnE,gBAC3BnnE,KAAKmxE,mBAAmBnxE,KAAKmnE,eAAgBnnE,KAAKonE,cAG/CsK,IAAkB1xE,KAAKukE,gBAI5B,IAAK,IAAIrjE,EAAI,EAAGC,EAAMswE,EAAOhxE,OAAQS,EAAIC,EAAKD,IACxCwwE,IACFz1D,EAAQ9d,OAAOiC,KAAK6B,OAAOuV,MAAMrZ,OAAOwzE,gBAAgBzwE,IAAI,IAE9DlB,KAAK4xE,WAAWH,EAAOvwE,GAAIA,EAAIC,EAAM,EAAG8a,QAPxCjc,KAAK4xE,WAAWH,GAAQ,IAiB5BG,WAAY,SAASvO,EAAOwO,EAAYC,GACtC,IAAIC,EAAiD,OAAnC/xE,KAAK4uB,KAAK5uB,KAAKmnE,gBACjCnnE,KAAK4uB,KAAO5uB,KAAK4uB,KAAK1lB,MAAM,EAAGlJ,KAAKmnE,gBAClC9D,EAAQrjE,KAAK4uB,KAAK1lB,MAAMlJ,KAAKonE,cAC/BpnE,KAAKiiE,WAAajiE,KAAKkiE,sBACvBliE,KAAKgyE,mBAAmB3O,EAAO0O,EAAaD,GAC5C9xE,KAAKmnE,gBAAkB9D,EAAM5iE,OAC7BT,KAAKonE,aAAepnE,KAAKmnE,eACrB0K,IAGJ7xE,KAAKqoE,kBACLroE,KAAKk/B,YACLl/B,KAAKooE,wBACLpoE,KAAKe,KAAK,WACVf,KAAK0wE,wBACD1wE,KAAK2/B,SACP3/B,KAAK2/B,OAAO5+B,KAAK,eAAgB,CAAE6N,OAAQ5O,OAC3CA,KAAK2/B,OAAO59B,eAIhB2uE,sBAAuB,WAChB1wE,KAAK+tE,oBAAqB/tE,KAAK+tE,kBAAkBK,WAChDpuE,KAAKwuE,4BAA6BxuE,KAAKwuE,0BAA0BJ,WAErEpuE,KAAKyuE,qBAUTwD,yBAA0B,SAAStO,EAAWrgC,EAAWyuC,GAEvD/xE,KAAKkyE,gBAAgBvO,EAAW,GAEhC,IAAIwO,EAAmB,GACnBC,EAAmB,GAQvB,GANIpyE,KAAK2c,OAAOgnD,IAAc3jE,KAAK2c,OAAOgnD,GAAWrgC,EAAY,KAC/D6uC,EAAmBnyE,KAAK2c,OAAOgnD,GAAWrgC,EAAY,IAKpDyuC,GAAeI,EACjBC,EAAc,GAAK56D,EAAM26D,GACzBnyE,KAAK2c,OAAOgnD,EAAY,GAAKyO,MAI1B,CACH,IAAIC,GAAiB,EACrB,IAAK,IAAInwE,KAASlC,KAAK2c,OAAOgnD,GAAY,CACxC,IAAI2O,EAAW7xD,SAASve,EAAO,IACfohC,GAAZgvC,IACFD,GAAiB,EACjBD,EAAcE,EAAWhvC,GAAatjC,KAAK2c,OAAOgnD,GAAWzhE,UAEtDlC,KAAK2c,OAAOgnD,GAAWzhE,IAGlCmwE,IAAmBryE,KAAK2c,OAAOgnD,EAAY,GAAKyO,GAElDpyE,KAAKolE,kBAAmB,GAS1BmN,sBAAuB,SAAS5O,EAAWrgC,EAAWrnB,GAEpD,IAAIu2D,EAA0BxyE,KAAK2c,OAAOgnD,GACtC8O,EAA0Bj7D,EAAMg7D,GAQpC,IAAK,IAAItwE,KANS,IAAdohC,GAAoBrnB,IACtBqnB,EAAY,GAKImvC,EAAyB,CACzC,IAAIC,EAAejyD,SAASve,EAAO,IAEfohC,GAAhBovC,IACFF,EAAkBE,EAAe,GAAKD,EAAwBC,GAGzDD,EAAwBC,EAAe,WACnCF,EAAkBE,IAI/B,IAAIC,EAAW12D,GAASzE,EAAMg7D,EAAkBlvC,EAAY,IAC5DqvC,IAAa3yE,KAAK2c,OAAOgnD,GAAWrgC,GAAaqvC,GACjD3yE,KAAKolE,kBAAmB,GAS1B4M,mBAAoB,SAASP,EAAQM,EAAaD,GAGhD,IAAI7H,EAAiBjqE,KAAK0oE,sBACtB/E,EAAiBsG,EAAetG,UAChCrgC,EAAiB2mC,EAAe3mC,UAE/BtjC,KAAK8oE,cAAcnF,IACtB3jE,KAAK+oE,cAAcpF,EAAW,IAGjB,OAAX8N,EACFzxE,KAAKiyE,yBAAyBtO,EAAWrgC,EAAWyuC,GAGpD/xE,KAAKuyE,sBAAsB5O,EAAWrgC,EAAWwuC,IASrDI,gBAAiB,SAASvO,EAAWxjD,GAEnC,IAAIyyD,EAAep7D,EAAMxX,KAAK2c,QAC9B,IAAK,IAAImzC,KAAQ8iB,EAAc,EACzBC,EAAcpyD,SAASqvC,EAAM,MACd6T,UACViP,EAAaC,GAGxB,IAAK,IAAI/iB,KAAQ9vD,KAAK2c,OAAQ,CAC5B,IAAIk2D,EACclP,GADdkP,EAAcpyD,SAASqvC,EAAM,OAE/B9vD,KAAK2c,OAAOk2D,EAAc1yD,GAAUyyD,EAAaC,GAC5CD,EAAaC,EAAc1yD,WACvBngB,KAAK2c,OAAOk2D,MAY3BtB,kBAAmB,SAASF,EAAmBnvE,GAE7C,IAAI+nE,EAAiBjqE,KAAK0oE,oBAAoBxmE,GAC1CyhE,EAAiBsG,EAAetG,UAChCrgC,EAAiB2mC,EAAe3mC,UAEpCtjC,KAAK8yE,mBAAmBzB,EAAmBpH,EAAgBtG,EAAWrgC,IAGxEyvC,uBAAwB,SAASC,GAC/B,OAAOhzE,KAAKiiE,WAAW+Q,EAAS,IAGlCF,mBAAoB,SAASzB,EAAmBpH,EAAgBtG,EAAWrgC,GAEzE,GAAI+tC,EAAmB,CACrB,IAAI4B,EAAyBjzE,KAAK+yE,uBAAuB9I,EAAetG,WACpEuP,EAAyBD,EAAqBA,EAAmBxyE,OAAS,EAK9E,IAAK6iC,KAHAtjC,KAAK2c,OAAOgnD,EAAY,KAC3B3jE,KAAK2c,OAAOgnD,EAAY,GAAK,IAEb3jE,KAAK2c,OAAOgnD,GAC5B3jE,KAAK2c,OAAOgnD,EAAY,GAAGljD,SAAS6iB,EAAW,IAAM4vC,GACjDlzE,KAAK2c,OAAOgnD,GAAWrgC,GAE7BtjC,KAAKkyE,gBAAgBjI,EAAetG,WAAY,OAE7C,CACH,IAAI6O,EAAoBxyE,KAAK2c,OAAOgnD,GAEhC6O,UACKA,EAAkBlvC,GAE3B,IAAImvC,EAA0Bj7D,EAAMg7D,GAEpC,IAAK,IAAItxE,KAAKuxE,EAAyB,CACrC,IAAIC,EAAejyD,SAASvf,EAAG,IACXoiC,GAAhBovC,GAA8C,IAAjBA,IAC/BF,EAAkBE,EAAe,GAAKD,EAAwBC,UACvDF,EAAkBE,OASjCS,cAAe,WACbnzE,KAAKwxE,YAAY,OAOnB4B,8BAA+B,SAAS7wD,EAAOyB,EAAKqvD,GAC9CA,GAAgB9wD,GACdyB,IAAQzB,EACVviB,KAAK4nE,oBAAsB,OAES,UAA7B5nE,KAAK4nE,sBACZ5nE,KAAK4nE,oBAAsB,OAC3B5nE,KAAKonE,aAAe7kD,GAEtBviB,KAAKmnE,eAAiBkM,GAEA9wD,EAAf8wD,GAAwBA,EAAervD,EACb,UAA7BhkB,KAAK4nE,oBACP5nE,KAAKonE,aAAeiM,EAGpBrzE,KAAKmnE,eAAiBkM,GAKpBrvD,IAAQzB,EACVviB,KAAK4nE,oBAAsB,QAES,SAA7B5nE,KAAK4nE,sBACZ5nE,KAAK4nE,oBAAsB,QAC3B5nE,KAAKmnE,eAAiBnjD,GAExBhkB,KAAKonE,aAAeiM,IAIxBC,yBAA0B,WACxB,IAAI7yE,EAAST,KAAK4uB,KAAKnuB,OACnBT,KAAKmnE,eAAiB1mE,EACxBT,KAAKmnE,eAAiB1mE,EAEfT,KAAKmnE,eAAiB,IAC7BnnE,KAAKmnE,eAAiB,GAEpBnnE,KAAKonE,aAAe3mE,EACtBT,KAAKonE,aAAe3mE,EAEbT,KAAKonE,aAAe,IAC3BpnE,KAAKonE,aAAe,MA/3B5B,GAs4BAjpE,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+oE,MAAM37D,UAAgD,CAIrFkiE,0BAA2B,WAGzBztE,KAAKuzE,iBAAmB,IAAI/wD,KAG5BxiB,KAAKwzE,qBAAuB,IAAIhxD,KAEhCxiB,KAAKyzE,cAAgB,GAErBzzE,KAAKW,GAAG,YAAaX,KAAK+lC,YAAY9tB,KAAKjY,QAG7C+lC,YAAa,SAAS/kC,GAEpBhB,KAAK0zE,gBAAkB,IAAIlxD,KAC3B,IAAImxD,EAAa3zE,KAAK2/B,OAAOhkB,WAAW3a,EAAQmZ,GAE5Cna,KAAK4zE,cAAcD,EAAY3yE,EAAQmZ,IACzCna,KAAKe,KAAK,cAAeC,GACzBhB,KAAK6zE,WAAW7yE,EAAQmZ,IAEjBna,KAAK8zE,cAAcH,KAC1B3zE,KAAKe,KAAK,WAAYC,GACtBhB,KAAK6zE,WAAW7yE,EAAQmZ,IAG1Bna,KAAKwzE,oBAAsBxzE,KAAKuzE,gBAChCvzE,KAAKuzE,gBAAkBvzE,KAAK0zE,eAC5B1zE,KAAKyzE,cAAgBE,EACrB3zE,KAAK+zE,gBAAkB/zE,KAAK60C,UAC5B70C,KAAKg0E,eAAiBh0E,KAAK2tE,UAG7BmG,cAAe,SAASH,GACtB,OAAO3zE,KAAK0zE,eAAiB1zE,KAAKuzE,gBAAkB,KAChDvzE,KAAKyzE,cAAcltE,IAAMotE,EAAWptE,GACpCvG,KAAKyzE,cAAcjtE,IAAMmtE,EAAWntE,GAAKxG,KAAK+zE,iBAGpDH,cAAe,SAASD,GACtB,OAAO3zE,KAAK0zE,eAAiB1zE,KAAKuzE,gBAAkB,KAChDvzE,KAAKuzE,gBAAkBvzE,KAAKwzE,oBAAsB,KAClDxzE,KAAKyzE,cAAcltE,IAAMotE,EAAWptE,GACpCvG,KAAKyzE,cAAcjtE,IAAMmtE,EAAWntE,GAM1CqtE,WAAY,SAAS15D,GACnBA,EAAEu/B,gBAAkBv/B,EAAEu/B,iBACtBv/B,EAAEs/B,iBAAmBt/B,EAAEs/B,mBAMzB+zB,4BAA6B,WAC3BxtE,KAAKi0E,uBACLj0E,KAAKk0E,qBACLl0E,KAAKm0E,cAMPA,WAAY,WACVn0E,KAAKW,GAAG,WAAY,SAASK,GAC3BhB,KAAK2vE,WAAW3vE,KAAKswE,6BAA6BtvE,EAAQmZ,MAE5Dna,KAAKW,GAAG,cAAe,SAASK,GAC9BhB,KAAK8vE,WAAW9vE,KAAKswE,6BAA6BtvE,EAAQmZ,OAO9D85D,qBAAsB,WACpBj0E,KAAKW,GAAG,YAAa,SAASK,GAC5B,GAAKhB,KAAKqnE,YAAarmE,EAAQmZ,EAAE09B,QAA+B,IAArB72C,EAAQmZ,EAAE09B,QAArD,CAGA,IAAI7R,EAAUhmC,KAAK2/B,OAAOhkB,WAAW3a,EAAQmZ,GAC7Cna,KAAKo0E,aAAepuC,EAAQz/B,EAC5BvG,KAAKq0E,aAAeruC,EAAQx/B,EAC5BxG,KAAKmqE,eAAgB,EAEjBnqE,KAAK2tE,UACP3tE,KAAKs0E,iBAAiBtzE,EAAQmZ,GAG5Bna,KAAK60C,YACP70C,KAAKywE,4BAA8BzwE,KAAKmnE,eACpCnnE,KAAKmnE,iBAAmBnnE,KAAKonE,cAC/BpnE,KAAK4uE,uBAEP5uE,KAAKmpE,+BAQXoL,eAAgB,SAASp6D,GACvB,IAAI6rB,EAAUhmC,KAAK2/B,OAAOhkB,WAAWxB,GAErC,OAAOna,KAAKo0E,eAAiBpuC,EAAQz/B,GAC9BvG,KAAKq0E,eAAiBruC,EAAQx/B,GAMvC0tE,mBAAoB,WAClBl0E,KAAKW,GAAG,UAAW,SAASK,GAC1BhB,KAAKmqE,eAAgB,GAChBnqE,KAAKqnE,UAAYrnE,KAAKu0E,eAAevzE,EAAQmZ,IAAOnZ,EAAQmZ,EAAE09B,QAA+B,IAArB72C,EAAQmZ,EAAE09B,SAInF73C,KAAKg0E,iBAAmBh0E,KAAK06C,WAC/B16C,KAAK+vE,aAAa/uE,EAAQmZ,GACtBna,KAAKmnE,iBAAmBnnE,KAAKonE,aAC/BpnE,KAAKyuE,mBAAkB,GAGvBzuE,KAAKmpE,2BAGTnpE,KAAK2tE,UAAW,MAQpB2G,iBAAkB,SAASn6D,GACzB,IAAIk5D,EAAerzE,KAAKswE,6BAA6Bn2D,GACjDoI,EAAQviB,KAAKmnE,eAAgBnjD,EAAMhkB,KAAKonE,aACxCjtD,EAAEm1B,SACJtvC,KAAKozE,8BAA8B7wD,EAAOyB,EAAKqvD,IAG/CrzE,KAAKmnE,eAAiBkM,EACtBrzE,KAAKonE,aAAeiM,GAElBrzE,KAAK60C,YACP70C,KAAKooE,wBACLpoE,KAAKqoE,oBASTiI,6BAA8B,SAASn2D,GASrC,IARA,IAMI21C,EANA0kB,EAAcx0E,KAAK+mD,gBAAgB5sC,GACnCs6D,EAAY,EACZntE,EAAQ,EACRM,EAAS,EACT07B,EAAY,EAIPpiC,EAAI,EAAGC,EAAMnB,KAAKiiE,WAAWxhE,OAAQS,EAAIC,EAAKD,IAAK,CAC1D4uD,EAAO9vD,KAAKiiE,WAAW/gE,GACvB0G,GAAU5H,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKxK,GAAKlB,KAAKkO,OAEpD,IAAIwmE,EAAc10E,KAAKijE,cAAcjjE,KAAK0L,IAAKxK,GAG/CoG,EAFqBtH,KAAK4kE,mBAAmB8P,GAEpB10E,KAAKiO,OAE9B,IAAK,IAAImH,EAAI,EAAGC,EAAOy6C,EAAKrvD,OAAQ2U,EAAIC,EAAMD,IAAK,CAOjD,GALAq/D,EAAYntE,EAEZA,GAAStH,KAAKgqE,gBAAgBhqE,KAAK0L,IAAKokD,EAAK16C,GAAIlU,EAAGlB,KAAK6O,MAAQwG,EAAOD,EAAIA,GACnEpV,KAAKiO,SAEVrG,GAAU4sE,EAAYhuE,GAAKc,GAASktE,EAAYjuE,GAKpD,OAAOvG,KAAK20E,gCACVH,EAAaC,EAAWntE,EAAOg8B,EAAYpiC,EAAGmU,GAL9CiuB,IAQJ,GAAIkxC,EAAYhuE,EAAIoB,EAElB,OAAO5H,KAAK20E,gCACVH,EAAaC,EAAWntE,EAAOg8B,EAAYpiC,EAAI,EAAGmU,GAMtD,OAAOrV,KAAK4uB,KAAKnuB,QAOrBk0E,gCAAiC,SAASH,EAAaC,EAAWntE,EAAOpF,EAAOmT,GAE9E,IAGIu6D,EAAoB1tE,GAHWsyE,EAAYjuE,EAAIkuE,EAChBntE,EAAQktE,EAAYjuE,EACoB,EAAI,GAY/E,OARIvG,KAAK6O,QACP+gE,EAAoBv6D,EAAOu6D,GAGzBA,EAAoB5vE,KAAK4uB,KAAKnuB,SAChCmvE,EAAoB5vE,KAAK4uB,KAAKnuB,QAGzBmvE,KAKXzxE,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+oE,MAAM37D,UAAgD,CAKrF0kE,mBAAoB,WAClBjwE,KAAKo5C,eAAiBj7C,OAAOG,SAASqO,cAAc,YACpD3M,KAAKo5C,eAAev7B,aAAa,iBAAkB,OACnD7d,KAAKo5C,eAAev7B,aAAa,cAAe,OAChD7d,KAAKo5C,eAAev7B,aAAa,eAAgB,OACjD7d,KAAKo5C,eAAev7B,aAAa,aAAc,SAC/C7d,KAAKo5C,eAAev7B,aAAa,6BAA8B,IAC/D7d,KAAKo5C,eAAev7B,aAAa,OAAQ,OACzC,IAAI5B,EAAQjc,KAAK4wE,wBACjB5wE,KAAKo5C,eAAen9B,MAAMY,QAAU,4BAA8BZ,EAAMtU,IACxE,WAAasU,EAAMvU,KAAO,wGACWuU,EAAM3T,SAAW,IACtDnK,OAAOG,SAASyf,KAAKsB,YAAYrf,KAAKo5C,gBAEtCj7C,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,UAAWp5C,KAAK40E,UAAU38D,KAAKjY,OAC5E7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,QAASp5C,KAAK60E,QAAQ58D,KAAKjY,OACxE7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,QAASp5C,KAAK80E,QAAQ78D,KAAKjY,OACxE7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,OAAQp5C,KAAK+0E,KAAK98D,KAAKjY,OACpE7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,MAAOp5C,KAAKg1E,IAAI/8D,KAAKjY,OAClE7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,QAASp5C,KAAKi1E,MAAMh9D,KAAKjY,OACtE7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,mBAAoBp5C,KAAKk1E,mBAAmBj9D,KAAKjY,OAC9F7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,oBAAqBp5C,KAAKm1E,oBAAoBl9D,KAAKjY,OAChG7B,OAAOiC,KAAKia,YAAYra,KAAKo5C,eAAgB,iBAAkBp5C,KAAKo1E,iBAAiBn9D,KAAKjY,QAErFA,KAAKq1E,0BAA4Br1E,KAAK2/B,SACzCxhC,OAAOiC,KAAKia,YAAYra,KAAK2/B,OAAOjB,cAAe,QAAS1+B,KAAKs1E,QAAQr9D,KAAKjY,OAC9EA,KAAKq1E,0BAA2B,IAepCE,QAAS,CACPC,EAAI,cACJC,EAAI,cACJC,GAAI,cACJC,GAAI,gBACJC,GAAI,eACJC,GAAI,iBACJC,GAAI,kBACJC,GAAI,iBACJC,GAAI,iBACJC,GAAI,eACJC,GAAI,kBACJC,GAAI,iBACJC,GAAI,iBAMNC,cAAe,CACbC,GAAI,OACJC,GAAI,OAMNC,gBAAiB,CACfC,GAAI,aAGNnB,QAAS,WAEPt1E,KAAKo5C,gBAAkBp5C,KAAKo5C,eAAeC,SAO7Cu7B,UAAW,SAASz6D,GAClB,GAAKna,KAAK60C,UAAV,CAGA,GAAI16B,EAAEu8D,WAAW12E,KAAKu1E,QACpBv1E,KAAKA,KAAKu1E,QAAQp7D,EAAEu8D,UAAUv8D,OAE3B,CAAA,KAAKA,EAAEu8D,WAAW12E,KAAKw2E,kBAAqBr8D,EAAEw8D,SAAWx8D,EAAEy8D,UAI9D,OAHA52E,KAAKA,KAAKw2E,gBAAgBr8D,EAAEu8D,UAAUv8D,GAKxCA,EAAE08D,2BACF18D,EAAEu/B,iBACe,IAAbv/B,EAAEu8D,SAAiBv8D,EAAEu8D,SAAW,IAElC12E,KAAKipE,kBACLjpE,KAAKmpE,2BAGLnpE,KAAK2/B,QAAU3/B,KAAK2/B,OAAO59B,cAU/B8yE,QAAS,SAAS16D,GACXna,KAAK60C,YAAa70C,KAAK82E,UAIvB38D,EAAEu8D,WAAW12E,KAAKq2E,gBAAmBl8D,EAAEw8D,SAAWx8D,EAAEy8D,WACvD52E,KAAKA,KAAKq2E,cAAcl8D,EAAEu8D,UAAUv8D,GAKtCA,EAAE08D,2BACF18D,EAAEu/B,iBACF15C,KAAK2/B,QAAU3/B,KAAK2/B,OAAO59B,aAXzB/B,KAAK82E,WAAY,GAkBrBhC,QAAS,SAAS36D,GAChB,GAAKna,KAAK60C,YAAa70C,KAAK2wE,kBAA5B,CAGA,IAIIoG,EAAMC,EAAez0D,EAJrBpC,EAASngB,KAAKmnE,gBAAkB,EAChC8P,EAAYj3E,KAAKonE,cAAgB,EACjC8P,EAAal3E,KAAK4uB,KAAKnuB,OACvB02E,EAAgBn3E,KAAKo5C,eAAe/3C,MAAMZ,OAM5Cu2E,EAJkBE,EAAhBC,GAEF50D,EAAqC,SAA7BviB,KAAK4nE,oBAAiCqP,EAAY92D,EAC1D42D,EAAOI,EAAgBD,EACPl3E,KAAKo5C,eAAe/3C,MAAM6H,MAAMqZ,EAAOA,EAAQw0D,KAK/DA,EAAOI,EAAgBD,EAAaD,EAAY92D,EAChCngB,KAAKo5C,eAAe/3C,MAAM6H,MAAMiX,EAAQA,EAAS42D,IAEnE/2E,KAAKwxE,YAAYwF,GACjB78D,EAAEs/B,oBAMJy7B,mBAAoB,WAClBl1E,KAAK2wE,mBAAoB,EACzB3wE,KAAKo3E,sBAAwB,EAC7Bp3E,KAAKq3E,iBAAmBr3E,KAAKmnE,gBAM/BiO,iBAAkB,WAChBp1E,KAAK2wE,mBAAoB,GAM3BwE,oBAAqB,SAASh7D,GAC5B,IAAI1K,EAAO0K,EAAE1K,KACbzP,KAAKmnE,eAAiBnnE,KAAKq3E,iBAC3Br3E,KAAKonE,aAAepnE,KAAKonE,eAAiBpnE,KAAKmnE,eAC7CnnE,KAAKq3E,iBAAmBr3E,KAAKo3E,sBAAwBp3E,KAAKonE,aAC5DpnE,KAAKwxE,YAAY/hE,GAAM,GACvBzP,KAAKo3E,sBAAwB3nE,EAAKhP,QAMpC62E,cAAe,SAASn9D,GACtB,GAAIna,KAAKmnE,iBAAmBnnE,KAAKonE,aAAc,CAC7C,GAAIpnE,KAAKmnE,iBAAmBnnE,KAAK4uB,KAAKnuB,OACpC,OAEFT,KAAKu3E,gBAAgBp9D,GAEvBna,KAAKw3E,YAAYr9D,IAOnB46D,KAAM,SAAS56D,GACb,GAAIna,KAAKmnE,iBAAmBnnE,KAAKonE,aAAjC,CAIA,IAAIkI,EAAetvE,KAAK+uE,kBACpB0I,EAAgBz3E,KAAK03E,kBAAkBv9D,GAGvCs9D,GACFA,EAAcE,QAAQ,OAAQrI,GAGhCnxE,OAAOy5E,WAAatI,EACpBnxE,OAAOwzE,gBAAkB3xE,KAAKsoE,mBAAmBtoE,KAAKmnE,eAAgBnnE,KAAKonE,cAC3EjtD,EAAE08D,2BACF18D,EAAEu/B,iBACF15C,KAAK82E,WAAY,IAOnB7B,MAAO,SAAS96D,GACd,IAAIy9D,EAAa,KACbH,EAAgBz3E,KAAK03E,kBAAkBv9D,GACvCu3D,GAAiB,EAGjB+F,GACFG,EAAaH,EAAcI,QAAQ,QAAQngE,QAAQ,MAAO,IACrDvZ,OAAOwzE,iBAAmBxzE,OAAOy5E,aAAeA,IACnDlG,GAAiB,IAInBkG,EAAaz5E,OAAOy5E,WAGlBA,GACF53E,KAAKwxE,YAAYoG,EAAYlG,GAE/Bv3D,EAAE08D,2BACF18D,EAAEu/B,kBAOJs7B,IAAK,SAAS76D,GACRna,KAAKmnE,iBAAmBnnE,KAAKonE,eAIjCpnE,KAAK+0E,KAAK56D,GACVna,KAAKw3E,YAAYr9D,KAQnBu9D,kBAAmB,SAASv9D,GAC1B,OAAQA,GAAKA,EAAEs9D,eAAkBt5E,OAAOI,OAAOk5E,eAUjDK,sBAAuB,SAASnU,EAAWrgC,GAKzC,IAJA,IAE8D+/B,EAF1D0U,EAAmB/3E,KAAKiiE,WAAW0B,GAAWz6D,MAAM,EAAGo6B,GACvDoxC,EAAc10E,KAAKijE,cAAcjjE,KAAK0L,IAAKi4D,GAC3CqU,EAAoBh4E,KAAK4kE,mBAAmB8P,GAEvCxzE,EAAI,EAAGC,EAAM42E,EAAiBt3E,OAAQS,EAAIC,EAAKD,IACtDmiE,EAAQ0U,EAAiB72E,GACzB82E,GAAqBh4E,KAAKgqE,gBAAgBhqE,KAAK0L,IAAK23D,EAAOM,EAAWziE,GAExE,OAAO82E,GASTC,oBAAqB,SAAS99D,EAAG+9D,GAC/B,IAAIC,EAAgBn4E,KAAKo4E,uBAAuBj+D,EAAG+9D,GAC/CjO,EAAiBjqE,KAAK0oE,oBAAoByP,GAC1CxU,EAAYsG,EAAetG,UAE/B,GAAIA,IAAc3jE,KAAKiiE,WAAWxhE,OAAS,GAAK0Z,EAAEy8D,SAAyB,KAAdz8D,EAAEu8D,QAE7D,OAAO12E,KAAK4uB,KAAKnuB,OAAS03E,EAE5B,IAAI70C,EAAY2mC,EAAe3mC,UAC3B00C,EAAoBh4E,KAAK83E,sBAAsBnU,EAAWrgC,GAC1D+0C,EAAmBr4E,KAAKs4E,gBAAgB3U,EAAY,EAAGqU,GAG3D,OAFsBh4E,KAAKiiE,WAAW0B,GAAWz6D,MAAMo6B,GAEhC7iC,OAAS43E,EAAmB,GAUrDD,uBAAwB,SAASj+D,EAAG+9D,GAClC,OAAI/9D,EAAEm1B,UAAYtvC,KAAKmnE,iBAAmBnnE,KAAKonE,cAAgB8Q,EACtDl4E,KAAKonE,aAGLpnE,KAAKmnE,gBAShBoR,kBAAmB,SAASp+D,EAAG+9D,GAC7B,IAAIC,EAAgBn4E,KAAKo4E,uBAAuBj+D,EAAG+9D,GAC/CjO,EAAiBjqE,KAAK0oE,oBAAoByP,GAC1CxU,EAAYsG,EAAetG,UAC/B,GAAkB,IAAdA,GAAmBxpD,EAAEy8D,SAAyB,KAAdz8D,EAAEu8D,QAEpC,OAAQyB,EAEV,IAAI70C,EAAY2mC,EAAe3mC,UAC3B00C,EAAoBh4E,KAAK83E,sBAAsBnU,EAAWrgC,GAC1D+0C,EAAmBr4E,KAAKs4E,gBAAgB3U,EAAY,EAAGqU,GACvDD,EAAmB/3E,KAAKiiE,WAAW0B,GAAWz6D,MAAM,EAAGo6B,GAE3D,OAAQtjC,KAAKiiE,WAAW0B,EAAY,GAAGljE,OAAS43E,EAAmBN,EAAiBt3E,QAOtF63E,gBAAiB,SAAS3U,EAAWr8D,GASnC,IAPA,IAKIkxE,EALA9D,EAAc10E,KAAKijE,cAAcjjE,KAAK0L,IAAKi4D,GAC3C8U,EAAaz4E,KAAKiiE,WAAW0B,GAE7B+U,EADiB14E,KAAK4kE,mBAAmB8P,GAEzCiE,EAAc,EAGTvjE,EAAI,EAAGC,EAAOojE,EAAWh4E,OAAQ2U,EAAIC,EAAMD,IAAK,CAEvD,IAAIiuD,EAAQoV,EAAWrjE,GACnBwjE,EAAc54E,KAAKgqE,gBAAgBhqE,KAAK0L,IAAK23D,EAAOM,EAAWvuD,GAInE,GAAyB9N,GAFzBoxE,GAAsBE,GAEU,CAE9BJ,GAAa,EAEb,IAAIK,EAAWH,EAAqBE,EAChCE,EAAYJ,EACZK,EAAqBh0E,KAAKG,IAAI2zE,EAAWvxE,GAG7CqxE,EAF0B5zE,KAAKG,IAAI4zE,EAAYxxE,GAEXyxE,EAAqB3jE,EAAKA,EAAI,EAElE,OASJ,OAJKojE,IACHG,EAAcF,EAAWh4E,OAAS,GAG7Bk4E,GAQTK,eAAgB,SAAS7+D,GACnBna,KAAKmnE,gBAAkBnnE,KAAK4uB,KAAKnuB,QAAUT,KAAKonE,cAAgBpnE,KAAK4uB,KAAKnuB,QAG9ET,KAAKi5E,oBAAoB,OAAQ9+D,IAOnC++D,aAAc,SAAS/+D,GACO,IAAxBna,KAAKmnE,gBAA8C,IAAtBnnE,KAAKonE,cAGtCpnE,KAAKi5E,oBAAoB,KAAM9+D,IAQjC8+D,oBAAqB,SAASxJ,EAAWt1D,GAGvC,IACIgG,EAASngB,KADA,MAAQyvE,EAAY,gBACPt1D,EAAgC,UAA7Bna,KAAK4nE,qBAC9BztD,EAAEm1B,SACJtvC,KAAKm5E,oBAAoBh5D,GAGzBngB,KAAKo5E,uBAAuBj5D,GAEf,IAAXA,IACFngB,KAAKszE,2BACLtzE,KAAK4uE,uBACL5uE,KAAK2nE,sBAAwB,EAC7B3nE,KAAKyuE,oBACLzuE,KAAKooE,wBACLpoE,KAAKqoE,oBAQT8Q,oBAAqB,SAASh5D,GAC5B,IAAIkzD,EAA4C,SAA7BrzE,KAAK4nE,oBACtB5nE,KAAKmnE,eAAiBhnD,EACtBngB,KAAKonE,aAAejnD,EAEtB,OADAngB,KAAKozE,8BAA8BpzE,KAAKmnE,eAAgBnnE,KAAKonE,aAAciM,GACzD,IAAXlzD,GAOTi5D,uBAAwB,SAASj5D,GAS/B,OARIA,EAAS,GACXngB,KAAKmnE,gBAAkBhnD,EACvBngB,KAAKonE,aAAepnE,KAAKmnE,iBAGzBnnE,KAAKonE,cAAgBjnD,EACrBngB,KAAKmnE,eAAiBnnE,KAAKonE,cAEX,IAAXjnD,GAOTk5D,eAAgB,SAASl/D,GACK,IAAxBna,KAAKmnE,gBAA8C,IAAtBnnE,KAAKonE,cAGtCpnE,KAAKs5E,uBAAuB,OAAQn/D,IAOtCo/D,MAAO,SAASp/D,EAAGzZ,EAAM+uE,GACvB,IAAIp+B,EACJ,GAAIl3B,EAAEy0B,OACJyC,EAAWrxC,KAAK,mBAAqByvE,GAAWzvE,KAAKU,QAElD,CAAA,IAAIyZ,EAAEy8D,SAAyB,KAAdz8D,EAAEu8D,SAAiC,KAAdv8D,EAAEu8D,QAK3C,OADA12E,KAAKU,IAAuB,SAAd+uE,GAAwB,EAAI,GACnC,EAJPp+B,EAAWrxC,KAAK,mBAAqByvE,GAAWzvE,KAAKU,IAMvD,QAAwB+d,WAAb4yB,GAA0BrxC,KAAKU,KAAU2wC,EAElD,OADArxC,KAAKU,GAAQ2wC,GACN,GAOXmoC,UAAW,SAASr/D,EAAGzZ,GACrB,OAAOV,KAAKu5E,MAAMp/D,EAAGzZ,EAAM,SAM7B+4E,WAAY,SAASt/D,EAAGzZ,GACtB,OAAOV,KAAKu5E,MAAMp/D,EAAGzZ,EAAM,UAO7Bg5E,2BAA4B,SAASv/D,GACnC,IAAIw/D,GAAS,EAUb,OATA35E,KAAK4nE,oBAAsB,OAIvB5nE,KAAKonE,eAAiBpnE,KAAKmnE,gBAA0C,IAAxBnnE,KAAKmnE,iBACpDwS,EAAS35E,KAAKw5E,UAAUr/D,EAAG,mBAG7Bna,KAAKonE,aAAepnE,KAAKmnE,eAClBwS,GAOTC,wBAAyB,SAASz/D,GAChC,MAAiC,UAA7Bna,KAAK4nE,qBAAmC5nE,KAAKmnE,iBAAmBnnE,KAAKonE,aAChEpnE,KAAKw5E,UAAUr/D,EAAG,gBAEM,IAAxBna,KAAKmnE,gBACZnnE,KAAK4nE,oBAAsB,OACpB5nE,KAAKw5E,UAAUr/D,EAAG,wBAFtB,GAUPo9D,gBAAiB,SAASp9D,GACpBna,KAAKmnE,gBAAkBnnE,KAAK4uB,KAAKnuB,QAAUT,KAAKonE,cAAgBpnE,KAAK4uB,KAAKnuB,QAG9ET,KAAKs5E,uBAAuB,QAASn/D,IAQvCm/D,uBAAwB,SAAS7J,EAAWt1D,GAC1C,IAAI0/D,EAAa,aAAepK,EAAY,OAC5CzvE,KAAK2nE,sBAAwB,EAEzBxtD,EAAEm1B,SACJuqC,GAAc,QAGdA,GAAc,WAEZ75E,KAAK65E,GAAY1/D,KACnBna,KAAK4uE,uBACL5uE,KAAKyuE,oBACLzuE,KAAKooE,wBACLpoE,KAAKqoE,oBAQTyR,yBAA0B,SAAS3/D,GACjC,MAAiC,SAA7Bna,KAAK4nE,qBAAkC5nE,KAAKmnE,iBAAmBnnE,KAAKonE,aAC/DpnE,KAAKy5E,WAAWt/D,EAAG,kBAEnBna,KAAKonE,eAAiBpnE,KAAK4uB,KAAKnuB,QACvCT,KAAK4nE,oBAAsB,QACpB5nE,KAAKy5E,WAAWt/D,EAAG,sBAFvB,GAUP4/D,4BAA6B,SAAS5/D,GACpC,IAAI6/D,GAAU,EAUd,OATAh6E,KAAK4nE,oBAAsB,QAEvB5nE,KAAKmnE,iBAAmBnnE,KAAKonE,cAC/B4S,EAAUh6E,KAAKy5E,WAAWt/D,EAAG,kBAC7Bna,KAAKonE,aAAepnE,KAAKmnE,gBAGzBnnE,KAAKmnE,eAAiBnnE,KAAKonE,aAEtB4S,GAOTxC,YAAa,SAASr9D,GAChBna,KAAKmnE,iBAAmBnnE,KAAKonE,aAC/BpnE,KAAKi6E,uBAAuB9/D,GAG5Bna,KAAKmxE,mBAAmBnxE,KAAKmnE,eAAgBnnE,KAAKonE,cAGpDpnE,KAAKyD,IAAI,SAAS,GAClBzD,KAAKmoE,gBAAgBnoE,KAAKmnE,gBAE1BnnE,KAAKkxE,0BAELlxE,KAAK2/B,QAAU3/B,KAAK2/B,OAAO59B,YAE3B/B,KAAKk/B,YACLl/B,KAAKe,KAAK,WACVf,KAAK2/B,QAAU3/B,KAAK2/B,OAAO5+B,KAAK,eAAgB,CAAE6N,OAAQ5O,QAO5Di6E,uBAAwB,SAAS9/D,GAC/B,GAA4B,IAAxBna,KAAKmnE,eAGT,GAAIhtD,EAAEy8D,QAAS,CAEb,IAAIsD,EAAmBl6E,KAAKmvE,qBAAqBnvE,KAAKmnE,gBAEtDnnE,KAAKmxE,mBAAmB+I,EAAkBl6E,KAAKmnE,gBAC/CnnE,KAAKioE,kBAAkBiS,QAEpB,GAAI//D,EAAEy0B,OAAQ,CAEjB,IAAIurC,EAAmBn6E,KAAKgvE,qBAAqBhvE,KAAKmnE,gBAEtDnnE,KAAKmxE,mBAAmBgJ,EAAkBn6E,KAAKmnE,gBAC/CnnE,KAAKioE,kBAAkBkS,QAGvBn6E,KAAKoxE,0BAA0BpxE,KAAKmnE,gBACpCnnE,KAAKioE,kBAAkBjoE,KAAKmnE,eAAiB,MAOnD,WACE,IAAIn/D,EAAU7J,OAAOiC,KAAK4H,QACtB0xB,EAAsBv7B,OAAOmN,OAAOouB,oBAExCv7B,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAO+oE,MAAM37D,UAAgD,CAKrFk7D,oBAAqB,SAAS9C,EAAWyC,EAAWx+D,EAAQ0+D,EAAgBD,EAAeF,GACpFnmE,KAAK8oE,cAAcnF,GAKtB3jE,KAAKo6E,qBACHzW,EAAWyC,EAAWx+D,EAAQ0+D,EAAgBH,GALhDhoE,OAAOsK,KAAK8C,UAAUk7D,oBAAoB3lE,KAAKd,KAC7C2jE,EAAWyC,EAAWx+D,EAAQ0+D,EAAgBD,IAWpD+T,qBAAsB,SAASzW,EAAWyC,EAAWx+D,EAAQ0+D,EAAgBH,GAQ3E,IANA,IAAI/C,EAAQpjE,KAAKiiE,WAAW0B,GACxBG,EAAa,EACbe,EAAiB7kE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcjjE,KAAK0L,IAAKi4D,IAAc3jE,KAAKsH,MAAQ,EACjGijE,EAAavqE,KAAKq6E,qBAAqB1W,GACvCe,EAAe1kE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKi4D,GAE1CziE,EAAI,EAAGC,EAAMiiE,EAAM3iE,OAAQS,EAAIC,EAAKD,IAAK,CAChD,IAAIo5E,EAAYt6E,KAAK2oE,qBAAqBhF,EAAWziE,IAAM,GAE3DklE,EAAUxlE,KACRZ,KAAKu6E,oBACHnX,EAAMliE,GAAIo5E,EAAWzV,EAAgB0F,EAAWrE,QAAUqE,EAAWpqD,OAAQ2jD,IAEjF,IAAIoH,EAAYlrE,KAAKgqE,gBAAgBhqE,KAAK0L,IAAK03D,EAAMliE,GAAIyiE,EAAWziE,GAEhEo5E,EAAU5Y,qBACZyE,EAAYvlE,KACVZ,KAAKw6E,kBACHF,EAAWzV,EAAgB0F,EAAWrE,QAASxB,EAAcwG,EAAWpH,IAG9EA,GAAcoH,IAOlBmP,qBAAsB,SAAS1W,GAE7B,IADA,IAAuB8W,EAAnB3V,EAAgB,EACX1vD,EAAI,EAAGA,EAAIuuD,EAAWvuD,IAC7B0vD,GAAiB9kE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAK0J,GAGnD,OADAqlE,EAAaz6E,KAAK+iE,iBAAiB/iE,KAAK0L,IAAK0J,GACtC,CACL8wD,QAASpB,EACT3kD,QAASngB,KAAK4hE,cAAgB5hE,KAAK2hE,mBAAqB8Y,GAAcz6E,KAAK2sB,WAAa3sB,KAAK4hE,iBAOjG4Y,kBAAmB,SAASF,EAAWzV,EAAgBC,EAAeJ,EAAcwG,EAAWpH,GAC7F,MAAO,CACL,mBAAoBwW,EAAU5Y,oBAC9B,QAAS15D,EAAQ68D,EAAiBf,EAAYpqC,GAC9C,QAAS1xB,EAAQ88D,EAAgB9kE,KAAK4H,OAAS,EAAG8xB,GAClD,YAAa1xB,EAAQkjE,EAAWxxC,GAChC,aAAc1xB,EAAQ08D,EAAe1kE,KAAK2sB,WAAY+M,GACtD,eACA3oB,KAAK,KAMTwpE,oBAAqB,SAASlX,EAAOiX,EAAWzV,EAAgBC,EAAehB,GAE7E,IAAI4W,EAAa16E,KAAKmrD,aAAarqD,KAAK3C,OAAOiC,KAAK6B,OAAOmV,OAAO,CAChEuW,SAAS,EACTrtB,KAAMN,KAAKM,KACXynB,OAAQ/nB,KAAK+nB,OACbllB,KAAM,OACNwoD,aAAcltD,OAAOmN,OAAOC,UAAU8/C,cACrCivB,IAEH,MAAO,CACL,mBAAoBtyE,EAAQ68D,EAAiBf,EAAYpqC,GAAsB,QAC/E1xB,EAAQ88D,EAAgB9kE,KAAK4H,OAAS,EAAG8xB,GAAsB,KAC5D4gD,EAAUnqE,WAAa,gBAAkBmqE,EAAUnqE,WAAWuH,QAAQ,KAAM,KAAQ,KAAO,GAC3F4iE,EAAUhyE,SAAW,cAAgBgyE,EAAUhyE,SAAW,KAAO,GACjEgyE,EAAU7tD,UAAY,eAAiB6tD,EAAU7tD,UAAY,KAAO,GACpE6tD,EAAU5tD,WAAa,gBAAkB4tD,EAAU5tD,WAAa,KAAO,GACvE4tD,EAAUjlB,eAAiB,oBAAsBilB,EAAUjlB,eAAiB,KAAO,GACtF,UAAWqlB,EAAY,KACvBv8E,OAAOiC,KAAK0I,OAAOiP,UAAUsrD,GAC7B,cACAtyD,KAAK,OAvGb,GA8GA,SAAUlM,GAER,aAEA,IAAI1G,EAAS0G,EAAO1G,SAAW0G,EAAO1G,OAAS,IAa/CA,EAAOw8E,QAAUx8E,EAAOiC,KAAK+Y,YAAYhb,EAAO+oE,MAAO/oE,EAAOmD,WAAY,CAOxEuB,KAAM,UAON+3E,SAAU,GASVC,gBAAiB,EAMjBC,cAAe,KAKf/oC,cAAc,EAKdC,iBAAiB,EAMjB+O,cAAc,EAOdwgB,yBAA0BpjE,EAAOsK,KAAK8C,UAAUg2D,yBAAyBnpD,OAAO,SAUhFgB,WAAY,SAASwV,EAAM5tB,GAEzBhB,KAAK8Y,UAAU,aAAc8V,EAAM5tB,GACnChB,KAAK4tD,sBAAsBzvD,EAAOw8E,QAAQI,+BAC1C/6E,KAAK0L,IAAM1L,KAAK0/C,cAAgB1/C,KAAKohD,cAAgBjjD,EAAOiC,KAAKqM,sBAAsBG,WAAW,OAUpGm1D,gBAAiB,SAASr2D,GACpB1L,KAAK8hE,kBAIJp2D,IACHA,EAAMvN,EAAOiC,KAAKqM,sBAAsBG,WAAW,MACnD5M,KAAKgiE,eAAet2D,GACpB1L,KAAKipE,mBAIPjpE,KAAK66E,gBAAkB,EAGvB76E,KAAKiiE,WAAajiE,KAAKkiE,oBAAoBx2D,GAEvC1L,KAAK66E,gBAAkB76E,KAAKsH,OAC9BtH,KAAKyE,KAAK,QAASzE,KAAK66E,iBAI1B76E,KAAKmiE,cACLniE,KAAK4H,OAAS5H,KAAKsiE,eAAe52D,GAClC1L,KAAKk/B,cAUP87C,kBAAmB,WAMjB,IALA,IAAIC,EAAoB,EACpBC,EAAoB,EACpBC,EAAoB,EACpBzkE,EAAoB,GAEfxV,EAAI,EAAGA,EAAIlB,KAAKiiE,WAAWxhE,OAAQS,IACb,OAAzBlB,KAAK4uB,KAAKusD,IAA2B,EAAJj6E,GACnCg6E,EAAoB,EACpBC,IACAF,KAEgC,MAAzBj7E,KAAK4uB,KAAKusD,IAA0B,EAAJj6E,IAEvCg6E,IACAC,KAGFzkE,EAAIxV,GAAK,CAAE4uD,KAAMmrB,EAAe96D,OAAQ+6D,GAExCC,GAAan7E,KAAKiiE,WAAW/gE,GAAGT,OAChCy6E,GAAqBl7E,KAAKiiE,WAAW/gE,GAAGT,OAG1C,OAAOiW,GASTiyD,qBAAsB,SAAShF,EAAWrgC,EAAW0pC,GACnD,GAAIhtE,KAAKo7E,UAAW,CAClB,IAAI1kE,EAAM1W,KAAKo7E,UAAUzX,GACzB,IAAKjtD,EACH,OAAOs2D,EAAqB,GAAM,KAEpCrJ,EAAYjtD,EAAIo5C,KAChBxsB,EAAY5sB,EAAIyJ,OAASmjB,EAE3B,OAAOtjC,KAAK8Y,UAAU,uBAAwB6qD,EAAWrgC,EAAW0pC,IAStEhE,qBAAsB,SAASrF,EAAWrgC,EAAWrnB,GACnD,IAAIvF,EAAM1W,KAAKo7E,UAAUzX,GACzBA,EAAYjtD,EAAIo5C,KAChBxsB,EAAY5sB,EAAIyJ,OAASmjB,EAEzBtjC,KAAK2c,OAAOgnD,GAAWrgC,GAAarnB,GAQtCgxD,wBAAyB,SAAStJ,EAAWrgC,GAC3C,IAAI5sB,EAAM1W,KAAKo7E,UAAUzX,GACzBA,EAAYjtD,EAAIo5C,KAChBxsB,EAAY5sB,EAAIyJ,OAASmjB,SAElBtjC,KAAK2c,OAAOgnD,GAAWrgC,IAOhCwlC,cAAe,SAASnF,GACtB,IAAIjtD,EAAM1W,KAAKo7E,UAAUzX,GACzB,OAAO3jE,KAAK2c,OAAOjG,EAAIo5C,OAQzBiZ,cAAe,SAASpF,EAAW1nD,GACjC,IAAIvF,EAAM1W,KAAKo7E,UAAUzX,GACzB3jE,KAAK2c,OAAOjG,EAAIo5C,MAAQ7zC,GAO1BixD,iBAAkB,SAASvJ,GACzB,IAAIjtD,EAAM1W,KAAKo7E,UAAUzX,UAClB3jE,KAAK2c,OAAOjG,EAAIo5C,OAYzBurB,UAAW,SAAS3vE,EAAKkjB,GACvB,IAAuD1tB,EAAnD+nD,EAAQr6B,EAAKvlB,MAAMrJ,KAAKwhE,YAAa8Z,EAAU,GAEnD,IAAKp6E,EAAI,EAAGA,EAAI+nD,EAAMxoD,OAAQS,IAC5Bo6E,EAAUA,EAAQljE,OAAOpY,KAAKu7E,UAAU7vE,EAAKu9C,EAAM/nD,GAAIA,IAGzD,OAAOo6E,GAaTE,aAAc,SAAS9vE,EAAKkjB,EAAM+0C,EAAWG,GAC3C,IAAIx8D,EAAQ,EACZw8D,EAAaA,GAAc,EAC3B,IAAK,IAAI5iE,EAAI,EAAGC,EAAMytB,EAAKnuB,OAAQS,EAAIC,EAAKD,IAC1CoG,GAAStH,KAAKgqE,gBAAgBt+D,EAAKkjB,EAAK1tB,GAAIyiE,EAAWziE,EAAI4iE,GAE7D,OAAOx8D,GAWTi0E,UAAW,SAAS7vE,EAAKkjB,EAAM+0C,GAc7B,IAbA,IAAIv+B,EAAmB,EACnB6jB,EAAmB,GACnB6G,EAAmB,GACnB+T,EAAmBj1C,EAAKvlB,MAAM,KAC9Bu6D,EAAmB,GACnBzjD,EAAmB,EAEnBs7D,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,GAAkB,EAClBrY,EAAkBvjE,KAAKwjE,yBAElBtiE,EAAI,EAAGA,EAAI2iE,EAAMpjE,OAAQS,IAChC0iE,EAAOC,EAAM3iE,GACbu6E,EAAYz7E,KAAKw7E,aAAa9vE,EAAKk4D,EAAMD,EAAWxjD,GAEpDA,GAAUyjD,EAAKnjE,QAEf2kC,GAAas2C,EAAaD,EAAYlY,IAErBvjE,KAAKsH,QAAUs0E,GAC9B3yB,EAAMroD,KAAKkvD,GAEX1qB,EAAYq2C,EACZG,IAFA9rB,EAAO,KAKP1qB,GAAam+B,EAGVqY,IACH9rB,GA1BmB,KA4BrBA,GAAQ8T,EAER8X,EAAa17E,KAAKw7E,aAAa9vE,EA9BV,IA8BsBi4D,EAAWxjD,GACtDA,IACAy7D,GAAkB,EAEFD,EAAZF,IACFE,EAAmBF,GAUvB,OANAv6E,GAAK+nD,EAAMroD,KAAKkvD,GAEZ6rB,EAAmB37E,KAAK66E,kBAC1B76E,KAAK66E,gBAAkBc,EAAmBpY,GAGrCta,GAQTiZ,oBAAqB,SAASx2D,GAC5BA,EAAMA,GAAO1L,KAAK0L,IAClB,IAAImwE,EAAgB77E,KAAKs1D,UACzBt1D,KAAKo7E,UAAY,KACjB1vE,EAAIU,OACJpM,KAAKgiE,eAAet2D,GACpB1L,KAAKs1D,UAAY,OACjB,IAAIrM,EAAQjpD,KAAKq7E,UAAU3vE,EAAK1L,KAAK4uB,MAKrC,OAJA5uB,KAAKs1D,UAAYumB,EACjBnwE,EAAIc,UACJxM,KAAKiiE,WAAahZ,EAClBjpD,KAAKo7E,UAAYp7E,KAAKg7E,oBACf/xB,GAaTxF,WAAY,SAAS/+C,EAAKrD,GACZ,WAARqD,IACF1E,KAAKyD,IAAI,SAAUsB,KAAKG,IAAI,EAAI7D,IAChCrB,KAAKyD,IAAI,QAAUzD,KAAK2E,IAAI,SAAWtD,QACR,IAArBrB,KAAK87E,YAA8B,EAAI97E,KAAK87E,cACtD97E,KAAK87E,YAAcz6E,IAUvBqnE,oBAAqB,SAASvB,QACE,IAAnBA,IACTA,EAAiBnnE,KAAKmnE,gBAMxB,IAHA,IAAI4U,EAAW/7E,KAAKiiE,WAAWxhE,OAC3Bu7E,EAAW,EAEN96E,EAAI,EAAGA,EAAI66E,EAAU76E,IAAK,CACjC,IACI+6E,EADUj8E,KAAKiiE,WAAW/gE,GACXT,OAEnB,GAAI0mE,GAAkB6U,EAAUC,EAC9B,MAAO,CACLtY,UAAWziE,EACXoiC,UAAW6jC,EAAiB6U,GAIhCA,GAAWC,EAEgB,OAAvBj8E,KAAK4uB,KAAKotD,IAA4C,MAAvBh8E,KAAK4uB,KAAKotD,IAC3CA,IAIJ,MAAO,CACLrY,UAAWoY,EAAW,EACtBz4C,UAAWtjC,KAAKiiE,WAAW8Z,EAAW,GAAGt7E,SAW7CopE,4BAA6B,SAASzG,EAAOwG,GAO3C,IANA,IAAIG,EAAiB,EACjB3F,EAAiB,EACjB6F,EAAiBjqE,KAAK0oE,sBACtBwT,EAAiBl8E,KAAKiiE,WAAWgI,EAAetG,WAAWt6D,MAAM,IACjEw7D,EAAiB7kE,KAAK4kE,mBAAmB5kE,KAAKijE,cAAcjjE,KAAK0L,IAAKu+D,EAAetG,YAEhFziE,EAAI,EAAGA,EAAI+oE,EAAe3mC,UAAWpiC,IAC5CkjE,GAAcpkE,KAAKgqE,gBAAgBhqE,KAAK0L,IAAKwwE,EAAUh7E,GAAI+oE,EAAetG,UAAWziE,GAGvF,IAAKA,EAAI,EAAGA,EAAI+oE,EAAetG,UAAWziE,IACxC6oE,GAAa/pE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKxK,GAS/C,MANyB,WAArB0oE,IACFG,IAAc,EAAI/pE,KAAK2hE,mBAAqB3hE,KAAK+iE,iBAAiB/iE,KAAK0L,IAAKu+D,EAAetG,WACvF3jE,KAAK2sB,WAAa3sB,KAAK0pE,uBAAuBO,EAAetG,UAAWsG,EAAe3mC,YACtF,EAAItjC,KAAK2hE,oBAGT,CACLh6D,IAAKoiE,EACLriE,KAAM08D,EACN0F,SAAUjF,IAIdsX,YAAa,WACX,OAAOp3E,KAAKU,IAAIzF,KAAK46E,SAAU56E,KAAK66E,kBAStCxiD,SAAU,SAASC,GACjB,OAAOt4B,KAAK8Y,UAAU,WAAY,CAAC,YAAYV,OAAOkgB,OAa1Dn6B,EAAOw8E,QAAQrwE,WAAa,SAASrI,EAAQU,EAAUwkD,GACrD,OAAOhpD,EAAOmN,OAAO47C,YAAY,UAAWjlD,EAAQU,EAAUwkD,EAAY,SAO5EhpD,EAAOw8E,QAAQI,4BAA8B,WAC3C,MAAO,CACL16C,IAAI,EACJE,IAAI,EACJD,IAAI,EACJE,IAAI,EACJkX,IAAI,EACJviC,IAAI,EACJqiC,IAAI,EACJC,IAAI,EACJ6S,KAAK,IAleX,CAsesB,oBAAZjsD,QAA0BA,QAAU2B,MAG9C,WAME,IAAIo8E,EAA2Bj+E,OAAO+rC,OAAO3+B,UAAU4mC,gBAEvDh0C,OAAO+rC,OAAO3+B,UAAU4mC,gBAAkB,SAAShB,EAAYpqB,EACZ+qB,EAAcC,EAAcjC,EAAIkC,EAAiBZ,GAElG,IAAIrqC,EAAIggB,EAAUnY,OAClB,KAAI7H,aAAa5I,OAAOw8E,SAQtB,OAAOyB,EAAyBt7E,KAAK3C,OAAO+rC,OAAO3+B,UAAW4lC,EAAYpqB,EACxE+qB,EAAcC,EAAcjC,EAAIkC,EAAiBZ,GARnD,IAAI+f,EAAIpqD,EAAEO,OAAU6pC,EAAW5qC,EAAIwgB,EAAU9Y,QAAWlH,EAAEO,MAAQP,EAAEugC,cACpE,OAAI6pB,GAAKpqD,EAAEo1E,eACTp1E,EAAEtD,IAAI,QAAS0tD,IACR,QAFT,GAgBJhzD,OAAOiqC,MAAM78B,UAAU8wE,2BAA6B,WAClD,QAA8B,IAAnBl+E,OAAOw8E,QAGlB,IAAK,IAAIz5E,EAAIlB,KAAK0B,SAASjB,OAAQS,KACjC,GAAIlB,KAAK0B,SAASR,aAAc/C,OAAOw8E,QAErC,YADA36E,KAAK4tD,sBAAsBzvD,OAAOw8E,QAAQI,gCAMhD58E,OAAOiC,KAAK6B,OAAOmV,OAAOjZ,OAAOw8E,QAAQpvE,UAAgD,CAIvF2lE,wBAAyB,WACvB,IAAK,IAAIxwE,KAAQV,KAAKo7E,UACfp7E,KAAKiiE,WAAWvhE,WACZV,KAAK2c,OAAO3c,KAAKo7E,UAAU16E,GAAMovD,OAW9CyiB,sBAAuB,SAAS5O,EAAWrgC,EAAWrnB,GAEpD,IAAIvF,EAAM1W,KAAKo7E,UAAUzX,GACzBA,EAAYjtD,EAAIo5C,KAChBxsB,EAAY5sB,EAAIyJ,OAASmjB,EAEzBnlC,OAAO+oE,MAAM37D,UAAUgnE,sBAAsB3wE,MAAM5B,KAAM,CAAC2jE,EAAWrgC,EAAWrnB,KASlFg2D,yBAA0B,SAAStO,EAAWrgC,EAAWyuC,GAEvD,IAAIr7D,EAAM1W,KAAKo7E,UAAUzX,GACzBA,EAAYjtD,EAAIo5C,KAChBxsB,EAAY5sB,EAAIyJ,OAASmjB,EAEzBnlC,OAAO+oE,MAAM37D,UAAU0mE,yBAAyBrwE,MAAM5B,KAAM,CAAC2jE,EAAWrgC,EAAWyuC,KAUrFG,gBAAiB,SAASvO,EAAWxjD,GAInCwjD,EAFU3jE,KAAKo7E,UAAUzX,GAET7T,KAChB3xD,OAAO+oE,MAAM37D,UAAU2mE,gBAAgBpxE,KAAKd,KAAM2jE,EAAWxjD,IAU/D4yD,uBAAwB,SAASC,GAG/B,IAFA,IAAIC,EAAqBjzE,KAAKiiE,WAAW+Q,EAAS,GAE3ChzE,KAAKo7E,UAAUpI,EAAS,IAAMhzE,KAAKo7E,UAAUpI,EAAS,GAAGljB,OAAS9vD,KAAKo7E,UAAUpI,EAAS,GAAGljB,MAClGmjB,EAAqBjzE,KAAKiiE,WAAW+Q,EAAS,GAAKC,EAEnDD,IAGF,OAAOC,GAQT1B,kBAAmB,SAASF,EAAmBnvE,GAE7C,IAAI+nE,EAAiBjqE,KAAK0oE,oBAAoBxmE,GAC1CwU,EAAiB1W,KAAKo7E,UAAUnR,EAAetG,WAC/CA,EAAiBjtD,EAAIo5C,KACrBxsB,EAAiB5sB,EAAIyJ,OAAS8pD,EAAe3mC,UACjDtjC,KAAK8yE,mBAAmBzB,EAAmBpH,EAAgBtG,EAAWrgC,MAjI5E,GAuIA,WACE,IAAIg5C,EAAWn+E,OAAO+oE,MAAM37D,UAAUopE,gCAWtCx2E,OAAO+oE,MAAM37D,UAAUopE,gCAAkC,SAASH,EAAaC,EAAWntE,EAAOpF,EAAOmT,GACtGnT,EAAQo6E,EAASx7E,KAAKd,KAAMw0E,EAAaC,EAAWntE,EAAOpF,EAAOmT,GAQlE,IAJA,IAAIknE,EAAU,EACVP,EAAU,EAGL96E,EAAI,EAAGA,EAAIlB,KAAKiiE,WAAWxhE,UAGbyB,IAFrBq6E,GAAOv8E,KAAKiiE,WAAW/gE,GAAGT,QAEhBu7E,GAHgC96E,IAOT,OAA7BlB,KAAK4uB,KAAK2tD,EAAMP,IAAkD,MAA7Bh8E,KAAK4uB,KAAK2tD,EAAMP,IACvDA,IAIJ,OAAO95E,EAAQhB,EAAI86E,GAjCvB,GAsCA,WAEE,GAAwB,oBAAb19E,UAA8C,oBAAXC,OAA9C,CAIA,IAAIkxB,UAAYjxB,QAAQ,UAAUixB,UAC9B+sD,IAAMh+E,QAAQ,OACdi+E,KAAOj+E,QAAQ,QACfk+E,MAAQl+E,QAAQ,SAEhB0rC,OAAS1rC,QAAQ,UACjBo/B,MAAQp/B,QAAQ,UAAUo/B,MA4D9Bz/B,OAAOiC,KAAKkJ,UAAY,SAASC,EAAK5G,EAAUC,GAC9C,SAAS+5E,EAAuBltE,GAC1BA,GACFhG,EAAIK,IAAM,IAAI/K,OAAO0Q,EAAM,UAE3BhG,EAAI+tD,KAAOjuD,EACX5G,GAAYA,EAAS7B,KAAK8B,EAAS6G,KAGnCA,EAAM,KACN9G,GAAYA,EAAS7B,KAAK8B,EAAS,MAAM,IAG7C,IAAI6G,EAAM,IAAIm0B,MACVr0B,IAAQA,aAAexK,QAAkC,IAAxBwK,EAAIpJ,QAAQ,UAC/CsJ,EAAIK,IAAML,EAAI+tD,KAAOjuD,EACrB5G,GAAYA,EAAS7B,KAAK8B,EAAS6G,IAE5BF,GAA+B,IAAxBA,EAAIpJ,QAAQ,QAC1By8E,UAAUrzE,EAAKozE,GAERpzE,EACP2X,QAAQ3X,EAAK,SAAUozE,GAGvBh6E,GAAYA,EAAS7B,KAAK8B,EAAS2G,IAIvCpL,OAAO6wB,eAAiB,SAASzlB,EAAK5G,EAAUqH,GAElB,KAD5BT,EAAMA,EAAImO,QAAQ,SAAU,IAAIA,QAAQ,QAAS,IAAID,QAC7CtX,QAAQ,QACdy8E,UAAUrzE,EAAK,SAASwU,GACtB5f,OAAOqxB,kBAAkBzR,EAAKvS,WAAY7I,EAAUqH,KAItDkX,QAAQ3X,EAAK,GAAI,SAASwU,GACxB5f,OAAOqxB,kBAAkBzR,EAAMpb,EAAUqH,MAK/C7L,OAAOqxB,kBAAoB,SAAS1mB,EAAQnG,EAAUqH,GACpD,IAAIgW,GAAM,IAAIyP,WAAYE,gBAAgB7mB,GAC1C3K,OAAO6sB,iBAAiBhL,EAAIxF,gBAAiB,SAAS8U,EAAStuB,GAC7D2B,GAAYA,EAAS2sB,EAAStuB,IAC7BgJ,IAGL7L,OAAOiC,KAAK0e,UAAY,SAASvV,IAAK5G,UACpCue,QAAQ3X,IAAK,GAAI,SAASwU,MAExB8+D,KAAK9+D,MACLpb,UAAYA,cAgBhBxE,OAAO2+E,oBAAsB,SAASx1E,EAAOM,EAAQ5G,EAAS+7E,GAC5DA,EAAoBA,GAAqB/7E,EAEzC,IAAI0L,EAAWvO,OAAOG,SAASqO,cAAc,UACzCqwE,EAAa,IAAI9yC,OAAO5iC,GAAS,IAAKM,GAAU,IAAKm1E,GACrDE,EAAkB,IAAI/yC,OAAO5iC,GAAS,IAAKM,GAAU,IAAKm1E,GAG9DrwE,EAASuP,MAAQ,GAEjBvP,EAASpF,MAAQ01E,EAAW11E,MAC5BoF,EAAS9E,OAASo1E,EAAWp1E,QAC7B5G,EAAUA,GAAW,IACbg8E,WAAaA,EACrBh8E,EAAQi8E,gBAAkBA,EAC1B,IACIC,EAAe,IADA/+E,OAAO+rC,QAAU/rC,OAAO88B,cACPvuB,EAAU1L,GAM9C,OALAk8E,EAAaF,WAAaA,EAC1BE,EAAaD,gBAAkBA,EAC/BC,EAAahgD,iBAAmB8/C,EAAWpwE,WAAW,MACtDswE,EAAa/uC,aAAe8uC,EAAgBrwE,WAAW,MACvDswE,EAAaC,KAAOjzC,OAAOizC,KACpBD,GAGT,IAAIE,kBAAoBj/E,OAAO88B,aAAa1vB,UAAU6vB,YACtDj9B,OAAO88B,aAAa1vB,UAAU6vB,YAAc,SAAS1d,EAAI1c,GACvD0c,EAAKA,GAAMvf,OAAOG,SAASqO,cAAc,UACzC3M,KAAKg9E,WAAa,IAAI9yC,OAAOxsB,EAAGpW,MAAOoW,EAAG9V,QAC1C5H,KAAKi9E,gBAAkB,IAAI/yC,OAAOxsB,EAAGpW,MAAOoW,EAAG9V,QAC/Cw1E,kBAAkBt8E,KAAKd,KAAM0d,EAAI1c,GACjChB,KAAKk9B,iBAAmBl9B,KAAKg9E,WAAWpwE,WAAW,MACnD5M,KAAKmuC,aAAenuC,KAAKi9E,gBAAgBrwE,WAAW,MACpD5M,KAAKm9E,KAAOjzC,OAAOizC,MAIrBh/E,OAAO88B,aAAa1vB,UAAU8xE,gBAAkB,WAC9C,OAAOr9E,KAAKg9E,WAAWK,mBAGzBl/E,OAAO88B,aAAa1vB,UAAU+xE,iBAAmB,SAAS94D,GACxD,OAAOxkB,KAAKg9E,WAAWM,iBAAiB94D,IAG1CrmB,OAAO88B,aAAa1vB,UAAUkxB,mBAAqB,WACjD,GAAKz8B,KAAK+8B,mBASV,OALA/8B,KAAKi9B,cAAcpf,aAAa,QAAS7d,KAAKsH,MAAQnJ,OAAOuB,kBAC7DM,KAAKi9B,cAAcpf,aAAa,SAAU7d,KAAK4H,OAASzJ,OAAOuB,kBAC/DM,KAAKg9E,WAAW11E,MAAQtH,KAAKsH,MAAQnJ,OAAOuB,iBAC5CM,KAAKg9E,WAAWp1E,OAAS5H,KAAK4H,OAASzJ,OAAOuB,iBAC9CM,KAAKk9B,iBAAiBC,MAAMh/B,OAAOuB,iBAAkBvB,OAAOuB,kBACrDM,MAEL7B,OAAO+rC,SACT/rC,OAAO+rC,OAAO3+B,UAAUkxB,mBAAqBt+B,OAAO88B,aAAa1vB,UAAUkxB,oBAG7E,IAAI8gD,0BAA4Bp/E,OAAO88B,aAAa1vB,UAAUgzB,uBAC9DpgC,OAAO88B,aAAa1vB,UAAUgzB,uBAAyB,SAAS79B,EAAMW,GAGpE,OAFAk8E,0BAA0Bz8E,KAAKd,KAAMU,EAAMW,GAC3CrB,KAAKg9E,WAAWt8E,GAAQW,EACjBrB,MAEL7B,OAAO+rC,SACT/rC,OAAO+rC,OAAO3+B,UAAUgzB,uBAAyBpgC,OAAO88B,aAAa1vB,UAAUgzB,wBAnMjF,SAASrd,QAAQ3X,EAAKy5B,EAAUrgC,GAC9B,IAAI66E,EAAOhB,IAAIruD,MAAM5kB,GAGfi0E,EAAKC,OACTD,EAAKC,KAA6C,IAApCD,EAAKE,SAASv9E,QAAQ,UAAoB,IAAM,IAIhE,IACIw9E,GADkD,IAApCH,EAAKE,SAASv9E,QAAQ,UAAoBu8E,MAAQD,MAC/Cv7D,QAAQ,CACvB08D,SAAUJ,EAAKI,SACfH,KAAMD,EAAKC,KACXzyE,KAAMwyE,EAAKxyE,KACXgM,OAAQ,OACP,SAAS6mE,GACV,IAAI9/D,EAAO,GACPilB,GACF66C,EAASC,YAAY96C,GAEvB66C,EAASl9E,GAAG,MAAO,WACjBgC,EAASob,KAEX8/D,EAASl9E,GAAG,OAAQ,SAAUytB,GACA,MAAxByvD,EAASE,aACXhgE,GAAQqQ,OAKlBuvD,EAAIh9E,GAAG,QAAS,SAAS2c,GACnBA,EAAI0gE,QAAU3e,QAAQ4e,aACxB9/E,OAAO0L,IAAI,uCAAyC2zE,EAAKI,SAAW,IAAMJ,EAAKC,MAG/Et/E,OAAO0L,IAAIyT,EAAI4gE,SAEjBv7E,EAAS,QAGXg7E,EAAI35D,MAIN,SAAS44D,UAAU5xE,EAAMrI,GACdnE,QAAQ,MACd2/E,SAASnzE,EAAM,SAAUsS,EAAK7N,GAC/B,GAAI6N,EAEF,MADAnf,OAAO0L,IAAIyT,GACLA,EAGN3a,EAAS8M,MAnEjB","file":"fabric.js","sourcesContent":["/* build: `node build.js modules=ALL exclude=json,gestures minifier=uglifyjs` */\n /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */\n\nvar fabric = fabric || { version: \"1.7.22\" };\nif (typeof exports !== 'undefined') {\n exports.fabric = fabric;\n}\n\nif (typeof document !== 'undefined' && typeof window !== 'undefined') {\n fabric.document = document;\n fabric.window = window;\n // ensure globality even if entire library were function wrapped (as in Meteor.js packaging system)\n window.fabric = fabric;\n}\nelse {\n // assume we're running under node.js when document/window are not present\n fabric.document = require(\"jsdom\")\n .jsdom(\n decodeURIComponent(\"%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E\")\n );\n\n if (fabric.document.createWindow) {\n fabric.window = fabric.document.createWindow();\n } else {\n fabric.window = fabric.document.parentWindow;\n }\n}\n\n/**\n * True when in environment that supports touch events\n * @type boolean\n */\n\nfabric.isTouchSupported = 'ontouchstart' in fabric.window;\n\n/**\n * True when in environment that's probably Node.js\n * @type boolean\n */\nfabric.isLikelyNode = typeof Buffer !== 'undefined' &&\n typeof window === 'undefined';\n\n/* _FROM_SVG_START_ */\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\nfabric.SHARED_ATTRIBUTES = [\n \"display\",\n \"transform\",\n \"fill\", \"fill-opacity\", \"fill-rule\",\n \"opacity\",\n \"stroke\", \"stroke-dasharray\", \"stroke-linecap\",\n \"stroke-linejoin\", \"stroke-miterlimit\",\n \"stroke-opacity\", \"stroke-width\",\n \"id\"\n];\n/* _FROM_SVG_END_ */\n\n/**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\nfabric.DPI = 96;\nfabric.reNum = '(?:[-+]?(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:e[-+]?\\\\d+)?)';\nfabric.fontPaths = { };\nfabric.iMatrix = [1, 0, 0, 1, 0, 0];\nfabric.canvasModule = 'canvas';\n\n/**\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.perfLimitSizeTotal = 2097152;\n\n/**\n * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.maxCacheSideLimit = 4096;\n\n/**\n * Lowest pixel limit for cache canvases, set at 256PX\n * @since 1.7.14\n * @type Number\n * @default\n */\nfabric.minCacheSideLimit = 256;\n\n/**\n * Cache Object for widths of chars in text rendering.\n */\nfabric.charWidthsCache = { };\n\n/**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\nfabric.devicePixelRatio = fabric.window.devicePixelRatio ||\n fabric.window.webkitDevicePixelRatio ||\n fabric.window.mozDevicePixelRatio ||\n 1;\n\n\n(function() {\n\n /**\n * @private\n * @param {String} eventName\n * @param {Function} handler\n */\n function _removeEventListener(eventName, handler) {\n if (!this.__eventListeners[eventName]) {\n return;\n }\n var eventListener = this.__eventListeners[eventName];\n if (handler) {\n eventListener[eventListener.indexOf(handler)] = false;\n }\n else {\n fabric.util.array.fill(eventListener, false);\n }\n }\n\n /**\n * Observes specified event\n * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)\n * @memberOf fabric.Observable\n * @alias on\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n * @return {Self} thisArg\n * @chainable\n */\n function observe(eventName, handler) {\n if (!this.__eventListeners) {\n this.__eventListeners = { };\n }\n // one object with key/value pairs was passed\n if (arguments.length === 1) {\n for (var prop in eventName) {\n this.on(prop, eventName[prop]);\n }\n }\n else {\n if (!this.__eventListeners[eventName]) {\n this.__eventListeners[eventName] = [];\n }\n this.__eventListeners[eventName].push(handler);\n }\n return this;\n }\n\n /**\n * Stops event observing for a particular event handler. Calling this method\n * without arguments removes all handlers for all events\n * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)\n * @memberOf fabric.Observable\n * @alias off\n * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n * @param {Function} handler Function to be deleted from EventListeners\n * @return {Self} thisArg\n * @chainable\n */\n function stopObserving(eventName, handler) {\n if (!this.__eventListeners) {\n return;\n }\n\n // remove all key/value pairs (event name -> event handler)\n if (arguments.length === 0) {\n for (eventName in this.__eventListeners) {\n _removeEventListener.call(this, eventName);\n }\n }\n // one object with key/value pairs was passed\n else if (arguments.length === 1 && typeof arguments[0] === 'object') {\n for (var prop in eventName) {\n _removeEventListener.call(this, prop, eventName[prop]);\n }\n }\n else {\n _removeEventListener.call(this, eventName, handler);\n }\n return this;\n }\n\n /**\n * Fires event with an optional options object\n * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)\n * @memberOf fabric.Observable\n * @alias trigger\n * @param {String} eventName Event name to fire\n * @param {Object} [options] Options object\n * @return {Self} thisArg\n * @chainable\n */\n function fire(eventName, options) {\n if (!this.__eventListeners) {\n return;\n }\n\n var listenersForEvent = this.__eventListeners[eventName];\n if (!listenersForEvent) {\n return;\n }\n\n for (var i = 0, len = listenersForEvent.length; i < len; i++) {\n listenersForEvent[i] && listenersForEvent[i].call(this, options || { });\n }\n this.__eventListeners[eventName] = listenersForEvent.filter(function(value) {\n return value !== false;\n });\n return this;\n }\n\n /**\n * @namespace fabric.Observable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\n * @see {@link http://fabricjs.com/events|Events demo}\n */\n fabric.Observable = {\n observe: observe,\n stopObserving: stopObserving,\n fire: fire,\n\n on: observe,\n off: stopObserving,\n trigger: fire\n };\n})();\n\n\n/**\n * @namespace fabric.Collection\n */\nfabric.Collection = {\n\n _objects: [],\n\n /**\n * Adds objects to collection, Canvas or Group, then renders canvas\n * (if `renderOnAddRemove` is not `false`).\n * in case of Group no changes to bounding box are made.\n * Objects should be instances of (or inherit from) fabric.Object\n * Use of this function is highly discouraged for groups.\n * you can add a bunch of objects with the add method but then you NEED\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n * @chainable\n */\n add: function () {\n this._objects.push.apply(this._objects, arguments);\n if (this._onObjectAdded) {\n for (var i = 0, length = arguments.length; i < length; i++) {\n this._onObjectAdded(arguments[i]);\n }\n }\n this.renderOnAddRemove && this.renderAll();\n return this;\n },\n\n /**\n * Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)\n * An object should be an instance of (or inherit from) fabric.Object\n * Use of this function is highly discouraged for groups.\n * you can add a bunch of objects with the insertAt method but then you NEED\n * to run a addWithUpdate call for the Group class or position/bbox will be wrong.\n * @param {Object} object Object to insert\n * @param {Number} index Index to insert object at\n * @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs\n * @return {Self} thisArg\n * @chainable\n */\n insertAt: function (object, index, nonSplicing) {\n var objects = this.getObjects();\n if (nonSplicing) {\n objects[index] = object;\n }\n else {\n objects.splice(index, 0, object);\n }\n this._onObjectAdded && this._onObjectAdded(object);\n this.renderOnAddRemove && this.renderAll();\n return this;\n },\n\n /**\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * @param {...fabric.Object} object Zero or more fabric instances\n * @return {Self} thisArg\n * @chainable\n */\n remove: function() {\n var objects = this.getObjects(),\n index, somethingRemoved = false;\n\n for (var i = 0, length = arguments.length; i < length; i++) {\n index = objects.indexOf(arguments[i]);\n\n // only call onObjectRemoved if an object was actually removed\n if (index !== -1) {\n somethingRemoved = true;\n objects.splice(index, 1);\n this._onObjectRemoved && this._onObjectRemoved(arguments[i]);\n }\n }\n\n this.renderOnAddRemove && somethingRemoved && this.renderAll();\n return this;\n },\n\n /**\n * Executes given function for each object in this group\n * @param {Function} callback\n * Callback invoked with current object as first argument,\n * index - as second and an array of all objects - as third.\n * Callback is invoked in a context of Global Object (e.g. `window`)\n * when no `context` argument is given\n *\n * @param {Object} context Context (aka thisObject)\n * @return {Self} thisArg\n * @chainable\n */\n forEachObject: function(callback, context) {\n var objects = this.getObjects();\n for (var i = 0, len = objects.length; i < len; i++) {\n callback.call(context, objects[i], i, objects);\n }\n return this;\n },\n\n /**\n * Returns an array of children objects of this instance\n * Type parameter introduced in 1.3.10\n * @param {String} [type] When specified, only objects of this type are returned\n * @return {Array}\n */\n getObjects: function(type) {\n if (typeof type === 'undefined') {\n return this._objects;\n }\n return this._objects.filter(function(o) {\n return o.type === type;\n });\n },\n\n /**\n * Returns object at specified index\n * @param {Number} index\n * @return {Self} thisArg\n */\n item: function (index) {\n return this.getObjects()[index];\n },\n\n /**\n * Returns true if collection contains no objects\n * @return {Boolean} true if collection is empty\n */\n isEmpty: function () {\n return this.getObjects().length === 0;\n },\n\n /**\n * Returns a size of a collection (i.e: length of an array containing its objects)\n * @return {Number} Collection size\n */\n size: function() {\n return this.getObjects().length;\n },\n\n /**\n * Returns true if collection contains an object\n * @param {Object} object Object to check against\n * @return {Boolean} `true` if collection contains an object\n */\n contains: function(object) {\n return this.getObjects().indexOf(object) > -1;\n },\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity: function () {\n return this.getObjects().reduce(function (memo, current) {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\n};\n\n\n/**\n * @namespace fabric.CommonMethods\n */\nfabric.CommonMethods = {\n\n /**\n * Sets object's properties from options\n * @param {Object} [options] Options object\n */\n _setOptions: function(options) {\n for (var prop in options) {\n this.set(prop, options[prop]);\n }\n },\n\n /**\n * @private\n * @param {Object} [filler] Options object\n * @param {String} [property] property to set the Gradient to\n */\n _initGradient: function(filler, property) {\n if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {\n this.set(property, new fabric.Gradient(filler));\n }\n },\n\n /**\n * @private\n * @param {Object} [filler] Options object\n * @param {String} [property] property to set the Pattern to\n * @param {Function} [callback] callback to invoke after pattern load\n */\n _initPattern: function(filler, property, callback) {\n if (filler && filler.source && !(filler instanceof fabric.Pattern)) {\n this.set(property, new fabric.Pattern(filler, callback));\n }\n else {\n callback && callback();\n }\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initClipping: function(options) {\n if (!options.clipTo || typeof options.clipTo !== 'string') {\n return;\n }\n\n var functionBody = fabric.util.getFunctionBody(options.clipTo);\n if (typeof functionBody !== 'undefined') {\n this.clipTo = new Function('ctx', functionBody);\n }\n },\n\n /**\n * @private\n */\n _setObject: function(obj) {\n for (var prop in obj) {\n this._set(prop, obj[prop]);\n }\n },\n\n /**\n * Sets property to a given value. When changing position/dimension -related properties (left, top, scale, angle, etc.) `set` does not update position of object's borders/controls. If you need to update those, call `setCoords()`.\n * @param {String|Object} key Property name or object (if object, iterate over the object properties)\n * @param {Object|Function} value Property value (if function, the value is passed into it and its return value is used as a new one)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n set: function(key, value) {\n if (typeof key === 'object') {\n this._setObject(key);\n }\n else {\n if (typeof value === 'function' && key !== 'clipTo') {\n this._set(key, value(this.get(key)));\n }\n else {\n this._set(key, value);\n }\n }\n return this;\n },\n\n _set: function(key, value) {\n this[key] = value;\n },\n\n /**\n * Toggles specified property from `true` to `false` or from `false` to `true`\n * @param {String} property Property to toggle\n * @return {fabric.Object} thisArg\n * @chainable\n */\n toggle: function(property) {\n var value = this.get(property);\n if (typeof value === 'boolean') {\n this.set(property, !value);\n }\n return this;\n },\n\n /**\n * Basic getter\n * @param {String} property Property name\n * @return {*} value of a property\n */\n get: function(property) {\n return this[property];\n }\n};\n\n\n(function(global) {\n\n var sqrt = Math.sqrt,\n atan2 = Math.atan2,\n pow = Math.pow,\n abs = Math.abs,\n PiBy180 = Math.PI / 180;\n\n /**\n * @namespace fabric.util\n */\n fabric.util = {\n\n /**\n * Removes value from an array.\n * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n * @static\n * @memberOf fabric.util\n * @param {Array} array\n * @param {*} value\n * @return {Array} original array\n */\n removeFromArray: function(array, value) {\n var idx = array.indexOf(value);\n if (idx !== -1) {\n array.splice(idx, 1);\n }\n return array;\n },\n\n /**\n * Returns random number between 2 specified ones.\n * @static\n * @memberOf fabric.util\n * @param {Number} min lower limit\n * @param {Number} max upper limit\n * @return {Number} random value (between min and max)\n */\n getRandomInt: function(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n },\n\n /**\n * Transforms degrees to radians.\n * @static\n * @memberOf fabric.util\n * @param {Number} degrees value in degrees\n * @return {Number} value in radians\n */\n degreesToRadians: function(degrees) {\n return degrees * PiBy180;\n },\n\n /**\n * Transforms radians to degrees.\n * @static\n * @memberOf fabric.util\n * @param {Number} radians value in radians\n * @return {Number} value in degrees\n */\n radiansToDegrees: function(radians) {\n return radians / PiBy180;\n },\n\n /**\n * Rotates `point` around `origin` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} point The point to rotate\n * @param {fabric.Point} origin The origin of the rotation\n * @param {Number} radians The radians of the angle for the rotation\n * @return {fabric.Point} The new rotated point\n */\n rotatePoint: function(point, origin, radians) {\n point.subtractEquals(origin);\n var v = fabric.util.rotateVector(point, radians);\n return new fabric.Point(v.x, v.y).addEquals(origin);\n },\n\n /**\n * Rotates `vector` with `radians`\n * @static\n * @memberOf fabric.util\n * @param {Object} vector The vector to rotate (x and y)\n * @param {Number} radians The radians of the angle for the rotation\n * @return {Object} The new rotated point\n */\n rotateVector: function(vector, radians) {\n var sin = Math.sin(radians),\n cos = Math.cos(radians),\n rx = vector.x * cos - vector.y * sin,\n ry = vector.x * sin + vector.y * cos;\n return {\n x: rx,\n y: ry\n };\n },\n\n /**\n * Apply transform t to point p\n * @static\n * @memberOf fabric.util\n * @param {fabric.Point} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {fabric.Point} The transformed point\n */\n transformPoint: function(p, t, ignoreOffset) {\n if (ignoreOffset) {\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y,\n t[1] * p.x + t[3] * p.y\n );\n }\n return new fabric.Point(\n t[0] * p.x + t[2] * p.y + t[4],\n t[1] * p.x + t[3] * p.y + t[5]\n );\n },\n\n /**\n * Returns coordinates of points's bounding rectangle (left, top, width, height)\n * @param {Array} points 4 points array\n * @return {Object} Object with left, top, width, height properties\n */\n makeBoundingBoxFromPoints: function(points) {\n var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],\n minX = fabric.util.array.min(xPoints),\n maxX = fabric.util.array.max(xPoints),\n width = Math.abs(minX - maxX),\n yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],\n minY = fabric.util.array.min(yPoints),\n maxY = fabric.util.array.max(yPoints),\n height = Math.abs(minY - maxY);\n\n return {\n left: minX,\n top: minY,\n width: width,\n height: height\n };\n },\n\n /**\n * Invert transformation t\n * @static\n * @memberOf fabric.util\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\n invertTransform: function(t) {\n var a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],\n o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);\n r[4] = -o.x;\n r[5] = -o.y;\n return r;\n },\n\n /**\n * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n * @static\n * @memberOf fabric.util\n * @param {Number|String} number number to operate on\n * @param {Number} fractionDigits number of fraction digits to \"leave\"\n * @return {Number}\n */\n toFixed: function(number, fractionDigits) {\n return parseFloat(Number(number).toFixed(fractionDigits));\n },\n\n /**\n * Converts from attribute value to pixel value if applicable.\n * Returns converted pixels or original value not converted.\n * @param {Number|String} value number to operate on\n * @param {Number} fontSize\n * @return {Number|String}\n */\n parseUnit: function(value, fontSize) {\n var unit = /\\D{0,2}$/.exec(value),\n number = parseFloat(value);\n if (!fontSize) {\n fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n }\n switch (unit[0]) {\n case 'mm':\n return number * fabric.DPI / 25.4;\n\n case 'cm':\n return number * fabric.DPI / 2.54;\n\n case 'in':\n return number * fabric.DPI;\n\n case 'pt':\n return number * fabric.DPI / 72; // or * 4 / 3\n\n case 'pc':\n return number * fabric.DPI / 72 * 12; // or * 16\n\n case 'em':\n return number * fontSize;\n\n default:\n return number;\n }\n },\n\n /**\n * Function which always returns `false`.\n * @static\n * @memberOf fabric.util\n * @return {Boolean}\n */\n falseFunction: function() {\n return false;\n },\n\n /**\n * Returns klass \"Class\" object of given namespace\n * @memberOf fabric.util\n * @param {String} type Type of object (eg. 'circle')\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @return {Object} klass \"Class\"\n */\n getKlass: function(type, namespace) {\n // capitalize first letter only\n type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));\n return fabric.util.resolveNamespace(namespace)[type];\n },\n\n /**\n * Returns object of given namespace\n * @memberOf fabric.util\n * @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'\n * @return {Object} Object for given namespace (default fabric)\n */\n resolveNamespace: function(namespace) {\n if (!namespace) {\n return fabric;\n }\n\n var parts = namespace.split('.'),\n len = parts.length, i,\n obj = global || fabric.window;\n\n for (i = 0; i < len; ++i) {\n obj = obj[parts[i]];\n }\n\n return obj;\n },\n\n /**\n * Loads image element from given url and passes it to a callback\n * @memberOf fabric.util\n * @param {String} url URL representing an image\n * @param {Function} callback Callback; invoked with loaded image\n * @param {*} [context] Context to invoke callback in\n * @param {Object} [crossOrigin] crossOrigin value to set image element to\n */\n loadImage: function(url, callback, context, crossOrigin) {\n if (!url) {\n callback && callback.call(context, url);\n return;\n }\n\n var img = fabric.util.createImage();\n\n /** @ignore */\n img.onload = function () {\n callback && callback.call(context, img);\n img = img.onload = img.onerror = null;\n };\n\n /** @ignore */\n img.onerror = function() {\n fabric.log('Error loading ' + img.src);\n callback && callback.call(context, null, true);\n img = img.onload = img.onerror = null;\n };\n\n // data-urls appear to be buggy with crossOrigin\n // https://github.com/kangax/fabric.js/commit/d0abb90f1cd5c5ef9d2a94d3fb21a22330da3e0a#commitcomment-4513767\n // see https://code.google.com/p/chromium/issues/detail?id=315152\n // https://bugzilla.mozilla.org/show_bug.cgi?id=935069\n if (url.indexOf('data') !== 0 && crossOrigin) {\n img.crossOrigin = crossOrigin;\n }\n\n img.src = url;\n },\n\n /**\n * Creates corresponding fabric instances from their object representations\n * @static\n * @memberOf fabric.util\n * @param {Array} objects Objects to enliven\n * @param {Function} callback Callback to invoke when all objects are created\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @param {Function} reviver Method for further parsing of object elements,\n * called after each fabric object created.\n */\n enlivenObjects: function(objects, callback, namespace, reviver) {\n objects = objects || [];\n\n function onLoaded() {\n if (++numLoadedObjects === numTotalObjects) {\n callback && callback(enlivenedObjects);\n }\n }\n\n var enlivenedObjects = [],\n numLoadedObjects = 0,\n numTotalObjects = objects.length,\n forceAsync = true;\n\n if (!numTotalObjects) {\n callback && callback(enlivenedObjects);\n return;\n }\n\n objects.forEach(function (o, index) {\n // if sparse array\n if (!o || !o.type) {\n onLoaded();\n return;\n }\n var klass = fabric.util.getKlass(o.type, namespace);\n klass.fromObject(o, function (obj, error) {\n error || (enlivenedObjects[index] = obj);\n reviver && reviver(o, obj, error);\n onLoaded();\n }, forceAsync);\n });\n },\n\n /**\n * Create and wait for loading of patterns\n * @static\n * @memberOf fabric.util\n * @param {Array} objects Objects to enliven\n * @param {Function} callback Callback to invoke when all objects are created\n * @param {String} namespace Namespace to get klass \"Class\" object from\n * @param {Function} reviver Method for further parsing of object elements,\n * called after each fabric object created.\n */\n enlivenPatterns: function(patterns, callback) {\n patterns = patterns || [];\n\n function onLoaded() {\n if (++numLoadedPatterns === numPatterns) {\n callback && callback(enlivenedPatterns);\n }\n }\n\n var enlivenedPatterns = [],\n numLoadedPatterns = 0,\n numPatterns = patterns.length;\n\n if (!numPatterns) {\n callback && callback(enlivenedPatterns);\n return;\n }\n\n patterns.forEach(function (p, index) {\n if (p && p.source) {\n new fabric.Pattern(p, function(pattern) {\n enlivenedPatterns[index] = pattern;\n onLoaded();\n });\n }\n else {\n enlivenedPatterns[index] = p;\n onLoaded();\n }\n });\n },\n\n /**\n * Groups SVG elements (usually those retrieved from SVG document)\n * @static\n * @memberOf fabric.util\n * @param {Array} elements SVG elements to group\n * @param {Object} [options] Options object\n * @param {String} path Value to set sourcePath to\n * @return {fabric.Object|fabric.PathGroup}\n */\n groupSVGElements: function(elements, options, path) {\n var object;\n\n object = new fabric.PathGroup(elements, options);\n\n if (typeof path !== 'undefined') {\n object.sourcePath = path;\n }\n return object;\n },\n\n /**\n * Populates an object with properties of another object\n * @static\n * @memberOf fabric.util\n * @param {Object} source Source object\n * @param {Object} destination Destination object\n * @return {Array} properties Propertie names to include\n */\n populateWithProperties: function(source, destination, properties) {\n if (properties && Object.prototype.toString.call(properties) === '[object Array]') {\n for (var i = 0, len = properties.length; i < len; i++) {\n if (properties[i] in source) {\n destination[properties[i]] = source[properties[i]];\n }\n }\n }\n },\n\n /**\n * Draws a dashed line between two points\n *\n * This method is used to draw dashed line around selection area.\n * See dotted stroke in canvas\n *\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x start x coordinate\n * @param {Number} y start y coordinate\n * @param {Number} x2 end x coordinate\n * @param {Number} y2 end y coordinate\n * @param {Array} da dash array pattern\n */\n drawDashedLine: function(ctx, x, y, x2, y2, da) {\n var dx = x2 - x,\n dy = y2 - y,\n len = sqrt(dx * dx + dy * dy),\n rot = atan2(dy, dx),\n dc = da.length,\n di = 0,\n draw = true;\n\n ctx.save();\n ctx.translate(x, y);\n ctx.moveTo(0, 0);\n ctx.rotate(rot);\n\n x = 0;\n while (len > x) {\n x += da[di++ % dc];\n if (x > len) {\n x = len;\n }\n ctx[draw ? 'lineTo' : 'moveTo'](x, 0);\n draw = !draw;\n }\n\n ctx.restore();\n },\n\n /**\n * Creates canvas element and initializes it via excanvas if necessary\n * @static\n * @memberOf fabric.util\n * @param {CanvasElement} [canvasEl] optional canvas element to initialize;\n * when not given, element is created implicitly\n * @return {CanvasElement} initialized canvas element\n */\n createCanvasElement: function(canvasEl) {\n canvasEl || (canvasEl = fabric.document.createElement('canvas'));\n /* eslint-disable camelcase */\n if (!canvasEl.getContext && typeof G_vmlCanvasManager !== 'undefined') {\n G_vmlCanvasManager.initElement(canvasEl);\n }\n /* eslint-enable camelcase */\n return canvasEl;\n },\n\n /**\n * Creates image element (works on client and node)\n * @static\n * @memberOf fabric.util\n * @return {HTMLImageElement} HTML image element\n */\n createImage: function() {\n return fabric.isLikelyNode\n ? new (require('canvas').Image)()\n : fabric.document.createElement('img');\n },\n\n /**\n * Creates accessors (getXXX, setXXX) for a \"class\", based on \"stateProperties\" array\n * @static\n * @memberOf fabric.util\n * @param {Object} klass \"Class\" to create accessors for\n */\n createAccessors: function(klass) {\n var proto = klass.prototype, i, propName,\n capitalizedPropName, setterName, getterName;\n\n for (i = proto.stateProperties.length; i--; ) {\n\n propName = proto.stateProperties[i];\n capitalizedPropName = propName.charAt(0).toUpperCase() + propName.slice(1);\n setterName = 'set' + capitalizedPropName;\n getterName = 'get' + capitalizedPropName;\n\n // using `new Function` for better introspection\n if (!proto[getterName]) {\n proto[getterName] = (function(property) {\n return new Function('return this.get(\"' + property + '\")');\n })(propName);\n }\n if (!proto[setterName]) {\n proto[setterName] = (function(property) {\n return new Function('value', 'return this.set(\"' + property + '\", value)');\n })(propName);\n }\n }\n },\n\n /**\n * @static\n * @memberOf fabric.util\n * @param {fabric.Object} receiver Object implementing `clipTo` method\n * @param {CanvasRenderingContext2D} ctx Context to clip\n */\n clipContext: function(receiver, ctx) {\n ctx.save();\n ctx.beginPath();\n receiver.clipTo(ctx);\n ctx.clip();\n },\n\n /**\n * Multiply matrix A by matrix B to nest transformations\n * @static\n * @memberOf fabric.util\n * @param {Array} a First transformMatrix\n * @param {Array} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {Array} The product of the two transform matrices\n */\n multiplyTransformMatrices: function(a, b, is2x2) {\n // Matrix multiply a * b\n return [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]\n ];\n },\n\n /**\n * Decomposes standard 2x2 matrix into transform componentes\n * @static\n * @memberOf fabric.util\n * @param {Array} a transformMatrix\n * @return {Object} Components of transform\n */\n qrDecompose: function(a) {\n var angle = atan2(a[1], a[0]),\n denom = pow(a[0], 2) + pow(a[1], 2),\n scaleX = sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a [1]) / scaleX,\n skewX = atan2(a[0] * a[2] + a[1] * a [3], denom);\n return {\n angle: angle / PiBy180,\n scaleX: scaleX,\n scaleY: scaleY,\n skewX: skewX / PiBy180,\n skewY: 0,\n translateX: a[4],\n translateY: a[5]\n };\n },\n\n customTransformMatrix: function(scaleX, scaleY, skewX) {\n var skewMatrixX = [1, 0, abs(Math.tan(skewX * PiBy180)), 1],\n scaleMatrix = [abs(scaleX), 0, 0, abs(scaleY)];\n return fabric.util.multiplyTransformMatrices(scaleMatrix, skewMatrixX, true);\n },\n\n resetObjectTransform: function (target) {\n target.scaleX = 1;\n target.scaleY = 1;\n target.skewX = 0;\n target.skewY = 0;\n target.flipX = false;\n target.flipY = false;\n target.setAngle(0);\n },\n\n /**\n * Returns string representation of function body\n * @param {Function} fn Function to get body of\n * @return {String} Function body\n */\n getFunctionBody: function(fn) {\n return (String(fn).match(/function[^{]*\\{([\\s\\S]*)\\}/) || {})[1];\n },\n\n /**\n * Returns true if context has transparent pixel\n * at specified location (taking tolerance into account)\n * @param {CanvasRenderingContext2D} ctx context\n * @param {Number} x x coordinate\n * @param {Number} y y coordinate\n * @param {Number} tolerance Tolerance\n */\n isTransparent: function(ctx, x, y, tolerance) {\n\n // If tolerance is > 0 adjust start coords to take into account.\n // If moves off Canvas fix to 0\n if (tolerance > 0) {\n if (x > tolerance) {\n x -= tolerance;\n }\n else {\n x = 0;\n }\n if (y > tolerance) {\n y -= tolerance;\n }\n else {\n y = 0;\n }\n }\n\n var _isTransparent = true, i, temp,\n imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1),\n l = imageData.data.length;\n\n // Split image data - for tolerance > 1, pixelDataSize = 4;\n for (i = 3; i < l; i += 4) {\n temp = imageData.data[i];\n _isTransparent = temp <= 0;\n if (_isTransparent === false) {\n break; // Stop if colour found\n }\n }\n\n imageData = null;\n\n return _isTransparent;\n },\n\n /**\n * Parse preserveAspectRatio attribute from element\n * @param {string} attribute to be parsed\n * @return {Object} an object containing align and meetOrSlice attribute\n */\n parsePreserveAspectRatioAttribute: function(attribute) {\n var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid',\n aspectRatioAttrs = attribute.split(' '), align;\n\n if (aspectRatioAttrs && aspectRatioAttrs.length) {\n meetOrSlice = aspectRatioAttrs.pop();\n if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {\n align = meetOrSlice;\n meetOrSlice = 'meet';\n }\n else if (aspectRatioAttrs.length) {\n align = aspectRatioAttrs.pop();\n }\n }\n //divide align in alignX and alignY\n alignX = align !== 'none' ? align.slice(1, 4) : 'none';\n alignY = align !== 'none' ? align.slice(5, 8) : 'none';\n return {\n meetOrSlice: meetOrSlice,\n alignX: alignX,\n alignY: alignY\n };\n },\n\n /**\n * Clear char widths cache for a font family.\n * @memberOf fabric.util\n * @param {String} [fontFamily] font family to clear\n */\n clearFabricFontCache: function(fontFamily) {\n if (!fontFamily) {\n fabric.charWidthsCache = { };\n }\n else if (fabric.charWidthsCache[fontFamily]) {\n delete fabric.charWidthsCache[fontFamily];\n }\n },\n\n /**\n * Clear char widths cache for a font family.\n * @memberOf fabric.util\n * @param {Number} ar aspect ratio\n * @param {Number} maximumArea Maximum area you want to achieve\n * @param {Number} maximumSide biggest side allowed\n * @return {Object.x} Limited dimensions by X\n * @return {Object.y} Limited dimensions by Y\n */\n limitDimsByArea: function(ar, maximumArea) {\n var roughWidth = Math.sqrt(maximumArea * ar),\n perfLimitSizeY = Math.floor(maximumArea / roughWidth);\n return { x: Math.floor(roughWidth), y: perfLimitSizeY };\n },\n\n capValue: function(min, value, max) {\n return Math.max(min, Math.min(value, max));\n }\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var arcToSegmentsCache = { },\n segmentToBezierCache = { },\n boundsOfCurveCache = { },\n _join = Array.prototype.join;\n\n /* Adapted from http://dxr.mozilla.org/mozilla-central/source/content/svg/content/src/nsSVGPathDataParser.cpp\n * by Andrea Bogazzi code is under MPL. if you don't have a copy of the license you can take it here\n * http://mozilla.org/MPL/2.0/\n */\n function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {\n var argsString = _join.call(arguments);\n if (arcToSegmentsCache[argsString]) {\n return arcToSegmentsCache[argsString];\n }\n\n var PI = Math.PI, th = rotateX * PI / 180,\n sinTh = Math.sin(th),\n cosTh = Math.cos(th),\n fromX = 0, fromY = 0;\n\n rx = Math.abs(rx);\n ry = Math.abs(ry);\n\n var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,\n py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,\n rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,\n pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,\n root = 0;\n\n if (pl < 0) {\n var s = Math.sqrt(1 - pl / (rx2 * ry2));\n rx *= s;\n ry *= s;\n }\n else {\n root = (large === sweep ? -1.0 : 1.0) *\n Math.sqrt( pl / (rx2 * py2 + ry2 * px2));\n }\n\n var cx = root * rx * py / ry,\n cy = -root * ry * px / rx,\n cx1 = cosTh * cx - sinTh * cy + toX * 0.5,\n cy1 = sinTh * cx + cosTh * cy + toY * 0.5,\n mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),\n dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);\n\n if (sweep === 0 && dtheta > 0) {\n dtheta -= 2 * PI;\n }\n else if (sweep === 1 && dtheta < 0) {\n dtheta += 2 * PI;\n }\n\n // Convert into cubic bezier segments <= 90deg\n var segments = Math.ceil(Math.abs(dtheta / PI * 2)),\n result = [], mDelta = dtheta / segments,\n mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),\n th3 = mTheta + mDelta;\n\n for (var i = 0; i < segments; i++) {\n result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);\n fromX = result[i][4];\n fromY = result[i][5];\n mTheta = th3;\n th3 += mDelta;\n }\n arcToSegmentsCache[argsString] = result;\n return result;\n }\n\n function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {\n var argsString2 = _join.call(arguments);\n if (segmentToBezierCache[argsString2]) {\n return segmentToBezierCache[argsString2];\n }\n\n var costh2 = Math.cos(th2),\n sinth2 = Math.sin(th2),\n costh3 = Math.cos(th3),\n sinth3 = Math.sin(th3),\n toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,\n toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,\n cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),\n cp1Y = fromY + mT * ( -sinTh * rx * sinth2 + cosTh * ry * costh2),\n cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),\n cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);\n\n segmentToBezierCache[argsString2] = [\n cp1X, cp1Y,\n cp2X, cp2Y,\n toX, toY\n ];\n return segmentToBezierCache[argsString2];\n }\n\n /*\n * Private\n */\n function calcVectorAngle(ux, uy, vx, vy) {\n var ta = Math.atan2(uy, ux),\n tb = Math.atan2(vy, vx);\n if (tb >= ta) {\n return tb - ta;\n }\n else {\n return 2 * Math.PI - (ta - tb);\n }\n }\n\n /**\n * Draws arc\n * @param {CanvasRenderingContext2D} ctx\n * @param {Number} fx\n * @param {Number} fy\n * @param {Array} coords\n */\n fabric.util.drawArc = function(ctx, fx, fy, coords) {\n var rx = coords[0],\n ry = coords[1],\n rot = coords[2],\n large = coords[3],\n sweep = coords[4],\n tx = coords[5],\n ty = coords[6],\n segs = [[], [], [], []],\n segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (var i = 0, len = segsNorm.length; i < len; i++) {\n segs[i][0] = segsNorm[i][0] + fx;\n segs[i][1] = segsNorm[i][1] + fy;\n segs[i][2] = segsNorm[i][2] + fx;\n segs[i][3] = segsNorm[i][3] + fy;\n segs[i][4] = segsNorm[i][4] + fx;\n segs[i][5] = segsNorm[i][5] + fy;\n ctx.bezierCurveTo.apply(ctx, segs[i]);\n }\n };\n\n /**\n * Calculate bounding box of a elliptic-arc\n * @param {Number} fx start point of arc\n * @param {Number} fy\n * @param {Number} rx horizontal radius\n * @param {Number} ry vertical radius\n * @param {Number} rot angle of horizontal axe\n * @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points\n * @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction\n * @param {Number} tx end point of arc\n * @param {Number} ty\n */\n fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) {\n\n var fromX = 0, fromY = 0, bound, bounds = [],\n segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (var i = 0, len = segs.length; i < len; i++) {\n bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]);\n bounds.push({ x: bound[0].x + fx, y: bound[0].y + fy });\n bounds.push({ x: bound[1].x + fx, y: bound[1].y + fy });\n fromX = segs[i][4];\n fromY = segs[i][5];\n }\n return bounds;\n };\n\n /**\n * Calculate bounding box of a beziercurve\n * @param {Number} x0 starting point\n * @param {Number} y0\n * @param {Number} x1 first control point\n * @param {Number} y1\n * @param {Number} x2 secondo control point\n * @param {Number} y2\n * @param {Number} x3 end of beizer\n * @param {Number} y3\n */\n // taken from http://jsbin.com/ivomiq/56/edit no credits available for that.\n function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {\n var argsString = _join.call(arguments);\n if (boundsOfCurveCache[argsString]) {\n return boundsOfCurveCache[argsString];\n }\n\n var sqrt = Math.sqrt,\n min = Math.min, max = Math.max,\n abs = Math.abs, tvalues = [],\n bounds = [[], []],\n a, b, c, t, t1, t2, b2ac, sqrtb2ac;\n\n b = 6 * x0 - 12 * x1 + 6 * x2;\n a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;\n c = 3 * x1 - 3 * x0;\n\n for (var i = 0; i < 2; ++i) {\n if (i > 0) {\n b = 6 * y0 - 12 * y1 + 6 * y2;\n a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;\n c = 3 * y1 - 3 * y0;\n }\n\n if (abs(a) < 1e-12) {\n if (abs(b) < 1e-12) {\n continue;\n }\n t = -c / b;\n if (0 < t && t < 1) {\n tvalues.push(t);\n }\n continue;\n }\n b2ac = b * b - 4 * c * a;\n if (b2ac < 0) {\n continue;\n }\n sqrtb2ac = sqrt(b2ac);\n t1 = (-b + sqrtb2ac) / (2 * a);\n if (0 < t1 && t1 < 1) {\n tvalues.push(t1);\n }\n t2 = (-b - sqrtb2ac) / (2 * a);\n if (0 < t2 && t2 < 1) {\n tvalues.push(t2);\n }\n }\n\n var x, y, j = tvalues.length, jlen = j, mt;\n while (j--) {\n t = tvalues[j];\n mt = 1 - t;\n x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);\n bounds[0][j] = x;\n\n y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);\n bounds[1][j] = y;\n }\n\n bounds[0][jlen] = x0;\n bounds[1][jlen] = y0;\n bounds[0][jlen + 1] = x3;\n bounds[1][jlen + 1] = y3;\n var result = [\n {\n x: min.apply(null, bounds[0]),\n y: min.apply(null, bounds[1])\n },\n {\n x: max.apply(null, bounds[0]),\n y: max.apply(null, bounds[1])\n }\n ];\n boundsOfCurveCache[argsString] = result;\n return result;\n }\n\n fabric.util.getBoundsOfCurve = getBoundsOfCurve;\n\n})();\n\n\n(function() {\n\n var slice = Array.prototype.slice;\n\n /* _ES5_COMPAT_START_ */\n\n if (!Array.prototype.indexOf) {\n /**\n * Finds index of an element in an array\n * @param {*} searchElement\n * @return {Number}\n */\n Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\n if (this === void 0 || this === null) {\n throw new TypeError();\n }\n var t = Object(this), len = t.length >>> 0;\n if (len === 0) {\n return -1;\n }\n var n = 0;\n if (arguments.length > 0) {\n n = Number(arguments[1]);\n if (n !== n) { // shortcut for verifying if it's NaN\n n = 0;\n }\n else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {\n n = (n > 0 || -1) * Math.floor(Math.abs(n));\n }\n }\n if (n >= len) {\n return -1;\n }\n var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n for (; k < len; k++) {\n if (k in t && t[k] === searchElement) {\n return k;\n }\n }\n return -1;\n };\n }\n\n if (!Array.prototype.forEach) {\n /**\n * Iterates an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.forEach = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n fn.call(context, this[i], i, this);\n }\n }\n };\n }\n\n if (!Array.prototype.map) {\n /**\n * Returns a result of iterating over an array, invoking callback for each element\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.map = function(fn, context) {\n var result = [];\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n result[i] = fn.call(context, this[i], i, this);\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.every) {\n /**\n * Returns true if a callback returns truthy value for all elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.every = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && !fn.call(context, this[i], i, this)) {\n return false;\n }\n }\n return true;\n };\n }\n\n if (!Array.prototype.some) {\n /**\n * Returns true if a callback returns truthy value for at least one element in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Boolean}\n */\n Array.prototype.some = function(fn, context) {\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this && fn.call(context, this[i], i, this)) {\n return true;\n }\n }\n return false;\n };\n }\n\n if (!Array.prototype.filter) {\n /**\n * Returns the result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @param {Object} [context] Context to invoke callback in\n * @return {Array}\n */\n Array.prototype.filter = function(fn, context) {\n var result = [], val;\n for (var i = 0, len = this.length >>> 0; i < len; i++) {\n if (i in this) {\n val = this[i]; // in case fn mutates this\n if (fn.call(context, val, i, this)) {\n result.push(val);\n }\n }\n }\n return result;\n };\n }\n\n if (!Array.prototype.reduce) {\n /**\n * Returns \"folded\" (reduced) result of iterating over elements in an array\n * @param {Function} fn Callback to invoke for each element\n * @return {*}\n */\n Array.prototype.reduce = function(fn /*, initial*/) {\n var len = this.length >>> 0,\n i = 0,\n rv;\n\n if (arguments.length > 1) {\n rv = arguments[1];\n }\n else {\n do {\n if (i in this) {\n rv = this[i++];\n break;\n }\n // if array contains no values, no initial value to return\n if (++i >= len) {\n throw new TypeError();\n }\n }\n while (true);\n }\n for (; i < len; i++) {\n if (i in this) {\n rv = fn.call(null, rv, this[i], i, this);\n }\n }\n return rv;\n };\n }\n\n /* _ES5_COMPAT_END_ */\n\n /**\n * Invokes method on all items in a given array\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} method Name of a method to invoke\n * @return {Array}\n */\n function invoke(array, method) {\n var args = slice.call(arguments, 2), result = [];\n for (var i = 0, len = array.length; i < len; i++) {\n result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);\n }\n return result;\n }\n\n /**\n * Finds maximum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {*}\n */\n function max(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 >= value2;\n });\n }\n\n /**\n * Finds minimum value in array (not necessarily \"first\" one)\n * @memberOf fabric.util.array\n * @param {Array} array Array to iterate over\n * @param {String} byProperty\n * @return {*}\n */\n function min(array, byProperty) {\n return find(array, byProperty, function(value1, value2) {\n return value1 < value2;\n });\n }\n\n /**\n * @private\n */\n function fill(array, value) {\n var k = array.length;\n while (k--) {\n array[k] = value;\n }\n return array;\n }\n\n /**\n * @private\n */\n function find(array, byProperty, condition) {\n if (!array || array.length === 0) {\n return;\n }\n\n var i = array.length - 1,\n result = byProperty ? array[i][byProperty] : array[i];\n if (byProperty) {\n while (i--) {\n if (condition(array[i][byProperty], result)) {\n result = array[i][byProperty];\n }\n }\n }\n else {\n while (i--) {\n if (condition(array[i], result)) {\n result = array[i];\n }\n }\n }\n return result;\n }\n\n /**\n * @namespace fabric.util.array\n */\n fabric.util.array = {\n fill: fill,\n invoke: invoke,\n min: min,\n max: max\n };\n\n})();\n\n\n(function() {\n /**\n * Copies all enumerable properties of one js object to another\n * Does not clone or extend fabric.Object subclasses.\n * @memberOf fabric.util.object\n * @param {Object} destination Where to copy to\n * @param {Object} source Where to copy from\n * @return {Object}\n */\n\n function extend(destination, source, deep) {\n // JScript DontEnum bug is not taken care of\n // the deep clone is for internal use, is not meant to avoid\n // javascript traps or cloning html element or self referenced objects.\n if (deep) {\n if (!fabric.isLikelyNode && source instanceof Element) {\n // avoid cloning deep images, canvases,\n destination = source;\n }\n else if (source instanceof Array) {\n destination = [];\n for (var i = 0, len = source.length; i < len; i++) {\n destination[i] = extend({ }, source[i], deep);\n }\n }\n else if (source && typeof source === 'object') {\n for (var property in source) {\n if (source.hasOwnProperty(property)) {\n destination[property] = extend({ }, source[property], deep);\n }\n }\n }\n else {\n // this sounds odd for an extend but is ok for recursive use\n destination = source;\n }\n }\n else {\n for (var property in source) {\n destination[property] = source[property];\n }\n }\n return destination;\n }\n\n /**\n * Creates an empty object and copies all enumerable properties of another object to it\n * @memberOf fabric.util.object\n * @param {Object} object Object to clone\n * @return {Object}\n */\n function clone(object, deep) {\n return extend({ }, object, deep);\n }\n\n /** @namespace fabric.util.object */\n fabric.util.object = {\n extend: extend,\n clone: clone\n };\n\n})();\n\n\n(function() {\n\n /* _ES5_COMPAT_START_ */\n if (!String.prototype.trim) {\n /**\n * Trims a string (removing whitespace from the beginning and the end)\n * @function external:String#trim\n * @see String#trim on MDN\n */\n String.prototype.trim = function () {\n // this trim is not fully ES3 or ES5 compliant, but it should cover most cases for now\n return this.replace(/^[\\s\\xA0]+/, '').replace(/[\\s\\xA0]+$/, '');\n };\n }\n /* _ES5_COMPAT_END_ */\n\n /**\n * Camelizes a string\n * @memberOf fabric.util.string\n * @param {String} string String to camelize\n * @return {String} Camelized version of a string\n */\n function camelize(string) {\n return string.replace(/-+(.)?/g, function(match, character) {\n return character ? character.toUpperCase() : '';\n });\n }\n\n /**\n * Capitalizes a string\n * @memberOf fabric.util.string\n * @param {String} string String to capitalize\n * @param {Boolean} [firstLetterOnly] If true only first letter is capitalized\n * and other letters stay untouched, if false first letter is capitalized\n * and other letters are converted to lowercase.\n * @return {String} Capitalized version of a string\n */\n function capitalize(string, firstLetterOnly) {\n return string.charAt(0).toUpperCase() +\n (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());\n }\n\n /**\n * Escapes XML in a string\n * @memberOf fabric.util.string\n * @param {String} string String to escape\n * @return {String} Escaped version of a string\n */\n function escapeXml(string) {\n return string.replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(//g, '>');\n }\n\n /**\n * String utilities\n * @namespace fabric.util.string\n */\n fabric.util.string = {\n camelize: camelize,\n capitalize: capitalize,\n escapeXml: escapeXml\n };\n})();\n\n\n/* _ES5_COMPAT_START_ */\n(function() {\n\n var slice = Array.prototype.slice,\n apply = Function.prototype.apply,\n Dummy = function() { };\n\n if (!Function.prototype.bind) {\n /**\n * Cross-browser approximation of ES5 Function.prototype.bind (not fully spec conforming)\n * @see Function#bind on MDN\n * @param {Object} thisArg Object to bind function to\n * @param {Any[]} Values to pass to a bound function\n * @return {Function}\n */\n Function.prototype.bind = function(thisArg) {\n var _this = this, args = slice.call(arguments, 1), bound;\n if (args.length) {\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, args.concat(slice.call(arguments)));\n };\n }\n else {\n /** @ignore */\n bound = function() {\n return apply.call(_this, this instanceof Dummy ? this : thisArg, arguments);\n };\n }\n Dummy.prototype = this.prototype;\n bound.prototype = new Dummy();\n\n return bound;\n };\n }\n\n})();\n/* _ES5_COMPAT_END_ */\n\n\n(function() {\n\n var slice = Array.prototype.slice, emptyFunction = function() { },\n\n IS_DONTENUM_BUGGY = (function() {\n for (var p in { toString: 1 }) {\n if (p === 'toString') {\n return false;\n }\n }\n return true;\n })(),\n\n /** @ignore */\n addMethods = function(klass, source, parent) {\n for (var property in source) {\n\n if (property in klass.prototype &&\n typeof klass.prototype[property] === 'function' &&\n (source[property] + '').indexOf('callSuper') > -1) {\n\n klass.prototype[property] = (function(property) {\n return function() {\n\n var superclass = this.constructor.superclass;\n this.constructor.superclass = parent;\n var returnValue = source[property].apply(this, arguments);\n this.constructor.superclass = superclass;\n\n if (property !== 'initialize') {\n return returnValue;\n }\n };\n })(property);\n }\n else {\n klass.prototype[property] = source[property];\n }\n\n if (IS_DONTENUM_BUGGY) {\n if (source.toString !== Object.prototype.toString) {\n klass.prototype.toString = source.toString;\n }\n if (source.valueOf !== Object.prototype.valueOf) {\n klass.prototype.valueOf = source.valueOf;\n }\n }\n }\n };\n\n function Subclass() { }\n\n function callSuper(methodName) {\n var parentMethod = null,\n _this = this;\n\n // climb prototype chain to find method not equal to callee's method\n while (_this.constructor.superclass) {\n var superClassMethod = _this.constructor.superclass.prototype[methodName];\n if (_this[methodName] !== superClassMethod) {\n parentMethod = superClassMethod;\n break;\n }\n // eslint-disable-next-line\n _this = _this.constructor.superclass.prototype;\n }\n\n if (!parentMethod) {\n return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);\n }\n\n return (arguments.length > 1)\n ? parentMethod.apply(this, slice.call(arguments, 1))\n : parentMethod.call(this);\n }\n\n /**\n * Helper for creation of \"classes\".\n * @memberOf fabric.util\n * @param {Function} [parent] optional \"Class\" to inherit from\n * @param {Object} [properties] Properties shared by all instances of this class\n * (be careful modifying objects defined here as this would affect all instances)\n */\n function createClass() {\n var parent = null,\n properties = slice.call(arguments, 0);\n\n if (typeof properties[0] === 'function') {\n parent = properties.shift();\n }\n function klass() {\n this.initialize.apply(this, arguments);\n }\n\n klass.superclass = parent;\n klass.subclasses = [];\n\n if (parent) {\n Subclass.prototype = parent.prototype;\n klass.prototype = new Subclass();\n parent.subclasses.push(klass);\n }\n for (var i = 0, length = properties.length; i < length; i++) {\n addMethods(klass, properties[i], parent);\n }\n if (!klass.prototype.initialize) {\n klass.prototype.initialize = emptyFunction;\n }\n klass.prototype.constructor = klass;\n klass.prototype.callSuper = callSuper;\n return klass;\n }\n\n fabric.util.createClass = createClass;\n})();\n\n\n(function () {\n\n var unknown = 'unknown';\n\n /* EVENT HANDLING */\n\n function areHostMethods(object) {\n var methodNames = Array.prototype.slice.call(arguments, 1),\n t, i, len = methodNames.length;\n for (i = 0; i < len; i++) {\n t = typeof object[methodNames[i]];\n if (!(/^(?:function|object|unknown)$/).test(t)) {\n return false;\n }\n }\n return true;\n }\n\n /** @ignore */\n var getElement,\n setElement,\n getUniqueId = (function () {\n var uid = 0;\n return function (element) {\n return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++);\n };\n })();\n\n (function () {\n var elements = { };\n /** @ignore */\n getElement = function (uid) {\n return elements[uid];\n };\n /** @ignore */\n setElement = function (uid, element) {\n elements[uid] = element;\n };\n })();\n\n function createListener(uid, handler) {\n return {\n handler: handler,\n wrappedHandler: createWrappedHandler(uid, handler)\n };\n }\n\n function createWrappedHandler(uid, handler) {\n return function (e) {\n handler.call(getElement(uid), e || fabric.window.event);\n };\n }\n\n function createDispatcher(uid, eventName) {\n return function (e) {\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n handlersForEvent[i].call(this, e || fabric.window.event);\n }\n }\n };\n }\n\n var shouldUseAddListenerRemoveListener = (\n areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') &&\n areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')),\n\n shouldUseAttachEventDetachEvent = (\n areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') &&\n areHostMethods(fabric.window, 'attachEvent', 'detachEvent')),\n\n // IE branch\n listeners = { },\n\n // DOM L0 branch\n handlers = { },\n\n addListener, removeListener;\n\n if (shouldUseAddListenerRemoveListener) {\n /** @ignore */\n addListener = function (element, eventName, handler, options) {\n // since ie10 or ie9 can use addEventListener but they do not support options, i need to check\n element && element.addEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler, options) {\n element && element.removeEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);\n };\n }\n\n else if (shouldUseAttachEventDetachEvent) {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n setElement(uid, element);\n if (!listeners[uid]) {\n listeners[uid] = { };\n }\n if (!listeners[uid][eventName]) {\n listeners[uid][eventName] = [];\n\n }\n var listener = createListener(uid, handler);\n listeners[uid][eventName].push(listener);\n element.attachEvent('on' + eventName, listener.wrappedHandler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element), listener;\n if (listeners[uid] && listeners[uid][eventName]) {\n for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {\n listener = listeners[uid][eventName][i];\n if (listener && listener.handler === handler) {\n element.detachEvent('on' + eventName, listener.wrappedHandler);\n listeners[uid][eventName][i] = null;\n }\n }\n }\n };\n }\n else {\n /** @ignore */\n addListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n if (!handlers[uid]) {\n handlers[uid] = { };\n }\n if (!handlers[uid][eventName]) {\n handlers[uid][eventName] = [];\n var existingHandler = element['on' + eventName];\n if (existingHandler) {\n handlers[uid][eventName].push(existingHandler);\n }\n element['on' + eventName] = createDispatcher(uid, eventName);\n }\n handlers[uid][eventName].push(handler);\n };\n /** @ignore */\n removeListener = function (element, eventName, handler) {\n if (!element) {\n return;\n }\n var uid = getUniqueId(element);\n if (handlers[uid] && handlers[uid][eventName]) {\n var handlersForEvent = handlers[uid][eventName];\n for (var i = 0, len = handlersForEvent.length; i < len; i++) {\n if (handlersForEvent[i] === handler) {\n handlersForEvent.splice(i, 1);\n }\n }\n }\n };\n }\n\n /**\n * Adds an event listener to an element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {String} eventName\n * @param {Function} handler\n */\n fabric.util.addListener = addListener;\n\n /**\n * Removes an event listener from an element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {String} eventName\n * @param {Function} handler\n */\n fabric.util.removeListener = removeListener;\n\n /**\n * Cross-browser wrapper for getting event's coordinates\n * @memberOf fabric.util\n * @param {Event} event Event object\n */\n function getPointer(event) {\n event || (event = fabric.window.event);\n\n var element = event.target ||\n (typeof event.srcElement !== unknown ? event.srcElement : null),\n\n scroll = fabric.util.getScrollLeftTop(element);\n\n return {\n x: pointerX(event) + scroll.left,\n y: pointerY(event) + scroll.top\n };\n }\n\n var pointerX = function(event) {\n // looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)\n // is represented as COM object, with all the consequences, like \"unknown\" type and error on [[Get]]\n // need to investigate later\n return (typeof event.clientX !== unknown ? event.clientX : 0);\n },\n\n pointerY = function(event) {\n return (typeof event.clientY !== unknown ? event.clientY : 0);\n };\n\n function _getPointer(event, pageProp, clientProp) {\n var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches';\n\n return (event[touchProp] && event[touchProp][0]\n ? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]))\n || event[clientProp]\n : event[clientProp]);\n }\n\n if (fabric.isTouchSupported) {\n pointerX = function(event) {\n return _getPointer(event, 'pageX', 'clientX');\n };\n pointerY = function(event) {\n return _getPointer(event, 'pageY', 'clientY');\n };\n }\n\n fabric.util.getPointer = getPointer;\n\n fabric.util.object.extend(fabric.util, fabric.Observable);\n\n})();\n\n\n(function () {\n\n /**\n * Cross-browser wrapper for setting element's style\n * @memberOf fabric.util\n * @param {HTMLElement} element\n * @param {Object} styles\n * @return {HTMLElement} Element that was passed as a first argument\n */\n function setStyle(element, styles) {\n var elementStyle = element.style;\n if (!elementStyle) {\n return element;\n }\n if (typeof styles === 'string') {\n element.style.cssText += ';' + styles;\n return styles.indexOf('opacity') > -1\n ? setOpacity(element, styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1])\n : element;\n }\n for (var property in styles) {\n if (property === 'opacity') {\n setOpacity(element, styles[property]);\n }\n else {\n var normalizedProperty = (property === 'float' || property === 'cssFloat')\n ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')\n : property;\n elementStyle[normalizedProperty] = styles[property];\n }\n }\n return element;\n }\n\n var parseEl = fabric.document.createElement('div'),\n supportsOpacity = typeof parseEl.style.opacity === 'string',\n supportsFilters = typeof parseEl.style.filter === 'string',\n reOpacity = /alpha\\s*\\(\\s*opacity\\s*=\\s*([^\\)]+)\\)/,\n\n /** @ignore */\n setOpacity = function (element) { return element; };\n\n if (supportsOpacity) {\n /** @ignore */\n setOpacity = function(element, value) {\n element.style.opacity = value;\n return element;\n };\n }\n else if (supportsFilters) {\n /** @ignore */\n setOpacity = function(element, value) {\n var es = element.style;\n if (element.currentStyle && !element.currentStyle.hasLayout) {\n es.zoom = 1;\n }\n if (reOpacity.test(es.filter)) {\n value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');\n es.filter = es.filter.replace(reOpacity, value);\n }\n else {\n es.filter += ' alpha(opacity=' + (value * 100) + ')';\n }\n return element;\n };\n }\n\n fabric.util.setStyle = setStyle;\n\n})();\n\n\n(function() {\n\n var _slice = Array.prototype.slice;\n\n /**\n * Takes id and returns an element with that id (if one exists in a document)\n * @memberOf fabric.util\n * @param {String|HTMLElement} id\n * @return {HTMLElement|null}\n */\n function getById(id) {\n return typeof id === 'string' ? fabric.document.getElementById(id) : id;\n }\n\n var sliceCanConvertNodelists,\n /**\n * Converts an array-like object (e.g. arguments or NodeList) to an array\n * @memberOf fabric.util\n * @param {Object} arrayLike\n * @return {Array}\n */\n toArray = function(arrayLike) {\n return _slice.call(arrayLike, 0);\n };\n\n try {\n sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;\n }\n catch (err) { }\n\n if (!sliceCanConvertNodelists) {\n toArray = function(arrayLike) {\n var arr = new Array(arrayLike.length), i = arrayLike.length;\n while (i--) {\n arr[i] = arrayLike[i];\n }\n return arr;\n };\n }\n\n /**\n * Creates specified element with specified attributes\n * @memberOf fabric.util\n * @param {String} tagName Type of an element to create\n * @param {Object} [attributes] Attributes to set on an element\n * @return {HTMLElement} Newly created element\n */\n function makeElement(tagName, attributes) {\n var el = fabric.document.createElement(tagName);\n for (var prop in attributes) {\n if (prop === 'class') {\n el.className = attributes[prop];\n }\n else if (prop === 'for') {\n el.htmlFor = attributes[prop];\n }\n else {\n el.setAttribute(prop, attributes[prop]);\n }\n }\n return el;\n }\n\n /**\n * Adds class to an element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to add class to\n * @param {String} className Class to add to an element\n */\n function addClass(element, className) {\n if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {\n element.className += (element.className ? ' ' : '') + className;\n }\n }\n\n /**\n * Wraps element with another element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to wrap\n * @param {HTMLElement|String} wrapper Element to wrap with\n * @param {Object} [attributes] Attributes to set on a wrapper\n * @return {HTMLElement} wrapper\n */\n function wrapElement(element, wrapper, attributes) {\n if (typeof wrapper === 'string') {\n wrapper = makeElement(wrapper, attributes);\n }\n if (element.parentNode) {\n element.parentNode.replaceChild(wrapper, element);\n }\n wrapper.appendChild(element);\n return wrapper;\n }\n\n /**\n * Returns element scroll offsets\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to operate on\n * @return {Object} Object with left/top values\n */\n function getScrollLeftTop(element) {\n\n var left = 0,\n top = 0,\n docElement = fabric.document.documentElement,\n body = fabric.document.body || {\n scrollLeft: 0, scrollTop: 0\n };\n\n // While loop checks (and then sets element to) .parentNode OR .host\n // to account for ShadowDOM. We still want to traverse up out of ShadowDOM,\n // but the .parentNode of a root ShadowDOM node will always be null, instead\n // it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938\n while (element && (element.parentNode || element.host)) {\n\n // Set element to element parent, or 'host' in case of ShadowDOM\n element = element.parentNode || element.host;\n\n if (element === fabric.document) {\n left = body.scrollLeft || docElement.scrollLeft || 0;\n top = body.scrollTop || docElement.scrollTop || 0;\n }\n else {\n left += element.scrollLeft || 0;\n top += element.scrollTop || 0;\n }\n\n if (element.nodeType === 1 &&\n fabric.util.getElementStyle(element, 'position') === 'fixed') {\n break;\n }\n }\n\n return { left: left, top: top };\n }\n\n /**\n * Returns offset for a given element\n * @function\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to get offset for\n * @return {Object} Object with \"left\" and \"top\" properties\n */\n function getElementOffset(element) {\n var docElem,\n doc = element && element.ownerDocument,\n box = { left: 0, top: 0 },\n offset = { left: 0, top: 0 },\n scrollLeftTop,\n offsetAttributes = {\n borderLeftWidth: 'left',\n borderTopWidth: 'top',\n paddingLeft: 'left',\n paddingTop: 'top'\n };\n\n if (!doc) {\n return offset;\n }\n\n for (var attr in offsetAttributes) {\n offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;\n }\n\n docElem = doc.documentElement;\n if ( typeof element.getBoundingClientRect !== 'undefined' ) {\n box = element.getBoundingClientRect();\n }\n\n scrollLeftTop = getScrollLeftTop(element);\n\n return {\n left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,\n top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top\n };\n }\n\n /**\n * Returns style attribute value of a given element\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to get style attribute for\n * @param {String} attr Style attribute to get for element\n * @return {String} Style attribute value of the given element.\n */\n var getElementStyle;\n if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {\n getElementStyle = function(element, attr) {\n var style = fabric.document.defaultView.getComputedStyle(element, null);\n return style ? style[attr] : undefined;\n };\n }\n else {\n getElementStyle = function(element, attr) {\n var value = element.style[attr];\n if (!value && element.currentStyle) {\n value = element.currentStyle[attr];\n }\n return value;\n };\n }\n\n (function () {\n var style = fabric.document.documentElement.style,\n selectProp = 'userSelect' in style\n ? 'userSelect'\n : 'MozUserSelect' in style\n ? 'MozUserSelect'\n : 'WebkitUserSelect' in style\n ? 'WebkitUserSelect'\n : 'KhtmlUserSelect' in style\n ? 'KhtmlUserSelect'\n : '';\n\n /**\n * Makes element unselectable\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to make unselectable\n * @return {HTMLElement} Element that was passed in\n */\n function makeElementUnselectable(element) {\n if (typeof element.onselectstart !== 'undefined') {\n element.onselectstart = fabric.util.falseFunction;\n }\n if (selectProp) {\n element.style[selectProp] = 'none';\n }\n else if (typeof element.unselectable === 'string') {\n element.unselectable = 'on';\n }\n return element;\n }\n\n /**\n * Makes element selectable\n * @memberOf fabric.util\n * @param {HTMLElement} element Element to make selectable\n * @return {HTMLElement} Element that was passed in\n */\n function makeElementSelectable(element) {\n if (typeof element.onselectstart !== 'undefined') {\n element.onselectstart = null;\n }\n if (selectProp) {\n element.style[selectProp] = '';\n }\n else if (typeof element.unselectable === 'string') {\n element.unselectable = '';\n }\n return element;\n }\n\n fabric.util.makeElementUnselectable = makeElementUnselectable;\n fabric.util.makeElementSelectable = makeElementSelectable;\n })();\n\n (function() {\n\n /**\n * Inserts a script element with a given url into a document; invokes callback, when that script is finished loading\n * @memberOf fabric.util\n * @param {String} url URL of a script to load\n * @param {Function} callback Callback to execute when script is finished loading\n */\n function getScript(url, callback) {\n var headEl = fabric.document.getElementsByTagName('head')[0],\n scriptEl = fabric.document.createElement('script'),\n loading = true;\n\n /** @ignore */\n scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) {\n if (loading) {\n if (typeof this.readyState === 'string' &&\n this.readyState !== 'loaded' &&\n this.readyState !== 'complete') {\n return;\n }\n loading = false;\n callback(e || fabric.window.event);\n scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;\n }\n };\n scriptEl.src = url;\n headEl.appendChild(scriptEl);\n // causes issue in Opera\n // headEl.removeChild(scriptEl);\n }\n\n fabric.util.getScript = getScript;\n })();\n\n fabric.util.getById = getById;\n fabric.util.toArray = toArray;\n fabric.util.makeElement = makeElement;\n fabric.util.addClass = addClass;\n fabric.util.wrapElement = wrapElement;\n fabric.util.getScrollLeftTop = getScrollLeftTop;\n fabric.util.getElementOffset = getElementOffset;\n fabric.util.getElementStyle = getElementStyle;\n\n})();\n\n\n(function() {\n\n function addParamToUrl(url, param) {\n return url + (/\\?/.test(url) ? '&' : '?') + param;\n }\n\n var makeXHR = (function() {\n var factories = [\n function() { return new ActiveXObject('Microsoft.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP'); },\n function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); },\n function() { return new XMLHttpRequest(); }\n ];\n for (var i = factories.length; i--; ) {\n try {\n var req = factories[i]();\n if (req) {\n return factories[i];\n }\n }\n catch (err) { }\n }\n })();\n\n function emptyFn() { }\n\n /**\n * Cross-browser abstraction for sending XMLHttpRequest\n * @memberOf fabric.util\n * @param {String} url URL to send XMLHttpRequest to\n * @param {Object} [options] Options object\n * @param {String} [options.method=\"GET\"]\n * @param {String} [options.parameters] parameters to append to url in GET or in body\n * @param {String} [options.body] body to send with POST or PUT request\n * @param {Function} options.onComplete Callback to invoke when request is completed\n * @return {XMLHttpRequest} request\n */\n function request(url, options) {\n\n options || (options = { });\n\n var method = options.method ? options.method.toUpperCase() : 'GET',\n onComplete = options.onComplete || function() { },\n xhr = makeXHR(),\n body = options.body || options.parameters;\n\n /** @ignore */\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n onComplete(xhr);\n xhr.onreadystatechange = emptyFn;\n }\n };\n\n if (method === 'GET') {\n body = null;\n if (typeof options.parameters === 'string') {\n url = addParamToUrl(url, options.parameters);\n }\n }\n\n xhr.open(method, url, true);\n\n if (method === 'POST' || method === 'PUT') {\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n }\n\n xhr.send(body);\n return xhr;\n }\n\n fabric.util.request = request;\n})();\n\n\n/**\n * Wrapper around `console.log` (when available)\n * @param {*} [values] Values to log\n */\nfabric.log = function() { };\n\n/**\n * Wrapper around `console.warn` (when available)\n * @param {*} [values] Values to log as a warning\n */\nfabric.warn = function() { };\n\n/* eslint-disable */\nif (typeof console !== 'undefined') {\n\n ['log', 'warn'].forEach(function(methodName) {\n\n if (typeof console[methodName] !== 'undefined' &&\n typeof console[methodName].apply === 'function') {\n\n fabric[methodName] = function() {\n return console[methodName].apply(console, arguments);\n };\n }\n });\n}\n/* eslint-enable */\n\n\n(function() {\n\n function noop() {\n return false;\n }\n\n /**\n * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.\n * @memberOf fabric.util\n * @param {Object} [options] Animation options\n * @param {Function} [options.onChange] Callback; invoked on every value change\n * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n * @param {Number} [options.startValue=0] Starting value\n * @param {Number} [options.endValue=100] Ending value\n * @param {Number} [options.byValue=100] Value to modify the property by\n * @param {Function} [options.easing] Easing function\n * @param {Number} [options.duration=500] Duration of change (in ms)\n */\n function animate(options) {\n\n requestAnimFrame(function(timestamp) {\n options || (options = { });\n\n var start = timestamp || +new Date(),\n duration = options.duration || 500,\n finish = start + duration, time,\n onChange = options.onChange || noop,\n abort = options.abort || noop,\n onComplete = options.onComplete || noop,\n easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;},\n startValue = 'startValue' in options ? options.startValue : 0,\n endValue = 'endValue' in options ? options.endValue : 100,\n byValue = options.byValue || endValue - startValue;\n\n options.onStart && options.onStart();\n\n (function tick(ticktime) {\n if (abort()) {\n onComplete(endValue, 1, 1);\n return;\n }\n time = ticktime || +new Date();\n var currentTime = time > finish ? duration : (time - start),\n timePerc = currentTime / duration,\n current = easing(currentTime, startValue, byValue, duration),\n valuePerc = Math.abs((current - startValue) / byValue);\n onChange(current, valuePerc, timePerc);\n if (time > finish) {\n options.onComplete && options.onComplete();\n return;\n }\n requestAnimFrame(tick);\n })(start);\n });\n\n }\n\n var _requestAnimFrame = fabric.window.requestAnimationFrame ||\n fabric.window.webkitRequestAnimationFrame ||\n fabric.window.mozRequestAnimationFrame ||\n fabric.window.oRequestAnimationFrame ||\n fabric.window.msRequestAnimationFrame ||\n function(callback) {\n fabric.window.setTimeout(callback, 1000 / 60);\n };\n\n /**\n * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n * In order to get a precise start time, `requestAnimFrame` should be called as an entry into the method\n * @memberOf fabric.util\n * @param {Function} callback Callback to invoke\n * @param {DOMElement} element optional Element to associate with animation\n */\n function requestAnimFrame() {\n return _requestAnimFrame.apply(fabric.window, arguments);\n }\n\n fabric.util.animate = animate;\n fabric.util.requestAnimFrame = requestAnimFrame;\n\n})();\n\n\n(function() {\n // Calculate an in-between color. Returns a \"rgba()\" string.\n // Credit: Edwin Martin \n // http://www.bitstorm.org/jquery/color-animation/jquery.animate-colors.js\n function calculateColor(begin, end, pos) {\n var color = 'rgba('\n + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','\n + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','\n + parseInt((begin[2] + pos * (end[2] - begin[2])), 10);\n\n color += ',' + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);\n color += ')';\n return color;\n }\n\n /**\n * Changes the color from one to another within certain period of time, invoking callbacks as value is being changed.\n * @memberOf fabric.util\n * @param {String} fromColor The starting color in hex or rgb(a) format.\n * @param {String} toColor The starting color in hex or rgb(a) format.\n * @param {Number} [duration] Duration of change (in ms).\n * @param {Object} [options] Animation options\n * @param {Function} [options.onChange] Callback; invoked on every value change\n * @param {Function} [options.onComplete] Callback; invoked when value change is completed\n * @param {Function} [options.colorEasing] Easing function. Note that this function only take two arguments (currentTime, duration). Thus the regular animation easing functions cannot be used.\n */\n function animateColor(fromColor, toColor, duration, options) {\n var startColor = new fabric.Color(fromColor).getSource(),\n endColor = new fabric.Color(toColor).getSource();\n\n options = options || {};\n\n fabric.util.animate(fabric.util.object.extend(options, {\n duration: duration || 500,\n startValue: startColor,\n endValue: endColor,\n byValue: endColor,\n easing: function (currentTime, startValue, byValue, duration) {\n var posValue = options.colorEasing\n ? options.colorEasing(currentTime, duration)\n : 1 - Math.cos(currentTime / duration * (Math.PI / 2));\n return calculateColor(startValue, byValue, posValue);\n }\n }));\n }\n\n fabric.util.animateColor = animateColor;\n\n})();\n\n\n(function() {\n\n function normalize(a, c, p, s) {\n if (a < Math.abs(c)) {\n a = c;\n s = p / 4;\n }\n else {\n //handle the 0/0 case:\n if (c === 0 && a === 0) {\n s = p / (2 * Math.PI) * Math.asin(1);\n }\n else {\n s = p / (2 * Math.PI) * Math.asin(c / a);\n }\n }\n return { a: a, c: c, p: p, s: s };\n }\n\n function elastic(opts, t, d) {\n return opts.a *\n Math.pow(2, 10 * (t -= 1)) *\n Math.sin( (t * d - opts.s) * (2 * Math.PI) / opts.p );\n }\n\n /**\n * Cubic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutCubic(t, b, c, d) {\n return c * ((t = t / d - 1) * t * t + 1) + b;\n }\n\n /**\n * Cubic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutCubic(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t + b;\n }\n return c / 2 * ((t -= 2) * t * t + 2) + b;\n }\n\n /**\n * Quartic easing in\n * @memberOf fabric.util.ease\n */\n function easeInQuart(t, b, c, d) {\n return c * (t /= d) * t * t * t + b;\n }\n\n /**\n * Quartic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutQuart(t, b, c, d) {\n return -c * ((t = t / d - 1) * t * t * t - 1) + b;\n }\n\n /**\n * Quartic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutQuart(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t * t + b;\n }\n return -c / 2 * ((t -= 2) * t * t * t - 2) + b;\n }\n\n /**\n * Quintic easing in\n * @memberOf fabric.util.ease\n */\n function easeInQuint(t, b, c, d) {\n return c * (t /= d) * t * t * t * t + b;\n }\n\n /**\n * Quintic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutQuint(t, b, c, d) {\n return c * ((t = t / d - 1) * t * t * t * t + 1) + b;\n }\n\n /**\n * Quintic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutQuint(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return c / 2 * t * t * t * t * t + b;\n }\n return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;\n }\n\n /**\n * Sinusoidal easing in\n * @memberOf fabric.util.ease\n */\n function easeInSine(t, b, c, d) {\n return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;\n }\n\n /**\n * Sinusoidal easing out\n * @memberOf fabric.util.ease\n */\n function easeOutSine(t, b, c, d) {\n return c * Math.sin(t / d * (Math.PI / 2)) + b;\n }\n\n /**\n * Sinusoidal easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutSine(t, b, c, d) {\n return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;\n }\n\n /**\n * Exponential easing in\n * @memberOf fabric.util.ease\n */\n function easeInExpo(t, b, c, d) {\n return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\n }\n\n /**\n * Exponential easing out\n * @memberOf fabric.util.ease\n */\n function easeOutExpo(t, b, c, d) {\n return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\n }\n\n /**\n * Exponential easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutExpo(t, b, c, d) {\n if (t === 0) {\n return b;\n }\n if (t === d) {\n return b + c;\n }\n t /= d / 2;\n if (t < 1) {\n return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\n }\n return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\n }\n\n /**\n * Circular easing in\n * @memberOf fabric.util.ease\n */\n function easeInCirc(t, b, c, d) {\n return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\n }\n\n /**\n * Circular easing out\n * @memberOf fabric.util.ease\n */\n function easeOutCirc(t, b, c, d) {\n return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\n }\n\n /**\n * Circular easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutCirc(t, b, c, d) {\n t /= d / 2;\n if (t < 1) {\n return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;\n }\n return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\n }\n\n /**\n * Elastic easing in\n * @memberOf fabric.util.ease\n */\n function easeInElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d;\n if (t === 1) {\n return b + c;\n }\n if (!p) {\n p = d * 0.3;\n }\n var opts = normalize(a, c, p, s);\n return -elastic(opts, t, d) + b;\n }\n\n /**\n * Elastic easing out\n * @memberOf fabric.util.ease\n */\n function easeOutElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d;\n if (t === 1) {\n return b + c;\n }\n if (!p) {\n p = d * 0.3;\n }\n var opts = normalize(a, c, p, s);\n return opts.a * Math.pow(2, -10 * t) * Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) + opts.c + b;\n }\n\n /**\n * Elastic easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutElastic(t, b, c, d) {\n var s = 1.70158, p = 0, a = c;\n if (t === 0) {\n return b;\n }\n t /= d / 2;\n if (t === 2) {\n return b + c;\n }\n if (!p) {\n p = d * (0.3 * 1.5);\n }\n var opts = normalize(a, c, p, s);\n if (t < 1) {\n return -0.5 * elastic(opts, t, d) + b;\n }\n return opts.a * Math.pow(2, -10 * (t -= 1)) *\n Math.sin((t * d - opts.s) * (2 * Math.PI) / opts.p ) * 0.5 + opts.c + b;\n }\n\n /**\n * Backwards easing in\n * @memberOf fabric.util.ease\n */\n function easeInBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n return c * (t /= d) * t * ((s + 1) * t - s) + b;\n }\n\n /**\n * Backwards easing out\n * @memberOf fabric.util.ease\n */\n function easeOutBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\n }\n\n /**\n * Backwards easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutBack(t, b, c, d, s) {\n if (s === undefined) {\n s = 1.70158;\n }\n t /= d / 2;\n if (t < 1) {\n return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;\n }\n return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\n }\n\n /**\n * Bouncing easing in\n * @memberOf fabric.util.ease\n */\n function easeInBounce(t, b, c, d) {\n return c - easeOutBounce (d - t, 0, c, d) + b;\n }\n\n /**\n * Bouncing easing out\n * @memberOf fabric.util.ease\n */\n function easeOutBounce(t, b, c, d) {\n if ((t /= d) < (1 / 2.75)) {\n return c * (7.5625 * t * t) + b;\n }\n else if (t < (2 / 2.75)) {\n return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;\n }\n else if (t < (2.5 / 2.75)) {\n return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;\n }\n else {\n return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;\n }\n }\n\n /**\n * Bouncing easing in and out\n * @memberOf fabric.util.ease\n */\n function easeInOutBounce(t, b, c, d) {\n if (t < d / 2) {\n return easeInBounce (t * 2, 0, c, d) * 0.5 + b;\n }\n return easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\n }\n\n /**\n * Easing functions\n * See Easing Equations by Robert Penner\n * @namespace fabric.util.ease\n */\n fabric.util.ease = {\n\n /**\n * Quadratic easing in\n * @memberOf fabric.util.ease\n */\n easeInQuad: function(t, b, c, d) {\n return c * (t /= d) * t + b;\n },\n\n /**\n * Quadratic easing out\n * @memberOf fabric.util.ease\n */\n easeOutQuad: function(t, b, c, d) {\n return -c * (t /= d) * (t - 2) + b;\n },\n\n /**\n * Quadratic easing in and out\n * @memberOf fabric.util.ease\n */\n easeInOutQuad: function(t, b, c, d) {\n t /= (d / 2);\n if (t < 1) {\n return c / 2 * t * t + b;\n }\n return -c / 2 * ((--t) * (t - 2) - 1) + b;\n },\n\n /**\n * Cubic easing in\n * @memberOf fabric.util.ease\n */\n easeInCubic: function(t, b, c, d) {\n return c * (t /= d) * t * t + b;\n },\n\n easeOutCubic: easeOutCubic,\n easeInOutCubic: easeInOutCubic,\n easeInQuart: easeInQuart,\n easeOutQuart: easeOutQuart,\n easeInOutQuart: easeInOutQuart,\n easeInQuint: easeInQuint,\n easeOutQuint: easeOutQuint,\n easeInOutQuint: easeInOutQuint,\n easeInSine: easeInSine,\n easeOutSine: easeOutSine,\n easeInOutSine: easeInOutSine,\n easeInExpo: easeInExpo,\n easeOutExpo: easeOutExpo,\n easeInOutExpo: easeInOutExpo,\n easeInCirc: easeInCirc,\n easeOutCirc: easeOutCirc,\n easeInOutCirc: easeInOutCirc,\n easeInElastic: easeInElastic,\n easeOutElastic: easeOutElastic,\n easeInOutElastic: easeInOutElastic,\n easeInBack: easeInBack,\n easeOutBack: easeOutBack,\n easeInOutBack: easeInOutBack,\n easeInBounce: easeInBounce,\n easeOutBounce: easeOutBounce,\n easeInOutBounce: easeInOutBounce\n };\n\n})();\n\n\n(function(global) {\n\n 'use strict';\n\n /**\n * @name fabric\n * @namespace\n */\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n parseUnit = fabric.util.parseUnit,\n multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,\n\n reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i,\n reViewBoxTagNames = /^(symbol|image|marker|pattern|view|svg)$/i,\n reNotAllowedAncestors = /^(?:pattern|defs|symbol|metadata|clipPath|mask)$/i,\n reAllowedParents = /^(symbol|g|a|svg)$/i,\n\n attributesMap = {\n cx: 'left',\n x: 'left',\n r: 'radius',\n cy: 'top',\n y: 'top',\n display: 'visible',\n visibility: 'visible',\n transform: 'transformMatrix',\n 'fill-opacity': 'fillOpacity',\n 'fill-rule': 'fillRule',\n 'font-family': 'fontFamily',\n 'font-size': 'fontSize',\n 'font-style': 'fontStyle',\n 'font-weight': 'fontWeight',\n 'stroke-dasharray': 'strokeDashArray',\n 'stroke-linecap': 'strokeLineCap',\n 'stroke-linejoin': 'strokeLineJoin',\n 'stroke-miterlimit': 'strokeMiterLimit',\n 'stroke-opacity': 'strokeOpacity',\n 'stroke-width': 'strokeWidth',\n 'text-decoration': 'textDecoration',\n 'text-anchor': 'originX',\n opacity: 'opacity'\n },\n\n colorAttributes = {\n stroke: 'strokeOpacity',\n fill: 'fillOpacity'\n };\n\n fabric.cssRules = { };\n fabric.gradientDefs = { };\n\n function normalizeAttr(attr) {\n // transform attribute names\n if (attr in attributesMap) {\n return attributesMap[attr];\n }\n return attr;\n }\n\n function normalizeValue(attr, value, parentAttributes, fontSize) {\n var isArray = Object.prototype.toString.call(value) === '[object Array]',\n parsed;\n\n if ((attr === 'fill' || attr === 'stroke') && value === 'none') {\n value = '';\n }\n else if (attr === 'strokeDashArray') {\n if (value === 'none') {\n value = null;\n }\n else {\n value = value.replace(/,/g, ' ').split(/\\s+/).map(function(n) {\n return parseFloat(n);\n });\n }\n }\n else if (attr === 'transformMatrix') {\n if (parentAttributes && parentAttributes.transformMatrix) {\n value = multiplyTransformMatrices(\n parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));\n }\n else {\n value = fabric.parseTransformAttribute(value);\n }\n }\n else if (attr === 'visible') {\n value = (value === 'none' || value === 'hidden') ? false : true;\n // display=none on parent element always takes precedence over child element\n if (parentAttributes && parentAttributes.visible === false) {\n value = false;\n }\n }\n else if (attr === 'opacity') {\n value = parseFloat(value);\n if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\n value *= parentAttributes.opacity;\n }\n }\n else if (attr === 'originX' /* text-anchor */) {\n value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';\n }\n else {\n parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);\n }\n\n return (!isArray && isNaN(parsed) ? value : parsed);\n }\n\n /**\n * @private\n * @param {Object} attributes Array of attributes to parse\n */\n function _setStrokeFillOpacity(attributes) {\n for (var attr in colorAttributes) {\n\n if (typeof attributes[colorAttributes[attr]] === 'undefined' || attributes[attr] === '') {\n continue;\n }\n\n if (typeof attributes[attr] === 'undefined') {\n if (!fabric.Object.prototype[attr]) {\n continue;\n }\n attributes[attr] = fabric.Object.prototype[attr];\n }\n\n if (attributes[attr].indexOf('url(') === 0) {\n continue;\n }\n\n var color = new fabric.Color(attributes[attr]);\n attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();\n }\n return attributes;\n }\n\n /**\n * @private\n */\n function _getMultipleNodes(doc, nodeNames) {\n var nodeName, nodeArray = [], nodeList;\n for (var i = 0; i < nodeNames.length; i++) {\n nodeName = nodeNames[i];\n nodeList = doc.getElementsByTagName(nodeName);\n nodeArray = nodeArray.concat(Array.prototype.slice.call(nodeList));\n }\n return nodeArray;\n }\n\n /**\n * Parses \"transform\" attribute, returning an array of values\n * @static\n * @function\n * @memberOf fabric\n * @param {String} attributeValue String containing attribute value\n * @return {Array} Array of 6 elements representing transformation matrix\n */\n fabric.parseTransformAttribute = (function() {\n function rotateMatrix(matrix, args) {\n var cos = Math.cos(args[0]), sin = Math.sin(args[0]),\n x = 0, y = 0;\n if (args.length === 3) {\n x = args[1];\n y = args[2];\n }\n\n matrix[0] = cos;\n matrix[1] = sin;\n matrix[2] = -sin;\n matrix[3] = cos;\n matrix[4] = x - (cos * x - sin * y);\n matrix[5] = y - (sin * x + cos * y);\n }\n\n function scaleMatrix(matrix, args) {\n var multiplierX = args[0],\n multiplierY = (args.length === 2) ? args[1] : args[0];\n\n matrix[0] = multiplierX;\n matrix[3] = multiplierY;\n }\n\n function skewMatrix(matrix, args, pos) {\n matrix[pos] = Math.tan(fabric.util.degreesToRadians(args[0]));\n }\n\n function translateMatrix(matrix, args) {\n matrix[4] = args[0];\n if (args.length === 2) {\n matrix[5] = args[1];\n }\n }\n\n // identity matrix\n var iMatrix = [\n 1, // a\n 0, // b\n 0, // c\n 1, // d\n 0, // e\n 0 // f\n ],\n\n // == begin transform regexp\n number = fabric.reNum,\n\n commaWsp = '(?:\\\\s+,?\\\\s*|,\\\\s*)',\n\n skewX = '(?:(skewX)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n skewY = '(?:(skewY)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*\\\\))',\n\n rotate = '(?:(rotate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + ')' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n scale = '(?:(scale)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n translate = '(?:(translate)\\\\s*\\\\(\\\\s*(' + number + ')(?:' +\n commaWsp + '(' + number + '))?\\\\s*\\\\))',\n\n matrix = '(?:(matrix)\\\\s*\\\\(\\\\s*' +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' + commaWsp +\n '(' + number + ')' +\n '\\\\s*\\\\))',\n\n transform = '(?:' +\n matrix + '|' +\n translate + '|' +\n scale + '|' +\n rotate + '|' +\n skewX + '|' +\n skewY +\n ')',\n\n transforms = '(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')',\n\n transformList = '^\\\\s*(?:' + transforms + '?)\\\\s*$',\n\n // http://www.w3.org/TR/SVG/coords.html#TransformAttribute\n reTransformList = new RegExp(transformList),\n // == end transform regexp\n\n reTransform = new RegExp(transform, 'g');\n\n return function(attributeValue) {\n\n // start with identity matrix\n var matrix = iMatrix.concat(),\n matrices = [];\n\n // return if no argument was given or\n // an argument does not match transform attribute regexp\n if (!attributeValue || (attributeValue && !reTransformList.test(attributeValue))) {\n return matrix;\n }\n\n attributeValue.replace(reTransform, function(match) {\n\n var m = new RegExp(transform).exec(match).filter(function (match) {\n // match !== '' && match != null\n return (!!match);\n }),\n operation = m[1],\n args = m.slice(2).map(parseFloat);\n\n switch (operation) {\n case 'translate':\n translateMatrix(matrix, args);\n break;\n case 'rotate':\n args[0] = fabric.util.degreesToRadians(args[0]);\n rotateMatrix(matrix, args);\n break;\n case 'scale':\n scaleMatrix(matrix, args);\n break;\n case 'skewX':\n skewMatrix(matrix, args, 2);\n break;\n case 'skewY':\n skewMatrix(matrix, args, 1);\n break;\n case 'matrix':\n matrix = args;\n break;\n }\n\n // snapshot current matrix into matrices array\n matrices.push(matrix.concat());\n // reset\n matrix = iMatrix.concat();\n });\n\n var combinedMatrix = matrices[0];\n while (matrices.length > 1) {\n matrices.shift();\n combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);\n }\n return combinedMatrix;\n };\n })();\n\n /**\n * @private\n */\n function parseStyleString(style, oStyle) {\n var attr, value;\n style.replace(/;\\s*$/, '').split(';').forEach(function (chunk) {\n var pair = chunk.split(':');\n\n attr = pair[0].trim().toLowerCase();\n value = pair[1].trim();\n\n oStyle[attr] = value;\n });\n }\n\n /**\n * @private\n */\n function parseStyleObject(style, oStyle) {\n var attr, value;\n for (var prop in style) {\n if (typeof style[prop] === 'undefined') {\n continue;\n }\n\n attr = prop.toLowerCase();\n value = style[prop];\n\n oStyle[attr] = value;\n }\n }\n\n /**\n * @private\n */\n function getGlobalStylesForElement(element, svgUid) {\n var styles = { };\n for (var rule in fabric.cssRules[svgUid]) {\n if (elementMatchesRule(element, rule.split(' '))) {\n for (var property in fabric.cssRules[svgUid][rule]) {\n styles[property] = fabric.cssRules[svgUid][rule][property];\n }\n }\n }\n return styles;\n }\n\n /**\n * @private\n */\n function elementMatchesRule(element, selectors) {\n var firstMatching, parentMatching = true;\n //start from rightmost selector.\n firstMatching = selectorMatches(element, selectors.pop());\n if (firstMatching && selectors.length) {\n parentMatching = doesSomeParentMatch(element, selectors);\n }\n return firstMatching && parentMatching && (selectors.length === 0);\n }\n\n function doesSomeParentMatch(element, selectors) {\n var selector, parentMatching = true;\n while (element.parentNode && element.parentNode.nodeType === 1 && selectors.length) {\n if (parentMatching) {\n selector = selectors.pop();\n }\n element = element.parentNode;\n parentMatching = selectorMatches(element, selector);\n }\n return selectors.length === 0;\n }\n\n /**\n * @private\n */\n function selectorMatches(element, selector) {\n var nodeName = element.nodeName,\n classNames = element.getAttribute('class'),\n id = element.getAttribute('id'), matcher;\n // i check if a selector matches slicing away part from it.\n // if i get empty string i should match\n matcher = new RegExp('^' + nodeName, 'i');\n selector = selector.replace(matcher, '');\n if (id && selector.length) {\n matcher = new RegExp('#' + id + '(?![a-zA-Z\\\\-]+)', 'i');\n selector = selector.replace(matcher, '');\n }\n if (classNames && selector.length) {\n classNames = classNames.split(' ');\n for (var i = classNames.length; i--;) {\n matcher = new RegExp('\\\\.' + classNames[i] + '(?![a-zA-Z\\\\-]+)', 'i');\n selector = selector.replace(matcher, '');\n }\n }\n return selector.length === 0;\n }\n\n /**\n * @private\n * to support IE8 missing getElementById on SVGdocument\n */\n function elementById(doc, id) {\n var el;\n doc.getElementById && (el = doc.getElementById(id));\n if (el) {\n return el;\n }\n var node, i, nodelist = doc.getElementsByTagName('*');\n for (i = 0; i < nodelist.length; i++) {\n node = nodelist[i];\n if (id === node.getAttribute('id')) {\n return node;\n }\n }\n }\n\n /**\n * @private\n */\n function parseUseDirectives(doc) {\n var nodelist = _getMultipleNodes(doc, ['use', 'svg:use']), i = 0;\n\n while (nodelist.length && i < nodelist.length) {\n var el = nodelist[i],\n xlink = el.getAttribute('xlink:href').substr(1),\n x = el.getAttribute('x') || 0,\n y = el.getAttribute('y') || 0,\n el2 = elementById(doc, xlink).cloneNode(true),\n currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')',\n parentNode, oldLength = nodelist.length, attr, j, attrs, l;\n\n applyViewboxTransform(el2);\n if (/^svg$/i.test(el2.nodeName)) {\n var el3 = el2.ownerDocument.createElement('g');\n for (j = 0, attrs = el2.attributes, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n el3.setAttribute(attr.nodeName, attr.nodeValue);\n }\n // el2.firstChild != null\n while (el2.firstChild) {\n el3.appendChild(el2.firstChild);\n }\n el2 = el3;\n }\n\n for (j = 0, attrs = el.attributes, l = attrs.length; j < l; j++) {\n attr = attrs.item(j);\n if (attr.nodeName === 'x' || attr.nodeName === 'y' || attr.nodeName === 'xlink:href') {\n continue;\n }\n\n if (attr.nodeName === 'transform') {\n currentTrans = attr.nodeValue + ' ' + currentTrans;\n }\n else {\n el2.setAttribute(attr.nodeName, attr.nodeValue);\n }\n }\n\n el2.setAttribute('transform', currentTrans);\n el2.setAttribute('instantiated_by_use', '1');\n el2.removeAttribute('id');\n parentNode = el.parentNode;\n parentNode.replaceChild(el2, el);\n // some browsers do not shorten nodelist after replaceChild (IE8)\n if (nodelist.length === oldLength) {\n i++;\n }\n }\n }\n\n // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\n // matches, e.g.: +14.56e-12, etc.\n var reViewBoxAttrValue = new RegExp(\n '^' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*,?' +\n '\\\\s*(' + fabric.reNum + '+)\\\\s*' +\n '$'\n );\n\n /**\n * Add a element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\n */\n function applyViewboxTransform(element) {\n\n var viewBoxAttr = element.getAttribute('viewBox'),\n scaleX = 1,\n scaleY = 1,\n minX = 0,\n minY = 0,\n viewBoxWidth, viewBoxHeight, matrix, el,\n widthAttr = element.getAttribute('width'),\n heightAttr = element.getAttribute('height'),\n x = element.getAttribute('x') || 0,\n y = element.getAttribute('y') || 0,\n preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',\n missingViewBox = (!viewBoxAttr || !reViewBoxTagNames.test(element.nodeName)\n || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),\n missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),\n toBeParsed = missingViewBox && missingDimAttr,\n parsedDim = { }, translateMatrix = '';\n\n parsedDim.width = 0;\n parsedDim.height = 0;\n parsedDim.toBeParsed = toBeParsed;\n\n if (toBeParsed) {\n return parsedDim;\n }\n\n if (missingViewBox) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n return parsedDim;\n }\n\n minX = -parseFloat(viewBoxAttr[1]);\n minY = -parseFloat(viewBoxAttr[2]);\n viewBoxWidth = parseFloat(viewBoxAttr[3]);\n viewBoxHeight = parseFloat(viewBoxAttr[4]);\n\n if (!missingDimAttr) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n scaleX = parsedDim.width / viewBoxWidth;\n scaleY = parsedDim.height / viewBoxHeight;\n }\n else {\n parsedDim.width = viewBoxWidth;\n parsedDim.height = viewBoxHeight;\n }\n\n // default is to preserve aspect ratio\n preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio);\n if (preserveAspectRatio.alignX !== 'none') {\n //translate all container for the effect of Mid, Min, Max\n scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX);\n }\n\n if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) {\n return parsedDim;\n }\n\n if (x || y) {\n translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') ';\n }\n\n matrix = translateMatrix + ' matrix(' + scaleX +\n ' 0' +\n ' 0 ' +\n scaleY + ' ' +\n (minX * scaleX) + ' ' +\n (minY * scaleY) + ') ';\n\n if (element.nodeName === 'svg') {\n el = element.ownerDocument.createElement('g');\n // element.firstChild != null\n while (element.firstChild) {\n el.appendChild(element.firstChild);\n }\n element.appendChild(el);\n }\n else {\n el = element;\n matrix = el.getAttribute('transform') + matrix;\n }\n\n el.setAttribute('transform', matrix);\n return parsedDim;\n }\n\n function hasAncestorWithNodeName(element, nodeName) {\n while (element && (element = element.parentNode)) {\n if (element.nodeName && nodeName.test(element.nodeName.replace('svg:', ''))\n && !element.getAttribute('instantiated_by_use')) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @param {Function} callback Callback to call when parsing is finished;\n * It's being passed an array of elements (parsed from a document).\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [parsingOptions] options for parsing document\n * @param {String} [parsingOptions.crossOrigin] crossOrigin settings\n */\n fabric.parseSVGDocument = function(doc, callback, reviver, parsingOptions) {\n if (!doc) {\n return;\n }\n\n parseUseDirectives(doc);\n\n var svgUid = fabric.Object.__uid++,\n options = applyViewboxTransform(doc),\n descendants = fabric.util.toArray(doc.getElementsByTagName('*'));\n options.crossOrigin = parsingOptions && parsingOptions.crossOrigin;\n options.svgUid = svgUid;\n\n if (descendants.length === 0 && fabric.isLikelyNode) {\n // we're likely in node, where \"o3-xml\" library fails to gEBTN(\"*\")\n // https://github.com/ajaxorg/node-o3-xml/issues/21\n descendants = doc.selectNodes('//*[name(.)!=\"svg\"]');\n var arr = [];\n for (var i = 0, len = descendants.length; i < len; i++) {\n arr[i] = descendants[i];\n }\n descendants = arr;\n }\n\n var elements = descendants.filter(function(el) {\n applyViewboxTransform(el);\n return reAllowedSVGTagNames.test(el.nodeName.replace('svg:', '')) &&\n !hasAncestorWithNodeName(el, reNotAllowedAncestors); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n });\n\n if (!elements || (elements && !elements.length)) {\n callback && callback([], {});\n return;\n }\n\n fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);\n fabric.cssRules[svgUid] = fabric.getCSSRules(doc);\n // Precedence of rules: style > class > attribute\n fabric.parseElements(elements, function(instances) {\n if (callback) {\n callback(instances, options);\n }\n }, clone(options), reviver, parsingOptions);\n };\n\n var reFontDeclaration = new RegExp(\n '(normal|italic)?\\\\s*(normal|small-caps)?\\\\s*' +\n '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\\\s*(' +\n fabric.reNum +\n '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' + fabric.reNum + '))?\\\\s+(.*)');\n\n extend(fabric, {\n /**\n * Parses a short font declaration, building adding its properties to a style object\n * @static\n * @function\n * @memberOf fabric\n * @param {String} value font declaration\n * @param {Object} oStyle definition\n */\n parseFontDeclaration: function(value, oStyle) {\n var match = value.match(reFontDeclaration);\n\n if (!match) {\n return;\n }\n var fontStyle = match[1],\n // font variant is not used\n // fontVariant = match[2],\n fontWeight = match[3],\n fontSize = match[4],\n lineHeight = match[5],\n fontFamily = match[6];\n\n if (fontStyle) {\n oStyle.fontStyle = fontStyle;\n }\n if (fontWeight) {\n oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);\n }\n if (fontSize) {\n oStyle.fontSize = parseUnit(fontSize);\n }\n if (fontFamily) {\n oStyle.fontFamily = fontFamily;\n }\n if (lineHeight) {\n oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;\n }\n },\n\n /**\n * Parses an SVG document, returning all of the gradient declarations found in it\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\n */\n getGradientDefs: function(doc) {\n var tagArray = [\n 'linearGradient',\n 'radialGradient',\n 'svg:linearGradient',\n 'svg:radialGradient'],\n elList = _getMultipleNodes(doc, tagArray),\n el, j = 0, id, xlink,\n gradientDefs = { }, idsToXlinkMap = { };\n\n j = elList.length;\n\n while (j--) {\n el = elList[j];\n xlink = el.getAttribute('xlink:href');\n id = el.getAttribute('id');\n if (xlink) {\n idsToXlinkMap[id] = xlink.substr(1);\n }\n gradientDefs[id] = el;\n }\n\n for (id in idsToXlinkMap) {\n var el2 = gradientDefs[idsToXlinkMap[id]].cloneNode(true);\n el = gradientDefs[id];\n while (el2.firstChild) {\n el.appendChild(el2.firstChild);\n }\n }\n return gradientDefs;\n },\n\n /**\n * Returns an object of attributes' name/value, given element and an array of attribute names;\n * Parses parent \"g\" nodes recursively upwards.\n * @static\n * @memberOf fabric\n * @param {DOMElement} element Element to parse\n * @param {Array} attributes Array of attributes to parse\n * @return {Object} object containing parsed attributes' names/values\n */\n parseAttributes: function(element, attributes, svgUid) {\n\n if (!element) {\n return;\n }\n\n var value,\n parentAttributes = { },\n fontSize;\n\n if (typeof svgUid === 'undefined') {\n svgUid = element.getAttribute('svgUid');\n }\n // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\n if (element.parentNode && reAllowedParents.test(element.parentNode.nodeName)) {\n parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);\n }\n fontSize = (parentAttributes && parentAttributes.fontSize ) ||\n element.getAttribute('font-size') || fabric.Text.DEFAULT_SVG_FONT_SIZE;\n\n var ownAttributes = attributes.reduce(function(memo, attr) {\n value = element.getAttribute(attr);\n if (value) { // eslint-disable-line\n memo[attr] = value;\n }\n return memo;\n }, { });\n // add values parsed from style, which take precedence over attributes\n // (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)\n ownAttributes = extend(ownAttributes,\n extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element)));\n\n var normalizedAttr, normalizedValue, normalizedStyle = {};\n for (var attr in ownAttributes) {\n normalizedAttr = normalizeAttr(attr);\n normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);\n normalizedStyle[normalizedAttr] = normalizedValue;\n }\n if (normalizedStyle && normalizedStyle.font) {\n fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);\n }\n var mergedAttrs = extend(parentAttributes, normalizedStyle);\n return reAllowedParents.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);\n },\n\n /**\n * Transforms an array of svg elements to corresponding fabric.* instances\n * @static\n * @memberOf fabric\n * @param {Array} elements Array of elements to parse\n * @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)\n * @param {Object} [options] Options object\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n */\n parseElements: function(elements, callback, options, reviver, parsingOptions) {\n new fabric.ElementsParser(elements, callback, options, reviver, parsingOptions).parse();\n },\n\n /**\n * Parses \"style\" attribute, retuning an object with values\n * @static\n * @memberOf fabric\n * @param {SVGElement} element Element to parse\n * @return {Object} Objects with values parsed from style attribute of an element\n */\n parseStyleAttribute: function(element) {\n var oStyle = { },\n style = element.getAttribute('style');\n\n if (!style) {\n return oStyle;\n }\n\n if (typeof style === 'string') {\n parseStyleString(style, oStyle);\n }\n else {\n parseStyleObject(style, oStyle);\n }\n\n return oStyle;\n },\n\n /**\n * Parses \"points\" attribute, returning an array of values\n * @static\n * @memberOf fabric\n * @param {String} points points attribute string\n * @return {Array} array of points\n */\n parsePointsAttribute: function(points) {\n\n // points attribute is required and must not be empty\n if (!points) {\n return null;\n }\n\n // replace commas with whitespace and remove bookending whitespace\n points = points.replace(/,/g, ' ').trim();\n\n points = points.split(/\\s+/);\n var parsedPoints = [], i, len;\n\n i = 0;\n len = points.length;\n for (; i < len; i += 2) {\n parsedPoints.push({\n x: parseFloat(points[i]),\n y: parseFloat(points[i + 1])\n });\n }\n\n // odd number of points is an error\n // if (parsedPoints.length % 2 !== 0) {\n // return null;\n // }\n\n return parsedPoints;\n },\n\n /**\n * Returns CSS rules for a given SVG document\n * @static\n * @function\n * @memberOf fabric\n * @param {SVGDocument} doc SVG document to parse\n * @return {Object} CSS rules of this document\n */\n getCSSRules: function(doc) {\n var styles = doc.getElementsByTagName('style'),\n allRules = { }, rules;\n\n // very crude parsing of style contents\n for (var i = 0, len = styles.length; i < len; i++) {\n // IE9 doesn't support textContent, but provides text instead.\n var styleContents = styles[i].textContent || styles[i].text;\n\n // remove comments\n styleContents = styleContents.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n if (styleContents.trim() === '') {\n continue;\n }\n rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n rules = rules.map(function(rule) { return rule.trim(); });\n rules.forEach(function(rule) {\n\n var match = rule.match(/([\\s\\S]*?)\\s*\\{([^}]*)\\}/),\n ruleObj = { }, declaration = match[2].trim(),\n propertyValuePairs = declaration.replace(/;$/, '').split(/\\s*;\\s*/);\n\n for (var i = 0, len = propertyValuePairs.length; i < len; i++) {\n var pair = propertyValuePairs[i].split(/\\s*:\\s*/),\n property = pair[0],\n value = pair[1];\n ruleObj[property] = value;\n }\n rule = match[1];\n rule.split(',').forEach(function(_rule) {\n _rule = _rule.replace(/^svg/i, '').trim();\n if (_rule === '') {\n return;\n }\n if (allRules[_rule]) {\n fabric.util.object.extend(allRules[_rule], ruleObj);\n }\n else {\n allRules[_rule] = fabric.util.object.clone(ruleObj);\n }\n });\n });\n }\n return allRules;\n },\n\n /**\n * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\n * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\n * @memberOf fabric\n * @param {String} url\n * @param {Function} callback\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n */\n loadSVGFromURL: function(url, callback, reviver, options) {\n\n url = url.replace(/^\\n\\s*/, '').trim();\n new fabric.util.request(url, {\n method: 'get',\n onComplete: onComplete\n });\n\n function onComplete(r) {\n\n var xml = r.responseXML;\n if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) {\n xml = new ActiveXObject('Microsoft.XMLDOM');\n xml.async = 'false';\n //IE chokes on DOCTYPE\n xml.loadXML(r.responseText.replace(//i, ''));\n }\n if (!xml || !xml.documentElement) {\n callback && callback(null);\n }\n\n fabric.parseSVGDocument(xml.documentElement, function (results, _options) {\n callback && callback(results, _options);\n }, reviver, options);\n }\n },\n\n /**\n * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\n * @memberOf fabric\n * @param {String} string\n * @param {Function} callback\n * @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources\n */\n loadSVGFromString: function(string, callback, reviver, options) {\n string = string.trim();\n var doc;\n if (typeof DOMParser !== 'undefined') {\n var parser = new DOMParser();\n if (parser && parser.parseFromString) {\n doc = parser.parseFromString(string, 'text/xml');\n }\n }\n else if (fabric.window.ActiveXObject) {\n doc = new ActiveXObject('Microsoft.XMLDOM');\n doc.async = 'false';\n // IE chokes on DOCTYPE\n doc.loadXML(string.replace(//i, ''));\n }\n\n fabric.parseSVGDocument(doc.documentElement, function (results, _options) {\n callback(results, _options);\n }, reviver, options);\n }\n });\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions) {\n this.elements = elements;\n this.callback = callback;\n this.options = options;\n this.reviver = reviver;\n this.svgUid = (options && options.svgUid) || 0;\n this.parsingOptions = parsingOptions;\n};\n\nfabric.ElementsParser.prototype.parse = function() {\n this.instances = new Array(this.elements.length);\n this.numElements = this.elements.length;\n\n this.createObjects();\n};\n\nfabric.ElementsParser.prototype.createObjects = function() {\n for (var i = 0, len = this.elements.length; i < len; i++) {\n this.elements[i].setAttribute('svgUid', this.svgUid);\n (function(_obj, i) {\n setTimeout(function() {\n _obj.createObject(_obj.elements[i], i);\n }, 0);\n })(this, i);\n }\n};\n\nfabric.ElementsParser.prototype.createObject = function(el, index) {\n var klass = fabric[fabric.util.string.capitalize(el.tagName.replace('svg:', ''))];\n if (klass && klass.fromElement) {\n try {\n this._createObject(klass, el, index);\n }\n catch (err) {\n fabric.log(err);\n }\n }\n else {\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype._createObject = function(klass, el, index) {\n if (klass.async) {\n klass.fromElement(el, this.createCallback(index, el), this.options);\n }\n else {\n var obj = klass.fromElement(el, this.options);\n this.resolveGradient(obj, 'fill');\n this.resolveGradient(obj, 'stroke');\n this.reviver && this.reviver(el, obj);\n this.instances[index] = obj;\n this.checkIfDone();\n }\n};\n\nfabric.ElementsParser.prototype.createCallback = function(index, el) {\n var _this = this;\n return function(obj) {\n _this.resolveGradient(obj, 'fill');\n _this.resolveGradient(obj, 'stroke');\n _this.reviver && _this.reviver(el, obj);\n _this.instances[index] = obj;\n _this.checkIfDone();\n };\n};\n\nfabric.ElementsParser.prototype.resolveGradient = function(obj, property) {\n\n var instanceFillValue = obj.get(property);\n if (!(/^url\\(/).test(instanceFillValue)) {\n return;\n }\n var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);\n if (fabric.gradientDefs[this.svgUid][gradientId]) {\n obj.set(property,\n fabric.Gradient.fromElement(fabric.gradientDefs[this.svgUid][gradientId], obj));\n }\n};\n\nfabric.ElementsParser.prototype.checkIfDone = function() {\n if (--this.numElements === 0) {\n this.instances = this.instances.filter(function(el) {\n // eslint-disable-next-line no-eq-null, eqeqeq\n return el != null;\n });\n this.callback(this.instances);\n }\n};\n\n\n(function(global) {\n\n 'use strict';\n\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Point) {\n fabric.warn('fabric.Point is already defined');\n return;\n }\n\n fabric.Point = Point;\n\n /**\n * Point class\n * @class fabric.Point\n * @memberOf fabric\n * @constructor\n * @param {Number} x\n * @param {Number} y\n * @return {fabric.Point} thisArg\n */\n function Point(x, y) {\n this.x = x;\n this.y = y;\n }\n\n Point.prototype = /** @lends fabric.Point.prototype */ {\n\n type: 'point',\n\n constructor: Point,\n\n /**\n * Adds another point to this one and returns another one\n * @param {fabric.Point} that\n * @return {fabric.Point} new Point instance with added values\n */\n add: function (that) {\n return new Point(this.x + that.x, this.y + that.y);\n },\n\n /**\n * Adds another point to this one\n * @param {fabric.Point} that\n * @return {fabric.Point} thisArg\n * @chainable\n */\n addEquals: function (that) {\n this.x += that.x;\n this.y += that.y;\n return this;\n },\n\n /**\n * Adds value to this point and returns a new one\n * @param {Number} scalar\n * @return {fabric.Point} new Point with added value\n */\n scalarAdd: function (scalar) {\n return new Point(this.x + scalar, this.y + scalar);\n },\n\n /**\n * Adds value to this point\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n scalarAddEquals: function (scalar) {\n this.x += scalar;\n this.y += scalar;\n return this;\n },\n\n /**\n * Subtracts another point from this point and returns a new one\n * @param {fabric.Point} that\n * @return {fabric.Point} new Point object with subtracted values\n */\n subtract: function (that) {\n return new Point(this.x - that.x, this.y - that.y);\n },\n\n /**\n * Subtracts another point from this point\n * @param {fabric.Point} that\n * @return {fabric.Point} thisArg\n * @chainable\n */\n subtractEquals: function (that) {\n this.x -= that.x;\n this.y -= that.y;\n return this;\n },\n\n /**\n * Subtracts value from this point and returns a new one\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n scalarSubtract: function (scalar) {\n return new Point(this.x - scalar, this.y - scalar);\n },\n\n /**\n * Subtracts value from this point\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n scalarSubtractEquals: function (scalar) {\n this.x -= scalar;\n this.y -= scalar;\n return this;\n },\n\n /**\n * Miltiplies this point by a value and returns a new one\n * TODO: rename in scalarMultiply in 2.0\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n multiply: function (scalar) {\n return new Point(this.x * scalar, this.y * scalar);\n },\n\n /**\n * Miltiplies this point by a value\n * TODO: rename in scalarMultiplyEquals in 2.0\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n multiplyEquals: function (scalar) {\n this.x *= scalar;\n this.y *= scalar;\n return this;\n },\n\n /**\n * Divides this point by a value and returns a new one\n * TODO: rename in scalarDivide in 2.0\n * @param {Number} scalar\n * @return {fabric.Point}\n */\n divide: function (scalar) {\n return new Point(this.x / scalar, this.y / scalar);\n },\n\n /**\n * Divides this point by a value\n * TODO: rename in scalarDivideEquals in 2.0\n * @param {Number} scalar\n * @return {fabric.Point} thisArg\n * @chainable\n */\n divideEquals: function (scalar) {\n this.x /= scalar;\n this.y /= scalar;\n return this;\n },\n\n /**\n * Returns true if this point is equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n eq: function (that) {\n return (this.x === that.x && this.y === that.y);\n },\n\n /**\n * Returns true if this point is less than another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n lt: function (that) {\n return (this.x < that.x && this.y < that.y);\n },\n\n /**\n * Returns true if this point is less than or equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n lte: function (that) {\n return (this.x <= that.x && this.y <= that.y);\n },\n\n /**\n\n * Returns true if this point is greater another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n gt: function (that) {\n return (this.x > that.x && this.y > that.y);\n },\n\n /**\n * Returns true if this point is greater than or equal to another one\n * @param {fabric.Point} that\n * @return {Boolean}\n */\n gte: function (that) {\n return (this.x >= that.x && this.y >= that.y);\n },\n\n /**\n * Returns new point which is the result of linear interpolation with this one and another one\n * @param {fabric.Point} that\n * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\n * @return {fabric.Point}\n */\n lerp: function (that, t) {\n if (typeof t === 'undefined') {\n t = 0.5;\n }\n t = Math.max(Math.min(1, t), 0);\n return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);\n },\n\n /**\n * Returns distance from this point and another one\n * @param {fabric.Point} that\n * @return {Number}\n */\n distanceFrom: function (that) {\n var dx = this.x - that.x,\n dy = this.y - that.y;\n return Math.sqrt(dx * dx + dy * dy);\n },\n\n /**\n * Returns the point between this point and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n midPointFrom: function (that) {\n return this.lerp(that);\n },\n\n /**\n * Returns a new point which is the min of this and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n min: function (that) {\n return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));\n },\n\n /**\n * Returns a new point which is the max of this and another one\n * @param {fabric.Point} that\n * @return {fabric.Point}\n */\n max: function (that) {\n return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));\n },\n\n /**\n * Returns string representation of this point\n * @return {String}\n */\n toString: function () {\n return this.x + ',' + this.y;\n },\n\n /**\n * Sets x/y of this point\n * @param {Number} x\n * @param {Number} y\n * @chainable\n */\n setXY: function (x, y) {\n this.x = x;\n this.y = y;\n return this;\n },\n\n /**\n * Sets x of this point\n * @param {Number} x\n * @chainable\n */\n setX: function (x) {\n this.x = x;\n return this;\n },\n\n /**\n * Sets y of this point\n * @param {Number} y\n * @chainable\n */\n setY: function (y) {\n this.y = y;\n return this;\n },\n\n /**\n * Sets x/y of this point from another point\n * @param {fabric.Point} that\n * @chainable\n */\n setFromPoint: function (that) {\n this.x = that.x;\n this.y = that.y;\n return this;\n },\n\n /**\n * Swaps x/y of this point and another point\n * @param {fabric.Point} that\n */\n swap: function (that) {\n var x = this.x,\n y = this.y;\n this.x = that.x;\n this.y = that.y;\n that.x = x;\n that.y = y;\n },\n\n /**\n * return a cloned instance of the point\n * @return {fabric.Point}\n */\n clone: function () {\n return new Point(this.x, this.y);\n }\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Intersection) {\n fabric.warn('fabric.Intersection is already defined');\n return;\n }\n\n /**\n * Intersection class\n * @class fabric.Intersection\n * @memberOf fabric\n * @constructor\n */\n function Intersection(status) {\n this.status = status;\n this.points = [];\n }\n\n fabric.Intersection = Intersection;\n\n fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {\n\n constructor: Intersection,\n\n /**\n * Appends a point to intersection\n * @param {fabric.Point} point\n * @return {fabric.Intersection} thisArg\n * @chainable\n */\n appendPoint: function (point) {\n this.points.push(point);\n return this;\n },\n\n /**\n * Appends points to intersection\n * @param {Array} points\n * @return {fabric.Intersection} thisArg\n * @chainable\n */\n appendPoints: function (points) {\n this.points = this.points.concat(points);\n return this;\n }\n };\n\n /**\n * Checks if one line intersects another\n * TODO: rename in intersectSegmentSegment\n * @static\n * @param {fabric.Point} a1\n * @param {fabric.Point} a2\n * @param {fabric.Point} b1\n * @param {fabric.Point} b2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {\n var result,\n uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),\n ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),\n uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n if (uB !== 0) {\n var ua = uaT / uB,\n ub = ubT / uB;\n if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n result = new Intersection('Intersection');\n result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));\n }\n else {\n result = new Intersection();\n }\n }\n else {\n if (uaT === 0 || ubT === 0) {\n result = new Intersection('Coincident');\n }\n else {\n result = new Intersection('Parallel');\n }\n }\n return result;\n };\n\n /**\n * Checks if line intersects polygon\n * TODO: rename in intersectSegmentPolygon\n * fix detection of coincident\n * @static\n * @param {fabric.Point} a1\n * @param {fabric.Point} a2\n * @param {Array} points\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectLinePolygon = function(a1, a2, points) {\n var result = new Intersection(),\n length = points.length,\n b1, b2, inter;\n\n for (var i = 0; i < length; i++) {\n b1 = points[i];\n b2 = points[(i + 1) % length];\n inter = Intersection.intersectLineLine(a1, a2, b1, b2);\n\n result.appendPoints(inter.points);\n }\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n /**\n * Checks if polygon intersects another polygon\n * @static\n * @param {Array} points1\n * @param {Array} points2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {\n var result = new Intersection(),\n length = points1.length;\n\n for (var i = 0; i < length; i++) {\n var a1 = points1[i],\n a2 = points1[(i + 1) % length],\n inter = Intersection.intersectLinePolygon(a1, a2, points2);\n\n result.appendPoints(inter.points);\n }\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n /**\n * Checks if polygon intersects rectangle\n * @static\n * @param {Array} points\n * @param {fabric.Point} r1\n * @param {fabric.Point} r2\n * @return {fabric.Intersection}\n */\n fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {\n var min = r1.min(r2),\n max = r1.max(r2),\n topRight = new fabric.Point(max.x, min.y),\n bottomLeft = new fabric.Point(min.x, max.y),\n inter1 = Intersection.intersectLinePolygon(min, topRight, points),\n inter2 = Intersection.intersectLinePolygon(topRight, max, points),\n inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),\n inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),\n result = new Intersection();\n\n result.appendPoints(inter1.points);\n result.appendPoints(inter2.points);\n result.appendPoints(inter3.points);\n result.appendPoints(inter4.points);\n\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n return result;\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Color) {\n fabric.warn('fabric.Color is already defined.');\n return;\n }\n\n /**\n * Color class\n * The purpose of {@link fabric.Color} is to abstract and encapsulate common color operations;\n * {@link fabric.Color} is a constructor and creates instances of {@link fabric.Color} objects.\n *\n * @class fabric.Color\n * @param {String} color optional in hex or rgb(a) or hsl format or from known color list\n * @return {fabric.Color} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors}\n */\n function Color(color) {\n if (!color) {\n this.setSource([0, 0, 0, 1]);\n }\n else {\n this._tryParsingColor(color);\n }\n }\n\n fabric.Color = Color;\n\n fabric.Color.prototype = /** @lends fabric.Color.prototype */ {\n\n /**\n * @private\n * @param {String|Array} color Color value to parse\n */\n _tryParsingColor: function(color) {\n var source;\n\n if (color in Color.colorNameMap) {\n color = Color.colorNameMap[color];\n }\n\n if (color === 'transparent') {\n source = [255, 255, 255, 0];\n }\n\n if (!source) {\n source = Color.sourceFromHex(color);\n }\n if (!source) {\n source = Color.sourceFromRgb(color);\n }\n if (!source) {\n source = Color.sourceFromHsl(color);\n }\n if (!source) {\n //if color is not recognize let's make black as canvas does\n source = [0, 0, 0, 1];\n }\n if (source) {\n this.setSource(source);\n }\n },\n\n /**\n * Adapted from https://github.com/mjijackson\n * @private\n * @param {Number} r Red color value\n * @param {Number} g Green color value\n * @param {Number} b Blue color value\n * @return {Array} Hsl color\n */\n _rgbToHsl: function(r, g, b) {\n r /= 255; g /= 255; b /= 255;\n\n var h, s, l,\n max = fabric.util.array.max([r, g, b]),\n min = fabric.util.array.min([r, g, b]);\n\n l = (max + min) / 2;\n\n if (max === min) {\n h = s = 0; // achromatic\n }\n else {\n var d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n\n return [\n Math.round(h * 360),\n Math.round(s * 100),\n Math.round(l * 100)\n ];\n },\n\n /**\n * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n * @return {Array}\n */\n getSource: function() {\n return this._source;\n },\n\n /**\n * Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n * @param {Array} source\n */\n setSource: function(source) {\n this._source = source;\n },\n\n /**\n * Returns color representation in RGB format\n * @return {String} ex: rgb(0-255,0-255,0-255)\n */\n toRgb: function() {\n var source = this.getSource();\n return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';\n },\n\n /**\n * Returns color representation in RGBA format\n * @return {String} ex: rgba(0-255,0-255,0-255,0-1)\n */\n toRgba: function() {\n var source = this.getSource();\n return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';\n },\n\n /**\n * Returns color representation in HSL format\n * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\n */\n toHsl: function() {\n var source = this.getSource(),\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';\n },\n\n /**\n * Returns color representation in HSLA format\n * @return {String} ex: hsla(0-360,0%-100%,0%-100%,0-1)\n */\n toHsla: function() {\n var source = this.getSource(),\n hsl = this._rgbToHsl(source[0], source[1], source[2]);\n\n return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';\n },\n\n /**\n * Returns color representation in HEX format\n * @return {String} ex: FF5555\n */\n toHex: function() {\n var source = this.getSource(), r, g, b;\n\n r = source[0].toString(16);\n r = (r.length === 1) ? ('0' + r) : r;\n\n g = source[1].toString(16);\n g = (g.length === 1) ? ('0' + g) : g;\n\n b = source[2].toString(16);\n b = (b.length === 1) ? ('0' + b) : b;\n\n return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();\n },\n\n /**\n * Returns color representation in HEXA format\n * @return {String} ex: FF5555CC\n */\n toHexa: function() {\n var source = this.getSource(), a;\n\n a = source[3] * 255;\n a = a.toString(16);\n a = (a.length === 1) ? ('0' + a) : a;\n\n return this.toHex() + a.toUpperCase();\n },\n\n /**\n * Gets value of alpha channel for this color\n * @return {Number} 0-1\n */\n getAlpha: function() {\n return this.getSource()[3];\n },\n\n /**\n * Sets value of alpha channel for this color\n * @param {Number} alpha Alpha value 0-1\n * @return {fabric.Color} thisArg\n */\n setAlpha: function(alpha) {\n var source = this.getSource();\n source[3] = alpha;\n this.setSource(source);\n return this;\n },\n\n /**\n * Transforms color to its grayscale representation\n * @return {fabric.Color} thisArg\n */\n toGrayscale: function() {\n var source = this.getSource(),\n average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),\n currentAlpha = source[3];\n this.setSource([average, average, average, currentAlpha]);\n return this;\n },\n\n /**\n * Transforms color to its black and white representation\n * @param {Number} threshold\n * @return {fabric.Color} thisArg\n */\n toBlackWhite: function(threshold) {\n var source = this.getSource(),\n average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),\n currentAlpha = source[3];\n\n threshold = threshold || 127;\n\n average = (Number(average) < Number(threshold)) ? 0 : 255;\n this.setSource([average, average, average, currentAlpha]);\n return this;\n },\n\n /**\n * Overlays color with another color\n * @param {String|fabric.Color} otherColor\n * @return {fabric.Color} thisArg\n */\n overlayWith: function(otherColor) {\n if (!(otherColor instanceof Color)) {\n otherColor = new Color(otherColor);\n }\n\n var result = [],\n alpha = this.getAlpha(),\n otherAlpha = 0.5,\n source = this.getSource(),\n otherSource = otherColor.getSource();\n\n for (var i = 0; i < 3; i++) {\n result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));\n }\n\n result[3] = alpha;\n this.setSource(result);\n return this;\n }\n };\n\n /**\n * Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5))\n * @static\n * @field\n * @memberOf fabric.Color\n */\n // eslint-disable-next-line max-len\n fabric.Color.reRGBa = /^rgba?\\(\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*,\\s*(\\d{1,3}(?:\\.\\d+)?\\%?)\\s*(?:\\s*,\\s*((?:\\d*\\.?\\d+)?)\\s*)?\\)$/;\n\n /**\n * Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 ))\n * @static\n * @field\n * @memberOf fabric.Color\n */\n fabric.Color.reHSLa = /^hsla?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3}\\%)\\s*,\\s*(\\d{1,3}\\%)\\s*(?:\\s*,\\s*(\\d+(?:\\.\\d+)?)\\s*)?\\)$/;\n\n /**\n * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\n * @static\n * @field\n * @memberOf fabric.Color\n */\n fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n\n /**\n * Map of the 17 basic color names with HEX code\n * @static\n * @field\n * @memberOf fabric.Color\n * @see: http://www.w3.org/TR/CSS2/syndata.html#color-units\n */\n fabric.Color.colorNameMap = {\n aqua: '#00FFFF',\n black: '#000000',\n blue: '#0000FF',\n fuchsia: '#FF00FF',\n gray: '#808080',\n grey: '#808080',\n green: '#008000',\n lime: '#00FF00',\n maroon: '#800000',\n navy: '#000080',\n olive: '#808000',\n orange: '#FFA500',\n purple: '#800080',\n red: '#FF0000',\n silver: '#C0C0C0',\n teal: '#008080',\n white: '#FFFFFF',\n yellow: '#FFFF00'\n };\n\n /**\n * @private\n * @param {Number} p\n * @param {Number} q\n * @param {Number} t\n * @return {Number}\n */\n function hue2rgb(p, q, t) {\n if (t < 0) {\n t += 1;\n }\n if (t > 1) {\n t -= 1;\n }\n if (t < 1 / 6) {\n return p + (q - p) * 6 * t;\n }\n if (t < 1 / 2) {\n return q;\n }\n if (t < 2 / 3) {\n return p + (q - p) * (2 / 3 - t) * 6;\n }\n return p;\n }\n\n /**\n * Returns new color object, when given a color in RGB format\n * @memberOf fabric.Color\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\n * @return {fabric.Color}\n */\n fabric.Color.fromRgb = function(color) {\n return Color.fromSource(Color.sourceFromRgb(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format\n * @memberOf fabric.Color\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\n * @return {Array} source\n */\n fabric.Color.sourceFromRgb = function(color) {\n var match = color.match(Color.reRGBa);\n if (match) {\n var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),\n g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),\n b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);\n\n return [\n parseInt(r, 10),\n parseInt(g, 10),\n parseInt(b, 10),\n match[4] ? parseFloat(match[4]) : 1\n ];\n }\n };\n\n /**\n * Returns new color object, when given a color in RGBA format\n * @static\n * @function\n * @memberOf fabric.Color\n * @param {String} color\n * @return {fabric.Color}\n */\n fabric.Color.fromRgba = Color.fromRgb;\n\n /**\n * Returns new color object, when given a color in HSL format\n * @param {String} color Color value ex: hsl(0-260,0%-100%,0%-100%)\n * @memberOf fabric.Color\n * @return {fabric.Color}\n */\n fabric.Color.fromHsl = function(color) {\n return Color.fromSource(Color.sourceFromHsl(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.\n * Adapted from https://github.com/mjijackson\n * @memberOf fabric.Color\n * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\n * @return {Array} source\n * @see http://http://www.w3.org/TR/css3-color/#hsl-color\n */\n fabric.Color.sourceFromHsl = function(color) {\n var match = color.match(Color.reHSLa);\n if (!match) {\n return;\n }\n\n var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,\n s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),\n l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),\n r, g, b;\n\n if (s === 0) {\n r = g = b = l;\n }\n else {\n var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,\n p = l * 2 - q;\n\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n\n return [\n Math.round(r * 255),\n Math.round(g * 255),\n Math.round(b * 255),\n match[4] ? parseFloat(match[4]) : 1\n ];\n };\n\n /**\n * Returns new color object, when given a color in HSLA format\n * @static\n * @function\n * @memberOf fabric.Color\n * @param {String} color\n * @return {fabric.Color}\n */\n fabric.Color.fromHsla = Color.fromHsl;\n\n /**\n * Returns new color object, when given a color in HEX format\n * @static\n * @memberOf fabric.Color\n * @param {String} color Color value ex: FF5555\n * @return {fabric.Color}\n */\n fabric.Color.fromHex = function(color) {\n return Color.fromSource(Color.sourceFromHex(color));\n };\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\n * @static\n * @memberOf fabric.Color\n * @param {String} color ex: FF5555 or FF5544CC (RGBa)\n * @return {Array} source\n */\n fabric.Color.sourceFromHex = function(color) {\n if (color.match(Color.reHex)) {\n var value = color.slice(color.indexOf('#') + 1),\n isShortNotation = (value.length === 3 || value.length === 4),\n isRGBa = (value.length === 8 || value.length === 4),\n r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),\n g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),\n b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),\n a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';\n\n return [\n parseInt(r, 16),\n parseInt(g, 16),\n parseInt(b, 16),\n parseFloat((parseInt(a, 16) / 255).toFixed(2))\n ];\n }\n };\n\n /**\n * Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])\n * @static\n * @memberOf fabric.Color\n * @param {Array} source\n * @return {fabric.Color}\n */\n fabric.Color.fromSource = function(source) {\n var oColor = new Color();\n oColor.setSource(source);\n return oColor;\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n /* _FROM_SVG_START_ */\n function getColorStop(el) {\n var style = el.getAttribute('style'),\n offset = el.getAttribute('offset') || 0,\n color, colorAlpha, opacity;\n\n // convert percents to absolute values\n offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);\n offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;\n if (style) {\n var keyValuePairs = style.split(/\\s*;\\s*/);\n\n if (keyValuePairs[keyValuePairs.length - 1] === '') {\n keyValuePairs.pop();\n }\n\n for (var i = keyValuePairs.length; i--; ) {\n\n var split = keyValuePairs[i].split(/\\s*:\\s*/),\n key = split[0].trim(),\n value = split[1].trim();\n\n if (key === 'stop-color') {\n color = value;\n }\n else if (key === 'stop-opacity') {\n opacity = value;\n }\n }\n }\n\n if (!color) {\n color = el.getAttribute('stop-color') || 'rgb(0,0,0)';\n }\n if (!opacity) {\n opacity = el.getAttribute('stop-opacity');\n }\n\n color = new fabric.Color(color);\n colorAlpha = color.getAlpha();\n opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity);\n opacity *= colorAlpha;\n\n return {\n offset: offset,\n color: color.toRgb(),\n opacity: opacity\n };\n }\n\n function getLinearCoords(el) {\n return {\n x1: el.getAttribute('x1') || 0,\n y1: el.getAttribute('y1') || 0,\n x2: el.getAttribute('x2') || '100%',\n y2: el.getAttribute('y2') || 0\n };\n }\n\n function getRadialCoords(el) {\n return {\n x1: el.getAttribute('fx') || el.getAttribute('cx') || '50%',\n y1: el.getAttribute('fy') || el.getAttribute('cy') || '50%',\n r1: 0,\n x2: el.getAttribute('cx') || '50%',\n y2: el.getAttribute('cy') || '50%',\n r2: el.getAttribute('r') || '50%'\n };\n }\n /* _FROM_SVG_END_ */\n\n var clone = fabric.util.object.clone;\n\n /**\n * Gradient class\n * @class fabric.Gradient\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#gradients}\n * @see {@link fabric.Gradient#initialize} for constructor definition\n */\n fabric.Gradient = fabric.util.createClass(/** @lends fabric.Gradient.prototype */ {\n\n /**\n * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n offsetX: 0,\n\n /**\n * Vertical offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n offsetY: 0,\n\n /**\n * Constructor\n * @param {Object} [options] Options object with type, coords, gradientUnits and colorStops\n * @return {fabric.Gradient} thisArg\n */\n initialize: function(options) {\n options || (options = { });\n\n var coords = { };\n\n this.id = fabric.Object.__uid++;\n this.type = options.type || 'linear';\n\n coords = {\n x1: options.coords.x1 || 0,\n y1: options.coords.y1 || 0,\n x2: options.coords.x2 || 0,\n y2: options.coords.y2 || 0\n };\n\n if (this.type === 'radial') {\n coords.r1 = options.coords.r1 || 0;\n coords.r2 = options.coords.r2 || 0;\n }\n this.coords = coords;\n this.colorStops = options.colorStops.slice();\n if (options.gradientTransform) {\n this.gradientTransform = options.gradientTransform;\n }\n this.offsetX = options.offsetX || this.offsetX;\n this.offsetY = options.offsetY || this.offsetY;\n },\n\n /**\n * Adds another colorStop\n * @param {Object} colorStop Object with offset and color\n * @return {fabric.Gradient} thisArg\n */\n addColorStop: function(colorStops) {\n for (var position in colorStops) {\n var color = new fabric.Color(colorStops[position]);\n this.colorStops.push({\n offset: parseFloat(position),\n color: color.toRgb(),\n opacity: color.getAlpha()\n });\n }\n return this;\n },\n\n /**\n * Returns object representation of a gradient\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object}\n */\n toObject: function(propertiesToInclude) {\n var object = {\n type: this.type,\n coords: this.coords,\n colorStops: this.colorStops,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n gradientTransform: this.gradientTransform ? this.gradientTransform.concat() : this.gradientTransform\n };\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n return object;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an gradient\n * @param {Object} object Object to create a gradient for\n * @return {String} SVG representation of an gradient (linear/radial)\n */\n toSVG: function(object) {\n var coords = clone(this.coords, true),\n markup, commonAttributes, colorStops = clone(this.colorStops, true),\n needsSwap = coords.r1 > coords.r2;\n // colorStops must be sorted ascending\n colorStops.sort(function(a, b) {\n return a.offset - b.offset;\n });\n\n if (!(object.group && object.group.type === 'path-group')) {\n for (var prop in coords) {\n if (prop === 'x1' || prop === 'x2') {\n coords[prop] += this.offsetX - object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += this.offsetY - object.height / 2;\n }\n }\n }\n\n commonAttributes = 'id=\"SVGID_' + this.id +\n '\" gradientUnits=\"userSpaceOnUse\"';\n if (this.gradientTransform) {\n commonAttributes += ' gradientTransform=\"matrix(' + this.gradientTransform.join(' ') + ')\" ';\n }\n if (this.type === 'linear') {\n markup = [\n '\\n'\n ];\n }\n else if (this.type === 'radial') {\n // svg radial gradient has just 1 radius. the biggest.\n markup = [\n '\\n'\n ];\n }\n\n if (this.type === 'radial') {\n if (needsSwap) {\n // svg goes from internal to external radius. if radius are inverted, swap color stops.\n colorStops = colorStops.concat();\n colorStops.reverse();\n for (var i = 0; i < colorStops.length; i++) {\n colorStops[i].offset = 1 - colorStops[i].offset;\n }\n }\n var minRadius = Math.min(coords.r1, coords.r2);\n if (minRadius > 0) {\n // i have to shift all colorStops and add new one in 0.\n var maxRadius = Math.max(coords.r1, coords.r2),\n percentageShift = minRadius / maxRadius;\n for (var i = 0; i < colorStops.length; i++) {\n colorStops[i].offset += percentageShift * (1 - colorStops[i].offset);\n }\n }\n }\n\n for (var i = 0; i < colorStops.length; i++) {\n var colorStop = colorStops[i];\n markup.push(\n '\\n'\n );\n }\n\n markup.push((this.type === 'linear' ? '\\n' : '\\n'));\n\n return markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns an instance of CanvasGradient\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} object\n * @return {CanvasGradient}\n */\n toLive: function(ctx, object) {\n var gradient, prop, coords = fabric.util.object.clone(this.coords);\n\n if (!this.type) {\n return;\n }\n\n if (object.group && object.group.type === 'path-group') {\n for (prop in coords) {\n if (prop === 'x1' || prop === 'x2') {\n coords[prop] += -this.offsetX + object.width / 2;\n }\n else if (prop === 'y1' || prop === 'y2') {\n coords[prop] += -this.offsetY + object.height / 2;\n }\n }\n }\n\n if (this.type === 'linear') {\n gradient = ctx.createLinearGradient(\n coords.x1, coords.y1, coords.x2, coords.y2);\n }\n else if (this.type === 'radial') {\n gradient = ctx.createRadialGradient(\n coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);\n }\n\n for (var i = 0, len = this.colorStops.length; i < len; i++) {\n var color = this.colorStops[i].color,\n opacity = this.colorStops[i].opacity,\n offset = this.colorStops[i].offset;\n\n if (typeof opacity !== 'undefined') {\n color = new fabric.Color(color).setAlpha(opacity).toRgba();\n }\n gradient.addColorStop(offset, color);\n }\n\n return gradient;\n }\n });\n\n fabric.util.object.extend(fabric.Gradient, {\n\n /* _FROM_SVG_START_ */\n /**\n * Returns {@link fabric.Gradient} instance from an SVG element\n * @static\n * @memberOf fabric.Gradient\n * @param {SVGGradientElement} el SVG gradient element\n * @param {fabric.Object} instance\n * @return {fabric.Gradient} Gradient instance\n * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement\n * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement\n */\n fromElement: function(el, instance) {\n\n /**\n * @example:\n *\n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \n *\n * OR\n *\n * \n * \n * \n * \n * \n *\n */\n\n var colorStopEls = el.getElementsByTagName('stop'),\n type,\n gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox',\n gradientTransform = el.getAttribute('gradientTransform'),\n colorStops = [],\n coords, ellipseMatrix;\n\n if (el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT') {\n type = 'linear';\n }\n else {\n type = 'radial';\n }\n\n if (type === 'linear') {\n coords = getLinearCoords(el);\n }\n else if (type === 'radial') {\n coords = getRadialCoords(el);\n }\n\n for (var i = colorStopEls.length; i--; ) {\n colorStops.push(getColorStop(colorStopEls[i]));\n }\n\n ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits);\n\n var gradient = new fabric.Gradient({\n type: type,\n coords: coords,\n colorStops: colorStops,\n offsetX: -instance.left,\n offsetY: -instance.top\n });\n\n if (gradientTransform || ellipseMatrix !== '') {\n gradient.gradientTransform = fabric.parseTransformAttribute((gradientTransform || '') + ellipseMatrix);\n }\n return gradient;\n },\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Gradient} instance from its object representation\n * @static\n * @memberOf fabric.Gradient\n * @param {Object} obj\n * @param {Object} [options] Options object\n */\n forObject: function(obj, options) {\n options || (options = { });\n _convertPercentUnitsToValues(obj, options.coords, 'userSpaceOnUse');\n return new fabric.Gradient(options);\n }\n });\n\n /**\n * @private\n */\n function _convertPercentUnitsToValues(object, options, gradientUnits) {\n var propValue, addFactor = 0, multFactor = 1, ellipseMatrix = '';\n for (var prop in options) {\n if (options[prop] === 'Infinity') {\n options[prop] = 1;\n }\n else if (options[prop] === '-Infinity') {\n options[prop] = 0;\n }\n propValue = parseFloat(options[prop], 10);\n if (typeof options[prop] === 'string' && /^\\d+%$/.test(options[prop])) {\n multFactor = 0.01;\n }\n else {\n multFactor = 1;\n }\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.width : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.left || 0 : 0;\n }\n else if (prop === 'y1' || prop === 'y2') {\n multFactor *= gradientUnits === 'objectBoundingBox' ? object.height : 1;\n addFactor = gradientUnits === 'objectBoundingBox' ? object.top || 0 : 0;\n }\n options[prop] = propValue * multFactor + addFactor;\n }\n if (object.type === 'ellipse' &&\n options.r2 !== null &&\n gradientUnits === 'objectBoundingBox' &&\n object.rx !== object.ry) {\n\n var scaleFactor = object.ry / object.rx;\n ellipseMatrix = ' scale(1, ' + scaleFactor + ')';\n if (options.y1) {\n options.y1 /= scaleFactor;\n }\n if (options.y2) {\n options.y2 /= scaleFactor;\n }\n }\n return ellipseMatrix;\n }\n})();\n\n\n(function() {\n\n 'use strict';\n\n var toFixed = fabric.util.toFixed;\n\n /**\n * Pattern class\n * @class fabric.Pattern\n * @see {@link http://fabricjs.com/patterns|Pattern demo}\n * @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}\n * @see {@link fabric.Pattern#initialize} for constructor definition\n */\n\n\n fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {\n\n /**\n * Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n * @type String\n * @default\n */\n repeat: 'repeat',\n\n /**\n * Pattern horizontal offset from object's left/top corner\n * @type Number\n * @default\n */\n offsetX: 0,\n\n /**\n * Pattern vertical offset from object's left/top corner\n * @type Number\n * @default\n */\n offsetY: 0,\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @param {Function} [callback] function to invoke after callback init.\n * @return {fabric.Pattern} thisArg\n */\n initialize: function(options, callback) {\n options || (options = { });\n\n this.id = fabric.Object.__uid++;\n this.setOptions(options);\n if (!options.source || (options.source && typeof options.source !== 'string')) {\n callback && callback(this);\n return;\n }\n // function string\n if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {\n this.source = new Function(fabric.util.getFunctionBody(options.source));\n callback && callback(this);\n }\n else {\n // img src string\n var _this = this;\n this.source = fabric.util.createImage();\n fabric.util.loadImage(options.source, function(img) {\n _this.source = img;\n callback && callback(_this);\n });\n }\n },\n\n /**\n * Returns object representation of a pattern\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of a pattern instance\n */\n toObject: function(propertiesToInclude) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n source, object;\n\n // callback\n if (typeof this.source === 'function') {\n source = String(this.source);\n }\n // element\n else if (typeof this.source.src === 'string') {\n source = this.source.src;\n }\n // element\n else if (typeof this.source === 'object' && this.source.toDataURL) {\n source = this.source.toDataURL();\n }\n\n object = {\n type: 'pattern',\n source: source,\n repeat: this.repeat,\n offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),\n offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),\n };\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n return object;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a pattern\n * @param {fabric.Object} object\n * @return {String} SVG representation of a pattern\n */\n toSVG: function(object) {\n var patternSource = typeof this.source === 'function' ? this.source() : this.source,\n patternWidth = patternSource.width / object.width,\n patternHeight = patternSource.height / object.height,\n patternOffsetX = this.offsetX / object.width,\n patternOffsetY = this.offsetY / object.height,\n patternImgSrc = '';\n if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {\n patternHeight = 1;\n }\n if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {\n patternWidth = 1;\n }\n if (patternSource.src) {\n patternImgSrc = patternSource.src;\n }\n else if (patternSource.toDataURL) {\n patternImgSrc = patternSource.toDataURL();\n }\n\n return '\\n' +\n '\\n' +\n '\\n';\n },\n /* _TO_SVG_END_ */\n\n setOptions: function(options) {\n for (var prop in options) {\n this[prop] = options[prop];\n }\n },\n\n /**\n * Returns an instance of CanvasPattern\n * @param {CanvasRenderingContext2D} ctx Context to create pattern\n * @return {CanvasPattern}\n */\n toLive: function(ctx) {\n var source = typeof this.source === 'function' ? this.source() : this.source;\n\n // if the image failed to load, return, and allow rest to continue loading\n if (!source) {\n return '';\n }\n\n // if an image\n if (typeof source.src !== 'undefined') {\n if (!source.complete) {\n return '';\n }\n if (source.naturalWidth === 0 || source.naturalHeight === 0) {\n return '';\n }\n }\n return ctx.createPattern(source, this.repeat);\n }\n });\n})();\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n toFixed = fabric.util.toFixed;\n\n if (fabric.Shadow) {\n fabric.warn('fabric.Shadow is already defined.');\n return;\n }\n\n /**\n * Shadow class\n * @class fabric.Shadow\n * @see {@link http://fabricjs.com/shadows|Shadow demo}\n * @see {@link fabric.Shadow#initialize} for constructor definition\n */\n fabric.Shadow = fabric.util.createClass(/** @lends fabric.Shadow.prototype */ {\n\n /**\n * Shadow color\n * @type String\n * @default\n */\n color: 'rgb(0,0,0)',\n\n /**\n * Shadow blur\n * @type Number\n */\n blur: 0,\n\n /**\n * Shadow horizontal offset\n * @type Number\n * @default\n */\n offsetX: 0,\n\n /**\n * Shadow vertical offset\n * @type Number\n * @default\n */\n offsetY: 0,\n\n /**\n * Whether the shadow should affect stroke operations\n * @type Boolean\n * @default\n */\n affectStroke: false,\n\n /**\n * Indicates whether toObject should include default values\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * Constructor\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetX properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px, \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @return {fabric.Shadow} thisArg\n */\n initialize: function(options) {\n\n if (typeof options === 'string') {\n options = this._parseShadow(options);\n }\n\n for (var prop in options) {\n this[prop] = options[prop];\n }\n\n this.id = fabric.Object.__uid++;\n },\n\n /**\n * @private\n * @param {String} shadow Shadow value to parse\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\n */\n _parseShadow: function(shadow) {\n var shadowStr = shadow.trim(),\n offsetsAndBlur = fabric.Shadow.reOffsetsAndBlur.exec(shadowStr) || [],\n color = shadowStr.replace(fabric.Shadow.reOffsetsAndBlur, '') || 'rgb(0,0,0)';\n\n return {\n color: color.trim(),\n offsetX: parseInt(offsetsAndBlur[1], 10) || 0,\n offsetY: parseInt(offsetsAndBlur[2], 10) || 0,\n blur: parseInt(offsetsAndBlur[3], 10) || 0\n };\n },\n\n /**\n * Returns a string representation of an instance\n * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n * @return {String} Returns CSS3 text-shadow declaration\n */\n toString: function() {\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a shadow\n * @param {fabric.Object} object\n * @return {String} SVG representation of a shadow\n */\n toSVG: function(object) {\n var fBoxX = 40, fBoxY = 40, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n offset = fabric.util.rotateVector(\n { x: this.offsetX, y: this.offsetY },\n fabric.util.degreesToRadians(-object.angle)),\n BLUR_BOX = 20;\n\n if (object.width && object.height) {\n //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n // we add some extra space to filter box to contain the blur ( 20 )\n fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;\n }\n if (object.flipX) {\n offset.x *= -1;\n }\n if (object.flipY) {\n offset.y *= -1;\n }\n return (\n '\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\t\\n' +\n '\\t\\n' +\n '\\n');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns object representation of a shadow\n * @return {Object} Object representation of a shadow instance\n */\n toObject: function() {\n if (this.includeDefaultValues) {\n return {\n color: this.color,\n blur: this.blur,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n affectStroke: this.affectStroke\n };\n }\n var obj = { }, proto = fabric.Shadow.prototype;\n\n ['color', 'blur', 'offsetX', 'offsetY', 'affectStroke'].forEach(function(prop) {\n if (this[prop] !== proto[prop]) {\n obj[prop] = this[prop];\n }\n }, this);\n\n return obj;\n }\n });\n\n /**\n * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n * @static\n * @field\n * @memberOf fabric.Shadow\n */\n // eslint-disable-next-line max-len\n fabric.Shadow.reOffsetsAndBlur = /(?:\\s|^)(-?\\d+(?:px)?(?:\\s?|$))?(-?\\d+(?:px)?(?:\\s?|$))?(\\d+(?:px)?)?(?:\\s?|$)(?:$|\\s)/;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function () {\n\n 'use strict';\n\n if (fabric.StaticCanvas) {\n fabric.warn('fabric.StaticCanvas is already defined.');\n return;\n }\n\n // aliases for faster resolution\n var extend = fabric.util.object.extend,\n getElementOffset = fabric.util.getElementOffset,\n removeFromArray = fabric.util.removeFromArray,\n toFixed = fabric.util.toFixed,\n transformPoint = fabric.util.transformPoint,\n invertTransform = fabric.util.invertTransform,\n\n CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');\n\n /**\n * Static canvas class\n * @class fabric.StaticCanvas\n * @mixes fabric.Collection\n * @mixes fabric.Observable\n * @see {@link http://fabricjs.com/static_canvas|StaticCanvas demo}\n * @see {@link fabric.StaticCanvas#initialize} for constructor definition\n * @fires before:render\n * @fires after:render\n * @fires canvas:cleared\n * @fires object:added\n * @fires object:removed\n */\n fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Constructor\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(el, options) {\n options || (options = { });\n\n this._initStatic(el, options);\n },\n\n /**\n * Background color of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.\n * @type {(String|fabric.Pattern)}\n * @default\n */\n backgroundColor: '',\n\n /**\n * Background image of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setBackgroundImage}.\n * Backwards incompatibility note: The \"backgroundImageOpacity\"\n * and \"backgroundImageStretch\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}.\n * @type fabric.Image\n * @default\n */\n backgroundImage: null,\n\n /**\n * Overlay color of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setOverlayColor}\n * @since 1.3.9\n * @type {(String|fabric.Pattern)}\n * @default\n */\n overlayColor: '',\n\n /**\n * Overlay image of canvas instance.\n * Should be set via {@link fabric.StaticCanvas#setOverlayImage}.\n * Backwards incompatibility note: The \"overlayImageLeft\"\n * and \"overlayImageTop\" properties are deprecated since 1.3.9.\n * Use {@link fabric.Image#left} and {@link fabric.Image#top}.\n * @type fabric.Image\n * @default\n */\n overlayImage: null,\n\n /**\n * Indicates whether toObject/toDatalessObject should include default values\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * Indicates whether objects' state should be saved\n * @type Boolean\n * @default\n */\n stateful: false,\n\n /**\n * Indicates whether {@link fabric.Collection.add}, {@link fabric.Collection.insertAt} and {@link fabric.Collection.remove} should also re-render canvas.\n * Disabling this option could give a great performance boost when adding/removing a lot of objects to/from canvas at once\n * (followed by a manual rendering after addition/deletion)\n * @type Boolean\n * @default\n */\n renderOnAddRemove: true,\n\n /**\n * Function that determines clipping of entire canvas area\n * Being passed context as first argument. See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ}\n * @type Function\n * @default\n */\n clipTo: null,\n\n /**\n * Indicates whether object controls (borders/controls) are rendered above overlay image\n * @type Boolean\n * @default\n */\n controlsAboveOverlay: false,\n\n /**\n * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\n * @type Boolean\n * @default\n */\n allowTouchScrolling: false,\n\n /**\n * Indicates whether this canvas will use image smoothing, this is on by default in browsers\n * @type Boolean\n * @default\n */\n imageSmoothingEnabled: true,\n\n /**\n * The transformation (in the format of Canvas transform) which focuses the viewport\n * @type Array\n * @default\n */\n viewportTransform: fabric.iMatrix.concat(),\n\n /**\n * if set to false background image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @default\n */\n backgroundVpt: true,\n\n /**\n * if set to false overlya image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @default\n */\n overlayVpt: true,\n\n /**\n * Callback; invoked right before object is about to be scaled/rotated\n */\n onBeforeScaleRotate: function () {\n /* NOOP */\n },\n\n /**\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n */\n enableRetinaScaling: true,\n\n /**\n * Describe canvas element extension over design\n * properties are tl,tr,bl,br.\n * if canvas is not zoomed/panned those points are the four corner of canvas\n * if canvas is viewportTransformed you those points indicate the extension\n * of canvas element in plain untrasformed coordinates\n * The coordinates get updated with @method calcViewportBoundaries.\n * @memberOf fabric.StaticCanvas.prototype\n */\n vptCoords: { },\n\n /**\n * Based on vptCoords and object.aCoords, skip rendering of objects that\n * are not included in current viewport.\n * May greatly help in applications with crowded canvas and use of zoom/pan\n * If One of the corner of the bounding box of the object is on the canvas\n * the objects get rendered.\n * @memberOf fabric.StaticCanvas.prototype\n */\n skipOffscreen: false,\n\n /**\n * @private\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n */\n _initStatic: function(el, options) {\n var cb = fabric.StaticCanvas.prototype.renderAll.bind(this);\n this._objects = [];\n this._createLowerCanvas(el);\n this._initOptions(options);\n this._setImageSmoothing();\n // only initialize retina scaling once\n if (!this.interactive) {\n this._initRetinaScaling();\n }\n\n if (options.overlayImage) {\n this.setOverlayImage(options.overlayImage, cb);\n }\n if (options.backgroundImage) {\n this.setBackgroundImage(options.backgroundImage, cb);\n }\n if (options.backgroundColor) {\n this.setBackgroundColor(options.backgroundColor, cb);\n }\n if (options.overlayColor) {\n this.setOverlayColor(options.overlayColor, cb);\n }\n this.calcOffset();\n },\n\n /**\n * @private\n */\n _isRetinaScaling: function() {\n return (fabric.devicePixelRatio !== 1 && this.enableRetinaScaling);\n },\n\n /**\n * @private\n * @return {Number} retinaScaling if applied, otherwise 1;\n */\n getRetinaScaling: function() {\n return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;\n },\n\n /**\n * @private\n */\n _initRetinaScaling: function() {\n if (!this._isRetinaScaling()) {\n return;\n }\n this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);\n this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);\n\n this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);\n },\n\n /**\n * Calculates canvas element offset relative to the document\n * This method is also attached as \"resize\" event handler of window\n * @return {fabric.Canvas} instance\n * @chainable\n */\n calcOffset: function () {\n this._offset = getElementOffset(this.lowerCanvasEl);\n return this;\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to\n * @param {Function} callback callback to invoke when image is loaded and set as an overlay\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}\n * @example Normal overlayImage with left/top = 0\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * // Needed to position overlayImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example overlayImage with different properties\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top'\n * });\n * @example Stretched overlayImage #1 - width/height correspond to canvas width/height\n * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) {\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));\n * });\n * @example Stretched overlayImage #2 - width/height correspond to canvas width/height\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * width: canvas.width,\n * height: canvas.height,\n * // Needed to position overlayImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example overlayImage loaded from cross-origin\n * canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top',\n * crossOrigin: 'anonymous'\n * });\n */\n setOverlayImage: function (image, callback, options) {\n return this.__setBgOverlayImage('overlayImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas\n * @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to\n * @param {Function} callback Callback to invoke when image is loaded and set as background\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo}\n * @example Normal backgroundImage with left/top = 0\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * // Needed to position backgroundImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example backgroundImage with different properties\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top'\n * });\n * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height\n * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) {\n * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});\n * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));\n * });\n * @example Stretched backgroundImage #2 - width/height correspond to canvas width/height\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * width: canvas.width,\n * height: canvas.height,\n * // Needed to position backgroundImage at 0/0\n * originX: 'left',\n * originY: 'top'\n * });\n * @example backgroundImage loaded from cross-origin\n * canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {\n * opacity: 0.5,\n * angle: 45,\n * left: 400,\n * top: 400,\n * originX: 'left',\n * originY: 'top',\n * crossOrigin: 'anonymous'\n * });\n */\n setBackgroundImage: function (image, callback, options) {\n return this.__setBgOverlayImage('backgroundImage', image, callback, options);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas\n * @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to\n * @param {Function} callback Callback to invoke when background color is set\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}\n * @example Normal overlayColor - color value\n * canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor\n * canvas.setOverlayColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as overlayColor with repeat and offset\n * canvas.setOverlayColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\n * repeat: 'repeat',\n * offsetX: 200,\n * offsetY: 100\n * }, canvas.renderAll.bind(canvas));\n */\n setOverlayColor: function(overlayColor, callback) {\n return this.__setBgOverlayColor('overlayColor', overlayColor, callback);\n },\n\n /**\n * Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas\n * @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to\n * @param {Function} callback Callback to invoke when background color is set\n * @return {fabric.Canvas} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}\n * @example Normal backgroundColor - color value\n * canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor\n * canvas.setBackgroundColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png'\n * }, canvas.renderAll.bind(canvas));\n * @example fabric.Pattern used as backgroundColor with repeat and offset\n * canvas.setBackgroundColor({\n * source: 'http://fabricjs.com/assets/escheresque_ste.png',\n * repeat: 'repeat',\n * offsetX: 200,\n * offsetY: 100\n * }, canvas.renderAll.bind(canvas));\n */\n setBackgroundColor: function(backgroundColor, callback) {\n return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);\n },\n\n /**\n * @private\n * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard}\n */\n _setImageSmoothing: function() {\n var ctx = this.getContext();\n\n ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled\n || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;\n ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;\n },\n\n /**\n * @private\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage}\n * or {@link fabric.StaticCanvas#overlayImage|overlayImage})\n * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to\n * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay\n * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.\n */\n __setBgOverlayImage: function(property, image, callback, options) {\n if (typeof image === 'string') {\n fabric.util.loadImage(image, function(img) {\n img && (this[property] = new fabric.Image(img, options));\n callback && callback(img);\n }, this, options && options.crossOrigin);\n }\n else {\n options && image.setOptions(options);\n this[property] = image;\n callback && callback(image);\n }\n\n return this;\n },\n\n /**\n * @private\n * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor}\n * or {@link fabric.StaticCanvas#overlayColor|overlayColor})\n * @param {(Object|String|null)} color Object with pattern information, color value or null\n * @param {Function} [callback] Callback is invoked when color is set\n */\n __setBgOverlayColor: function(property, color, callback) {\n this[property] = color;\n this._initGradient(color, property);\n this._initPattern(color, property, callback);\n return this;\n },\n\n /**\n * @private\n */\n _createCanvasElement: function(canvasEl) {\n var element = fabric.util.createCanvasElement(canvasEl);\n if (!element.style) {\n element.style = { };\n }\n if (!element) {\n throw CANVAS_INIT_ERROR;\n }\n if (typeof element.getContext === 'undefined') {\n throw CANVAS_INIT_ERROR;\n }\n return element;\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initOptions: function (options) {\n this._setOptions(options);\n\n this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0;\n this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0;\n\n if (!this.lowerCanvasEl.style) {\n return;\n }\n\n this.lowerCanvasEl.width = this.width;\n this.lowerCanvasEl.height = this.height;\n\n this.lowerCanvasEl.style.width = this.width + 'px';\n this.lowerCanvasEl.style.height = this.height + 'px';\n\n this.viewportTransform = this.viewportTransform.slice();\n },\n\n /**\n * Creates a bottom canvas\n * @private\n * @param {HTMLElement} [canvasEl]\n */\n _createLowerCanvas: function (canvasEl) {\n this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement(canvasEl);\n\n fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');\n\n if (this.interactive) {\n this._applyCanvasStyle(this.lowerCanvasEl);\n }\n\n this.contextContainer = this.lowerCanvasEl.getContext('2d');\n },\n\n /**\n * Returns canvas width (in px)\n * @return {Number}\n */\n getWidth: function () {\n return this.width;\n },\n\n /**\n * Returns canvas height (in px)\n * @return {Number}\n */\n getHeight: function () {\n return this.height;\n },\n\n /**\n * Sets width of this canvas instance\n * @param {Number|String} value Value to set width to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setWidth: function (value, options) {\n return this.setDimensions({ width: value }, options);\n },\n\n /**\n * Sets height of this canvas instance\n * @param {Number|String} value Value to set height to\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setHeight: function (value, options) {\n return this.setDimensions({ height: value }, options);\n },\n\n /**\n * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n * @param {Object} dimensions Object with width/height properties\n * @param {Number|String} [dimensions.width] Width of canvas element\n * @param {Number|String} [dimensions.height] Height of canvas element\n * @param {Object} [options] Options object\n * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setDimensions: function (dimensions, options) {\n var cssValue;\n\n options = options || {};\n\n for (var prop in dimensions) {\n cssValue = dimensions[prop];\n\n if (!options.cssOnly) {\n this._setBackstoreDimension(prop, dimensions[prop]);\n cssValue += 'px';\n }\n\n if (!options.backstoreOnly) {\n this._setCssDimension(prop, cssValue);\n }\n }\n this._initRetinaScaling();\n this._setImageSmoothing();\n this.calcOffset();\n\n if (!options.cssOnly) {\n this.renderAll();\n }\n\n return this;\n },\n\n /**\n * Helper for setting width/height\n * @private\n * @param {String} prop property (width|height)\n * @param {Number} value value to set property to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n _setBackstoreDimension: function (prop, value) {\n this.lowerCanvasEl[prop] = value;\n\n if (this.upperCanvasEl) {\n this.upperCanvasEl[prop] = value;\n }\n\n if (this.cacheCanvasEl) {\n this.cacheCanvasEl[prop] = value;\n }\n\n this[prop] = value;\n\n return this;\n },\n\n /**\n * Helper for setting css width/height\n * @private\n * @param {String} prop property (width|height)\n * @param {String} value value to set property to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n _setCssDimension: function (prop, value) {\n this.lowerCanvasEl.style[prop] = value;\n\n if (this.upperCanvasEl) {\n this.upperCanvasEl.style[prop] = value;\n }\n\n if (this.wrapperEl) {\n this.wrapperEl.style[prop] = value;\n }\n\n return this;\n },\n\n /**\n * Returns canvas zoom level\n * @return {Number}\n */\n getZoom: function () {\n return this.viewportTransform[0];\n },\n\n /**\n * Sets viewport transform of this canvas instance\n * @param {Array} vpt the transform in the form of context.transform\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setViewportTransform: function (vpt) {\n var activeGroup = this._activeGroup, object, ignoreVpt = false, skipAbsolute = true;\n this.viewportTransform = vpt;\n for (var i = 0, len = this._objects.length; i < len; i++) {\n object = this._objects[i];\n object.group || object.setCoords(ignoreVpt, skipAbsolute);\n }\n if (activeGroup) {\n activeGroup.setCoords(ignoreVpt, skipAbsolute);\n }\n this.calcViewportBoundaries();\n this.renderAll();\n return this;\n },\n\n /**\n * Sets zoom level of this canvas instance, zoom centered around point\n * @param {fabric.Point} point to zoom with respect to\n * @param {Number} value to set zoom to, less than 1 zooms out\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n zoomToPoint: function (point, value) {\n // TODO: just change the scale, preserve other transformations\n var before = point, vpt = this.viewportTransform.slice(0);\n point = transformPoint(point, invertTransform(this.viewportTransform));\n vpt[0] = value;\n vpt[3] = value;\n var after = transformPoint(point, vpt);\n vpt[4] += before.x - after.x;\n vpt[5] += before.y - after.y;\n return this.setViewportTransform(vpt);\n },\n\n /**\n * Sets zoom level of this canvas instance\n * @param {Number} value to set zoom to, less than 1 zooms out\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n setZoom: function (value) {\n this.zoomToPoint(new fabric.Point(0, 0), value);\n return this;\n },\n\n /**\n * Pan viewport so as to place point at top left corner of canvas\n * @param {fabric.Point} point to move to\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n absolutePan: function (point) {\n var vpt = this.viewportTransform.slice(0);\n vpt[4] = -point.x;\n vpt[5] = -point.y;\n return this.setViewportTransform(vpt);\n },\n\n /**\n * Pans viewpoint relatively\n * @param {fabric.Point} point (position vector) to move by\n * @return {fabric.Canvas} instance\n * @chainable true\n */\n relativePan: function (point) {\n return this.absolutePan(new fabric.Point(\n -point.x - this.viewportTransform[4],\n -point.y - this.viewportTransform[5]\n ));\n },\n\n /**\n * Returns <canvas> element corresponding to this instance\n * @return {HTMLCanvasElement}\n */\n getElement: function () {\n return this.lowerCanvasEl;\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was added\n */\n _onObjectAdded: function(obj) {\n this.stateful && obj.setupState();\n obj._set('canvas', this);\n obj.setCoords();\n this.fire('object:added', { target: obj });\n obj.fire('added');\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was removed\n */\n _onObjectRemoved: function(obj) {\n this.fire('object:removed', { target: obj });\n obj.fire('removed');\n delete obj.canvas;\n },\n\n /**\n * Clears specified context of canvas element\n * @param {CanvasRenderingContext2D} ctx Context to clear\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clearContext: function(ctx) {\n ctx.clearRect(0, 0, this.width, this.height);\n return this;\n },\n\n /**\n * Returns context of canvas where objects are drawn\n * @return {CanvasRenderingContext2D}\n */\n getContext: function () {\n return this.contextContainer;\n },\n\n /**\n * Clears all contexts (background, main, top) of an instance\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clear: function () {\n this._objects.length = 0;\n this.backgroundImage = null;\n this.overlayImage = null;\n this.backgroundColor = '';\n this.overlayColor = '';\n if (this._hasITextHandlers) {\n this.off('mouse:up', this._mouseUpITextHandler);\n this._iTextInstances = null;\n this._hasITextHandlers = false;\n }\n this.clearContext(this.contextContainer);\n this.fire('canvas:cleared');\n this.renderAll();\n return this;\n },\n\n /**\n * Renders the canvas\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAll: function () {\n var canvasToDrawOn = this.contextContainer;\n this.renderCanvas(canvasToDrawOn, this._objects);\n return this;\n },\n\n /**\n * Calculate the position of the 4 corner of canvas with current viewportTransform.\n * helps to determinate when an object is in the current rendering viewport using\n * object absolute coordinates ( aCoords )\n * @return {Object} points.tl\n * @chainable\n */\n calcViewportBoundaries: function() {\n var points = { }, width = this.getWidth(), height = this.getHeight(),\n iVpt = invertTransform(this.viewportTransform);\n points.tl = transformPoint({ x: 0, y: 0 }, iVpt);\n points.br = transformPoint({ x: width, y: height }, iVpt);\n points.tr = new fabric.Point(points.br.x, points.tl.y);\n points.bl = new fabric.Point(points.tl.x, points.br.y);\n this.vptCoords = points;\n return points;\n },\n\n /**\n * Renders background, objects, overlay and controls.\n * @param {CanvasRenderingContext2D} ctx\n * @param {Array} objects to render\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderCanvas: function(ctx, objects) {\n this.calcViewportBoundaries();\n this.clearContext(ctx);\n this.fire('before:render');\n if (this.clipTo) {\n fabric.util.clipContext(this, ctx);\n }\n this._renderBackground(ctx);\n\n ctx.save();\n //apply viewport transform once for all rendering process\n ctx.transform.apply(ctx, this.viewportTransform);\n this._renderObjects(ctx, objects);\n ctx.restore();\n if (!this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n if (this.clipTo) {\n ctx.restore();\n }\n this._renderOverlay(ctx);\n if (this.controlsAboveOverlay && this.interactive) {\n this.drawControls(ctx);\n }\n this.fire('after:render');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} objects to render\n */\n _renderObjects: function(ctx, objects) {\n for (var i = 0, length = objects.length; i < length; ++i) {\n objects[i] && objects[i].render(ctx);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {string} property 'background' or 'overlay'\n */\n _renderBackgroundOrOverlay: function(ctx, property) {\n var object = this[property + 'Color'];\n if (object) {\n ctx.fillStyle = object.toLive\n ? object.toLive(ctx, this)\n : object;\n\n ctx.fillRect(\n object.offsetX || 0,\n object.offsetY || 0,\n this.width,\n this.height);\n }\n object = this[property + 'Image'];\n if (object) {\n if (this[property + 'Vpt']) {\n ctx.save();\n ctx.transform.apply(ctx, this.viewportTransform);\n }\n object.render(ctx);\n this[property + 'Vpt'] && ctx.restore();\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground: function(ctx) {\n this._renderBackgroundOrOverlay(ctx, 'background');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderOverlay: function(ctx) {\n this._renderBackgroundOrOverlay(ctx, 'overlay');\n },\n\n /**\n * Returns coordinates of a center of canvas.\n * Returned value is an object with top and left properties\n * @return {Object} object with \"top\" and \"left\" number values\n */\n getCenter: function () {\n return {\n top: this.getHeight() / 2,\n left: this.getWidth() / 2\n };\n },\n\n /**\n * Centers object horizontally in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center horizontally\n * @return {fabric.Canvas} thisArg\n */\n centerObjectH: function (object) {\n return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));\n },\n\n /**\n * Centers object vertically in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObjectV: function (object) {\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));\n },\n\n /**\n * Centers object vertically and horizontally in the canvas\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n centerObject: function(object) {\n var center = this.getCenter();\n\n return this._centerObject(object, new fabric.Point(center.left, center.top));\n },\n\n /**\n * Centers object vertically and horizontally in the viewport\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObject: function(object) {\n var vpCenter = this.getVpCenter();\n\n return this._centerObject(object, vpCenter);\n },\n\n /**\n * Centers object horizontally in the viewport, object.top is unchanged\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObjectH: function(object) {\n var vpCenter = this.getVpCenter();\n this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));\n return this;\n },\n\n /**\n * Centers object Vertically in the viewport, object.top is unchanged\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @param {fabric.Object} object Object to center vertically and horizontally\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n viewportCenterObjectV: function(object) {\n var vpCenter = this.getVpCenter();\n\n return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));\n },\n\n /**\n * Calculate the point in canvas that correspond to the center of actual viewport.\n * @return {fabric.Point} vpCenter, viewport center\n * @chainable\n */\n getVpCenter: function() {\n var center = this.getCenter(),\n iVpt = invertTransform(this.viewportTransform);\n return transformPoint({ x: center.left, y: center.top }, iVpt);\n },\n\n /**\n * @private\n * @param {fabric.Object} object Object to center\n * @param {fabric.Point} center Center point\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n _centerObject: function(object, center) {\n object.setPositionByOrigin(center, 'center', 'center');\n this.renderAll();\n return this;\n },\n\n /**\n * Returs dataless JSON representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} json string\n */\n toDatalessJSON: function (propertiesToInclude) {\n return this.toDatalessObject(propertiesToInclude);\n },\n\n /**\n * Returns object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function (propertiesToInclude) {\n return this._toObjectMethod('toObject', propertiesToInclude);\n },\n\n /**\n * Returns dataless object representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function (propertiesToInclude) {\n return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n },\n\n /**\n * @private\n */\n _toObjectMethod: function (methodName, propertiesToInclude) {\n\n var data = {\n objects: this._toObjects(methodName, propertiesToInclude)\n };\n\n extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));\n\n fabric.util.populateWithProperties(this, data, propertiesToInclude);\n\n return data;\n },\n\n /**\n * @private\n */\n _toObjects: function(methodName, propertiesToInclude) {\n return this.getObjects().filter(function(object) {\n return !object.excludeFromExport;\n }).map(function(instance) {\n return this._toObject(instance, methodName, propertiesToInclude);\n }, this);\n },\n\n /**\n * @private\n */\n _toObject: function(instance, methodName, propertiesToInclude) {\n var originalValue;\n\n if (!this.includeDefaultValues) {\n originalValue = instance.includeDefaultValues;\n instance.includeDefaultValues = false;\n }\n\n var object = instance[methodName](propertiesToInclude);\n if (!this.includeDefaultValues) {\n instance.includeDefaultValues = originalValue;\n }\n return object;\n },\n\n /**\n * @private\n */\n __serializeBgOverlay: function(methodName, propertiesToInclude) {\n var data = { }, bgImage = this.backgroundImage, overlay = this.overlayImage;\n\n if (this.backgroundColor) {\n data.background = this.backgroundColor.toObject\n ? this.backgroundColor.toObject(propertiesToInclude)\n : this.backgroundColor;\n }\n\n if (this.overlayColor) {\n data.overlay = this.overlayColor.toObject\n ? this.overlayColor.toObject(propertiesToInclude)\n : this.overlayColor;\n }\n if (bgImage && !bgImage.excludeFromExport) {\n data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);\n }\n if (overlay && !overlay.excludeFromExport) {\n data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude);\n }\n\n return data;\n },\n\n /* _TO_SVG_START_ */\n /**\n * When true, getSvgTransform() will apply the StaticCanvas.viewportTransform to the SVG transformation. When true,\n * a zoomed canvas will then produce zoomed SVG output.\n * @type Boolean\n * @default\n */\n svgViewportTransformation: true,\n\n /**\n * Returns SVG representation of canvas\n * @function\n * @param {Object} [options] Options object for SVG output\n * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n * @param {Object} [options.viewBox] SVG viewbox object\n * @param {Number} [options.viewBox.x] x-cooridnate of viewbox\n * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n * @param {Number} [options.viewBox.width] Width of viewbox\n * @param {Number} [options.viewBox.height] Height of viewbox\n * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n * @param {String} [options.width] desired width of svg with or without units\n * @param {String} [options.height] desired height of svg with or without units\n * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n * @return {String} SVG string\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n * @example Normal SVG output\n * var svg = canvas.toSVG();\n * @example SVG output without preamble (without <?xml ../>)\n * var svg = canvas.toSVG({suppressPreamble: true});\n * @example SVG output with viewBox attribute\n * var svg = canvas.toSVG({\n * viewBox: {\n * x: 100,\n * y: 100,\n * width: 200,\n * height: 300\n * }\n * });\n * @example SVG output with different encoding (default: UTF-8)\n * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n * @example Modify SVG output with reviver function\n * var svg = canvas.toSVG(null, function(svg) {\n * return svg.replace('stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; ', '');\n * });\n */\n toSVG: function(options, reviver) {\n options || (options = { });\n\n var markup = [];\n\n this._setSVGPreamble(markup, options);\n this._setSVGHeader(markup, options);\n\n this._setSVGBgOverlayColor(markup, 'backgroundColor');\n this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n\n this._setSVGObjects(markup, reviver);\n\n this._setSVGBgOverlayColor(markup, 'overlayColor');\n this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n markup.push('');\n\n return markup.join('');\n },\n\n /**\n * @private\n */\n _setSVGPreamble: function(markup, options) {\n if (options.suppressPreamble) {\n return;\n }\n markup.push(\n '\\n',\n '\\n'\n );\n },\n\n /**\n * @private\n */\n _setSVGHeader: function(markup, options) {\n var width = options.width || this.width,\n height = options.height || this.height,\n vpt, viewBox = 'viewBox=\"0 0 ' + this.width + ' ' + this.height + '\" ',\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n if (options.viewBox) {\n viewBox = 'viewBox=\"' +\n options.viewBox.x + ' ' +\n options.viewBox.y + ' ' +\n options.viewBox.width + ' ' +\n options.viewBox.height + '\" ';\n }\n else {\n if (this.svgViewportTransformation) {\n vpt = this.viewportTransform;\n viewBox = 'viewBox=\"' +\n toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +\n toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '\" ';\n }\n }\n\n markup.push(\n '\\n',\n 'Created with Fabric.js ', fabric.version, '\\n',\n '\\n',\n this.createSVGFontFacesMarkup(),\n this.createSVGRefElementsMarkup(),\n '\\n'\n );\n },\n\n /**\n * Creates markup containing SVG referenced elements like patterns, gradients etc.\n * @return {String}\n */\n createSVGRefElementsMarkup: function() {\n var _this = this,\n markup = ['backgroundColor', 'overlayColor'].map(function(prop) {\n var fill = _this[prop];\n if (fill && fill.toLive) {\n return fill.toSVG(_this, false);\n }\n });\n return markup.join('');\n },\n\n /**\n * Creates markup containing SVG font faces,\n * font URLs for font faces must be collected by developers\n * and are not extracted from the DOM by fabricjs\n * @param {Array} objects Array of fabric objects\n * @return {String}\n */\n createSVGFontFacesMarkup: function() {\n var markup = '', fontList = { }, obj, fontFamily,\n style, row, rowIndex, _char, charIndex,\n fontPaths = fabric.fontPaths, objects = this.getObjects();\n\n for (var i = 0, len = objects.length; i < len; i++) {\n obj = objects[i];\n fontFamily = obj.fontFamily;\n if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {\n continue;\n }\n fontList[fontFamily] = true;\n if (!obj.styles) {\n continue;\n }\n style = obj.styles;\n for (rowIndex in style) {\n row = style[rowIndex];\n for (charIndex in row) {\n _char = row[charIndex];\n fontFamily = _char.fontFamily;\n if (!fontList[fontFamily] && fontPaths[fontFamily]) {\n fontList[fontFamily] = true;\n }\n }\n }\n }\n\n for (var j in fontList) {\n markup += [\n '\\t\\t@font-face {\\n',\n '\\t\\t\\tfont-family: \\'', j, '\\';\\n',\n '\\t\\t\\tsrc: url(\\'', fontPaths[j], '\\');\\n',\n '\\t\\t}\\n'\n ].join('');\n }\n\n if (markup) {\n markup = [\n '\\t\\n'\n ].join('');\n }\n\n return markup;\n },\n\n /**\n * @private\n */\n _setSVGObjects: function(markup, reviver) {\n var instance;\n for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) {\n instance = objects[i];\n if (instance.excludeFromExport) {\n continue;\n }\n this._setSVGObject(markup, instance, reviver);\n }\n },\n\n /**\n * push single object svg representation in the markup\n * @private\n */\n _setSVGObject: function(markup, instance, reviver) {\n markup.push(instance.toSVG(reviver));\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayImage: function(markup, property, reviver) {\n if (this[property] && this[property].toSVG) {\n markup.push(this[property].toSVG(reviver));\n }\n },\n\n /**\n * @private\n */\n _setSVGBgOverlayColor: function(markup, property) {\n var filler = this[property];\n if (!filler) {\n return;\n }\n if (filler.toLive) {\n var repeat = filler.repeat;\n markup.push(\n '\\n'\n );\n }\n else {\n markup.push(\n '\\n'\n );\n }\n },\n /* _TO_SVG_END_ */\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the bottom of the stack of drawn objects\n * @param {fabric.Object} object Object to send to back\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n sendToBack: function (object) {\n if (!object) {\n return this;\n }\n var activeGroup = this._activeGroup,\n i, obj, objs;\n if (object === activeGroup) {\n objs = activeGroup._objects;\n for (i = objs.length; i--;) {\n obj = objs[i];\n removeFromArray(this._objects, obj);\n this._objects.unshift(obj);\n }\n }\n else {\n removeFromArray(this._objects, object);\n this._objects.unshift(object);\n }\n return this.renderAll && this.renderAll();\n },\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the top of the stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n bringToFront: function (object) {\n if (!object) {\n return this;\n }\n var activeGroup = this._activeGroup,\n i, obj, objs;\n if (object === activeGroup) {\n objs = activeGroup._objects;\n for (i = 0; i < objs.length; i++) {\n obj = objs[i];\n removeFromArray(this._objects, obj);\n this._objects.push(obj);\n }\n }\n else {\n removeFromArray(this._objects, object);\n this._objects.push(object);\n }\n return this.renderAll && this.renderAll();\n },\n\n /**\n * Moves an object or a selection down in stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n sendBackwards: function (object, intersecting) {\n if (!object) {\n return this;\n }\n\n var activeGroup = this._activeGroup,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeGroup) {\n objs = activeGroup._objects;\n for (i = 0; i < objs.length; i++) {\n obj = objs[i];\n idx = this._objects.indexOf(obj);\n if (idx > 0 + objsMoved) {\n newIdx = idx - 1;\n removeFromArray(this._objects, obj);\n this._objects.splice(newIdx, 0, obj);\n }\n objsMoved++;\n }\n }\n else {\n idx = this._objects.indexOf(object);\n if (idx !== 0) {\n // if object is not on the bottom of stack\n newIdx = this._findNewLowerIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n }\n }\n this.renderAll && this.renderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewLowerIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse down the stack looking for the nearest intersecting object\n for (var i = idx - 1; i >= 0; --i) {\n\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n object.isContainedWithinObject(this._objects[i]) ||\n this._objects[i].isContainedWithinObject(object);\n\n if (isIntersecting) {\n newIdx = i;\n break;\n }\n }\n }\n else {\n newIdx = idx - 1;\n }\n\n return newIdx;\n },\n\n /**\n * Moves an object or a selection up in stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n bringForward: function (object, intersecting) {\n if (!object) {\n return this;\n }\n\n var activeGroup = this._activeGroup,\n i, obj, idx, newIdx, objs, objsMoved = 0;\n\n if (object === activeGroup) {\n objs = activeGroup._objects;\n for (i = objs.length; i--;) {\n obj = objs[i];\n idx = this._objects.indexOf(obj);\n if (idx < this._objects.length - 1 - objsMoved) {\n newIdx = idx + 1;\n removeFromArray(this._objects, obj);\n this._objects.splice(newIdx, 0, obj);\n }\n objsMoved++;\n }\n }\n else {\n idx = this._objects.indexOf(object);\n if (idx !== this._objects.length - 1) {\n // if object is not on top of stack (last item in an array)\n newIdx = this._findNewUpperIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n }\n }\n this.renderAll && this.renderAll();\n return this;\n },\n\n /**\n * @private\n */\n _findNewUpperIndex: function(object, idx, intersecting) {\n var newIdx;\n\n if (intersecting) {\n newIdx = idx;\n\n // traverse up the stack looking for the nearest intersecting object\n for (var i = idx + 1; i < this._objects.length; ++i) {\n\n var isIntersecting = object.intersectsWithObject(this._objects[i]) ||\n object.isContainedWithinObject(this._objects[i]) ||\n this._objects[i].isContainedWithinObject(object);\n\n if (isIntersecting) {\n newIdx = i;\n break;\n }\n }\n }\n else {\n newIdx = idx + 1;\n }\n\n return newIdx;\n },\n\n /**\n * Moves an object to specified level in stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @param {Number} index Position to move to\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n moveTo: function (object, index) {\n removeFromArray(this._objects, object);\n this._objects.splice(index, 0, object);\n return this.renderAll && this.renderAll();\n },\n\n /**\n * Clears a canvas element and removes all event listeners\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n dispose: function () {\n this.clear();\n return this;\n },\n\n /**\n * Returns a string representation of an instance\n * @return {String} string representation of an instance\n */\n toString: function () {\n return '#';\n }\n });\n\n extend(fabric.StaticCanvas.prototype, fabric.Observable);\n extend(fabric.StaticCanvas.prototype, fabric.Collection);\n extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);\n\n extend(fabric.StaticCanvas, /** @lends fabric.StaticCanvas */ {\n\n /**\n * @static\n * @type String\n * @default\n */\n EMPTY_JSON: '{\"objects\": [], \"background\": \"white\"}',\n\n /**\n * Provides a way to check support of some of the canvas methods\n * (either those of HTMLCanvasElement itself, or rendering context)\n *\n * @param {String} methodName Method to check support for;\n * Could be one of \"getImageData\", \"toDataURL\", \"toDataURLWithQuality\" or \"setLineDash\"\n * @return {Boolean | null} `true` if method is supported (or at least exists),\n * `null` if canvas element or context can not be initialized\n */\n supports: function (methodName) {\n var el = fabric.util.createCanvasElement();\n\n if (!el || !el.getContext) {\n return null;\n }\n\n var ctx = el.getContext('2d');\n if (!ctx) {\n return null;\n }\n\n switch (methodName) {\n\n case 'getImageData':\n return typeof ctx.getImageData !== 'undefined';\n\n case 'setLineDash':\n return typeof ctx.setLineDash !== 'undefined';\n\n case 'toDataURL':\n return typeof el.toDataURL !== 'undefined';\n\n case 'toDataURLWithQuality':\n try {\n el.toDataURL('image/jpeg', 0);\n return true;\n }\n catch (e) { }\n return false;\n\n default:\n return null;\n }\n }\n });\n\n /**\n * Returns JSON representation of canvas\n * @function\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} JSON string\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n * @example JSON without additional properties\n * var json = canvas.toJSON();\n * @example JSON with additional properties included\n * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']);\n * @example JSON without default values\n * canvas.includeDefaultValues = false;\n * var json = canvas.toJSON();\n */\n fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;\n\n})();\n\n\n/**\n * BaseBrush class\n * @class fabric.BaseBrush\n * @see {@link http://fabricjs.com/freedrawing|Freedrawing demo}\n */\nfabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype */ {\n\n /**\n * Color of a brush\n * @type String\n * @default\n */\n color: 'rgb(0, 0, 0)',\n\n /**\n * Width of a brush\n * @type Number\n * @default\n */\n width: 1,\n\n /**\n * Shadow object representing shadow of this shape.\n * Backwards incompatibility note: This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\n * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n * @type String\n * @default\n */\n strokeLineCap: 'round',\n\n /**\n * Corner style of a brush (one of \"bevil\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'round',\n\n /**\n * Stroke Dash Array.\n * @type Array\n * @default\n */\n strokeDashArray: null,\n\n /**\n * Sets shadow of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setShadow: function(options) {\n this.shadow = new fabric.Shadow(options);\n return this;\n },\n\n /**\n * Sets brush styles\n * @private\n */\n _setBrushStyles: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.width;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n if (this.strokeDashArray && fabric.StaticCanvas.supports('setLineDash')) {\n ctx.setLineDash(this.strokeDashArray);\n }\n },\n\n /**\n * Sets brush shadow styles\n * @private\n */\n _setShadow: function() {\n if (!this.shadow) {\n return;\n }\n\n var ctx = this.canvas.contextTop,\n zoom = this.canvas.getZoom();\n\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur * zoom;\n ctx.shadowOffsetX = this.shadow.offsetX * zoom;\n ctx.shadowOffsetY = this.shadow.offsetY * zoom;\n },\n\n /**\n * Removes brush shadow styles\n * @private\n */\n _resetShadow: function() {\n var ctx = this.canvas.contextTop;\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n }\n});\n\n\n(function() {\n\n /**\n * PencilBrush class\n * @class fabric.PencilBrush\n * @extends fabric.BaseBrush\n */\n fabric.PencilBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.PencilBrush.prototype */ {\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.PencilBrush} Instance of a pencil brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this._points = [];\n },\n\n /**\n * Inovoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer) {\n this._prepareForDrawing(pointer);\n // capture coordinates immediately\n // this allows to draw dots (when movement never occurs)\n this._captureDrawingPath(pointer);\n this._render();\n },\n\n /**\n * Inovoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this._captureDrawingPath(pointer);\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n this._finalizeAndAddPath();\n },\n\n /**\n * @private\n * @param {Object} pointer Actual mouse position related to the canvas.\n */\n _prepareForDrawing: function(pointer) {\n\n var p = new fabric.Point(pointer.x, pointer.y);\n\n this._reset();\n this._addPoint(p);\n\n this.canvas.contextTop.moveTo(p.x, p.y);\n },\n\n /**\n * @private\n * @param {fabric.Point} point Point to be added to points array\n */\n _addPoint: function(point) {\n if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {\n return;\n }\n this._points.push(point);\n },\n\n /**\n * Clear points array and set contextTop canvas style.\n * @private\n */\n _reset: function() {\n this._points.length = 0;\n\n this._setBrushStyles();\n this._setShadow();\n },\n\n /**\n * @private\n * @param {Object} pointer Actual mouse position related to the canvas.\n */\n _captureDrawingPath: function(pointer) {\n var pointerPoint = new fabric.Point(pointer.x, pointer.y);\n this._addPoint(pointerPoint);\n },\n\n /**\n * Draw a smooth path on the topCanvas using quadraticCurveTo\n * @private\n */\n _render: function() {\n var ctx = this.canvas.contextTop, i, len,\n v = this.canvas.viewportTransform,\n p1 = this._points[0],\n p2 = this._points[1];\n\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n ctx.beginPath();\n\n //if we only have 2 points in the path and they are the same\n //it means that the user only clicked the canvas without moving the mouse\n //then we should be drawing a dot. A path isn't drawn between two identical dots\n //that's why we set them apart a bit\n if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\n var width = this.width / 1000;\n p1 = new fabric.Point(p1.x, p1.y);\n p2 = new fabric.Point(p2.x, p2.y);\n p1.x -= width;\n p2.x += width;\n }\n ctx.moveTo(p1.x, p1.y);\n\n for (i = 1, len = this._points.length; i < len; i++) {\n // we pick the point between pi + 1 & pi + 2 as the\n // end point and p1 as our control point.\n var midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n\n p1 = this._points[i];\n p2 = this._points[i + 1];\n }\n // Draw last line as a straight line while\n // we wait for the next point to be able to calculate\n // the bezier control point\n ctx.lineTo(p1.x, p1.y);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Converts points to SVG path\n * @param {Array} points Array of points\n * @return {String} SVG path\n */\n convertPointsToSVGPath: function(points) {\n var path = [], i, width = this.width / 1000,\n p1 = new fabric.Point(points[0].x, points[0].y),\n p2 = new fabric.Point(points[1].x, points[1].y),\n len = points.length, multSignX = 1, multSignY = 1, manyPoints = len > 2;\n\n if (manyPoints) {\n multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;\n multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;\n }\n path.push('M ', p1.x - multSignX * width, ' ', p1.y - multSignY * width, ' ');\n for (i = 1; i < len; i++) {\n if (!p1.eq(p2)) {\n var midPoint = p1.midPointFrom(p2);\n // p1 is our bezier control point\n // midpoint is our endpoint\n // start point is p(i-1) value.\n path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');\n }\n p1 = points[i];\n if ((i + 1) < points.length) {\n p2 = points[i + 1];\n }\n }\n if (manyPoints) {\n multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;\n multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;\n }\n path.push('L ', p1.x + multSignX * width, ' ', p1.y + multSignY * width);\n return path;\n },\n\n /**\n * Creates fabric.Path object to add on canvas\n * @param {String} pathData Path data\n * @return {fabric.Path} Path to add on canvas\n */\n createPath: function(pathData) {\n var path = new fabric.Path(pathData, {\n fill: null,\n stroke: this.color,\n strokeWidth: this.width,\n strokeLineCap: this.strokeLineCap,\n strokeLineJoin: this.strokeLineJoin,\n strokeDashArray: this.strokeDashArray,\n originX: 'center',\n originY: 'center'\n });\n var position = new fabric.Point(path.left, path.top);\n path.originX = fabric.Object.prototype.originX;\n path.originY = fabric.Object.prototype.originY;\n position = path.translateToGivenOrigin(\n position, 'center', 'center', path.originX, path.originY);\n path.top = position.y;\n path.left = position.x;\n if (this.shadow) {\n this.shadow.affectStroke = true;\n path.setShadow(this.shadow);\n }\n\n return path;\n },\n\n /**\n * On mouseup after drawing the path on contextTop canvas\n * we use the points captured to create an new fabric path object\n * and add it to the fabric canvas.\n */\n _finalizeAndAddPath: function() {\n var ctx = this.canvas.contextTop;\n ctx.closePath();\n\n var pathData = this.convertPointsToSVGPath(this._points).join('');\n if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {\n // do not create 0 width/height paths, as they are\n // rendered inconsistently across browsers\n // Firefox 4, for example, renders a dot,\n // whereas Chrome 10 renders nothing\n this.canvas.renderAll();\n return;\n }\n\n var path = this.createPath(pathData);\n\n this.canvas.add(path);\n path.setCoords();\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderAll();\n\n // fire event 'path' created\n this.canvas.fire('path:created', { path: path });\n }\n });\n})();\n\n\n/**\n * CircleBrush class\n * @class fabric.CircleBrush\n */\nfabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric.CircleBrush.prototype */ {\n\n /**\n * Width of a brush\n * @type Number\n * @default\n */\n width: 10,\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.CircleBrush} Instance of a circle brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this.points = [];\n },\n\n /**\n * Invoked inside on mouse down and mouse move\n * @param {Object} pointer\n */\n drawDot: function(pointer) {\n var point = this.addPoint(pointer),\n ctx = this.canvas.contextTop,\n v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n\n ctx.fillStyle = point.fill;\n ctx.beginPath();\n ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\n ctx.closePath();\n ctx.fill();\n\n ctx.restore();\n },\n\n /**\n * Invoked on mouse down\n */\n onMouseDown: function(pointer) {\n this.points.length = 0;\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n this.drawDot(pointer);\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.drawDot(pointer);\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n this.canvas.renderOnAddRemove = false;\n\n var circles = [];\n\n for (var i = 0, len = this.points.length; i < len; i++) {\n var point = this.points[i],\n circle = new fabric.Circle({\n radius: point.radius,\n left: point.x,\n top: point.y,\n originX: 'center',\n originY: 'center',\n fill: point.fill\n });\n\n this.shadow && circle.setShadow(this.shadow);\n\n circles.push(circle);\n }\n var group = new fabric.Group(circles, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.renderAll();\n },\n\n /**\n * @param {Object} pointer\n * @return {fabric.Point} Just added pointer point\n */\n addPoint: function(pointer) {\n var pointerPoint = new fabric.Point(pointer.x, pointer.y),\n\n circleRadius = fabric.util.getRandomInt(\n Math.max(0, this.width - 20), this.width + 20) / 2,\n\n circleColor = new fabric.Color(this.color)\n .setAlpha(fabric.util.getRandomInt(0, 100) / 100)\n .toRgba();\n\n pointerPoint.radius = circleRadius;\n pointerPoint.fill = circleColor;\n\n this.points.push(pointerPoint);\n\n return pointerPoint;\n }\n});\n\n\n/**\n * SprayBrush class\n * @class fabric.SprayBrush\n */\nfabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric.SprayBrush.prototype */ {\n\n /**\n * Width of a spray\n * @type Number\n * @default\n */\n width: 10,\n\n /**\n * Density of a spray (number of dots per chunk)\n * @type Number\n * @default\n */\n density: 20,\n\n /**\n * Width of spray dots\n * @type Number\n * @default\n */\n dotWidth: 1,\n\n /**\n * Width variance of spray dots\n * @type Number\n * @default\n */\n dotWidthVariance: 1,\n\n /**\n * Whether opacity of a dot should be random\n * @type Boolean\n * @default\n */\n randomOpacity: false,\n\n /**\n * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n * @type Boolean\n * @default\n */\n optimizeOverlapping: true,\n\n /**\n * Constructor\n * @param {fabric.Canvas} canvas\n * @return {fabric.SprayBrush} Instance of a spray brush\n */\n initialize: function(canvas) {\n this.canvas = canvas;\n this.sprayChunks = [];\n },\n\n /**\n * Invoked on mouse down\n * @param {Object} pointer\n */\n onMouseDown: function(pointer) {\n this.sprayChunks.length = 0;\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n\n this.addSprayChunk(pointer);\n this.render();\n },\n\n /**\n * Invoked on mouse move\n * @param {Object} pointer\n */\n onMouseMove: function(pointer) {\n this.addSprayChunk(pointer);\n this.render();\n },\n\n /**\n * Invoked on mouse up\n */\n onMouseUp: function() {\n var originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n this.canvas.renderOnAddRemove = false;\n\n var rects = [];\n\n for (var i = 0, ilen = this.sprayChunks.length; i < ilen; i++) {\n var sprayChunk = this.sprayChunks[i];\n\n for (var j = 0, jlen = sprayChunk.length; j < jlen; j++) {\n\n var rect = new fabric.Rect({\n width: sprayChunk[j].width,\n height: sprayChunk[j].width,\n left: sprayChunk[j].x + 1,\n top: sprayChunk[j].y + 1,\n originX: 'center',\n originY: 'center',\n fill: this.color\n });\n\n this.shadow && rect.setShadow(this.shadow);\n rects.push(rect);\n }\n }\n\n if (this.optimizeOverlapping) {\n rects = this._getOptimizedRects(rects);\n }\n\n var group = new fabric.Group(rects, { originX: 'center', originY: 'center' });\n group.canvas = this.canvas;\n\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.renderAll();\n },\n\n /**\n * @private\n * @param {Array} rects\n */\n _getOptimizedRects: function(rects) {\n\n // avoid creating duplicate rects at the same coordinates\n var uniqueRects = { }, key;\n\n for (var i = 0, len = rects.length; i < len; i++) {\n key = rects[i].left + '' + rects[i].top;\n if (!uniqueRects[key]) {\n uniqueRects[key] = rects[i];\n }\n }\n var uniqueRectsArray = [];\n for (key in uniqueRects) {\n uniqueRectsArray.push(uniqueRects[key]);\n }\n\n return uniqueRectsArray;\n },\n\n /**\n * Renders brush\n */\n render: function() {\n var ctx = this.canvas.contextTop;\n ctx.fillStyle = this.color;\n\n var v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n\n for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {\n var point = this.sprayChunkPoints[i];\n if (typeof point.opacity !== 'undefined') {\n ctx.globalAlpha = point.opacity;\n }\n ctx.fillRect(point.x, point.y, point.width, point.width);\n }\n ctx.restore();\n },\n\n /**\n * @param {Object} pointer\n */\n addSprayChunk: function(pointer) {\n this.sprayChunkPoints = [];\n\n var x, y, width, radius = this.width / 2;\n\n for (var i = 0; i < this.density; i++) {\n\n x = fabric.util.getRandomInt(pointer.x - radius, pointer.x + radius);\n y = fabric.util.getRandomInt(pointer.y - radius, pointer.y + radius);\n\n if (this.dotWidthVariance) {\n width = fabric.util.getRandomInt(\n // bottom clamp width to 1\n Math.max(1, this.dotWidth - this.dotWidthVariance),\n this.dotWidth + this.dotWidthVariance);\n }\n else {\n width = this.dotWidth;\n }\n\n var point = new fabric.Point(x, y);\n point.width = width;\n\n if (this.randomOpacity) {\n point.opacity = fabric.util.getRandomInt(0, 100) / 100;\n }\n\n this.sprayChunkPoints.push(point);\n }\n\n this.sprayChunks.push(this.sprayChunkPoints);\n }\n});\n\n\n/**\n * PatternBrush class\n * @class fabric.PatternBrush\n * @extends fabric.BaseBrush\n */\nfabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.PatternBrush.prototype */ {\n\n getPatternSrc: function() {\n\n var dotWidth = 20,\n dotDistance = 5,\n patternCanvas = fabric.document.createElement('canvas'),\n patternCtx = patternCanvas.getContext('2d');\n\n patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n\n patternCtx.fillStyle = this.color;\n patternCtx.beginPath();\n patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false);\n patternCtx.closePath();\n patternCtx.fill();\n\n return patternCanvas;\n },\n\n getPatternSrcFunction: function() {\n return String(this.getPatternSrc).replace('this.color', '\"' + this.color + '\"');\n },\n\n /**\n * Creates \"pattern\" instance property\n */\n getPattern: function() {\n return this.canvas.contextTop.createPattern(this.source || this.getPatternSrc(), 'repeat');\n },\n\n /**\n * Sets brush styles\n */\n _setBrushStyles: function() {\n this.callSuper('_setBrushStyles');\n this.canvas.contextTop.strokeStyle = this.getPattern();\n },\n\n /**\n * Creates path\n */\n createPath: function(pathData) {\n var path = this.callSuper('createPath', pathData),\n topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\n\n path.stroke = new fabric.Pattern({\n source: this.source || this.getPatternSrcFunction(),\n offsetX: -topLeft.x,\n offsetY: -topLeft.y\n });\n return path;\n }\n});\n\n\n(function() {\n\n var getPointer = fabric.util.getPointer,\n degreesToRadians = fabric.util.degreesToRadians,\n radiansToDegrees = fabric.util.radiansToDegrees,\n atan2 = Math.atan2,\n abs = Math.abs,\n supportLineDash = fabric.StaticCanvas.supports('setLineDash'),\n\n STROKE_OFFSET = 0.5;\n\n /**\n * Canvas class\n * @class fabric.Canvas\n * @extends fabric.StaticCanvas\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#canvas}\n * @see {@link fabric.Canvas#initialize} for constructor definition\n *\n * @fires object:added\n * @fires object:modified\n * @fires object:rotating\n * @fires object:scaling\n * @fires object:moving\n * @fires object:selected\n *\n * @fires before:selection:cleared\n * @fires selection:cleared\n * @fires selection:created\n *\n * @fires path:created\n * @fires mouse:down\n * @fires mouse:move\n * @fires mouse:up\n * @fires mouse:over\n * @fires mouse:out\n *\n */\n fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Constructor\n * @param {HTMLElement | String} el <canvas> element to initialize instance on\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(el, options) {\n options || (options = { });\n\n this._initStatic(el, options);\n this._initInteractive();\n this._createCacheCanvas();\n },\n\n /**\n * When true, objects can be transformed by one side (unproportionally)\n * @type Boolean\n * @default\n */\n uniScaleTransform: false,\n\n /**\n * Indicates which key enable unproportional scaling\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n uniScaleKey: 'shiftKey',\n\n /**\n * When true, objects use center point as the origin of scale transformation.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredScaling: false,\n\n /**\n * When true, objects use center point as the origin of rotate transformation.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredRotation: false,\n\n /**\n * Indicates which key enable centered Transfrom\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n centeredKey: 'altKey',\n\n /**\n * Indicates which key enable alternate action on corner\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n altActionKey: 'shiftKey',\n\n /**\n * Indicates that canvas is interactive. This property should not be changed.\n * @type Boolean\n * @default\n */\n interactive: true,\n\n /**\n * Indicates whether group selection should be enabled\n * @type Boolean\n * @default\n */\n selection: true,\n\n /**\n * Indicates which key enable multiple click selection\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type String\n * @default\n */\n selectionKey: 'shiftKey',\n\n /**\n * Indicates which key enable alternative selection\n * in case of target overlapping with active object\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.5\n * @type null|String\n * @default\n */\n altSelectionKey: null,\n\n /**\n * Color of selection\n * @type String\n * @default\n */\n selectionColor: 'rgba(100, 100, 255, 0.3)', // blue\n\n /**\n * Default dash array pattern\n * If not empty the selection border is dashed\n * @type Array\n */\n selectionDashArray: [],\n\n /**\n * Color of the border of selection (usually slightly darker than color of selection itself)\n * @type String\n * @default\n */\n selectionBorderColor: 'rgba(255, 255, 255, 0.3)',\n\n /**\n * Width of a line used in object/group selection\n * @type Number\n * @default\n */\n selectionLineWidth: 1,\n\n /**\n * Default cursor value used when hovering over an object on canvas\n * @type String\n * @default\n */\n hoverCursor: 'move',\n\n /**\n * Default cursor value used when moving an object on canvas\n * @type String\n * @default\n */\n moveCursor: 'move',\n\n /**\n * Default cursor value used for the entire canvas\n * @type String\n * @default\n */\n defaultCursor: 'default',\n\n /**\n * Cursor value used during free drawing\n * @type String\n * @default\n */\n freeDrawingCursor: 'crosshair',\n\n /**\n * Cursor value used for rotation point\n * @type String\n * @default\n */\n rotationCursor: 'crosshair',\n\n /**\n * Default element class that's given to wrapper (div) element of canvas\n * @type String\n * @default\n */\n containerClass: 'canvas-container',\n\n /**\n * When true, object detection happens on per-pixel basis rather than on per-bounding-box\n * @type Boolean\n * @default\n */\n perPixelTargetFind: false,\n\n /**\n * Number of pixels around target pixel to tolerate (consider active) during object detection\n * @type Number\n * @default\n */\n targetFindTolerance: 0,\n\n /**\n * When true, target detection is skipped when hovering over canvas. This can be used to improve performance.\n * @type Boolean\n * @default\n */\n skipTargetFind: false,\n\n /**\n * When true, mouse events on canvas (mousedown/mousemove/mouseup) result in free drawing.\n * After mousedown, mousemove creates a shape,\n * and then mouseup finalizes it and adds an instance of `fabric.Path` onto canvas.\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\n * @type Boolean\n * @default\n */\n isDrawingMode: false,\n\n /**\n * Indicates whether objects should remain in current stack position when selected.\n * When false objects are brought to top and rendered as part of the selection group\n * @type Boolean\n * @default\n */\n preserveObjectStacking: false,\n\n /**\n * Indicates the angle that an object will lock to while rotating.\n * @type Number\n * @since 1.6.7\n * @default\n */\n snapAngle: 0,\n\n /**\n * Indicates the distance from the snapAngle the rotation will lock to the snapAngle.\n * When `null`, the snapThreshold will default to the snapAngle.\n * @type null|Number\n * @since 1.6.7\n * @default\n */\n snapThreshold: null,\n\n /**\n * Indicates if the right click on canvas can output the context menu or not\n * @type Boolean\n * @since 1.6.5\n * @default\n */\n stopContextMenu: false,\n\n /**\n * Indicates if the canvas can fire right click events\n * @type Boolean\n * @since 1.6.5\n * @default\n */\n fireRightClick: false,\n\n /**\n * Indicates if the canvas can fire middle click events\n * @type Boolean\n * @since 1.7.8\n * @default\n */\n fireMiddleClick: false,\n\n /**\n * @private\n */\n _initInteractive: function() {\n this._currentTransform = null;\n this._groupSelector = null;\n this._initWrapperElement();\n this._createUpperCanvas();\n this._initEventListeners();\n\n this._initRetinaScaling();\n\n this.freeDrawingBrush = fabric.PencilBrush && new fabric.PencilBrush(this);\n\n this.calcOffset();\n },\n\n /**\n * Divides objects in two groups, one to render immediately\n * and one to render as activeGroup.\n * @return {Array} objects to render immediately and pushes the other in the activeGroup.\n */\n _chooseObjectsToRender: function() {\n var activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject(),\n object, objsToRender = [], activeGroupObjects = [];\n\n if ((activeGroup || activeObject) && !this.preserveObjectStacking) {\n for (var i = 0, length = this._objects.length; i < length; i++) {\n object = this._objects[i];\n if ((!activeGroup || !activeGroup.contains(object)) && object !== activeObject) {\n objsToRender.push(object);\n }\n else {\n activeGroupObjects.push(object);\n }\n }\n if (activeGroup) {\n activeGroup._set('_objects', activeGroupObjects);\n objsToRender.push(activeGroup);\n }\n activeObject && objsToRender.push(activeObject);\n }\n else {\n objsToRender = this._objects;\n }\n return objsToRender;\n },\n\n /**\n * Renders both the top canvas and the secondary container canvas.\n * @return {fabric.Canvas} instance\n * @chainable\n */\n renderAll: function () {\n if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\n this.clearContext(this.contextTop);\n this.contextTopDirty = false;\n }\n var canvasToDrawOn = this.contextContainer;\n this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());\n return this;\n },\n\n /**\n * Method to render only the top canvas.\n * Also used to render the group selection box.\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n renderTop: function () {\n var ctx = this.contextTop;\n this.clearContext(ctx);\n\n // we render the top context - last object\n if (this.selection && this._groupSelector) {\n this._drawSelection(ctx);\n }\n\n this.fire('after:render');\n this.contextTopDirty = true;\n return this;\n },\n\n /**\n * Resets the current transform to its original values and chooses the type of resizing based on the event\n * @private\n */\n _resetCurrentTransform: function() {\n var t = this._currentTransform;\n\n t.target.set({\n scaleX: t.original.scaleX,\n scaleY: t.original.scaleY,\n skewX: t.original.skewX,\n skewY: t.original.skewY,\n left: t.original.left,\n top: t.original.top\n });\n\n if (this._shouldCenterTransform(t.target)) {\n if (t.action === 'rotate') {\n this._setOriginToCenter(t.target);\n }\n else {\n if (t.originX !== 'center') {\n if (t.originX === 'right') {\n t.mouseXSign = -1;\n }\n else {\n t.mouseXSign = 1;\n }\n }\n if (t.originY !== 'center') {\n if (t.originY === 'bottom') {\n t.mouseYSign = -1;\n }\n else {\n t.mouseYSign = 1;\n }\n }\n\n t.originX = 'center';\n t.originY = 'center';\n }\n }\n else {\n t.originX = t.original.originX;\n t.originY = t.original.originY;\n }\n },\n\n /**\n * Checks if point is contained within an area of given object\n * @param {Event} e Event object\n * @param {fabric.Object} target Object to test against\n * @param {Object} [point] x,y object of point coordinates we want to check.\n * @return {Boolean} true if point is contained within an area of given object\n */\n containsPoint: function (e, target, point) {\n var ignoreZoom = true,\n pointer = point || this.getPointer(e, ignoreZoom),\n xy;\n\n if (target.group && target.group === this.getActiveGroup()) {\n xy = this._normalizePointer(target.group, pointer);\n }\n else {\n xy = { x: pointer.x, y: pointer.y };\n }\n // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html\n // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html\n return (target.containsPoint(xy) || target._findTargetCorner(pointer));\n },\n\n /**\n * @private\n */\n _normalizePointer: function (object, pointer) {\n var m = object.calcTransformMatrix(),\n invertedM = fabric.util.invertTransform(m),\n vptPointer = this.restorePointerVpt(pointer);\n return fabric.util.transformPoint(vptPointer, invertedM);\n },\n\n /**\n * Returns true if object is transparent at a certain location\n * @param {fabric.Object} target Object to check\n * @param {Number} x Left coordinate\n * @param {Number} y Top coordinate\n * @return {Boolean}\n */\n isTargetTransparent: function (target, x, y) {\n var hasBorders = target.hasBorders,\n transparentCorners = target.transparentCorners,\n ctx = this.contextCache,\n originalColor = target.selectionBackgroundColor;\n\n target.hasBorders = target.transparentCorners = false;\n target.selectionBackgroundColor = '';\n\n ctx.save();\n ctx.transform.apply(ctx, this.viewportTransform);\n target.render(ctx);\n ctx.restore();\n\n target.active && target._renderControls(ctx);\n\n target.hasBorders = hasBorders;\n target.transparentCorners = transparentCorners;\n target.selectionBackgroundColor = originalColor;\n\n var isTransparent = fabric.util.isTransparent(\n ctx, x, y, this.targetFindTolerance);\n\n this.clearContext(ctx);\n\n return isTransparent;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _shouldClearSelection: function (e, target) {\n var activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject();\n\n return (\n !target\n ||\n (target &&\n activeGroup &&\n !activeGroup.contains(target) &&\n activeGroup !== target &&\n !e[this.selectionKey])\n ||\n (target && !target.evented)\n ||\n (target &&\n !target.selectable &&\n activeObject &&\n activeObject !== target)\n );\n },\n\n /**\n * @private\n * @param {fabric.Object} target\n */\n _shouldCenterTransform: function (target) {\n if (!target) {\n return;\n }\n\n var t = this._currentTransform,\n centerTransform;\n\n if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') {\n centerTransform = this.centeredScaling || target.centeredScaling;\n }\n else if (t.action === 'rotate') {\n centerTransform = this.centeredRotation || target.centeredRotation;\n }\n\n return centerTransform ? !t.altKey : t.altKey;\n },\n\n /**\n * @private\n */\n _getOriginFromCorner: function(target, corner) {\n var origin = {\n x: target.originX,\n y: target.originY\n };\n\n if (corner === 'ml' || corner === 'tl' || corner === 'bl') {\n origin.x = 'right';\n }\n else if (corner === 'mr' || corner === 'tr' || corner === 'br') {\n origin.x = 'left';\n }\n\n if (corner === 'tl' || corner === 'mt' || corner === 'tr') {\n origin.y = 'bottom';\n }\n else if (corner === 'bl' || corner === 'mb' || corner === 'br') {\n origin.y = 'top';\n }\n\n return origin;\n },\n\n /**\n * @private\n */\n _getActionFromCorner: function(target, corner, e) {\n if (!corner) {\n return 'drag';\n }\n\n switch (corner) {\n case 'mtr':\n return 'rotate';\n case 'ml':\n case 'mr':\n return e[this.altActionKey] ? 'skewY' : 'scaleX';\n case 'mt':\n case 'mb':\n return e[this.altActionKey] ? 'skewX' : 'scaleY';\n default:\n return 'scale';\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _setupCurrentTransform: function (e, target) {\n if (!target) {\n return;\n }\n\n var pointer = this.getPointer(e),\n corner = target._findTargetCorner(this.getPointer(e, true)),\n action = this._getActionFromCorner(target, corner, e),\n origin = this._getOriginFromCorner(target, corner);\n\n this._currentTransform = {\n target: target,\n action: action,\n corner: corner,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n offsetX: pointer.x - target.left,\n offsetY: pointer.y - target.top,\n originX: origin.x,\n originY: origin.y,\n ex: pointer.x,\n ey: pointer.y,\n lastX: pointer.x,\n lastY: pointer.y,\n left: target.left,\n top: target.top,\n theta: degreesToRadians(target.angle),\n width: target.width * target.scaleX,\n mouseXSign: 1,\n mouseYSign: 1,\n shiftKey: e.shiftKey,\n altKey: e[this.centeredKey]\n };\n\n this._currentTransform.original = {\n left: target.left,\n top: target.top,\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n originX: origin.x,\n originY: origin.y\n };\n\n this._resetCurrentTransform();\n },\n\n /**\n * Translates object by \"setting\" its left/top\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @return {Boolean} true if the translation occurred\n */\n _translateObject: function (x, y) {\n var transform = this._currentTransform,\n target = transform.target,\n newLeft = x - transform.offsetX,\n newTop = y - transform.offsetY,\n moveX = !target.get('lockMovementX') && target.left !== newLeft,\n moveY = !target.get('lockMovementY') && target.top !== newTop;\n\n moveX && target.set('left', newLeft);\n moveY && target.set('top', newTop);\n return moveX || moveY;\n },\n\n /**\n * Check if we are increasing a positive skew or lower it,\n * checking mouse direction and pressed corner.\n * @private\n */\n _changeSkewTransformOrigin: function(mouseMove, t, by) {\n var property = 'originX', origins = { 0: 'center' },\n skew = t.target.skewX, originA = 'left', originB = 'right',\n corner = t.corner === 'mt' || t.corner === 'ml' ? 1 : -1,\n flipSign = 1;\n\n mouseMove = mouseMove > 0 ? 1 : -1;\n if (by === 'y') {\n skew = t.target.skewY;\n originA = 'top';\n originB = 'bottom';\n property = 'originY';\n }\n origins[-1] = originA;\n origins[1] = originB;\n\n t.target.flipX && (flipSign *= -1);\n t.target.flipY && (flipSign *= -1);\n\n if (skew === 0) {\n t.skewSign = -corner * mouseMove * flipSign;\n t[property] = origins[-mouseMove];\n }\n else {\n skew = skew > 0 ? 1 : -1;\n t.skewSign = skew;\n t[property] = origins[skew * corner * flipSign];\n }\n },\n\n /**\n * Skew object by mouse events\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @param {String} by Either 'x' or 'y'\n * @return {Boolean} true if the skewing occurred\n */\n _skewObject: function (x, y, by) {\n var t = this._currentTransform,\n target = t.target, skewed = false,\n lockSkewingX = target.get('lockSkewingX'),\n lockSkewingY = target.get('lockSkewingY');\n\n if ((lockSkewingX && by === 'x') || (lockSkewingY && by === 'y')) {\n return false;\n }\n\n // Get the constraint point\n var center = target.getCenterPoint(),\n actualMouseByCenter = target.toLocalPoint(new fabric.Point(x, y), 'center', 'center')[by],\n lastMouseByCenter = target.toLocalPoint(new fabric.Point(t.lastX, t.lastY), 'center', 'center')[by],\n actualMouseByOrigin, constraintPosition, dim = target._getTransformedDimensions();\n\n this._changeSkewTransformOrigin(actualMouseByCenter - lastMouseByCenter, t, by);\n actualMouseByOrigin = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY)[by];\n constraintPosition = target.translateToOriginPoint(center, t.originX, t.originY);\n // Actually skew the object\n skewed = this._setObjectSkew(actualMouseByOrigin, t, by, dim);\n t.lastX = x;\n t.lastY = y;\n // Make sure the constraints apply\n target.setPositionByOrigin(constraintPosition, t.originX, t.originY);\n return skewed;\n },\n\n /**\n * Set object skew\n * @private\n * @return {Boolean} true if the skewing occurred\n */\n _setObjectSkew: function(localMouse, transform, by, _dim) {\n var target = transform.target, newValue, skewed = false,\n skewSign = transform.skewSign, newDim, dimNoSkew,\n otherBy, _otherBy, _by, newDimMouse, skewX, skewY;\n\n if (by === 'x') {\n otherBy = 'y';\n _otherBy = 'Y';\n _by = 'X';\n skewX = 0;\n skewY = target.skewY;\n }\n else {\n otherBy = 'x';\n _otherBy = 'X';\n _by = 'Y';\n skewX = target.skewX;\n skewY = 0;\n }\n\n dimNoSkew = target._getTransformedDimensions(skewX, skewY);\n newDimMouse = 2 * Math.abs(localMouse) - dimNoSkew[by];\n if (newDimMouse <= 2) {\n newValue = 0;\n }\n else {\n newValue = skewSign * Math.atan((newDimMouse / target['scale' + _by]) /\n (dimNoSkew[otherBy] / target['scale' + _otherBy]));\n newValue = fabric.util.radiansToDegrees(newValue);\n }\n skewed = target['skew' + _by] !== newValue;\n target.set('skew' + _by, newValue);\n if (target['skew' + _otherBy] !== 0) {\n newDim = target._getTransformedDimensions();\n newValue = (_dim[otherBy] / newDim[otherBy]) * target['scale' + _otherBy];\n target.set('scale' + _otherBy, newValue);\n }\n return skewed;\n },\n\n /**\n * Scales object by invoking its scaleX/scaleY methods\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @param {String} by Either 'x' or 'y' - specifies dimension constraint by which to scale an object.\n * When not provided, an object is scaled by both dimensions equally\n * @return {Boolean} true if the scaling occurred\n */\n _scaleObject: function (x, y, by) {\n var t = this._currentTransform,\n target = t.target,\n lockScalingX = target.get('lockScalingX'),\n lockScalingY = target.get('lockScalingY'),\n lockScalingFlip = target.get('lockScalingFlip');\n\n if (lockScalingX && lockScalingY) {\n return false;\n }\n\n // Get the constraint point\n var constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY),\n localMouse = target.toLocalPoint(new fabric.Point(x, y), t.originX, t.originY),\n dim = target._getTransformedDimensions(), scaled = false;\n\n this._setLocalMouse(localMouse, t);\n\n // Actually scale the object\n scaled = this._setObjectScale(localMouse, t, lockScalingX, lockScalingY, by, lockScalingFlip, dim);\n\n // Make sure the constraints apply\n target.setPositionByOrigin(constraintPosition, t.originX, t.originY);\n return scaled;\n },\n\n /**\n * @private\n * @return {Boolean} true if the scaling occurred\n */\n _setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {\n var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false,\n changeX, changeY, scaleX, scaleY;\n\n scaleX = localMouse.x * target.scaleX / _dim.x;\n scaleY = localMouse.y * target.scaleY / _dim.y;\n changeX = target.scaleX !== scaleX;\n changeY = target.scaleY !== scaleY;\n\n if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) {\n forbidScalingX = true;\n }\n\n if (lockScalingFlip && scaleY <= 0 && scaleY < target.scaleY) {\n forbidScalingY = true;\n }\n\n if (by === 'equally' && !lockScalingX && !lockScalingY) {\n forbidScalingX || forbidScalingY || (scaled = this._scaleObjectEqually(localMouse, target, transform, _dim));\n }\n else if (!by) {\n forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX));\n forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));\n }\n else if (by === 'x' && !target.get('lockUniScaling')) {\n forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX));\n }\n else if (by === 'y' && !target.get('lockUniScaling')) {\n forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));\n }\n transform.newScaleX = scaleX;\n transform.newScaleY = scaleY;\n forbidScalingX || forbidScalingY || this._flipObject(transform, by);\n return scaled;\n },\n\n /**\n * @private\n * @return {Boolean} true if the scaling occurred\n */\n _scaleObjectEqually: function(localMouse, target, transform, _dim) {\n\n var dist = localMouse.y + localMouse.x,\n lastDist = _dim.y * transform.original.scaleY / target.scaleY +\n _dim.x * transform.original.scaleX / target.scaleX,\n scaled, signX = localMouse.x / Math.abs(localMouse.x),\n signY = localMouse.y / Math.abs(localMouse.y);\n\n // We use transform.scaleX/Y instead of target.scaleX/Y\n // because the object may have a min scale and we'll loose the proportions\n transform.newScaleX = signX * Math.abs(transform.original.scaleX * dist / lastDist);\n transform.newScaleY = signY * Math.abs(transform.original.scaleY * dist / lastDist);\n scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY;\n target.set('scaleX', transform.newScaleX);\n target.set('scaleY', transform.newScaleY);\n return scaled;\n },\n\n /**\n * @private\n */\n _flipObject: function(transform, by) {\n if (transform.newScaleX < 0 && by !== 'y') {\n if (transform.originX === 'left') {\n transform.originX = 'right';\n }\n else if (transform.originX === 'right') {\n transform.originX = 'left';\n }\n }\n\n if (transform.newScaleY < 0 && by !== 'x') {\n if (transform.originY === 'top') {\n transform.originY = 'bottom';\n }\n else if (transform.originY === 'bottom') {\n transform.originY = 'top';\n }\n }\n },\n\n /**\n * @private\n */\n _setLocalMouse: function(localMouse, t) {\n var target = t.target, zoom = this.getZoom(),\n padding = target.padding / zoom;\n\n if (t.originX === 'right') {\n localMouse.x *= -1;\n }\n else if (t.originX === 'center') {\n localMouse.x *= t.mouseXSign * 2;\n if (localMouse.x < 0) {\n t.mouseXSign = -t.mouseXSign;\n }\n }\n\n if (t.originY === 'bottom') {\n localMouse.y *= -1;\n }\n else if (t.originY === 'center') {\n localMouse.y *= t.mouseYSign * 2;\n if (localMouse.y < 0) {\n t.mouseYSign = -t.mouseYSign;\n }\n }\n\n // adjust the mouse coordinates when dealing with padding\n if (abs(localMouse.x) > padding) {\n if (localMouse.x < 0) {\n localMouse.x += padding;\n }\n else {\n localMouse.x -= padding;\n }\n }\n else { // mouse is within the padding, set to 0\n localMouse.x = 0;\n }\n\n if (abs(localMouse.y) > padding) {\n if (localMouse.y < 0) {\n localMouse.y += padding;\n }\n else {\n localMouse.y -= padding;\n }\n }\n else {\n localMouse.y = 0;\n }\n },\n\n /**\n * Rotates object by invoking its rotate method\n * @private\n * @param {Number} x pointer's x coordinate\n * @param {Number} y pointer's y coordinate\n * @return {Boolean} true if the rotation occurred\n */\n _rotateObject: function (x, y) {\n\n var t = this._currentTransform;\n\n if (t.target.get('lockRotation')) {\n return false;\n }\n\n var lastAngle = atan2(t.ey - t.top, t.ex - t.left),\n curAngle = atan2(y - t.top, x - t.left),\n angle = radiansToDegrees(curAngle - lastAngle + t.theta),\n hasRoated = true;\n\n if (t.target.snapAngle > 0) {\n var snapAngle = t.target.snapAngle,\n snapThreshold = t.target.snapThreshold || snapAngle,\n rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\n leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\n\n if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\n angle = leftAngleLocked;\n }\n else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {\n angle = rightAngleLocked;\n }\n }\n\n // normalize angle to positive value\n if (angle < 0) {\n angle = 360 + angle;\n }\n angle %= 360;\n\n if (t.target.angle === angle) {\n hasRoated = false;\n }\n else {\n t.target.angle = angle;\n }\n\n return hasRoated;\n },\n\n /**\n * Set the cursor type of the canvas element\n * @param {String} value Cursor type of the canvas element.\n * @see http://www.w3.org/TR/css3-ui/#cursor\n */\n setCursor: function (value) {\n this.upperCanvasEl.style.cursor = value;\n },\n\n /**\n * @param {fabric.Object} target to reset transform\n * @private\n */\n _resetObjectTransform: function (target) {\n target.scaleX = 1;\n target.scaleY = 1;\n target.skewX = 0;\n target.skewY = 0;\n target.setAngle(0);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx to draw the selection on\n */\n _drawSelection: function (ctx) {\n var groupSelector = this._groupSelector,\n left = groupSelector.left,\n top = groupSelector.top,\n aleft = abs(left),\n atop = abs(top);\n\n if (this.selectionColor) {\n ctx.fillStyle = this.selectionColor;\n\n ctx.fillRect(\n groupSelector.ex - ((left > 0) ? 0 : -left),\n groupSelector.ey - ((top > 0) ? 0 : -top),\n aleft,\n atop\n );\n }\n\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\n return;\n }\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n // selection border\n if (this.selectionDashArray.length > 1 && !supportLineDash) {\n\n var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop);\n\n ctx.beginPath();\n\n fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);\n fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);\n\n ctx.closePath();\n ctx.stroke();\n }\n else {\n fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);\n ctx.strokeRect(\n groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),\n groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),\n aleft,\n atop\n );\n }\n },\n\n /**\n * Method that determines what object we are clicking on\n * the skipGroup parameter is for internal use, is needed for shift+click action\n * @param {Event} e mouse event\n * @param {Boolean} skipGroup when true, activeGroup is skipped and only objects are traversed through\n */\n findTarget: function (e, skipGroup) {\n if (this.skipTargetFind) {\n return;\n }\n\n var ignoreZoom = true,\n pointer = this.getPointer(e, ignoreZoom),\n activeGroup = this.getActiveGroup(),\n activeObject = this.getActiveObject(),\n activeTarget, activeTargetSubs;\n // first check current group (if one exists)\n // active group does not check sub targets like normal groups.\n // if active group just exits.\n this.targets = [];\n if (activeGroup && !skipGroup && activeGroup === this._searchPossibleTargets([activeGroup], pointer)) {\n this._fireOverOutEvents(activeGroup, e);\n return activeGroup;\n }\n // if we hit the corner of an activeObject, let's return that.\n if (activeObject && activeObject._findTargetCorner(pointer)) {\n this._fireOverOutEvents(activeObject, e);\n return activeObject;\n }\n if (activeObject && activeObject === this._searchPossibleTargets([activeObject], pointer)) {\n if (!this.preserveObjectStacking) {\n this._fireOverOutEvents(activeObject, e);\n return activeObject;\n }\n else {\n activeTarget = activeObject;\n activeTargetSubs = this.targets;\n this.targets = [];\n }\n }\n\n var target = this._searchPossibleTargets(this._objects, pointer);\n if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {\n target = activeTarget;\n this.targets = activeTargetSubs;\n }\n this._fireOverOutEvents(target, e);\n return target;\n },\n\n /**\n * @private\n */\n _fireOverOutEvents: function(target, e) {\n var overOpt, outOpt, hoveredTarget = this._hoveredTarget;\n if (hoveredTarget !== target) {\n overOpt = { e: e, target: target, previousTarget: this._hoveredTarget };\n outOpt = { e: e, target: this._hoveredTarget, nextTarget: target };\n this._hoveredTarget = target;\n }\n if (target) {\n if (hoveredTarget !== target) {\n if (hoveredTarget) {\n this.fire('mouse:out', outOpt);\n hoveredTarget.fire('mouseout', outOpt);\n }\n this.fire('mouse:over', overOpt);\n target.fire('mouseover', overOpt);\n }\n }\n else if (hoveredTarget) {\n this.fire('mouse:out', outOpt);\n hoveredTarget.fire('mouseout', outOpt);\n }\n },\n\n /**\n * @private\n */\n _checkTarget: function(pointer, obj) {\n if (obj &&\n obj.visible &&\n obj.evented &&\n this.containsPoint(null, obj, pointer)){\n if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {\n var isTransparent = this.isTargetTransparent(obj, pointer.x, pointer.y);\n if (!isTransparent) {\n return true;\n }\n }\n else {\n return true;\n }\n }\n },\n\n /**\n * @private\n */\n _searchPossibleTargets: function(objects, pointer) {\n\n // Cache all targets where their bounding box contains point.\n var target, i = objects.length, normalizedPointer, subTarget;\n // Do not check for currently grouped objects, since we check the parent group itself.\n // untill we call this function specifically to search inside the activeGroup\n while (i--) {\n if (this._checkTarget(pointer, objects[i])) {\n target = objects[i];\n if (target.type === 'group' && target.subTargetCheck) {\n normalizedPointer = this._normalizePointer(target, pointer);\n subTarget = this._searchPossibleTargets(target._objects, normalizedPointer);\n subTarget && this.targets.push(subTarget);\n }\n break;\n }\n }\n return target;\n },\n\n /**\n * Returns pointer coordinates without the effect of the viewport\n * @param {Object} pointer with \"x\" and \"y\" number values\n * @return {Object} object with \"x\" and \"y\" number values\n */\n restorePointerVpt: function(pointer) {\n return fabric.util.transformPoint(\n pointer,\n fabric.util.invertTransform(this.viewportTransform)\n );\n },\n\n /**\n * Returns pointer coordinates relative to canvas.\n * Can return coordinates with or without viewportTransform.\n * ignoreZoom false gives back coordinates that represent\n * the point clicked on canvas element.\n * ignoreZoom true gives back coordinates after being processed\n * by the viewportTransform ( sort of coordinates of what is displayed\n * on the canvas where you are clicking.\n * To interact with your shapes top and left you want to use ignoreZoom true\n * most of the time, while ignoreZoom false will give you coordinates\n * compatible with the object.oCoords system.\n * of the time.\n * @param {Event} e\n * @param {Boolean} ignoreZoom\n * @return {Object} object with \"x\" and \"y\" number values\n */\n getPointer: function (e, ignoreZoom, upperCanvasEl) {\n if (!upperCanvasEl) {\n upperCanvasEl = this.upperCanvasEl;\n }\n var pointer = getPointer(e),\n bounds = upperCanvasEl.getBoundingClientRect(),\n boundsWidth = bounds.width || 0,\n boundsHeight = bounds.height || 0,\n cssScale;\n\n if (!boundsWidth || !boundsHeight ) {\n if ('top' in bounds && 'bottom' in bounds) {\n boundsHeight = Math.abs( bounds.top - bounds.bottom );\n }\n if ('right' in bounds && 'left' in bounds) {\n boundsWidth = Math.abs( bounds.right - bounds.left );\n }\n }\n\n this.calcOffset();\n\n pointer.x = pointer.x - this._offset.left;\n pointer.y = pointer.y - this._offset.top;\n if (!ignoreZoom) {\n pointer = this.restorePointerVpt(pointer);\n }\n\n if (boundsWidth === 0 || boundsHeight === 0) {\n // If bounds are not available (i.e. not visible), do not apply scale.\n cssScale = { width: 1, height: 1 };\n }\n else {\n cssScale = {\n width: upperCanvasEl.width / boundsWidth,\n height: upperCanvasEl.height / boundsHeight\n };\n }\n\n return {\n x: pointer.x * cssScale.width,\n y: pointer.y * cssScale.height\n };\n },\n\n /**\n * @private\n * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized\n */\n _createUpperCanvas: function () {\n var lowerCanvasClass = this.lowerCanvasEl.className.replace(/\\s*lower-canvas\\s*/, '');\n\n if (this.upperCanvasEl) {\n this.upperCanvasEl.className = '';\n }\n else {\n this.upperCanvasEl = this._createCanvasElement();\n }\n fabric.util.addClass(this.upperCanvasEl, 'upper-canvas ' + lowerCanvasClass);\n\n this.wrapperEl.appendChild(this.upperCanvasEl);\n\n this._copyCanvasStyle(this.lowerCanvasEl, this.upperCanvasEl);\n this._applyCanvasStyle(this.upperCanvasEl);\n this.contextTop = this.upperCanvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _createCacheCanvas: function () {\n this.cacheCanvasEl = this._createCanvasElement();\n this.cacheCanvasEl.setAttribute('width', this.width);\n this.cacheCanvasEl.setAttribute('height', this.height);\n this.contextCache = this.cacheCanvasEl.getContext('2d');\n },\n\n /**\n * @private\n */\n _initWrapperElement: function () {\n this.wrapperEl = fabric.util.wrapElement(this.lowerCanvasEl, 'div', {\n 'class': this.containerClass\n });\n fabric.util.setStyle(this.wrapperEl, {\n width: this.getWidth() + 'px',\n height: this.getHeight() + 'px',\n position: 'relative'\n });\n fabric.util.makeElementUnselectable(this.wrapperEl);\n },\n\n /**\n * @private\n * @param {HTMLElement} element canvas element to apply styles on\n */\n _applyCanvasStyle: function (element) {\n var width = this.getWidth() || element.width,\n height = this.getHeight() || element.height;\n\n fabric.util.setStyle(element, {\n position: 'absolute',\n width: width + 'px',\n height: height + 'px',\n left: 0,\n top: 0,\n 'touch-action': 'none'\n });\n element.width = width;\n element.height = height;\n fabric.util.makeElementUnselectable(element);\n },\n\n /**\n * Copys the the entire inline style from one element (fromEl) to another (toEl)\n * @private\n * @param {Element} fromEl Element style is copied from\n * @param {Element} toEl Element copied style is applied to\n */\n _copyCanvasStyle: function (fromEl, toEl) {\n toEl.style.cssText = fromEl.style.cssText;\n },\n\n /**\n * Returns context of canvas where object selection is drawn\n * @return {CanvasRenderingContext2D}\n */\n getSelectionContext: function() {\n return this.contextTop;\n },\n\n /**\n * Returns <canvas> element on which object selection is drawn\n * @return {HTMLCanvasElement}\n */\n getSelectionElement: function () {\n return this.upperCanvasEl;\n },\n\n /**\n * @private\n * @param {Object} object\n */\n _setActiveObject: function(object) {\n var obj = this._activeObject;\n if (obj) {\n obj.set('active', false);\n if (object !== obj && obj.onDeselect && typeof obj.onDeselect === 'function') {\n obj.onDeselect();\n }\n }\n this._activeObject = object;\n object.set('active', true);\n },\n\n /**\n * Sets given object as the only active object on canvas\n * @param {fabric.Object} object Object to set as an active one\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setActiveObject: function (object, e) {\n var currentActiveObject = this.getActiveObject();\n if (currentActiveObject && currentActiveObject !== object) {\n currentActiveObject.fire('deselected', { e: e });\n }\n this._setActiveObject(object);\n this.fire('object:selected', { target: object, e: e });\n object.fire('selected', { e: e });\n this.renderAll();\n return this;\n },\n\n /**\n * Returns currently active object\n * @return {fabric.Object} active object\n */\n getActiveObject: function () {\n return this._activeObject;\n },\n\n /**\n * @private\n * @param {fabric.Object} obj Object that was removed\n */\n _onObjectRemoved: function(obj) {\n // removing active object should fire \"selection:cleared\" events\n if (this.getActiveObject() === obj) {\n this.fire('before:selection:cleared', { target: obj });\n this._discardActiveObject();\n this.fire('selection:cleared', { target: obj });\n obj.fire('deselected');\n }\n if (this._hoveredTarget === obj) {\n this._hoveredTarget = null;\n }\n this.callSuper('_onObjectRemoved', obj);\n },\n\n /**\n * @private\n */\n _discardActiveObject: function() {\n var obj = this._activeObject;\n if (obj) {\n obj.set('active', false);\n if (obj.onDeselect && typeof obj.onDeselect === 'function') {\n obj.onDeselect();\n }\n }\n this._activeObject = null;\n },\n\n /**\n * Discards currently active object and fire events. If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @param {event} e\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n discardActiveObject: function (e) {\n var activeObject = this._activeObject;\n if (activeObject) {\n this.fire('before:selection:cleared', { target: activeObject, e: e });\n this._discardActiveObject();\n this.fire('selection:cleared', { e: e });\n activeObject.fire('deselected', { e: e });\n }\n return this;\n },\n\n /**\n * @private\n * @param {fabric.Group} group\n */\n _setActiveGroup: function(group) {\n this._activeGroup = group;\n if (group) {\n group.set('active', true);\n }\n },\n\n /**\n * Sets active group to a specified one. If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @param {fabric.Group} group Group to set as a current one\n * @param {Event} e Event object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n setActiveGroup: function (group, e) {\n this._setActiveGroup(group);\n if (group) {\n this.fire('object:selected', { target: group, e: e });\n group.fire('selected', { e: e });\n }\n return this;\n },\n\n /**\n * Returns currently active group\n * @return {fabric.Group} Current group\n */\n getActiveGroup: function () {\n return this._activeGroup;\n },\n\n /**\n * @private\n */\n _discardActiveGroup: function() {\n var g = this.getActiveGroup();\n if (g) {\n g.destroy();\n }\n this.setActiveGroup(null);\n },\n\n /**\n * Discards currently active group and fire events If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n discardActiveGroup: function (e) {\n var g = this.getActiveGroup();\n if (g) {\n this.fire('before:selection:cleared', { e: e, target: g });\n this._discardActiveGroup();\n this.fire('selection:cleared', { e: e });\n }\n return this;\n },\n\n /**\n * Deactivates all objects on canvas, removing any active group or object\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n deactivateAll: function () {\n var allObjects = this.getObjects(),\n i = 0,\n len = allObjects.length,\n obj;\n for ( ; i < len; i++) {\n obj = allObjects[i];\n obj && obj.set('active', false);\n }\n this._discardActiveGroup();\n this._discardActiveObject();\n return this;\n },\n\n /**\n * Deactivates all objects and dispatches appropriate events If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parmater and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n deactivateAllWithDispatch: function (e) {\n var allObjects = this.getObjects(),\n i = 0,\n len = allObjects.length,\n obj;\n for ( ; i < len; i++) {\n obj = allObjects[i];\n obj && obj.set('active', false);\n }\n this.discardActiveGroup(e);\n this.discardActiveObject(e);\n return this;\n },\n\n /**\n * Clears a canvas element and removes all event listeners\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n dispose: function () {\n fabric.StaticCanvas.prototype.dispose.call(this);\n var wrapper = this.wrapperEl;\n this.removeListeners();\n wrapper.removeChild(this.upperCanvasEl);\n wrapper.removeChild(this.lowerCanvasEl);\n delete this.upperCanvasEl;\n if (wrapper.parentNode) {\n wrapper.parentNode.replaceChild(this.lowerCanvasEl, this.wrapperEl);\n }\n delete this.wrapperEl;\n return this;\n },\n\n /**\n * Clears all contexts (background, main, top) of an instance\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n clear: function () {\n this.discardActiveGroup();\n this.discardActiveObject();\n this.clearContext(this.contextTop);\n return this.callSuper('clear');\n },\n\n /**\n * Draws objects' controls (borders/controls)\n * @param {CanvasRenderingContext2D} ctx Context to render controls on\n */\n drawControls: function(ctx) {\n var activeGroup = this.getActiveGroup();\n\n if (activeGroup) {\n activeGroup._renderControls(ctx);\n }\n else {\n this._drawObjectsControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _drawObjectsControls: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; ++i) {\n if (!this._objects[i] || !this._objects[i].active) {\n continue;\n }\n this._objects[i]._renderControls(ctx);\n }\n },\n\n /**\n * @private\n */\n _toObject: function(instance, methodName, propertiesToInclude) {\n //If the object is part of the current selection group, it should\n //be transformed appropriately\n //i.e. it should be serialised as it would appear if the selection group\n //were to be destroyed.\n var originalProperties = this._realizeGroupTransformOnObject(instance),\n object = this.callSuper('_toObject', instance, methodName, propertiesToInclude);\n //Undo the damage we did by changing all of its properties\n this._unwindGroupTransformOnObject(instance, originalProperties);\n return object;\n },\n\n /**\n * Realises an object's group transformation on it\n * @private\n * @param {fabric.Object} [instance] the object to transform (gets mutated)\n * @returns the original values of instance which were changed\n */\n _realizeGroupTransformOnObject: function(instance) {\n if (instance.group && instance.group === this.getActiveGroup()) {\n //Copy all the positionally relevant properties across now\n var originalValues = {},\n layoutProps = ['angle', 'flipX', 'flipY', 'left', 'scaleX', 'scaleY', 'skewX', 'skewY', 'top'];\n layoutProps.forEach(function(prop) {\n originalValues[prop] = instance[prop];\n });\n this.getActiveGroup().realizeTransform(instance);\n return originalValues;\n }\n else {\n return null;\n }\n },\n\n /**\n * Restores the changed properties of instance\n * @private\n * @param {fabric.Object} [instance] the object to un-transform (gets mutated)\n * @param {Object} [originalValues] the original values of instance, as returned by _realizeGroupTransformOnObject\n */\n _unwindGroupTransformOnObject: function(instance, originalValues) {\n if (originalValues) {\n instance.set(originalValues);\n }\n },\n\n /**\n * @private\n */\n _setSVGObject: function(markup, instance, reviver) {\n var originalProperties;\n //If the object is in a selection group, simulate what would happen to that\n //object when the group is deselected\n originalProperties = this._realizeGroupTransformOnObject(instance);\n this.callSuper('_setSVGObject', markup, instance, reviver);\n this._unwindGroupTransformOnObject(instance, originalProperties);\n },\n });\n\n // copying static properties manually to work around Opera's bug,\n // where \"prototype\" property is enumerable and overrides existing prototype\n for (var prop in fabric.StaticCanvas) {\n if (prop !== 'prototype') {\n fabric.Canvas[prop] = fabric.StaticCanvas[prop];\n }\n }\n\n if (fabric.isTouchSupported) {\n /** @ignore */\n fabric.Canvas.prototype._setCursorFromEvent = function() { };\n }\n\n /**\n * @ignore\n * @class fabric.Element\n * @alias fabric.Canvas\n * @deprecated Use {@link fabric.Canvas} instead.\n * @constructor\n */\n fabric.Element = fabric.Canvas;\n})();\n\n\n(function() {\n\n var cursorOffset = {\n mt: 0, // n\n tr: 1, // ne\n mr: 2, // e\n br: 3, // se\n mb: 4, // s\n bl: 5, // sw\n ml: 6, // w\n tl: 7 // nw\n },\n addListener = fabric.util.addListener,\n removeListener = fabric.util.removeListener,\n RIGHT_CLICK = 3, MIDDLE_CLICK = 2, LEFT_CLICK = 1;\n\n function checkClick(e, value) {\n return 'which' in e ? e.which === value : e.button === value - 1;\n }\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * Map of cursor style values for each of the object controls\n * @private\n */\n cursorMap: [\n 'n-resize',\n 'ne-resize',\n 'e-resize',\n 'se-resize',\n 's-resize',\n 'sw-resize',\n 'w-resize',\n 'nw-resize'\n ],\n\n /**\n * Adds mouse listeners to canvas\n * @private\n */\n _initEventListeners: function () {\n // in case we initialized the class twice. This should not happen normally\n // but in some kind of applications where the canvas element may be changed\n // this is a workaround to having double listeners.\n this.removeListeners();\n this._bindEvents();\n\n addListener(fabric.window, 'resize', this._onResize);\n\n // mouse events\n addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);\n addListener(this.upperCanvasEl, 'mouseenter', this._onMouseEnter);\n addListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);\n addListener(this.upperCanvasEl, 'contextmenu', this._onContextMenu);\n\n // touch events\n addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown, { passive: false });\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove, { passive: false });\n\n if (typeof eventjs !== 'undefined' && 'add' in eventjs) {\n eventjs.add(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.add(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.add(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.add(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.add(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\n },\n\n /**\n * @private\n */\n _bindEvents: function() {\n if (this.eventsBinded) {\n // for any reason we pass here twice we do not want to bind events twice.\n return;\n }\n this._onMouseDown = this._onMouseDown.bind(this);\n this._onMouseMove = this._onMouseMove.bind(this);\n this._onMouseUp = this._onMouseUp.bind(this);\n this._onResize = this._onResize.bind(this);\n this._onGesture = this._onGesture.bind(this);\n this._onDrag = this._onDrag.bind(this);\n this._onShake = this._onShake.bind(this);\n this._onLongPress = this._onLongPress.bind(this);\n this._onOrientationChange = this._onOrientationChange.bind(this);\n this._onMouseWheel = this._onMouseWheel.bind(this);\n this._onMouseOut = this._onMouseOut.bind(this);\n this._onMouseEnter = this._onMouseEnter.bind(this);\n this._onContextMenu = this._onContextMenu.bind(this);\n this.eventsBinded = true;\n },\n\n /**\n * Removes all event listeners\n */\n removeListeners: function() {\n removeListener(fabric.window, 'resize', this._onResize);\n\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);\n removeListener(this.upperCanvasEl, 'mouseenter', this._onMouseEnter);\n removeListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);\n removeListener(this.upperCanvasEl, 'contextmenu', this._onContextMenu);\n\n removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (typeof eventjs !== 'undefined' && 'remove' in eventjs) {\n eventjs.remove(this.upperCanvasEl, 'gesture', this._onGesture);\n eventjs.remove(this.upperCanvasEl, 'drag', this._onDrag);\n eventjs.remove(this.upperCanvasEl, 'orientation', this._onOrientationChange);\n eventjs.remove(this.upperCanvasEl, 'shake', this._onShake);\n eventjs.remove(this.upperCanvasEl, 'longpress', this._onLongPress);\n }\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js gesture\n * @param {Event} [self] Inner Event object\n */\n _onGesture: function(e, self) {\n this.__onTransformGesture && this.__onTransformGesture(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js drag\n * @param {Event} [self] Inner Event object\n */\n _onDrag: function(e, self) {\n this.__onDrag && this.__onDrag(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on wheel event\n */\n _onMouseWheel: function(e) {\n this.__onMouseWheel(e);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseOut: function(e) {\n var target = this._hoveredTarget;\n this.fire('mouse:out', { target: target, e: e });\n this._hoveredTarget = null;\n target && target.fire('mouseout', { e: e });\n if (this._iTextInstances) {\n this._iTextInstances.forEach(function(obj) {\n if (obj.isEditing) {\n obj.hiddenTextarea.focus();\n }\n });\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseenter\n */\n _onMouseEnter: function(e) {\n if (!this.findTarget(e)) {\n this.fire('mouse:over', { target: null, e: e });\n this._hoveredTarget = null;\n }\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js orientation change\n * @param {Event} [self] Inner Event object\n */\n _onOrientationChange: function(e, self) {\n this.__onOrientationChange && this.__onOrientationChange(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n * @param {Event} [self] Inner Event object\n */\n _onShake: function(e, self) {\n this.__onShake && this.__onShake(e, self);\n },\n\n /**\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n * @param {Event} [self] Inner Event object\n */\n _onLongPress: function(e, self) {\n this.__onLongPress && this.__onLongPress(e, self);\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onContextMenu: function (e) {\n if (this.stopContextMenu) {\n e.stopPropagation();\n e.preventDefault();\n }\n return false;\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDown: function (e) {\n this.__onMouseDown(e);\n\n addListener(fabric.document, 'touchend', this._onMouseUp, { passive: false });\n addListener(fabric.document, 'touchmove', this._onMouseMove, { passive: false });\n\n removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);\n\n if (e.type === 'touchstart') {\n // Unbind mousedown to prevent double triggers from touch devices\n removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);\n }\n else {\n addListener(fabric.document, 'mouseup', this._onMouseUp);\n addListener(fabric.document, 'mousemove', this._onMouseMove);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUp: function (e) {\n this.__onMouseUp(e);\n\n removeListener(fabric.document, 'mouseup', this._onMouseUp);\n removeListener(fabric.document, 'touchend', this._onMouseUp);\n\n removeListener(fabric.document, 'mousemove', this._onMouseMove);\n removeListener(fabric.document, 'touchmove', this._onMouseMove);\n\n addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);\n addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove, { passive: false });\n\n if (e.type === 'touchend') {\n // Wait 400ms before rebinding mousedown to prevent double triggers\n // from touch devices\n var _this = this;\n setTimeout(function() {\n addListener(_this.upperCanvasEl, 'mousedown', _this._onMouseDown);\n }, 400);\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMove: function (e) {\n !this.allowTouchScrolling && e.preventDefault && e.preventDefault();\n this.__onMouseMove(e);\n },\n\n /**\n * @private\n */\n _onResize: function () {\n this.calcOffset();\n },\n\n /**\n * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n * @private\n * @param {Object} target\n * @param {Object} pointer\n */\n _shouldRender: function(target, pointer) {\n var activeObject = this.getActiveGroup() || this.getActiveObject();\n\n if (activeObject && activeObject.isEditing && target === activeObject) {\n // if we mouse up/down over a editing textbox a cursor change,\n // there is no need to re render\n return false;\n }\n return !!(\n (target && (\n target.isMoving ||\n target !== activeObject))\n ||\n (!target && !!activeObject)\n ||\n (!target && !activeObject && !this._groupSelector)\n ||\n (pointer &&\n this._previousPointer &&\n this.selection && (\n pointer.x !== this._previousPointer.x ||\n pointer.y !== this._previousPointer.y))\n );\n },\n\n /**\n * Method that defines the actions when mouse is released on canvas.\n * The method resets the currentTransform parameters, store the image corner\n * position in the image object and render the canvas on top.\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n __onMouseUp: function (e) {\n\n var target;\n // if right/middle click just fire events and return\n // target undefined will make the _handleEvent search the target\n if (checkClick(e, RIGHT_CLICK)) {\n if (this.fireRightClick) {\n this._handleEvent(e, 'up', target, RIGHT_CLICK);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'up', target, MIDDLE_CLICK);\n }\n return;\n }\n\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this._onMouseUpInDrawingMode(e);\n return;\n }\n\n var searchTarget = true, transform = this._currentTransform,\n groupSelector = this._groupSelector,\n isClick = (!groupSelector || (groupSelector.left === 0 && groupSelector.top === 0));\n\n if (transform) {\n this._finalizeCurrentTransform(e);\n searchTarget = !transform.actionPerformed;\n }\n\n target = searchTarget ? this.findTarget(e, true) : transform.target;\n\n var shouldRender = this._shouldRender(target, this.getPointer(e));\n\n if (target || !isClick) {\n this._maybeGroupObjects(e);\n }\n else {\n // those are done by default on mouse up\n // by _maybeGroupObjects, we are skipping it in case of no target find\n this._groupSelector = null;\n this._currentTransform = null;\n }\n\n if (target) {\n target.isMoving = false;\n }\n this._setCursorFromEvent(e, target);\n this._handleEvent(e, 'up', target ? target : null, LEFT_CLICK, isClick);\n target && (target.__corner = 0);\n shouldRender && this.renderAll();\n },\n\n /**\n * @private\n * Handle event firing for target and subtargets\n * @param {Event} e event from mouse\n * @param {String} eventType event to fire (up, down or move)\n * @param {fabric.Object} targetObj receiving event\n * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right\n * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.\n */\n _handleEvent: function(e, eventType, targetObj, button, isClick) {\n var target = typeof targetObj === 'undefined' ? this.findTarget(e) : targetObj,\n targets = this.targets || [],\n options = {\n e: e,\n target: target,\n subTargets: targets,\n button: button || LEFT_CLICK,\n isClick: isClick || false\n };\n this.fire('mouse:' + eventType, options);\n target && target.fire('mouse' + eventType, options);\n for (var i = 0; i < targets.length; i++) {\n targets[i].fire('mouse' + eventType, options);\n }\n },\n\n /**\n * @private\n * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event\n */\n _finalizeCurrentTransform: function(e) {\n\n var transform = this._currentTransform,\n target = transform.target;\n\n if (target._scaling) {\n target._scaling = false;\n }\n\n target.setCoords();\n this._restoreOriginXY(target);\n\n if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {\n this.fire('object:modified', { target: target, e: e });\n target.fire('modified', { e: e });\n }\n },\n\n /**\n * @private\n * @param {Object} target Object to restore\n */\n _restoreOriginXY: function(target) {\n if (this._previousOriginX && this._previousOriginY) {\n\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDownInDrawingMode: function(e) {\n this._isCurrentlyDrawing = true;\n this.discardActiveObject(e).renderAll();\n if (this.clipTo) {\n fabric.util.clipContext(this, this.contextTop);\n }\n var pointer = this.getPointer(e);\n this.freeDrawingBrush.onMouseDown(pointer);\n this._handleEvent(e, 'down');\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMoveInDrawingMode: function(e) {\n if (this._isCurrentlyDrawing) {\n var pointer = this.getPointer(e);\n this.freeDrawingBrush.onMouseMove(pointer);\n }\n this.setCursor(this.freeDrawingCursor);\n this._handleEvent(e, 'move');\n },\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUpInDrawingMode: function(e) {\n this._isCurrentlyDrawing = false;\n if (this.clipTo) {\n this.contextTop.restore();\n }\n this.freeDrawingBrush.onMouseUp();\n this._handleEvent(e, 'up');\n },\n\n /**\n * Method that defines the actions when mouse is clicked on canvas.\n * The method inits the currentTransform parameters and renders all the\n * canvas so the current image can be placed on the top canvas and the rest\n * in on the container one.\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n __onMouseDown: function (e) {\n\n var target = this.findTarget(e);\n\n // if right click just fire events\n if (checkClick(e, RIGHT_CLICK)) {\n if (this.fireRightClick) {\n this._handleEvent(e, 'down', target ? target : null, RIGHT_CLICK);\n }\n return;\n }\n\n if (checkClick(e, MIDDLE_CLICK)) {\n if (this.fireMiddleClick) {\n this._handleEvent(e, 'down', target ? target : null, MIDDLE_CLICK);\n }\n return;\n }\n\n if (this.isDrawingMode) {\n this._onMouseDownInDrawingMode(e);\n return;\n }\n\n // ignore if some object is being transformed at this moment\n if (this._currentTransform) {\n return;\n }\n\n // save pointer for check in __onMouseUp event\n var pointer = this.getPointer(e, true);\n this._previousPointer = pointer;\n\n var shouldRender = this._shouldRender(target, pointer),\n shouldGroup = this._shouldGroup(e, target);\n\n if (this._shouldClearSelection(e, target)) {\n this.deactivateAllWithDispatch(e);\n }\n else if (shouldGroup) {\n this._handleGrouping(e, target);\n target = this.getActiveGroup();\n }\n\n if (this.selection && (!target || (!target.selectable && !target.isEditing))) {\n this._groupSelector = {\n ex: pointer.x,\n ey: pointer.y,\n top: 0,\n left: 0\n };\n }\n\n if (target) {\n if (target.selectable && (target.__corner || !shouldGroup)) {\n this._beforeTransform(e, target);\n this._setupCurrentTransform(e, target);\n }\n var activeObject = this.getActiveObject();\n if (target !== this.getActiveGroup() && target !== activeObject) {\n this.deactivateAll();\n if (target.selectable) {\n activeObject && activeObject.fire('deselected', { e: e });\n this.setActiveObject(target, e);\n }\n }\n }\n this._handleEvent(e, 'down', target ? target : null);\n // we must renderAll so that we update the visuals\n shouldRender && this.renderAll();\n },\n\n /**\n * @private\n */\n _beforeTransform: function(e, target) {\n this.stateful && target.saveState();\n\n // determine if it's a drag or rotate case\n if (target._findTargetCorner(this.getPointer(e))) {\n this.onBeforeScaleRotate(target);\n }\n\n },\n\n /**\n * @private\n * @param {Object} target Object for that origin is set to center\n */\n _setOriginToCenter: function(target) {\n this._previousOriginX = this._currentTransform.target.originX;\n this._previousOriginY = this._currentTransform.target.originY;\n\n var center = target.getCenterPoint();\n\n target.originX = 'center';\n target.originY = 'center';\n\n target.left = center.x;\n target.top = center.y;\n\n this._currentTransform.left = target.left;\n this._currentTransform.top = target.top;\n },\n\n /**\n * @private\n * @param {Object} target Object for that center is set to origin\n */\n _setCenterToOrigin: function(target) {\n var originPoint = target.translateToOriginPoint(\n target.getCenterPoint(),\n this._previousOriginX,\n this._previousOriginY);\n\n target.originX = this._previousOriginX;\n target.originY = this._previousOriginY;\n\n target.left = originPoint.x;\n target.top = originPoint.y;\n\n this._previousOriginX = null;\n this._previousOriginY = null;\n },\n\n /**\n * Method that defines the actions when mouse is hovering the canvas.\n * The currentTransform parameter will definde whether the user is rotating/scaling/translating\n * an image or neither of them (only hovering). A group selection is also possible and would cancel\n * all any other type of action.\n * In case of an image transformation only the top canvas will be rendered.\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n __onMouseMove: function (e) {\n\n var target, pointer;\n\n if (this.isDrawingMode) {\n this._onMouseMoveInDrawingMode(e);\n return;\n }\n if (typeof e.touches !== 'undefined' && e.touches.length > 1) {\n return;\n }\n\n var groupSelector = this._groupSelector;\n\n // We initially clicked in an empty area, so we draw a box for multiple selection\n if (groupSelector) {\n pointer = this.getPointer(e, true);\n\n groupSelector.left = pointer.x - groupSelector.ex;\n groupSelector.top = pointer.y - groupSelector.ey;\n\n this.renderTop();\n }\n else if (!this._currentTransform) {\n target = this.findTarget(e);\n this._setCursorFromEvent(e, target);\n }\n else {\n this._transformObject(e);\n }\n this._handleEvent(e, 'move', target ? target : null);\n },\n\n /**\n * Method that defines actions when an Event Mouse Wheel\n * @param {Event} e Event object fired on mouseup\n */\n __onMouseWheel: function(e) {\n this._handleEvent(e, 'wheel');\n },\n\n /**\n * @private\n * @param {Event} e Event fired on mousemove\n */\n _transformObject: function(e) {\n var pointer = this.getPointer(e),\n transform = this._currentTransform;\n\n transform.reset = false;\n transform.target.isMoving = true;\n transform.shiftKey = e.shiftKey;\n transform.altKey = e[this.centeredKey];\n\n this._beforeScaleTransform(e, transform);\n this._performTransformAction(e, transform, pointer);\n\n transform.actionPerformed && this.renderAll();\n },\n\n /**\n * @private\n */\n _performTransformAction: function(e, transform, pointer) {\n var x = pointer.x,\n y = pointer.y,\n target = transform.target,\n action = transform.action,\n actionPerformed = false;\n\n if (action === 'rotate') {\n (actionPerformed = this._rotateObject(x, y)) && this._fire('rotating', target, e);\n }\n else if (action === 'scale') {\n (actionPerformed = this._onScale(e, transform, x, y)) && this._fire('scaling', target, e);\n }\n else if (action === 'scaleX') {\n (actionPerformed = this._scaleObject(x, y, 'x')) && this._fire('scaling', target, e);\n }\n else if (action === 'scaleY') {\n (actionPerformed = this._scaleObject(x, y, 'y')) && this._fire('scaling', target, e);\n }\n else if (action === 'skewX') {\n (actionPerformed = this._skewObject(x, y, 'x')) && this._fire('skewing', target, e);\n }\n else if (action === 'skewY') {\n (actionPerformed = this._skewObject(x, y, 'y')) && this._fire('skewing', target, e);\n }\n else {\n actionPerformed = this._translateObject(x, y);\n if (actionPerformed) {\n this._fire('moving', target, e);\n this.setCursor(target.moveCursor || this.moveCursor);\n }\n }\n transform.actionPerformed = transform.actionPerformed || actionPerformed;\n },\n\n /**\n * @private\n */\n _fire: function(eventName, target, e) {\n this.fire('object:' + eventName, { target: target, e: e });\n target.fire(eventName, { e: e });\n },\n\n /**\n * @private\n */\n _beforeScaleTransform: function(e, transform) {\n if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') {\n var centerTransform = this._shouldCenterTransform(transform.target);\n\n // Switch from a normal resize to center-based\n if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) ||\n // Switch from center-based resize to normal one\n (!centerTransform && transform.originX === 'center' && transform.originY === 'center')\n ) {\n this._resetCurrentTransform();\n transform.reset = true;\n }\n }\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {Object} transform current tranform\n * @param {Number} x mouse position x from origin\n * @param {Number} y mouse poistion y from origin\n * @return {Boolean} true if the scaling occurred\n */\n _onScale: function(e, transform, x, y) {\n if ((e[this.uniScaleKey] || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) {\n transform.currentAction = 'scale';\n return this._scaleObject(x, y);\n }\n else {\n // Switch from a normal resize to proportional\n if (!transform.reset && transform.currentAction === 'scale') {\n this._resetCurrentTransform();\n }\n\n transform.currentAction = 'scaleEqually';\n return this._scaleObject(x, y, 'equally');\n }\n },\n\n /**\n * Sets the cursor depending on where the canvas is being hovered.\n * Note: very buggy in Opera\n * @param {Event} e Event object\n * @param {Object} target Object that the mouse is hovering, if so.\n */\n _setCursorFromEvent: function (e, target) {\n if (!target) {\n this.setCursor(this.defaultCursor);\n return false;\n }\n\n var hoverCursor = target.hoverCursor || this.hoverCursor,\n activeGroup = this.getActiveGroup(),\n // only show proper corner when group selection is not active\n corner = target._findTargetCorner\n && (!activeGroup || !activeGroup.contains(target))\n && target._findTargetCorner(this.getPointer(e, true));\n\n if (!corner) {\n this.setCursor(hoverCursor);\n }\n else {\n this._setCornerCursor(corner, target, e);\n }\n //actually unclear why it should return something\n //is never evaluated\n return true;\n },\n\n /**\n * @private\n */\n _setCornerCursor: function(corner, target, e) {\n if (corner in cursorOffset) {\n this.setCursor(this._getRotatedCornerCursor(corner, target, e));\n }\n else if (corner === 'mtr' && target.hasRotatingPoint) {\n this.setCursor(this.rotationCursor);\n }\n else {\n this.setCursor(this.defaultCursor);\n return false;\n }\n },\n\n /**\n * @private\n */\n _getRotatedCornerCursor: function(corner, target, e) {\n var n = Math.round((target.getAngle() % 360) / 45);\n\n if (n < 0) {\n n += 8; // full circle ahead\n }\n n += cursorOffset[corner];\n if (e[this.altActionKey] && cursorOffset[corner] % 2 === 0) {\n //if we are holding shift and we are on a mx corner...\n n += 2;\n }\n // normalize n to be from 0 to 7\n n %= 8;\n\n return this.cursorMap[n];\n }\n });\n})();\n\n\n(function() {\n\n var min = Math.min,\n max = Math.max;\n\n fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n * @return {Boolean}\n */\n _shouldGroup: function(e, target) {\n var activeObject = this.getActiveObject();\n return e[this.selectionKey] && target && target.selectable &&\n (this.getActiveGroup() || (activeObject && activeObject !== target))\n && this.selection;\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {fabric.Object} target\n */\n _handleGrouping: function (e, target) {\n var activeGroup = this.getActiveGroup();\n\n if (target === activeGroup) {\n // if it's a group, find target again, using activeGroup objects\n target = this.findTarget(e, true);\n // if even object is not found, bail out\n if (!target) {\n return;\n }\n }\n if (activeGroup) {\n this._updateActiveGroup(target, e);\n }\n else {\n this._createActiveGroup(target, e);\n }\n\n if (this._activeGroup) {\n this._activeGroup.saveCoords();\n }\n },\n\n /**\n * @private\n */\n _updateActiveGroup: function(target, e) {\n var activeGroup = this.getActiveGroup();\n\n if (activeGroup.contains(target)) {\n\n activeGroup.removeWithUpdate(target);\n target.set('active', false);\n\n if (activeGroup.size() === 1) {\n // remove group alltogether if after removal it only contains 1 object\n this.discardActiveGroup(e);\n // activate last remaining object\n this.setActiveObject(activeGroup.item(0), e);\n return;\n }\n }\n else {\n activeGroup.addWithUpdate(target);\n }\n this.fire('selection:created', { target: activeGroup, e: e });\n activeGroup.set('active', true);\n },\n\n /**\n * @private\n */\n _createActiveGroup: function(target, e) {\n\n if (this._activeObject && target !== this._activeObject) {\n\n var group = this._createGroup(target);\n group.addWithUpdate();\n\n this.setActiveGroup(group, e);\n this._activeObject = null;\n\n this.fire('selection:created', { target: group, e: e });\n }\n\n target.set('active', true);\n },\n\n /**\n * @private\n * @param {Object} target\n */\n _createGroup: function(target) {\n\n var objects = this.getObjects(),\n isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),\n groupObjects = isActiveLower\n ? [this._activeObject, target]\n : [target, this._activeObject];\n this._activeObject.isEditing && this._activeObject.exitEditing();\n return new fabric.Group(groupObjects, {\n canvas: this\n });\n },\n\n /**\n * @private\n * @param {Event} e mouse event\n */\n _groupSelectedObjects: function (e) {\n\n var group = this._collectObjects();\n\n // do not create group for 1 element only\n if (group.length === 1) {\n this.setActiveObject(group[0], e);\n }\n else if (group.length > 1) {\n group = new fabric.Group(group.reverse(), {\n canvas: this\n });\n group.addWithUpdate();\n this.setActiveGroup(group, e);\n group.saveCoords();\n this.fire('selection:created', { target: group, e: e });\n this.renderAll();\n }\n },\n\n /**\n * @private\n */\n _collectObjects: function() {\n var group = [],\n currentObject,\n x1 = this._groupSelector.ex,\n y1 = this._groupSelector.ey,\n x2 = x1 + this._groupSelector.left,\n y2 = y1 + this._groupSelector.top,\n selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),\n selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),\n isClick = x1 === x2 && y1 === y2;\n\n for (var i = this._objects.length; i--; ) {\n currentObject = this._objects[i];\n\n if (!currentObject || !currentObject.selectable || !currentObject.visible) {\n continue;\n }\n\n if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||\n currentObject.containsPoint(selectionX1Y1) ||\n currentObject.containsPoint(selectionX2Y2)\n ) {\n currentObject.set('active', true);\n group.push(currentObject);\n\n // only add one object if it's a click\n if (isClick) {\n break;\n }\n }\n }\n\n return group;\n },\n\n /**\n * @private\n */\n _maybeGroupObjects: function(e) {\n if (this.selection && this._groupSelector) {\n this._groupSelectedObjects(e);\n }\n\n var activeGroup = this.getActiveGroup();\n if (activeGroup) {\n activeGroup.setObjectsCoords().setCoords();\n activeGroup.isMoving = false;\n this.setCursor(this.defaultCursor);\n }\n\n // clear selection and current transformation\n this._groupSelector = null;\n this._currentTransform = null;\n }\n });\n\n})();\n\n\n(function () {\n\n var supportQuality = fabric.StaticCanvas.supports('toDataURLWithQuality');\n\n fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n * @param {Object} [options] Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n * @see {@link http://jsfiddle.net/fabricjs/NfZVb/|jsFiddle demo}\n * @example Generate jpeg dataURL with lower quality\n * var dataURL = canvas.toDataURL({\n * format: 'jpeg',\n * quality: 0.8\n * });\n * @example Generate cropped png dataURL (clipping of canvas)\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * left: 100,\n * top: 100,\n * width: 200,\n * height: 200\n * });\n * @example Generate double scaled png dataURL\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * multiplier: 2\n * });\n */\n toDataURL: function (options) {\n options || (options = { });\n\n var format = options.format || 'png',\n quality = options.quality || 1,\n multiplier = options.multiplier || 1,\n cropping = {\n left: options.left || 0,\n top: options.top || 0,\n width: options.width || 0,\n height: options.height || 0,\n };\n return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);\n },\n\n /**\n * @private\n */\n __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {\n\n var origWidth = this.getWidth(),\n origHeight = this.getHeight(),\n scaledWidth = (cropping.width || this.getWidth()) * multiplier,\n scaledHeight = (cropping.height || this.getHeight()) * multiplier,\n zoom = this.getZoom(),\n newZoom = zoom * multiplier,\n vp = this.viewportTransform,\n translateX = (vp[4] - cropping.left) * multiplier,\n translateY = (vp[5] - cropping.top) * multiplier,\n newVp = [newZoom, 0, 0, newZoom, translateX, translateY],\n originalInteractive = this.interactive;\n\n this.viewportTransform = newVp;\n // setting interactive to false avoid exporting controls\n this.interactive && (this.interactive = false);\n if (origWidth !== scaledWidth || origHeight !== scaledHeight) {\n // this.setDimensions is going to renderAll also;\n this.setDimensions({ width: scaledWidth, height: scaledHeight }, { backstoreOnly: true });\n }\n else {\n this.renderAll();\n }\n var data = this.__toDataURL(format, quality, cropping);\n originalInteractive && (this.interactive = originalInteractive);\n this.viewportTransform = vp;\n //setDimensions with no option object is taking care of:\n //this.width, this.height, this.renderAll()\n this.setDimensions({ width: origWidth, height: origHeight }, { backstoreOnly: true });\n return data;\n },\n\n /**\n * @private\n */\n __toDataURL: function(format, quality) {\n\n var canvasEl = this.contextContainer.canvas;\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (format === 'jpg') {\n format = 'jpeg';\n }\n\n var data = supportQuality\n ? canvasEl.toDataURL('image/' + format, quality)\n : canvasEl.toDataURL('image/' + format);\n\n return data;\n },\n\n /**\n * Exports canvas element to a dataurl image (allowing to change image size via multiplier).\n * @deprecated since 1.0.13\n * @param {String} format (png|jpeg)\n * @param {Number} multiplier\n * @param {Number} quality (0..1)\n * @return {String}\n */\n toDataURLWithMultiplier: function (format, multiplier, quality) {\n return this.toDataURL({\n format: format,\n multiplier: multiplier,\n quality: quality\n });\n },\n });\n\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Populates canvas with data from the specified dataless JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON}\n * @deprecated since 1.2.2\n * @param {String|Object} json JSON string or object\n * @param {Function} callback Callback, invoked when json is parsed\n * and corresponding objects (e.g: {@link fabric.Image})\n * are initialized\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n * @return {fabric.Canvas} instance\n * @chainable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\n */\n loadFromDatalessJSON: function (json, callback, reviver) {\n return this.loadFromJSON(json, callback, reviver);\n },\n\n /**\n * Populates canvas with data from the specified JSON.\n * JSON format must conform to the one of {@link fabric.Canvas#toJSON}\n * @param {String|Object} json JSON string or object\n * @param {Function} callback Callback, invoked when json is parsed\n * and corresponding objects (e.g: {@link fabric.Image})\n * are initialized\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n * @return {fabric.Canvas} instance\n * @chainable\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}\n * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n * @example loadFromJSON\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));\n * @example loadFromJSON with reviver\n * canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {\n * // `o` = json object\n * // `object` = fabric.Object instance\n * // ... do some stuff ...\n * });\n */\n loadFromJSON: function (json, callback, reviver) {\n if (!json) {\n return;\n }\n\n // serialize if it wasn't already\n var serialized = (typeof json === 'string')\n ? JSON.parse(json)\n : fabric.util.object.clone(json);\n\n var _this = this,\n renderOnAddRemove = this.renderOnAddRemove;\n this.renderOnAddRemove = false;\n\n this._enlivenObjects(serialized.objects, function (enlivenedObjects) {\n _this.clear();\n _this._setBgOverlay(serialized, function () {\n enlivenedObjects.forEach(function(obj, index) {\n // we splice the array just in case some custom classes restored from JSON\n // will add more object to canvas at canvas init.\n _this.insertAt(obj, index);\n });\n _this.renderOnAddRemove = renderOnAddRemove;\n // remove parts i cannot set as options\n delete serialized.objects;\n delete serialized.backgroundImage;\n delete serialized.overlayImage;\n delete serialized.background;\n delete serialized.overlay;\n // this._initOptions does too many things to just\n // call it. Normally loading an Object from JSON\n // create the Object instance. Here the Canvas is\n // already an instance and we are just loading things over it\n _this._setOptions(serialized);\n _this.renderAll();\n callback && callback();\n });\n }, reviver);\n return this;\n },\n\n /**\n * @private\n * @param {Object} serialized Object with background and overlay information\n * @param {Function} callback Invoked after all background and overlay images/patterns loaded\n */\n _setBgOverlay: function(serialized, callback) {\n var loaded = {\n backgroundColor: false,\n overlayColor: false,\n backgroundImage: false,\n overlayImage: false\n };\n\n if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {\n callback && callback();\n return;\n }\n\n var cbIfLoaded = function () {\n if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {\n callback && callback();\n }\n };\n\n this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);\n this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);\n this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);\n this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);\n },\n\n /**\n * @private\n * @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)\n * @param {(Object|String)} value Value to set\n * @param {Object} loaded Set loaded property to true if property is set\n * @param {Object} callback Callback function to invoke after property is set\n */\n __setBgOverlay: function(property, value, loaded, callback) {\n var _this = this;\n\n if (!value) {\n loaded[property] = true;\n callback && callback();\n return;\n }\n\n if (property === 'backgroundImage' || property === 'overlayImage') {\n fabric.util.enlivenObjects([value], function(enlivedObject){\n _this[property] = enlivedObject[0];\n loaded[property] = true;\n callback && callback();\n });\n }\n else {\n this['set' + fabric.util.string.capitalize(property, true)](value, function() {\n loaded[property] = true;\n callback && callback();\n });\n }\n },\n\n /**\n * @private\n * @param {Array} objects\n * @param {Function} callback\n * @param {Function} [reviver]\n */\n _enlivenObjects: function (objects, callback, reviver) {\n if (!objects || objects.length === 0) {\n callback && callback([]);\n return;\n }\n\n fabric.util.enlivenObjects(objects, function(enlivenedObjects) {\n callback && callback(enlivenedObjects);\n }, null, reviver);\n },\n\n /**\n * @private\n * @param {String} format\n * @param {Function} callback\n */\n _toDataURL: function (format, callback) {\n this.clone(function (clone) {\n callback(clone.toDataURL(format));\n });\n },\n\n /**\n * @private\n * @param {String} format\n * @param {Number} multiplier\n * @param {Function} callback\n */\n _toDataURLWithMultiplier: function (format, multiplier, callback) {\n this.clone(function (clone) {\n callback(clone.toDataURLWithMultiplier(format, multiplier));\n });\n },\n\n /**\n * Clones canvas instance\n * @param {Object} [callback] Receives cloned instance as a first argument\n * @param {Array} [properties] Array of properties to include in the cloned canvas and children\n */\n clone: function (callback, properties) {\n var data = JSON.stringify(this.toJSON(properties));\n this.cloneWithoutData(function(clone) {\n clone.loadFromJSON(data, function() {\n callback && callback(clone);\n });\n });\n },\n\n /**\n * Clones canvas instance without cloning existing data.\n * This essentially copies canvas dimensions, clipping properties, etc.\n * but leaves data empty (so that you can populate it with your own)\n * @param {Object} [callback] Receives cloned instance as a first argument\n */\n cloneWithoutData: function(callback) {\n var el = fabric.document.createElement('canvas');\n\n el.width = this.getWidth();\n el.height = this.getHeight();\n\n var clone = new fabric.Canvas(el);\n clone.clipTo = this.clipTo;\n if (this.backgroundImage) {\n clone.setBackgroundImage(this.backgroundImage.src, function() {\n clone.renderAll();\n callback && callback(clone);\n });\n clone.backgroundImageOpacity = this.backgroundImageOpacity;\n clone.backgroundImageStretch = this.backgroundImageStretch;\n }\n else {\n callback && callback(clone);\n }\n }\n});\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n toFixed = fabric.util.toFixed,\n capitalize = fabric.util.string.capitalize,\n degreesToRadians = fabric.util.degreesToRadians,\n supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),\n objectCaching = !fabric.isLikelyNode,\n ALIASING_LIMIT = 2;\n\n if (fabric.Object) {\n return;\n }\n\n /**\n * Root object class from which all 2d shape classes inherit from\n * @class fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#objects}\n * @see {@link fabric.Object#initialize} for constructor definition\n *\n * @fires added\n * @fires removed\n *\n * @fires selected\n * @fires deselected\n * @fires modified\n * @fires rotating\n * @fires scaling\n * @fires moving\n * @fires skewing\n *\n * @fires mousedown\n * @fires mouseup\n * @fires mouseover\n * @fires mouseout\n * @fires mousewheel\n */\n fabric.Object = fabric.util.createClass(fabric.CommonMethods, /** @lends fabric.Object.prototype */ {\n\n /**\n * Retrieves object's {@link fabric.Object#clipTo|clipping function}\n * @method getClipTo\n * @memberOf fabric.Object.prototype\n * @return {Function}\n */\n\n /**\n * Sets object's {@link fabric.Object#clipTo|clipping function}\n * @method setClipTo\n * @memberOf fabric.Object.prototype\n * @param {Function} clipTo Clipping function\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method getTransformMatrix\n * @memberOf fabric.Object.prototype\n * @return {Array} transformMatrix\n */\n\n /**\n * Sets object's {@link fabric.Object#transformMatrix|transformMatrix}\n * @method setTransformMatrix\n * @memberOf fabric.Object.prototype\n * @param {Array} transformMatrix\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#visible|visible} state\n * @method getVisible\n * @memberOf fabric.Object.prototype\n * @return {Boolean} True if visible\n */\n\n /**\n * Sets object's {@link fabric.Object#visible|visible} state\n * @method setVisible\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value visible value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#shadow|shadow}\n * @method getShadow\n * @memberOf fabric.Object.prototype\n * @return {Object} Shadow instance\n */\n\n /**\n * Retrieves object's {@link fabric.Object#stroke|stroke}\n * @method getStroke\n * @memberOf fabric.Object.prototype\n * @return {String} stroke value\n */\n\n /**\n * Sets object's {@link fabric.Object#stroke|stroke}\n * @method setStroke\n * @memberOf fabric.Object.prototype\n * @param {String} value stroke value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method getStrokeWidth\n * @memberOf fabric.Object.prototype\n * @return {Number} strokeWidth value\n */\n\n /**\n * Sets object's {@link fabric.Object#strokeWidth|strokeWidth}\n * @method setStrokeWidth\n * @memberOf fabric.Object.prototype\n * @param {Number} value strokeWidth value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originX|originX}\n * @method getOriginX\n * @memberOf fabric.Object.prototype\n * @return {String} originX value\n */\n\n /**\n * Sets object's {@link fabric.Object#originX|originX}\n * @method setOriginX\n * @memberOf fabric.Object.prototype\n * @param {String} value originX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#originY|originY}\n * @method getOriginY\n * @memberOf fabric.Object.prototype\n * @return {String} originY value\n */\n\n /**\n * Sets object's {@link fabric.Object#originY|originY}\n * @method setOriginY\n * @memberOf fabric.Object.prototype\n * @param {String} value originY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#fill|fill}\n * @method getFill\n * @memberOf fabric.Object.prototype\n * @return {String} Fill value\n */\n\n /**\n * Sets object's {@link fabric.Object#fill|fill}\n * @method setFill\n * @memberOf fabric.Object.prototype\n * @param {String} value Fill value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#opacity|opacity}\n * @method getOpacity\n * @memberOf fabric.Object.prototype\n * @return {Number} Opacity value (0-1)\n */\n\n /**\n * Sets object's {@link fabric.Object#opacity|opacity}\n * @method setOpacity\n * @memberOf fabric.Object.prototype\n * @param {Number} value Opacity value (0-1)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#angle|angle} (in degrees)\n * @method getAngle\n * @memberOf fabric.Object.prototype\n * @return {Number}\n */\n\n /**\n * Retrieves object's {@link fabric.Object#top|top position}\n * @method getTop\n * @memberOf fabric.Object.prototype\n * @return {Number} Top value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#top|top position}\n * @method setTop\n * @memberOf fabric.Object.prototype\n * @param {Number} value Top value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#left|left position}\n * @method getLeft\n * @memberOf fabric.Object.prototype\n * @return {Number} Left value (in pixels)\n */\n\n /**\n * Sets object's {@link fabric.Object#left|left position}\n * @method setLeft\n * @memberOf fabric.Object.prototype\n * @param {Number} value Left value (in pixels)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleX|scaleX} value\n * @method getScaleX\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleX value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleX|scaleX} value\n * @method setScaleX\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#scaleY|scaleY} value\n * @method getScaleY\n * @memberOf fabric.Object.prototype\n * @return {Number} scaleY value\n */\n\n /**\n * Sets object's {@link fabric.Object#scaleY|scaleY} value\n * @method setScaleY\n * @memberOf fabric.Object.prototype\n * @param {Number} value scaleY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipX|flipX} value\n * @method getFlipX\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipX value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipX|flipX} value\n * @method setFlipX\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipX value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Retrieves object's {@link fabric.Object#flipY|flipY} value\n * @method getFlipY\n * @memberOf fabric.Object.prototype\n * @return {Boolean} flipY value\n */\n\n /**\n * Sets object's {@link fabric.Object#flipY|flipY} value\n * @method setFlipY\n * @memberOf fabric.Object.prototype\n * @param {Boolean} value flipY value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n\n /**\n * Type of an object (rect, circle, path, etc.).\n * Note that this property is meant to be read-only and not meant to be modified.\n * If you modify, certain parts of Fabric (such as JSON loading) won't work correctly.\n * @type String\n * @default\n */\n type: 'object',\n\n /**\n * Horizontal origin of transformation of an object (one of \"left\", \"right\", \"center\")\n * See http://jsfiddle.net/1ow02gea/40/ on how originX/originY affect objects in groups\n * @type String\n * @default\n */\n originX: 'left',\n\n /**\n * Vertical origin of transformation of an object (one of \"top\", \"bottom\", \"center\")\n * See http://jsfiddle.net/1ow02gea/40/ on how originX/originY affect objects in groups\n * @type String\n * @default\n */\n originY: 'top',\n\n /**\n * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom}\n * @type Number\n * @default\n */\n top: 0,\n\n /**\n * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right}\n * @type Number\n * @default\n */\n left: 0,\n\n /**\n * Object width\n * @type Number\n * @default\n */\n width: 0,\n\n /**\n * Object height\n * @type Number\n * @default\n */\n height: 0,\n\n /**\n * Object scale factor (horizontal)\n * @type Number\n * @default\n */\n scaleX: 1,\n\n /**\n * Object scale factor (vertical)\n * @type Number\n * @default\n */\n scaleY: 1,\n\n /**\n * When true, an object is rendered as flipped horizontally\n * @type Boolean\n * @default\n */\n flipX: false,\n\n /**\n * When true, an object is rendered as flipped vertically\n * @type Boolean\n * @default\n */\n flipY: false,\n\n /**\n * Opacity of an object\n * @type Number\n * @default\n */\n opacity: 1,\n\n /**\n * Angle of rotation of an object (in degrees)\n * @type Number\n * @default\n */\n angle: 0,\n\n /**\n * Angle of skew on x axes of an object (in degrees)\n * @type Number\n * @default\n */\n skewX: 0,\n\n /**\n * Angle of skew on y axes of an object (in degrees)\n * @type Number\n * @default\n */\n skewY: 0,\n\n /**\n * Size of object's controlling corners (in pixels)\n * @type Number\n * @default\n */\n cornerSize: 13,\n\n /**\n * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill)\n * @type Boolean\n * @default\n */\n transparentCorners: true,\n\n /**\n * Default cursor value used when hovering over this object on canvas\n * @type String\n * @default\n */\n hoverCursor: null,\n\n /**\n * Default cursor value used when moving this object on canvas\n * @type String\n * @default\n */\n moveCursor: null,\n\n /**\n * Padding between object and its controlling borders (in pixels)\n * @type Number\n * @default\n */\n padding: 0,\n\n /**\n * Color of controlling borders of an object (when it's active)\n * @type String\n * @default\n */\n borderColor: 'rgba(102,153,255,0.75)',\n\n /**\n * Array specifying dash pattern of an object's borders (hasBorder must be true)\n * @since 1.6.2\n * @type Array\n */\n borderDashArray: null,\n\n /**\n * Color of controlling corners of an object (when it's active)\n * @type String\n * @default\n */\n cornerColor: 'rgba(102,153,255,0.5)',\n\n /**\n * Color of controlling corners of an object (when it's active and transparentCorners false)\n * @since 1.6.2\n * @type String\n * @default\n */\n cornerStrokeColor: null,\n\n /**\n * Specify style of control, 'rect' or 'circle'\n * @since 1.6.2\n * @type String\n */\n cornerStyle: 'rect',\n\n /**\n * Array specifying dash pattern of an object's control (hasBorder must be true)\n * @since 1.6.2\n * @type Array\n */\n cornerDashArray: null,\n\n /**\n * When true, this object will use center point as the origin of transformation\n * when being scaled via the controls.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredScaling: false,\n\n /**\n * When true, this object will use center point as the origin of transformation\n * when being rotated via the controls.\n * Backwards incompatibility note: This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n * @default\n */\n centeredRotation: true,\n\n /**\n * Color of object's fill\n * @type String\n * @default\n */\n fill: 'rgb(0,0,0)',\n\n /**\n * Fill rule used to fill an object\n * accepted values are nonzero, evenodd\n * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead)\n * @type String\n * @default\n */\n fillRule: 'nonzero',\n\n /**\n * Composite rule used for canvas globalCompositeOperation\n * @type String\n * @default\n */\n globalCompositeOperation: 'source-over',\n\n /**\n * Background color of an object.\n * @type String\n * @default\n */\n backgroundColor: '',\n\n /**\n * Selection Background color of an object. colored layer behind the object when it is active.\n * does not mix good with globalCompositeOperation methods.\n * @type String\n * @default\n */\n selectionBackgroundColor: '',\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color\n * @type String\n * @default\n */\n stroke: null,\n\n /**\n * Width of a stroke used to render this object\n * @type Number\n * @default\n */\n strokeWidth: 1,\n\n /**\n * Array specifying dash pattern of an object's stroke (stroke must be defined)\n * @type Array\n */\n strokeDashArray: null,\n\n /**\n * Line endings style of an object's stroke (one of \"butt\", \"round\", \"square\")\n * @type String\n * @default\n */\n strokeLineCap: 'butt',\n\n /**\n * Corner style of an object's stroke (one of \"bevil\", \"round\", \"miter\")\n * @type String\n * @default\n */\n strokeLineJoin: 'miter',\n\n /**\n * Maximum miter length (used for strokeLineJoin = \"miter\") of an object's stroke\n * @type Number\n * @default\n */\n strokeMiterLimit: 10,\n\n /**\n * Shadow object representing shadow of this shape\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * Opacity of object's controlling borders when object is active and moving\n * @type Number\n * @default\n */\n borderOpacityWhenMoving: 0.4,\n\n /**\n * Scale factor of object's controlling borders\n * @type Number\n * @default\n */\n borderScaleFactor: 1,\n\n /**\n * Transform matrix (similar to SVG's transform matrix)\n * @type Array\n */\n transformMatrix: null,\n\n /**\n * Minimum allowed scale value of an object\n * @type Number\n * @default\n */\n minScaleLimit: 0.01,\n\n /**\n * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection).\n * But events still fire on it.\n * @type Boolean\n * @default\n */\n selectable: true,\n\n /**\n * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4\n * @type Boolean\n * @default\n */\n evented: true,\n\n /**\n * When set to `false`, an object is not rendered on canvas\n * @type Boolean\n * @default\n */\n visible: true,\n\n /**\n * When set to `false`, object's controls are not displayed and can not be used to manipulate object\n * @type Boolean\n * @default\n */\n hasControls: true,\n\n /**\n * When set to `false`, object's controlling borders are not rendered\n * @type Boolean\n * @default\n */\n hasBorders: true,\n\n /**\n * When set to `false`, object's controlling rotating point will not be visible or selectable\n * @type Boolean\n * @default\n */\n hasRotatingPoint: true,\n\n /**\n * Offset for object's controlling rotating point (when enabled via `hasRotatingPoint`)\n * @type Number\n * @default\n */\n rotatingPointOffset: 40,\n\n /**\n * When set to `true`, objects are \"found\" on canvas on per-pixel basis rather than according to bounding box\n * @type Boolean\n * @default\n */\n perPixelTargetFind: false,\n\n /**\n * When `false`, default object's values are not included in its serialization\n * @type Boolean\n * @default\n */\n includeDefaultValues: true,\n\n /**\n * Function that determines clipping of an object (context is passed as a first argument)\n * Note that context origin is at the object's center point (not left/top corner)\n * @type Function\n */\n clipTo: null,\n\n /**\n * When `true`, object horizontal movement is locked\n * @type Boolean\n * @default\n */\n lockMovementX: false,\n\n /**\n * When `true`, object vertical movement is locked\n * @type Boolean\n * @default\n */\n lockMovementY: false,\n\n /**\n * When `true`, object rotation is locked\n * @type Boolean\n * @default\n */\n lockRotation: false,\n\n /**\n * When `true`, object horizontal scaling is locked\n * @type Boolean\n * @default\n */\n lockScalingX: false,\n\n /**\n * When `true`, object vertical scaling is locked\n * @type Boolean\n * @default\n */\n lockScalingY: false,\n\n /**\n * When `true`, object non-uniform scaling is locked\n * @type Boolean\n * @default\n */\n lockUniScaling: false,\n\n /**\n * When `true`, object horizontal skewing is locked\n * @type Boolean\n * @default\n */\n lockSkewingX: false,\n\n /**\n * When `true`, object vertical skewing is locked\n * @type Boolean\n * @default\n */\n lockSkewingY: false,\n\n /**\n * When `true`, object cannot be flipped by scaling into negative values\n * @type Boolean\n * @default\n */\n lockScalingFlip: false,\n\n /**\n * When `true`, object is not exported in SVG or OBJECT/JSON\n * since 1.6.3\n * @type Boolean\n * @default\n */\n excludeFromExport: false,\n\n /**\n * When `true`, object is cached on an additional canvas.\n * default to true\n * since 1.7.0\n * @type Boolean\n * @default true\n */\n objectCaching: objectCaching,\n\n /**\n * When `true`, object properties are checked for cache invalidation. In some particular\n * situation you may want this to be disabled ( spray brush, very big pathgroups, groups)\n * or if your application does not allow you to modify properties for groups child you want\n * to disable it for groups.\n * default to false\n * since 1.7.0\n * @type Boolean\n * @default false\n */\n statefullCache: false,\n\n /**\n * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled\n * too much and will be redrawn with correct details at the end of scaling.\n * this setting is performance and application dependant.\n * default to true\n * since 1.7.0\n * @type Boolean\n * @default true\n */\n noScaleCache: true,\n\n /**\n * When set to `true`, object's cache will be rerendered next render call.\n * since 1.7.0\n * @type Boolean\n * @default true\n */\n dirty: true,\n\n /**\n * List of properties to consider when checking if state\n * of an object is changed (fabric.Object#hasStateChanged)\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: (\n 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +\n 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' +\n 'angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor ' +\n 'skewX skewY fillRule'\n ).split(' '),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * @type Array\n */\n cacheProperties: (\n 'fill stroke strokeWidth strokeDashArray width height' +\n ' strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor'\n ).split(' '),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n options = options || { };\n if (options) {\n this.setOptions(options);\n }\n },\n\n /**\n * Create a the canvas used to keep the cached copy of the object\n * @private\n */\n _createCacheCanvas: function() {\n this._cacheProperties = {};\n this._cacheCanvas = fabric.document.createElement('canvas');\n this._cacheContext = this._cacheCanvas.getContext('2d');\n this._updateCacheCanvas();\n },\n\n /**\n * Limit the cache dimensions so that X * Y do not cross fabric.perfLimitSizeTotal\n * and each side do not cross fabric.cacheSideLimit\n * those numbers are configurable so that you can get as much detail as you want\n * making bargain with performances.\n * @param {Object} dims\n * @param {Object} dims.width width of canvas\n * @param {Object} dims.height height of canvas\n * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _limitCacheSize: function(dims) {\n var perfLimitSizeTotal = fabric.perfLimitSizeTotal,\n width = dims.width, height = dims.height,\n max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit;\n if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {\n if (width < min) {\n dims.width = min;\n }\n if (height < min) {\n dims.height = min;\n }\n return dims;\n }\n var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),\n capValue = fabric.util.capValue,\n x = capValue(min, limitedDims.x, max),\n y = capValue(min, limitedDims.y, max);\n if (width > x) {\n dims.zoomX /= width / x;\n dims.width = x;\n dims.capped = true;\n }\n if (height > y) {\n dims.zoomY /= height / y;\n dims.height = y;\n dims.capped = true;\n }\n return dims;\n },\n\n /**\n * Return the dimension and the zoom level needed to create a cache canvas\n * big enough to host the object to be cached.\n * @private\n * @param {Object} dim.x width of object to be cached\n * @param {Object} dim.y height of object to be cached\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _getCacheCanvasDimensions: function() {\n var zoom = this.canvas && this.canvas.getZoom() || 1,\n objectScale = this.getObjectScaling(),\n retina = this.canvas && this.canvas._isRetinaScaling() ? fabric.devicePixelRatio : 1,\n dim = this._getNonTransformedDimensions(),\n zoomX = objectScale.scaleX * zoom * retina,\n zoomY = objectScale.scaleY * zoom * retina,\n width = dim.x * zoomX,\n height = dim.y * zoomY;\n return {\n width: width + ALIASING_LIMIT,\n height: height + ALIASING_LIMIT,\n zoomX: zoomX,\n zoomY: zoomY,\n x: dim.x,\n y: dim.y\n };\n },\n\n /**\n * Update width and height of the canvas for cache\n * returns true or false if canvas needed resize.\n * @private\n * @return {Boolean} true if the canvas has been resized\n */\n _updateCacheCanvas: function() {\n if (this.noScaleCache && this.canvas && this.canvas._currentTransform) {\n var target = this.canvas._currentTransform.target,\n action = this.canvas._currentTransform.action;\n if (this === target && action.slice && action.slice(0, 5) === 'scale') {\n return false;\n }\n }\n var canvas = this._cacheCanvas,\n dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n minCacheSize = fabric.minCacheSideLimit,\n width = dims.width, height = dims.height, drawingWidth, drawingHeight,\n zoomX = dims.zoomX, zoomY = dims.zoomY,\n dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,\n zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,\n shouldRedraw = dimensionsChanged || zoomChanged,\n additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false;\n if (dimensionsChanged) {\n var canvasWidth = this._cacheCanvas.width,\n canvasHeight = this._cacheCanvas.height,\n sizeGrowing = width > canvasWidth || height > canvasHeight,\n sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) &&\n canvasWidth > minCacheSize && canvasHeight > minCacheSize;\n shouldResizeCanvas = sizeGrowing || sizeShrinking;\n if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {\n additionalWidth = width * 0.1;\n additionalHeight = height * 0.1;\n }\n }\n if (shouldRedraw) {\n if (shouldResizeCanvas) {\n canvas.width = Math.ceil(width + additionalWidth);\n canvas.height = Math.ceil(height + additionalHeight);\n }\n else {\n this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);\n this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);\n }\n drawingWidth = dims.x * zoomX / 2;\n drawingHeight = dims.y * zoomY / 2;\n this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\n this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\n this.cacheWidth = width;\n this.cacheHeight = height;\n this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);\n this._cacheContext.scale(zoomX, zoomY);\n this.zoomX = zoomX;\n this.zoomY = zoomY;\n return true;\n }\n return false;\n },\n\n /**\n * Sets object's properties from options\n * @param {Object} [options] Options object\n */\n setOptions: function(options) {\n this._setOptions(options);\n this._initGradient(options.fill, 'fill');\n this._initGradient(options.stroke, 'stroke');\n this._initClipping(options);\n this._initPattern(options.fill, 'fill');\n this._initPattern(options.stroke, 'stroke');\n },\n\n /**\n * Transforms context when rendering an object\n * @param {CanvasRenderingContext2D} ctx Context\n * @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node\n */\n transform: function(ctx, fromLeft) {\n if (this.group && !this.group._transformDone && this.group === this.canvas._activeGroup) {\n this.group.transform(ctx);\n }\n var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();\n ctx.translate(center.x, center.y);\n this.angle && ctx.rotate(degreesToRadians(this.angle));\n ctx.scale(\n this.scaleX * (this.flipX ? -1 : 1),\n this.scaleY * (this.flipY ? -1 : 1)\n );\n this.skewX && ctx.transform(1, 0, Math.tan(degreesToRadians(this.skewX)), 1, 0, 0);\n this.skewY && ctx.transform(1, Math.tan(degreesToRadians(this.skewY)), 0, 1, 0, 0);\n },\n\n /**\n * Returns an object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n object = {\n type: this.type,\n originX: this.originX,\n originY: this.originY,\n left: toFixed(this.left, NUM_FRACTION_DIGITS),\n top: toFixed(this.top, NUM_FRACTION_DIGITS),\n width: toFixed(this.width, NUM_FRACTION_DIGITS),\n height: toFixed(this.height, NUM_FRACTION_DIGITS),\n fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,\n stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,\n strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),\n strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,\n strokeLineCap: this.strokeLineCap,\n strokeLineJoin: this.strokeLineJoin,\n strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),\n scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),\n scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),\n angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS),\n flipX: this.flipX,\n flipY: this.flipY,\n opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),\n shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,\n visible: this.visible,\n clipTo: this.clipTo && String(this.clipTo),\n backgroundColor: this.backgroundColor,\n fillRule: this.fillRule,\n globalCompositeOperation: this.globalCompositeOperation,\n transformMatrix: this.transformMatrix ? this.transformMatrix.concat() : null,\n skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),\n skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS)\n };\n\n fabric.util.populateWithProperties(this, object, propertiesToInclude);\n\n if (!this.includeDefaultValues) {\n object = this._removeDefaultValues(object);\n }\n\n return object;\n },\n\n /**\n * Returns (dataless) object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n // will be overwritten by subclasses\n return this.toObject(propertiesToInclude);\n },\n\n /**\n * @private\n * @param {Object} object\n */\n _removeDefaultValues: function(object) {\n var prototype = fabric.util.getKlass(object.type).prototype,\n stateProperties = prototype.stateProperties;\n stateProperties.forEach(function(prop) {\n if (object[prop] === prototype[prop]) {\n delete object[prop];\n }\n var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&\n Object.prototype.toString.call(prototype[prop]) === '[object Array]';\n\n // basically a check for [] === []\n if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {\n delete object[prop];\n }\n });\n\n return object;\n },\n\n /**\n * Returns a string representation of an instance\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Return the object scale factor counting also the group scaling\n * @return {Object} object with scaleX and scaleY properties\n */\n getObjectScaling: function() {\n var scaleX = this.scaleX, scaleY = this.scaleY;\n if (this.group) {\n var scaling = this.group.getObjectScaling();\n scaleX *= scaling.scaleX;\n scaleY *= scaling.scaleY;\n }\n return { scaleX: scaleX, scaleY: scaleY };\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Object} thisArg\n */\n _set: function(key, value) {\n var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'),\n isChanged = this[key] !== value;\n\n if (shouldConstrainValue) {\n value = this._constrainScale(value);\n }\n if (key === 'scaleX' && value < 0) {\n this.flipX = !this.flipX;\n value *= -1;\n }\n else if (key === 'scaleY' && value < 0) {\n this.flipY = !this.flipY;\n value *= -1;\n }\n else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {\n value = new fabric.Shadow(value);\n }\n else if (key === 'dirty' && this.group) {\n this.group.set('dirty', value);\n }\n\n this[key] = value;\n\n if (isChanged && this.cacheProperties.indexOf(key) > -1) {\n if (this.group) {\n this.group.set('dirty', true);\n }\n this.dirty = true;\n }\n\n if (isChanged && this.group && this.stateProperties.indexOf(key) > -1) {\n this.group.set('dirty', true);\n }\n\n if (key === 'width' || key === 'height') {\n this.minScaleLimit = Math.min(0.1, 1 / Math.max(this.width, this.height));\n }\n\n return this;\n },\n\n /**\n * This callback function is called by the parent group of an object every\n * time a non-delegated property changes on the group. It is passed the key\n * and value as parameters. Not adding in this function's signature to avoid\n * Travis build error about unused variables.\n */\n setOnGroup: function() {\n // implemented by sub-classes, as needed.\n },\n\n /**\n * Sets sourcePath of an object\n * @param {String} value Value to set sourcePath to\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setSourcePath: function(value) {\n this.sourcePath = value;\n return this;\n },\n\n /**\n * Retrieves viewportTransform from Object's canvas if possible\n * @method getViewportTransform\n * @memberOf fabric.Object.prototype\n * @return {Boolean}\n */\n getViewportTransform: function() {\n if (this.canvas && this.canvas.viewportTransform) {\n return this.canvas.viewportTransform;\n }\n return fabric.iMatrix.concat();\n },\n\n /*\n * @private\n * return if the object would be visible in rendering\n * @memberOf fabric.Object.prototype\n * @return {Boolean}\n */\n isNotVisible: function() {\n return this.opacity === 0 || (this.width === 0 && this.height === 0) || !this.visible;\n },\n\n /**\n * Renders an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n render: function(ctx, noTransform) {\n // do not render if width/height are zeros or object is not visible\n if (this.isNotVisible()) {\n return;\n }\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n return;\n }\n ctx.save();\n //setup fill rule for current object\n this._setupCompositeOperation(ctx);\n this.drawSelectionBackground(ctx);\n if (!noTransform) {\n this.transform(ctx);\n }\n this._setOpacity(ctx);\n this._setShadow(ctx);\n if (this.transformMatrix) {\n ctx.transform.apply(ctx, this.transformMatrix);\n }\n this.clipTo && fabric.util.clipContext(this, ctx);\n if (this.shouldCache(noTransform)) {\n if (!this._cacheCanvas) {\n this._createCacheCanvas();\n }\n if (this.isCacheDirty(noTransform)) {\n this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });\n this.drawObject(this._cacheContext, noTransform);\n this.dirty = false;\n }\n this.drawCacheOnCanvas(ctx);\n }\n else {\n this._removeCacheCanvas();\n this.dirty = false;\n this.drawObject(ctx, noTransform);\n if (noTransform && this.objectCaching && this.statefullCache) {\n this.saveState({ propertySet: 'cacheProperties' });\n }\n }\n this.clipTo && ctx.restore();\n ctx.restore();\n },\n\n /**\n * Remove cacheCanvas and its dimensions from the objects\n */\n _removeCacheCanvas: function() {\n this._cacheCanvas = null;\n this.cacheWidth = 0;\n this.cacheHeight = 0;\n },\n\n /**\n * When set to `true`, force the object to have its own cache, even if it is inside a group\n * it may be needed when your object behave in a particular way on the cache and always needs\n * its own isolated canvas to render correctly.\n * This function is created to be subclassed by custom classes.\n * since 1.7.12\n * @type function\n * @return false\n */\n needsItsOwnCache: function() {\n return false;\n },\n\n /**\n * Decide if the object should cache or not.\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * @param {Boolean} noTransform if rendereing in pathGroup, caching is not supported at object level\n * @return {Boolean}\n */\n shouldCache: function(noTransform) {\n return !noTransform && this.objectCaching &&\n (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\n },\n\n /**\n * Check if this object or a child object will cast a shadow\n * used by Group.shouldCache to know if child has a shadow recursively\n * @return {Boolean}\n */\n willDrawShadow: function() {\n return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx, noTransform) {\n this._renderBackground(ctx);\n this._setStrokeStyles(ctx);\n this._setFillStyles(ctx);\n this._render(ctx, noTransform);\n },\n\n /**\n * Paint the cached copy of the object on the target context.\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawCacheOnCanvas: function(ctx) {\n ctx.scale(1 / this.zoomX, 1 / this.zoomY);\n ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);\n },\n\n /**\n * Check if cache is dirty\n * @param {Boolean} skipCanvas skip canvas checks because this object is painted\n * on parent canvas.\n */\n isCacheDirty: function(skipCanvas) {\n if (this.isNotVisible()) {\n return false;\n }\n if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) {\n // in this case the context is already cleared.\n return true;\n }\n else {\n if (this.dirty || (this.statefullCache && this.hasStateChanged('cacheProperties'))) {\n if (this._cacheCanvas && !skipCanvas) {\n var width = this.cacheWidth / this.zoomX;\n var height = this.cacheHeight / this.zoomY;\n this._cacheContext.clearRect(-width / 2, -height / 2, width, height);\n }\n return true;\n }\n }\n return false;\n },\n\n /**\n * Draws a background for the object big as its untrasformed dimensions\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground: function(ctx) {\n if (!this.backgroundColor) {\n return;\n }\n var dim = this._getNonTransformedDimensions();\n ctx.fillStyle = this.backgroundColor;\n\n ctx.fillRect(\n -dim.x / 2,\n -dim.y / 2,\n dim.x,\n dim.y\n );\n // if there is background color no other shadows\n // should be casted\n this._removeShadow(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setOpacity: function(ctx) {\n ctx.globalAlpha *= this.opacity;\n },\n\n _setStrokeStyles: function(ctx) {\n if (this.stroke) {\n ctx.lineWidth = this.strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n ctx.strokeStyle = this.stroke.toLive\n ? this.stroke.toLive(ctx, this)\n : this.stroke;\n }\n },\n\n _setFillStyles: function(ctx) {\n if (this.fill) {\n ctx.fillStyle = this.fill.toLive\n ? this.fill.toLive(ctx, this)\n : this.fill;\n }\n },\n\n /**\n * @private\n * Sets line dash\n * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\n * @param {Array} dashArray array representing dashes\n * @param {Function} alternative function to call if browaser does not support lineDash\n */\n _setLineDash: function(ctx, dashArray, alternative) {\n if (!dashArray) {\n return;\n }\n // Spec requires the concatenation of two copies the dash list when the number of elements is odd\n if (1 & dashArray.length) {\n dashArray.push.apply(dashArray, dashArray);\n }\n if (supportsLineDash) {\n ctx.setLineDash(dashArray);\n }\n else {\n alternative && alternative(ctx);\n }\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderControls: function(ctx) {\n if (!this.active || (this.group && this.group !== this.canvas.getActiveGroup())) {\n return;\n }\n\n var vpt = this.getViewportTransform(),\n matrix = this.calcTransformMatrix(),\n options;\n matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);\n options = fabric.util.qrDecompose(matrix);\n\n ctx.save();\n ctx.translate(options.translateX, options.translateY);\n ctx.lineWidth = 1 * this.borderScaleFactor;\n if (!this.group) {\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n }\n if (this.group && this.group === this.canvas.getActiveGroup()) {\n ctx.rotate(degreesToRadians(options.angle));\n this.drawBordersInGroup(ctx, options);\n }\n else {\n ctx.rotate(degreesToRadians(this.angle));\n this.drawBorders(ctx);\n }\n this.drawControls(ctx);\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setShadow: function(ctx) {\n if (!this.shadow) {\n return;\n }\n\n var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1,\n multY = (this.canvas && this.canvas.viewportTransform[3]) || 1,\n scaling = this.getObjectScaling();\n if (this.canvas && this.canvas._isRetinaScaling()) {\n multX *= fabric.devicePixelRatio;\n multY *= fabric.devicePixelRatio;\n }\n ctx.shadowColor = this.shadow.color;\n ctx.shadowBlur = this.shadow.blur * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;\n ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX;\n ctx.shadowOffsetY = this.shadow.offsetY * multY * scaling.scaleY;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _removeShadow: function(ctx) {\n if (!this.shadow) {\n return;\n }\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} filler fabric.Pattern or fabric.Gradient\n */\n _applyPatternGradientTransform: function(ctx, filler) {\n if (!filler.toLive) {\n return;\n }\n var transform = filler.gradientTransform || filler.patternTransform;\n if (transform) {\n ctx.transform.apply(ctx, transform);\n }\n var offsetX = -this.width / 2 + filler.offsetX || 0,\n offsetY = -this.height / 2 + filler.offsetY || 0;\n ctx.translate(offsetX, offsetY);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderFill: function(ctx) {\n if (!this.fill) {\n return;\n }\n\n ctx.save();\n this._applyPatternGradientTransform(ctx, this.fill);\n if (this.fillRule === 'evenodd') {\n ctx.fill('evenodd');\n }\n else {\n ctx.fill();\n }\n ctx.restore();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderStroke: function(ctx) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);\n this._applyPatternGradientTransform(ctx, this.stroke);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Clones an instance, some objects are async, so using callback method will work for every object.\n * Using the direct return does not work for images and groups.\n * @param {Function} callback Callback is invoked with a clone as a first argument\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {fabric.Object} clone of an instance\n */\n clone: function(callback, propertiesToInclude) {\n if (this.constructor.fromObject) {\n return this.constructor.fromObject(this.toObject(propertiesToInclude), callback);\n }\n return new fabric.Object(this.toObject(propertiesToInclude));\n },\n\n /**\n * Creates an instance of fabric.Image out of an object\n * @param {Function} callback callback, invoked with an instance as a first argument\n * @param {Object} [options] for clone as image, passed to toDataURL\n * @param {Boolean} [options.enableRetinaScaling] enable retina scaling for the cloned image\n * @return {fabric.Object} thisArg\n */\n cloneAsImage: function(callback, options) {\n var dataUrl = this.toDataURL(options);\n fabric.util.loadImage(dataUrl, function(img) {\n if (callback) {\n callback(new fabric.Image(img));\n }\n });\n return this;\n },\n\n /**\n * Converts an object into a data-url-like string\n * @param {Object} options Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetina] Enable retina scaling for clone image. Introduce in 1.6.4\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n */\n toDataURL: function(options) {\n options || (options = { });\n\n var el = fabric.util.createCanvasElement(),\n boundingRect = this.getBoundingRect();\n\n el.width = boundingRect.width;\n el.height = boundingRect.height;\n fabric.util.wrapElement(el, 'div');\n var canvas = new fabric.StaticCanvas(el, { enableRetinaScaling: options.enableRetinaScaling });\n // to avoid common confusion https://github.com/kangax/fabric.js/issues/806\n if (options.format === 'jpg') {\n options.format = 'jpeg';\n }\n\n if (options.format === 'jpeg') {\n canvas.backgroundColor = '#fff';\n }\n\n var origParams = {\n active: this.get('active'),\n left: this.getLeft(),\n top: this.getTop()\n };\n\n this.set('active', false);\n this.setPositionByOrigin(new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2), 'center', 'center');\n\n var originalCanvas = this.canvas;\n canvas.add(this);\n var data = canvas.toDataURL(options);\n\n this.set(origParams).setCoords();\n this.canvas = originalCanvas;\n\n canvas.dispose();\n canvas = null;\n\n return data;\n },\n\n /**\n * Returns true if specified type is identical to the type of an instance\n * @param {String} type Type to check against\n * @return {Boolean}\n */\n isType: function(type) {\n return this.type === type;\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance (is 1 unless subclassed)\n */\n complexity: function() {\n return 1;\n },\n\n /**\n * Returns a JSON representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} JSON\n */\n toJSON: function(propertiesToInclude) {\n // delegate, not alias\n return this.toObject(propertiesToInclude);\n },\n\n /**\n * Sets gradient (fill or stroke) of an object\n * Backwards incompatibility note: This method was named \"setGradientFill\" until v1.1.0\n * @param {String} property Property name 'stroke' or 'fill'\n * @param {Object} [options] Options object\n * @param {String} [options.type] Type of gradient 'radial' or 'linear'\n * @param {Number} [options.x1=0] x-coordinate of start point\n * @param {Number} [options.y1=0] y-coordinate of start point\n * @param {Number} [options.x2=0] x-coordinate of end point\n * @param {Number} [options.y2=0] y-coordinate of end point\n * @param {Number} [options.r1=0] Radius of start point (only for radial gradients)\n * @param {Number} [options.r2=0] Radius of end point (only for radial gradients)\n * @param {Object} [options.colorStops] Color stops object eg. {0: 'ff0000', 1: '000000'}\n * @param {Object} [options.gradientTransform] transforMatrix for gradient\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/58y8b/|jsFiddle demo}\n * @example Set linear gradient\n * object.setGradient('fill', {\n * type: 'linear',\n * x1: -object.width / 2,\n * y1: 0,\n * x2: object.width / 2,\n * y2: 0,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n * @example Set radial gradient\n * object.setGradient('fill', {\n * type: 'radial',\n * x1: 0,\n * y1: 0,\n * x2: 0,\n * y2: 0,\n * r1: object.width / 2,\n * r2: 10,\n * colorStops: {\n * 0: 'red',\n * 0.5: '#005555',\n * 1: 'rgba(0,0,255,0.5)'\n * }\n * });\n * canvas.renderAll();\n */\n setGradient: function(property, options) {\n options || (options = { });\n\n var gradient = { colorStops: [] };\n\n gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear');\n gradient.coords = {\n x1: options.x1,\n y1: options.y1,\n x2: options.x2,\n y2: options.y2\n };\n\n if (options.r1 || options.r2) {\n gradient.coords.r1 = options.r1;\n gradient.coords.r2 = options.r2;\n }\n\n gradient.gradientTransform = options.gradientTransform;\n fabric.Gradient.prototype.addColorStop.call(gradient, options.colorStops);\n\n return this.set(property, fabric.Gradient.forObject(this, gradient));\n },\n\n /**\n * Sets pattern fill of an object\n * @param {Object} options Options object\n * @param {(String|HTMLImageElement)} options.source Pattern source\n * @param {String} [options.repeat=repeat] Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)\n * @param {Number} [options.offsetX=0] Pattern horizontal offset from object's left/top corner\n * @param {Number} [options.offsetY=0] Pattern vertical offset from object's left/top corner\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/QT3pa/|jsFiddle demo}\n * @example Set pattern\n * fabric.util.loadImage('http://fabricjs.com/assets/escheresque_ste.png', function(img) {\n * object.setPatternFill({\n * source: img,\n * repeat: 'repeat'\n * });\n * canvas.renderAll();\n * });\n */\n setPatternFill: function(options) {\n return this.set('fill', new fabric.Pattern(options));\n },\n\n /**\n * Sets {@link fabric.Object#shadow|shadow} of an object\n * @param {Object|String} [options] Options object or string (e.g. \"2px 2px 10px rgba(0,0,0,0.2)\")\n * @param {String} [options.color=rgb(0,0,0)] Shadow color\n * @param {Number} [options.blur=0] Shadow blur\n * @param {Number} [options.offsetX=0] Shadow horizontal offset\n * @param {Number} [options.offsetY=0] Shadow vertical offset\n * @return {fabric.Object} thisArg\n * @chainable\n * @see {@link http://jsfiddle.net/fabricjs/7gvJG/|jsFiddle demo}\n * @example Set shadow with string notation\n * object.setShadow('2px 2px 10px rgba(0,0,0,0.2)');\n * canvas.renderAll();\n * @example Set shadow with object notation\n * object.setShadow({\n * color: 'red',\n * blur: 10,\n * offsetX: 20,\n * offsetY: 20\n * });\n * canvas.renderAll();\n */\n setShadow: function(options) {\n return this.set('shadow', options ? new fabric.Shadow(options) : null);\n },\n\n /**\n * Sets \"color\" of an instance (alias of `set('fill', …)`)\n * @param {String} color Color value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setColor: function(color) {\n this.set('fill', color);\n return this;\n },\n\n /**\n * Sets \"angle\" of an instance\n * @param {Number} angle Angle value (in degrees)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setAngle: function(angle) {\n var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;\n\n if (shouldCenterOrigin) {\n this._setOriginToCenter();\n }\n\n this.set('angle', angle);\n\n if (shouldCenterOrigin) {\n this._resetOrigin();\n }\n\n return this;\n },\n\n /**\n * Centers object horizontally on canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n centerH: function () {\n this.canvas && this.canvas.centerObjectH(this);\n return this;\n },\n\n /**\n * Centers object horizontally on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenterH: function () {\n this.canvas && this.canvas.viewportCenterObjectH(this);\n return this;\n },\n\n /**\n * Centers object vertically on canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n centerV: function () {\n this.canvas && this.canvas.centerObjectV(this);\n return this;\n },\n\n /**\n * Centers object vertically on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenterV: function () {\n this.canvas && this.canvas.viewportCenterObjectV(this);\n return this;\n },\n\n /**\n * Centers object vertically and horizontally on canvas to which is was added last\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n center: function () {\n this.canvas && this.canvas.centerObject(this);\n return this;\n },\n\n /**\n * Centers object on current viewport of canvas to which it was added last.\n * You might need to call `setCoords` on an object after centering, to update controls area.\n * @return {fabric.Object} thisArg\n * @chainable\n */\n viewportCenter: function () {\n this.canvas && this.canvas.viewportCenterObject(this);\n return this;\n },\n\n /**\n * Removes object from canvas to which it was added last\n * @return {fabric.Object} thisArg\n * @chainable\n */\n remove: function() {\n if (this.canvas) {\n if (this.group && this.group === this.canvas._activeGroup) {\n this.group.remove(this);\n }\n this.canvas.remove(this);\n }\n return this;\n },\n\n /**\n * Returns coordinates of a pointer relative to an object\n * @param {Event} e Event to operate upon\n * @param {Object} [pointer] Pointer to operate upon (instead of event)\n * @return {Object} Coordinates of a pointer (x, y)\n */\n getLocalPointer: function(e, pointer) {\n pointer = pointer || this.canvas.getPointer(e);\n var pClicked = new fabric.Point(pointer.x, pointer.y),\n objectLeftTop = this._getLeftTopCoords();\n if (this.angle) {\n pClicked = fabric.util.rotatePoint(\n pClicked, objectLeftTop, degreesToRadians(-this.angle));\n }\n return {\n x: pClicked.x - objectLeftTop.x,\n y: pClicked.y - objectLeftTop.y\n };\n },\n\n /**\n * Sets canvas globalCompositeOperation for specific object\n * custom composition operation for the particular object can be specifed using globalCompositeOperation property\n * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n */\n _setupCompositeOperation: function (ctx) {\n if (this.globalCompositeOperation) {\n ctx.globalCompositeOperation = this.globalCompositeOperation;\n }\n }\n });\n\n fabric.util.createAccessors(fabric.Object);\n\n /**\n * Alias for {@link fabric.Object.prototype.setAngle}\n * @alias rotate -> setAngle\n * @memberOf fabric.Object\n */\n fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;\n\n extend(fabric.Object.prototype, fabric.Observable);\n\n /**\n * Defines the number of fraction digits to use when serializing object values.\n * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\n * @static\n * @memberOf fabric.Object\n * @constant\n * @type Number\n */\n fabric.Object.NUM_FRACTION_DIGITS = 2;\n\n fabric.Object._fromObject = function(className, object, callback, forceAsync, extraParam) {\n var klass = fabric[className];\n object = clone(object, true);\n if (forceAsync) {\n fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {\n if (typeof patterns[0] !== 'undefined') {\n object.fill = patterns[0];\n }\n if (typeof patterns[1] !== 'undefined') {\n object.stroke = patterns[1];\n }\n var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n callback && callback(instance);\n });\n }\n else {\n var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);\n callback && callback(instance);\n return instance;\n }\n };\n\n /**\n * Unique id used internally when creating SVG elements\n * @static\n * @memberOf fabric.Object\n * @type Number\n */\n fabric.Object.__uid = 0;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var degreesToRadians = fabric.util.degreesToRadians,\n originXOffset = {\n left: -0.5,\n center: 0,\n right: 0.5\n },\n originYOffset = {\n top: -0.5,\n center: 0,\n bottom: 0.5\n };\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @param {String} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @param {String} toOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) {\n var x = point.x,\n y = point.y,\n offsetX, offsetY, dim;\n\n if (typeof fromOriginX === 'string') {\n fromOriginX = originXOffset[fromOriginX];\n }\n else {\n fromOriginX -= 0.5;\n }\n\n if (typeof toOriginX === 'string') {\n toOriginX = originXOffset[toOriginX];\n }\n else {\n toOriginX -= 0.5;\n }\n\n offsetX = toOriginX - fromOriginX;\n\n if (typeof fromOriginY === 'string') {\n fromOriginY = originYOffset[fromOriginY];\n }\n else {\n fromOriginY -= 0.5;\n }\n\n if (typeof toOriginY === 'string') {\n toOriginY = originYOffset[toOriginY];\n }\n else {\n toOriginY -= 0.5;\n }\n\n offsetY = toOriginY - fromOriginY;\n\n if (offsetX || offsetY) {\n dim = this._getTransformedDimensions();\n x = point.x + offsetX * dim.x;\n y = point.y + offsetY * dim.y;\n }\n\n return new fabric.Point(x, y);\n },\n\n /**\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToCenterPoint: function(point, originX, originY) {\n var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');\n if (this.angle) {\n return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));\n }\n return p;\n },\n\n /**\n * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n * @param {fabric.Point} center The point which corresponds to center of the object\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n translateToOriginPoint: function(center, originX, originY) {\n var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n if (this.angle) {\n return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));\n }\n return p;\n },\n\n /**\n * Returns the real center coordinates of the object\n * @return {fabric.Point}\n */\n getCenterPoint: function() {\n var leftTop = new fabric.Point(this.left, this.top);\n return this.translateToCenterPoint(leftTop, this.originX, this.originY);\n },\n\n /**\n * Returns the coordinates of the object based on center coordinates\n * @param {fabric.Point} point The point which corresponds to the originX and originY params\n * @return {fabric.Point}\n */\n // getOriginPoint: function(center) {\n // return this.translateToOriginPoint(center, this.originX, this.originY);\n // },\n\n /**\n * Returns the coordinates of the object as if it has a different origin\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n getPointByOrigin: function(originX, originY) {\n var center = this.getCenterPoint();\n return this.translateToOriginPoint(center, originX, originY);\n },\n\n /**\n * Returns the point in local coordinates\n * @param {fabric.Point} point The point relative to the global coordinate system\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {fabric.Point}\n */\n toLocalPoint: function(point, originX, originY) {\n var center = this.getCenterPoint(),\n p, p2;\n\n if (typeof originX !== 'undefined' && typeof originY !== 'undefined' ) {\n p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);\n }\n else {\n p = new fabric.Point(this.left, this.top);\n }\n\n p2 = new fabric.Point(point.x, point.y);\n if (this.angle) {\n p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));\n }\n return p2.subtractEquals(p);\n },\n\n /**\n * Returns the point in global coordinates\n * @param {fabric.Point} The point relative to the local coordinate system\n * @return {fabric.Point}\n */\n // toGlobalPoint: function(point) {\n // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top));\n // },\n\n /**\n * Sets the position of the object taking into consideration the object's origin\n * @param {fabric.Point} pos The new position of the object\n * @param {String} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {String} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {void}\n */\n setPositionByOrigin: function(pos, originX, originY) {\n var center = this.translateToCenterPoint(pos, originX, originY),\n position = this.translateToOriginPoint(center, this.originX, this.originY);\n\n this.set('left', position.x);\n this.set('top', position.y);\n },\n\n /**\n * @param {String} to One of 'left', 'center', 'right'\n */\n adjustPosition: function(to) {\n var angle = degreesToRadians(this.angle),\n hypotFull = this.getWidth(),\n xFull = Math.cos(angle) * hypotFull,\n yFull = Math.sin(angle) * hypotFull,\n offsetFrom, offsetTo;\n\n //TODO: this function does not consider mixed situation like top, center.\n if (typeof this.originX === 'string') {\n offsetFrom = originXOffset[this.originX];\n }\n else {\n offsetFrom = this.originX - 0.5;\n }\n if (typeof to === 'string') {\n offsetTo = originXOffset[to];\n }\n else {\n offsetTo = to - 0.5;\n }\n this.left += xFull * (offsetTo - offsetFrom);\n this.top += yFull * (offsetTo - offsetFrom);\n this.setCoords();\n this.originX = to;\n },\n\n /**\n * Sets the origin/position of the object to it's center point\n * @private\n * @return {void}\n */\n _setOriginToCenter: function() {\n this._originalOriginX = this.originX;\n this._originalOriginY = this.originY;\n\n var center = this.getCenterPoint();\n\n this.originX = 'center';\n this.originY = 'center';\n\n this.left = center.x;\n this.top = center.y;\n },\n\n /**\n * Resets the origin/position of the object to it's original origin\n * @private\n * @return {void}\n */\n _resetOrigin: function() {\n var originPoint = this.translateToOriginPoint(\n this.getCenterPoint(),\n this._originalOriginX,\n this._originalOriginY);\n\n this.originX = this._originalOriginX;\n this.originY = this._originalOriginY;\n\n this.left = originPoint.x;\n this.top = originPoint.y;\n\n this._originalOriginX = null;\n this._originalOriginY = null;\n },\n\n /**\n * @private\n */\n _getLeftTopCoords: function() {\n return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');\n },\n\n /**\n * Callback; invoked right before object is about to go from active to inactive\n */\n onDeselect: function() {\n /* NOOP */\n }\n });\n\n})();\n\n\n(function() {\n\n function getCoords(coords) {\n return [\n new fabric.Point(coords.tl.x, coords.tl.y),\n new fabric.Point(coords.tr.x, coords.tr.y),\n new fabric.Point(coords.br.x, coords.br.y),\n new fabric.Point(coords.bl.x, coords.bl.y)\n ];\n }\n\n var degreesToRadians = fabric.util.degreesToRadians,\n multiplyMatrices = fabric.util.multiplyTransformMatrices;\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Describe object's corner position in canvas element coordinates.\n * properties are tl,mt,tr,ml,mr,bl,mb,br,mtr for the main controls.\n * each property is an object with x, y and corner.\n * The `corner` property contains in a similar manner the 4 points of the\n * interactive area of the corner.\n * The coordinates depends from this properties: width, height, scaleX, scaleY\n * skewX, skewY, angle, strokeWidth, viewportTransform, top, left, padding.\n * The coordinates get updated with @method setCoords.\n * You can calculate them without updating with @method calcCoords;\n * @memberOf fabric.Object.prototype\n */\n oCoords: null,\n\n /**\n * Describe object's corner position in canvas object absolute coordinates\n * properties are tl,tr,bl,br and describe the four main corner.\n * each property is an object with x, y, instance of Fabric.Point.\n * The coordinates depends from this properties: width, height, scaleX, scaleY\n * skewX, skewY, angle, strokeWidth, top, left.\n * Those coordinates are usefull to understand where an object is. They get updated\n * with oCoords but they do not need to be updated when zoom or panning change.\n * The coordinates get updated with @method setCoords.\n * You can calculate them without updating with @method calcCoords(true);\n * @memberOf fabric.Object.prototype\n */\n aCoords: null,\n\n /**\n * return correct set of coordinates for intersection\n */\n getCoords: function(absolute, calculate) {\n if (!this.oCoords) {\n this.setCoords();\n }\n var coords = absolute ? this.aCoords : this.oCoords;\n return getCoords(calculate ? this.calcCoords(absolute) : coords);\n },\n\n /**\n * Checks if object intersects with an area formed by 2 points\n * @param {Object} pointTL top-left point of area\n * @param {Object} pointBR bottom-right point of area\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object intersects with an area formed by 2 points\n */\n intersectsWithRect: function(pointTL, pointBR, absolute, calculate) {\n var coords = this.getCoords(absolute, calculate),\n intersection = fabric.Intersection.intersectPolygonRectangle(\n coords,\n pointTL,\n pointBR\n );\n return intersection.status === 'Intersection';\n },\n\n /**\n * Checks if object intersects with another object\n * @param {Object} other Object to test\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object intersects with another object\n */\n intersectsWithObject: function(other, absolute, calculate) {\n var intersection = fabric.Intersection.intersectPolygonPolygon(\n this.getCoords(absolute, calculate),\n other.getCoords(absolute, calculate)\n );\n\n return intersection.status === 'Intersection'\n || other.isContainedWithinObject(this, absolute, calculate)\n || this.isContainedWithinObject(other, absolute, calculate);\n },\n\n /**\n * Checks if object is fully contained within area of another object\n * @param {Object} other Object to test\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully contained within area of another object\n */\n isContainedWithinObject: function(other, absolute, calculate) {\n var points = this.getCoords(absolute, calculate),\n i = 0, lines = other._getImageLines(\n calculate ? other.calcCoords(absolute) : absolute ? other.aCoords : other.oCoords\n );\n for (; i < 4; i++) {\n if (!other.containsPoint(points[i], lines)) {\n return false;\n }\n }\n return true;\n },\n\n /**\n * Checks if object is fully contained within area formed by 2 points\n * @param {Object} pointTL top-left point of area\n * @param {Object} pointBR bottom-right point of area\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully contained within area formed by 2 points\n */\n isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) {\n var boundingRect = this.getBoundingRect(absolute, calculate);\n\n return (\n boundingRect.left >= pointTL.x &&\n boundingRect.left + boundingRect.width <= pointBR.x &&\n boundingRect.top >= pointTL.y &&\n boundingRect.top + boundingRect.height <= pointBR.y\n );\n },\n\n /**\n * Checks if point is inside the object\n * @param {fabric.Point} point Point to check against\n * @param {Object} [lines] object returned from @method _getImageLines\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if point is inside the object\n */\n containsPoint: function(point, lines, absolute, calculate) {\n var lines = lines || this._getImageLines(\n calculate ? this.calcCoords(absolute) : absolute ? this.aCoords : this.oCoords\n ),\n xPoints = this._findCrossPoints(point, lines);\n\n // if xPoints is odd then point is inside the object\n return (xPoints !== 0 && xPoints % 2 === 1);\n },\n\n /**\n * Checks if object is contained within the canvas with current viewportTransform\n * the check is done stopping at first point that appear on screen\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Boolean} true if object is fully contained within canvas\n */\n isOnScreen: function(calculate) {\n if (!this.canvas) {\n return false;\n }\n var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;\n var points = this.getCoords(true, calculate), point;\n for (var i = 0; i < 4; i++) {\n point = points[i];\n if (point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y) {\n return true;\n }\n }\n // no points on screen, check intersection with absolute coordinates\n if (this.intersectsWithRect(pointTL, pointBR, true)) {\n return true;\n }\n // worst case scenario the object is so big that contanins the screen\n var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };\n if (this.containsPoint(centerPoint, null, true)) {\n return true;\n }\n return false;\n },\n\n /**\n * Method that returns an object with the object edges in it, given the coordinates of the corners\n * @private\n * @param {Object} oCoords Coordinates of the object corners\n */\n _getImageLines: function(oCoords) {\n return {\n topline: {\n o: oCoords.tl,\n d: oCoords.tr\n },\n rightline: {\n o: oCoords.tr,\n d: oCoords.br\n },\n bottomline: {\n o: oCoords.br,\n d: oCoords.bl\n },\n leftline: {\n o: oCoords.bl,\n d: oCoords.tl\n }\n };\n },\n\n /**\n * Helper method to determine how many cross points are between the 4 object edges\n * and the horizontal line determined by a point on canvas\n * @private\n * @param {fabric.Point} point Point to check\n * @param {Object} lines Coordinates of the object being evaluated\n */\n // remove yi, not used but left code here just in case.\n _findCrossPoints: function(point, lines) {\n var b1, b2, a1, a2, xi, // yi,\n xcount = 0,\n iLine;\n\n for (var lineKey in lines) {\n iLine = lines[lineKey];\n // optimisation 1: line below point. no cross\n if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {\n continue;\n }\n // optimisation 2: line above point. no cross\n if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {\n continue;\n }\n // optimisation 3: vertical line case\n if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {\n xi = iLine.o.x;\n // yi = point.y;\n }\n // calculate the intersection point\n else {\n b1 = 0;\n b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);\n a1 = point.y - b1 * point.x;\n a2 = iLine.o.y - b2 * iLine.o.x;\n\n xi = -(a1 - a2) / (b1 - b2);\n // yi = a1 + b1 * xi;\n }\n // dont count xi < point.x cases\n if (xi >= point.x) {\n xcount += 1;\n }\n // optimisation 4: specific for square images\n if (xcount === 2) {\n break;\n }\n }\n return xcount;\n },\n\n /**\n * Returns width of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} width value\n */\n getBoundingRectWidth: function() {\n return this.getBoundingRect().width;\n },\n\n /**\n * Returns height of an object's bounding rectangle\n * @deprecated since 1.0.4\n * @return {Number} height value\n */\n getBoundingRectHeight: function() {\n return this.getBoundingRect().height;\n },\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * the box is intented as aligned to axis of canvas.\n * @param {Boolean} [absolute] use coordinates without viewportTransform\n * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords\n * @return {Object} Object with left, top, width, height properties\n */\n getBoundingRect: function(absolute, calculate) {\n var coords = this.getCoords(absolute, calculate);\n return fabric.util.makeBoundingBoxFromPoints(coords);\n },\n\n /**\n * Returns width of an object bounding box counting transformations\n * @return {Number} width value\n */\n getWidth: function() {\n return this._getTransformedDimensions().x;\n },\n\n /**\n * Returns height of an object bounding box counting transformations\n * to be renamed in 2.0\n * @return {Number} height value\n */\n getHeight: function() {\n return this._getTransformedDimensions().y;\n },\n\n /**\n * Makes sure the scale is valid and modifies it if necessary\n * @private\n * @param {Number} value\n * @return {Number}\n */\n _constrainScale: function(value) {\n if (Math.abs(value) < this.minScaleLimit) {\n if (value < 0) {\n return -this.minScaleLimit;\n }\n else {\n return this.minScaleLimit;\n }\n }\n return value;\n },\n\n /**\n * Scales an object (equally by x and y)\n * @param {Number} value Scale factor\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scale: function(value) {\n value = this._constrainScale(value);\n\n if (value < 0) {\n this.flipX = !this.flipX;\n this.flipY = !this.flipY;\n value *= -1;\n }\n\n this.scaleX = value;\n this.scaleY = value;\n return this.setCoords();\n },\n\n /**\n * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New width value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToWidth: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect().width / this.getWidth();\n return this.scale(value / this.width / boundingRectFactor);\n },\n\n /**\n * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New height value\n * @return {fabric.Object} thisArg\n * @chainable\n */\n scaleToHeight: function(value) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n var boundingRectFactor = this.getBoundingRect().height / this.getHeight();\n return this.scale(value / this.height / boundingRectFactor);\n },\n\n /**\n * Calculate and returns the .coords of an object.\n * @return {Object} Object with tl, tr, br, bl ....\n * @chainable\n */\n calcCoords: function(absolute) {\n var theta = degreesToRadians(this.angle),\n vpt = this.getViewportTransform(),\n dim = absolute ? this._getTransformedDimensions() : this._calculateCurrentDimensions(),\n currentWidth = dim.x, currentHeight = dim.y,\n sinTh = Math.sin(theta),\n cosTh = Math.cos(theta),\n _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,\n _hypotenuse = (currentWidth / Math.cos(_angle)) / 2,\n offsetX = Math.cos(_angle + theta) * _hypotenuse,\n offsetY = Math.sin(_angle + theta) * _hypotenuse,\n center = this.getCenterPoint(),\n // offset added for rotate and scale actions\n coords = absolute ? center : fabric.util.transformPoint(center, vpt),\n tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),\n tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),\n bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),\n br = new fabric.Point(coords.x + offsetX, coords.y + offsetY);\n if (!absolute) {\n var ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2),\n mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2),\n mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2),\n mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2),\n mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset);\n }\n\n // debugging\n\n /* setTimeout(function() {\n canvas.contextTop.fillStyle = 'green';\n canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);\n canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);\n canvas.contextTop.fillRect(br.x, br.y, 3, 3);\n canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);\n canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);\n canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);\n canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);\n canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);\n canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);\n }, 50); */\n\n var coords = {\n // corners\n tl: tl, tr: tr, br: br, bl: bl,\n };\n if (!absolute) {\n // middle\n coords.ml = ml;\n coords.mt = mt;\n coords.mr = mr;\n coords.mb = mb;\n // rotating point\n coords.mtr = mtr;\n }\n return coords;\n },\n\n /**\n * Sets corner position coordinates based on current angle, width and height\n * See https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords\n * @param {Boolean} [ignoreZoom] set oCoords with or without the viewport transform.\n * @param {Boolean} [skipAbsolute] skip calculation of aCoords, usefull in setViewportTransform\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setCoords: function(ignoreZoom, skipAbsolute) {\n this.oCoords = this.calcCoords(ignoreZoom);\n if (!skipAbsolute) {\n this.aCoords = this.calcCoords(true);\n }\n\n // set coordinates of the draggable boxes in the corners used to scale/rotate the image\n ignoreZoom || (this._setCornerCoords && this._setCornerCoords());\n\n return this;\n },\n\n /**\n * calculate rotation matrix of an object\n * @return {Array} rotation matrix for the object\n */\n _calcRotateMatrix: function() {\n if (this.angle) {\n var theta = degreesToRadians(this.angle), cos = Math.cos(theta), sin = Math.sin(theta);\n // trying to keep rounding error small, ugly but it works.\n if (cos === 6.123233995736766e-17 || cos === -1.8369701987210297e-16) {\n cos = 0;\n }\n return [cos, sin, -sin, cos, 0, 0];\n }\n return fabric.iMatrix.concat();\n },\n\n /**\n * calculate trasform Matrix that represent current transformation from\n * object properties.\n * @param {Boolean} [skipGroup] return transformMatrix for object and not go upward with parents\n * @return {Array} matrix Transform Matrix for the object\n */\n calcTransformMatrix: function(skipGroup) {\n var center = this.getCenterPoint(),\n translateMatrix = [1, 0, 0, 1, center.x, center.y],\n rotateMatrix,\n dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true),\n matrix;\n if (this.group && !skipGroup) {\n matrix = multiplyMatrices(this.group.calcTransformMatrix(), translateMatrix);\n }\n else {\n matrix = translateMatrix;\n }\n if (this.angle) {\n rotateMatrix = this._calcRotateMatrix();\n matrix = multiplyMatrices(matrix, rotateMatrix);\n }\n matrix = multiplyMatrices(matrix, dimensionMatrix);\n return matrix;\n },\n\n _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {\n var skewMatrix,\n scaleX = this.scaleX * (flipping && this.flipX ? -1 : 1),\n scaleY = this.scaleY * (flipping && this.flipY ? -1 : 1),\n scaleMatrix = [scaleX, 0, 0, scaleY, 0, 0];\n if (skewX) {\n skewMatrix = [1, 0, Math.tan(degreesToRadians(skewX)), 1];\n scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);\n }\n if (skewY) {\n skewMatrix = [1, Math.tan(degreesToRadians(skewY)), 0, 1];\n scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);\n }\n return scaleMatrix;\n },\n\n /*\n * Calculate object dimensions from its properties\n * @private\n * @return {Object} .x width dimension\n * @return {Object} .y height dimension\n */\n _getNonTransformedDimensions: function() {\n var strokeWidth = this.strokeWidth,\n w = this.width + strokeWidth,\n h = this.height + strokeWidth;\n return { x: w, y: h };\n },\n\n /*\n * Calculate object bounding boxdimensions from its properties scale, skew.\n * @private\n * @return {Object} .x width dimension\n * @return {Object} .y height dimension\n */\n _getTransformedDimensions: function(skewX, skewY) {\n if (typeof skewX === 'undefined') {\n skewX = this.skewX;\n }\n if (typeof skewY === 'undefined') {\n skewY = this.skewY;\n }\n var dimensions = this._getNonTransformedDimensions(),\n dimX = dimensions.x / 2, dimY = dimensions.y / 2,\n points = [\n {\n x: -dimX,\n y: -dimY\n },\n {\n x: dimX,\n y: -dimY\n },\n {\n x: -dimX,\n y: dimY\n },\n {\n x: dimX,\n y: dimY\n }],\n i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false),\n bbox;\n for (i = 0; i < points.length; i++) {\n points[i] = fabric.util.transformPoint(points[i], transformMatrix);\n }\n bbox = fabric.util.makeBoundingBoxFromPoints(points);\n return { x: bbox.width, y: bbox.height };\n },\n\n /*\n * Calculate object dimensions for controls. include padding and canvas zoom\n * private\n */\n _calculateCurrentDimensions: function() {\n var vpt = this.getViewportTransform(),\n dim = this._getTransformedDimensions(),\n p = fabric.util.transformPoint(dim, vpt, true);\n\n return p.scalarAdd(2 * this.padding);\n },\n });\n})();\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Moves an object to the bottom of the stack of drawn objects\n * @return {fabric.Object} thisArg\n * @chainable\n */\n sendToBack: function() {\n if (this.group) {\n fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);\n }\n else {\n this.canvas.sendToBack(this);\n }\n return this;\n },\n\n /**\n * Moves an object to the top of the stack of drawn objects\n * @return {fabric.Object} thisArg\n * @chainable\n */\n bringToFront: function() {\n if (this.group) {\n fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);\n }\n else {\n this.canvas.bringToFront(this);\n }\n return this;\n },\n\n /**\n * Moves an object down in stack of drawn objects\n * @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n sendBackwards: function(intersecting) {\n if (this.group) {\n fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);\n }\n else {\n this.canvas.sendBackwards(this, intersecting);\n }\n return this;\n },\n\n /**\n * Moves an object up in stack of drawn objects\n * @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n bringForward: function(intersecting) {\n if (this.group) {\n fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);\n }\n else {\n this.canvas.bringForward(this, intersecting);\n }\n return this;\n },\n\n /**\n * Moves an object to specified level in stack of drawn objects\n * @param {Number} index New position of object\n * @return {fabric.Object} thisArg\n * @chainable\n */\n moveTo: function(index) {\n if (this.group) {\n fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);\n }\n else {\n this.canvas.moveTo(this, index);\n }\n return this;\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n\n function getSvgColorString(prop, value) {\n if (!value) {\n return prop + ': none; ';\n }\n else if (value.toLive) {\n return prop + ': url(#SVGID_' + value.id + '); ';\n }\n else {\n var color = new fabric.Color(value),\n str = prop + ': ' + color.toRgb() + '; ',\n opacity = color.getAlpha();\n if (opacity !== 1) {\n //change the color in rgb + opacity\n str += prop + '-opacity: ' + opacity.toString() + '; ';\n }\n return str;\n }\n }\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles: function(skipShadow) {\n\n var fillRule = this.fillRule,\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',\n strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n visibility = this.visible ? '' : ' visibility: hidden;',\n filter = skipShadow ? '' : this.getSvgFilter(),\n fill = getSvgColorString('fill', this.fill),\n stroke = getSvgColorString('stroke', this.stroke);\n\n return [\n stroke,\n 'stroke-width: ', strokeWidth, '; ',\n 'stroke-dasharray: ', strokeDashArray, '; ',\n 'stroke-linecap: ', strokeLineCap, '; ',\n 'stroke-linejoin: ', strokeLineJoin, '; ',\n 'stroke-miterlimit: ', strokeMiterLimit, '; ',\n fill,\n 'fill-rule: ', fillRule, '; ',\n 'opacity: ', opacity, ';',\n filter,\n visibility\n ].join('');\n },\n\n /**\n * Returns filter for svg shadow\n * @return {String}\n */\n getSvgFilter: function() {\n return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';\n },\n\n /**\n * Returns id attribute for svg output\n * @return {String}\n */\n getSvgId: function() {\n return this.id ? 'id=\"' + this.id + '\" ' : '';\n },\n\n /**\n * Returns transform-string for svg-export\n * @return {String}\n */\n getSvgTransform: function() {\n if (this.group && this.group.type === 'path-group') {\n return '';\n }\n var toFixed = fabric.util.toFixed,\n angle = this.getAngle(),\n skewX = (this.getSkewX() % 360),\n skewY = (this.getSkewY() % 360),\n center = this.getCenterPoint(),\n\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n\n translatePart = this.type === 'path-group' ? '' : 'translate(' +\n toFixed(center.x, NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(center.y, NUM_FRACTION_DIGITS) +\n ')',\n\n anglePart = angle !== 0\n ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')')\n : '',\n\n scalePart = (this.scaleX === 1 && this.scaleY === 1)\n ? '' :\n (' scale(' +\n toFixed(this.scaleX, NUM_FRACTION_DIGITS) +\n ' ' +\n toFixed(this.scaleY, NUM_FRACTION_DIGITS) +\n ')'),\n\n skewXPart = skewX !== 0 ? ' skewX(' + toFixed(skewX, NUM_FRACTION_DIGITS) + ')' : '',\n\n skewYPart = skewY !== 0 ? ' skewY(' + toFixed(skewY, NUM_FRACTION_DIGITS) + ')' : '',\n\n addTranslateX = this.type === 'path-group' ? this.width : 0,\n\n flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '',\n\n addTranslateY = this.type === 'path-group' ? this.height : 0,\n\n flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : '';\n\n return [\n translatePart, anglePart, scalePart, flipXPart, flipYPart, skewXPart, skewYPart\n ].join('');\n },\n\n /**\n * Returns transform-string for svg-export from the transform matrix of single elements\n * @return {String}\n */\n getSvgTransformMatrix: function() {\n return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : '';\n },\n\n /**\n * @private\n */\n _createBaseSVGMarkup: function() {\n var markup = [];\n\n if (this.fill && this.fill.toLive) {\n markup.push(this.fill.toSVG(this, false));\n }\n if (this.stroke && this.stroke.toLive) {\n markup.push(this.stroke.toSVG(this, false));\n }\n if (this.shadow) {\n markup.push(this.shadow.toSVG(this));\n }\n return markup;\n }\n });\n})();\n/* _TO_SVG_END_ */\n\n\n(function() {\n\n var extend = fabric.util.object.extend,\n originalSet = 'stateProperties';\n\n /*\n Depends on `stateProperties`\n */\n function saveProps(origin, destination, props) {\n var tmpObj = { }, deep = true;\n props.forEach(function(prop) {\n tmpObj[prop] = origin[prop];\n });\n extend(origin[destination], tmpObj, deep);\n }\n\n function _isEqual(origValue, currentValue, firstPass) {\n if (origValue === currentValue) {\n // if the objects are identical, return\n return true;\n }\n else if (Array.isArray(origValue)) {\n if (origValue.length !== currentValue.length) {\n return false;\n }\n for (var i = 0, len = origValue.length; i < len; i++) {\n if (!_isEqual(origValue[i], currentValue[i])) {\n return false;\n }\n }\n return true;\n }\n else if (origValue && typeof origValue === 'object') {\n var keys = Object.keys(origValue), key;\n if (!firstPass && keys.length !== Object.keys(currentValue).length) {\n return false;\n }\n for (var i = 0, len = keys.length; i < len; i++) {\n key = keys[i];\n if (!_isEqual(origValue[key], currentValue[key])) {\n return false;\n }\n }\n return true;\n }\n }\n\n\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * Returns true if object state (one of its state properties) was changed\n * @param {String} [propertySet] optional name for the set of property we want to save\n * @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called\n */\n hasStateChanged: function(propertySet) {\n propertySet = propertySet || originalSet;\n var dashedPropertySet = '_' + propertySet;\n if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {\n return true;\n }\n return !_isEqual(this[dashedPropertySet], this, true);\n },\n\n /**\n * Saves state of an object\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n * @return {fabric.Object} thisArg\n */\n saveState: function(options) {\n var propertySet = options && options.propertySet || originalSet,\n destination = '_' + propertySet;\n if (!this[destination]) {\n return this.setupState(options);\n }\n saveProps(this, destination, this[propertySet]);\n if (options && options.stateProperties) {\n saveProps(this, destination, options.stateProperties);\n }\n return this;\n },\n\n /**\n * Setups state of an object\n * @param {Object} [options] Object with additional `stateProperties` array to include when saving state\n * @return {fabric.Object} thisArg\n */\n setupState: function(options) {\n options = options || { };\n var propertySet = options.propertySet || originalSet;\n options.propertySet = propertySet;\n this['_' + propertySet] = { };\n this.saveState(options);\n return this;\n }\n });\n})();\n\n\n(function() {\n\n var degreesToRadians = fabric.util.degreesToRadians,\n /* eslint-disable camelcase */\n isVML = function() { return typeof G_vmlCanvasManager !== 'undefined'; };\n /* eslint-enable camelcase */\n fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * The object interactivity controls.\n * @private\n */\n _controlsVisibility: null,\n\n /**\n * Determines which corner has been clicked\n * @private\n * @param {Object} pointer The pointer indicating the mouse position\n * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or false if nothing is found\n */\n _findTargetCorner: function(pointer) {\n if (!this.hasControls || !this.active) {\n return false;\n }\n\n var ex = pointer.x,\n ey = pointer.y,\n xPoints,\n lines;\n this.__corner = 0;\n for (var i in this.oCoords) {\n\n if (!this.isControlVisible(i)) {\n continue;\n }\n\n if (i === 'mtr' && !this.hasRotatingPoint) {\n continue;\n }\n\n if (this.get('lockUniScaling') &&\n (i === 'mt' || i === 'mr' || i === 'mb' || i === 'ml')) {\n continue;\n }\n\n lines = this._getImageLines(this.oCoords[i].corner);\n\n // debugging\n\n // canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);\n\n // canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);\n // canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);\n\n xPoints = this._findCrossPoints({ x: ex, y: ey }, lines);\n if (xPoints !== 0 && xPoints % 2 === 1) {\n this.__corner = i;\n return i;\n }\n }\n return false;\n },\n\n /**\n * Sets the coordinates of the draggable boxes in the corners of\n * the image used to scale/rotate it.\n * @private\n */\n _setCornerCoords: function() {\n var coords = this.oCoords,\n newTheta = degreesToRadians(45 - this.angle),\n /* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */\n /* 0.707106 stands for sqrt(2)/2 */\n cornerHypotenuse = this.cornerSize * 0.707106,\n cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),\n sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),\n x, y;\n\n for (var point in coords) {\n x = coords[point].x;\n y = coords[point].y;\n coords[point].corner = {\n tl: {\n x: x - sinHalfOffset,\n y: y - cosHalfOffset\n },\n tr: {\n x: x + cosHalfOffset,\n y: y - sinHalfOffset\n },\n bl: {\n x: x - cosHalfOffset,\n y: y + sinHalfOffset\n },\n br: {\n x: x + sinHalfOffset,\n y: y + cosHalfOffset\n }\n };\n }\n },\n\n /**\n * Draws a colored layer behind the object, inside its selection borders.\n * Requires public options: padding, selectionBackgroundColor\n * this function is called when the context is transformed\n * has checks to be skipped when the object is on a staticCanvas\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawSelectionBackground: function(ctx) {\n if (!this.selectionBackgroundColor || this.group || !this.active ||\n (this.canvas && !this.canvas.interactive)) {\n return this;\n }\n ctx.save();\n var center = this.getCenterPoint(), wh = this._calculateCurrentDimensions(),\n vpt = this.canvas.viewportTransform;\n ctx.translate(center.x, center.y);\n ctx.scale(1 / vpt[0], 1 / vpt[3]);\n ctx.rotate(degreesToRadians(this.angle));\n ctx.fillStyle = this.selectionBackgroundColor;\n ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\n ctx.restore();\n return this;\n },\n\n /**\n * Draws borders of an object's bounding box.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBorders: function(ctx) {\n if (!this.hasBorders) {\n return this;\n }\n\n var wh = this._calculateCurrentDimensions(),\n strokeWidth = 1 / this.borderScaleFactor,\n width = wh.x + strokeWidth,\n height = wh.y + strokeWidth;\n\n ctx.save();\n ctx.strokeStyle = this.borderColor;\n this._setLineDash(ctx, this.borderDashArray, null);\n\n ctx.strokeRect(\n -width / 2,\n -height / 2,\n width,\n height\n );\n\n if (this.hasRotatingPoint && this.isControlVisible('mtr') && !this.get('lockRotation') && this.hasControls) {\n\n var rotateHeight = -height / 2;\n\n ctx.beginPath();\n ctx.moveTo(0, rotateHeight);\n ctx.lineTo(0, rotateHeight - this.rotatingPointOffset);\n ctx.closePath();\n ctx.stroke();\n }\n\n ctx.restore();\n return this;\n },\n\n /**\n * Draws borders of an object's bounding box when it is inside a group.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {object} options object representing current object parameters\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawBordersInGroup: function(ctx, options) {\n if (!this.hasBorders) {\n return this;\n }\n\n var p = this._getNonTransformedDimensions(),\n matrix = fabric.util.customTransformMatrix(options.scaleX, options.scaleY, options.skewX),\n wh = fabric.util.transformPoint(p, matrix),\n strokeWidth = 1 / this.borderScaleFactor,\n width = wh.x + strokeWidth,\n height = wh.y + strokeWidth;\n\n ctx.save();\n this._setLineDash(ctx, this.borderDashArray, null);\n ctx.strokeStyle = this.borderColor;\n\n ctx.strokeRect(\n -width / 2,\n -height / 2,\n width,\n height\n );\n\n ctx.restore();\n return this;\n },\n\n /**\n * Draws corners of an object's bounding box.\n * Requires public properties: width, height\n * Requires public options: cornerSize, padding\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @return {fabric.Object} thisArg\n * @chainable\n */\n drawControls: function(ctx) {\n if (!this.hasControls) {\n return this;\n }\n\n var wh = this._calculateCurrentDimensions(),\n width = wh.x,\n height = wh.y,\n scaleOffset = this.cornerSize,\n left = -(width + scaleOffset) / 2,\n top = -(height + scaleOffset) / 2,\n methodName = this.transparentCorners ? 'stroke' : 'fill';\n\n ctx.save();\n ctx.strokeStyle = ctx.fillStyle = this.cornerColor;\n if (!this.transparentCorners) {\n ctx.strokeStyle = this.cornerStrokeColor;\n }\n this._setLineDash(ctx, this.cornerDashArray, null);\n\n // top-left\n this._drawControl('tl', ctx, methodName,\n left,\n top);\n\n // top-right\n this._drawControl('tr', ctx, methodName,\n left + width,\n top);\n\n // bottom-left\n this._drawControl('bl', ctx, methodName,\n left,\n top + height);\n\n // bottom-right\n this._drawControl('br', ctx, methodName,\n left + width,\n top + height);\n\n if (!this.get('lockUniScaling')) {\n\n // middle-top\n this._drawControl('mt', ctx, methodName,\n left + width / 2,\n top);\n\n // middle-bottom\n this._drawControl('mb', ctx, methodName,\n left + width / 2,\n top + height);\n\n // middle-right\n this._drawControl('mr', ctx, methodName,\n left + width,\n top + height / 2);\n\n // middle-left\n this._drawControl('ml', ctx, methodName,\n left,\n top + height / 2);\n }\n\n // middle-top-rotate\n if (this.hasRotatingPoint) {\n this._drawControl('mtr', ctx, methodName,\n left + width / 2,\n top - this.rotatingPointOffset);\n }\n\n ctx.restore();\n\n return this;\n },\n\n /**\n * @private\n */\n _drawControl: function(control, ctx, methodName, left, top) {\n if (!this.isControlVisible(control)) {\n return;\n }\n var size = this.cornerSize, stroke = !this.transparentCorners && this.cornerStrokeColor;\n switch (this.cornerStyle) {\n case 'circle':\n ctx.beginPath();\n ctx.arc(left + size / 2, top + size / 2, size / 2, 0, 2 * Math.PI, false);\n ctx[methodName]();\n if (stroke) {\n ctx.stroke();\n }\n break;\n default:\n isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size);\n ctx[methodName + 'Rect'](left, top, size, size);\n if (stroke) {\n ctx.strokeRect(left, top, size, size);\n }\n }\n },\n\n /**\n * Returns true if the specified control is visible, false otherwise.\n * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n * @returns {Boolean} true if the specified control is visible, false otherwise\n */\n isControlVisible: function(controlName) {\n return this._getControlsVisibility()[controlName];\n },\n\n /**\n * Sets the visibility of the specified control.\n * @param {String} controlName The name of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n * @param {Boolean} visible true to set the specified control visible, false otherwise\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setControlVisible: function(controlName, visible) {\n this._getControlsVisibility()[controlName] = visible;\n return this;\n },\n\n /**\n * Sets the visibility state of object controls.\n * @param {Object} [options] Options object\n * @param {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n * @param {Boolean} [options.br] true to enable the bottom-right control, false to disable it\n * @param {Boolean} [options.mb] true to enable the middle-bottom control, false to disable it\n * @param {Boolean} [options.ml] true to enable the middle-left control, false to disable it\n * @param {Boolean} [options.mr] true to enable the middle-right control, false to disable it\n * @param {Boolean} [options.mt] true to enable the middle-top control, false to disable it\n * @param {Boolean} [options.tl] true to enable the top-left control, false to disable it\n * @param {Boolean} [options.tr] true to enable the top-right control, false to disable it\n * @param {Boolean} [options.mtr] true to enable the middle-top-rotate control, false to disable it\n * @return {fabric.Object} thisArg\n * @chainable\n */\n setControlsVisibility: function(options) {\n options || (options = { });\n\n for (var p in options) {\n this.setControlVisible(p, options[p]);\n }\n return this;\n },\n\n /**\n * Returns the instance of the control visibility set for this object.\n * @private\n * @returns {Object}\n */\n _getControlsVisibility: function() {\n if (!this._controlsVisibility) {\n this._controlsVisibility = {\n tl: true,\n tr: true,\n br: true,\n bl: true,\n ml: true,\n mt: true,\n mr: true,\n mb: true,\n mtr: true\n };\n }\n return this._controlsVisibility;\n }\n });\n})();\n\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Animation duration (in ms) for fx* methods\n * @type Number\n * @default\n */\n FX_DURATION: 500,\n\n /**\n * Centers object horizontally with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxCenterObjectH: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('left'),\n endValue: this.getCenter().left,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('left', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\n },\n\n /**\n * Centers object vertically with animation.\n * @param {fabric.Object} object Object to center\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxCenterObjectV: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('top'),\n endValue: this.getCenter().top,\n duration: this.FX_DURATION,\n onChange: function(value) {\n object.set('top', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function() {\n object.setCoords();\n onComplete();\n }\n });\n\n return this;\n },\n\n /**\n * Same as `fabric.Canvas#remove` but animated\n * @param {fabric.Object} object Object to remove\n * @param {Object} [callbacks] Callbacks object with optional \"onComplete\" and/or \"onChange\" properties\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxRemove: function (object, callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: object.get('opacity'),\n endValue: 0,\n duration: this.FX_DURATION,\n onStart: function() {\n object.set('active', false);\n },\n onChange: function(value) {\n object.set('opacity', value);\n _this.renderAll();\n onChange();\n },\n onComplete: function () {\n _this.remove(object);\n onComplete();\n }\n });\n\n return this;\n }\n});\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n /**\n * Animates object's properties\n * @param {String|Object} property Property to animate (if string) or properties to animate (if object)\n * @param {Number|Object} value Value to animate property to (if string was given first) or options object\n * @return {fabric.Object} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}\n * @chainable\n *\n * As object — multiple properties\n *\n * object.animate({ left: ..., top: ... });\n * object.animate({ left: ..., top: ... }, { duration: ... });\n *\n * As string — one property\n *\n * object.animate('left', ...);\n * object.animate('left', { duration: ... });\n *\n */\n animate: function() {\n if (arguments[0] && typeof arguments[0] === 'object') {\n var propsToAnimate = [], prop, skipCallbacks;\n for (prop in arguments[0]) {\n propsToAnimate.push(prop);\n }\n for (var i = 0, len = propsToAnimate.length; i < len; i++) {\n prop = propsToAnimate[i];\n skipCallbacks = i !== len - 1;\n this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);\n }\n }\n else {\n this._animate.apply(this, arguments);\n }\n return this;\n },\n\n /**\n * @private\n * @param {String} property Property to animate\n * @param {String} to Value to animate to\n * @param {Object} [options] Options object\n * @param {Boolean} [skipCallbacks] When true, callbacks like onchange and oncomplete are not invoked\n */\n _animate: function(property, to, options, skipCallbacks) {\n var _this = this, propPair;\n\n to = to.toString();\n\n if (!options) {\n options = { };\n }\n else {\n options = fabric.util.object.clone(options);\n }\n\n if (~property.indexOf('.')) {\n propPair = property.split('.');\n }\n\n var currentValue = propPair\n ? this.get(propPair[0])[propPair[1]]\n : this.get(property);\n\n if (!('from' in options)) {\n options.from = currentValue;\n }\n\n if (~to.indexOf('=')) {\n to = currentValue + parseFloat(to.replace('=', ''));\n }\n else {\n to = parseFloat(to);\n }\n\n fabric.util.animate({\n startValue: options.from,\n endValue: to,\n byValue: options.by,\n easing: options.easing,\n duration: options.duration,\n abort: options.abort && function() {\n return options.abort.call(_this);\n },\n onChange: function(value, valueProgress, timeProgress) {\n if (propPair) {\n _this[propPair[0]][propPair[1]] = value;\n }\n else {\n _this.set(property, value);\n }\n if (skipCallbacks) {\n return;\n }\n options.onChange && options.onChange(value, valueProgress, timeProgress);\n },\n onComplete: function(value, valueProgress, timeProgress) {\n if (skipCallbacks) {\n return;\n }\n\n _this.setCoords();\n options.onComplete && options.onComplete(value, valueProgress, timeProgress);\n }\n });\n }\n});\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n clone = fabric.util.object.clone,\n coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },\n supportsLineDash = fabric.StaticCanvas.supports('setLineDash');\n\n if (fabric.Line) {\n fabric.warn('fabric.Line is already defined');\n return;\n }\n\n /**\n * Line class\n * @class fabric.Line\n * @extends fabric.Object\n * @see {@link fabric.Line#initialize} for constructor definition\n */\n fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'line',\n\n /**\n * x value or first line edge\n * @type Number\n * @default\n */\n x1: 0,\n\n /**\n * y value or first line edge\n * @type Number\n * @default\n */\n y1: 0,\n\n /**\n * x value or second line edge\n * @type Number\n * @default\n */\n x2: 0,\n\n /**\n * y value or second line edge\n * @type Number\n * @default\n */\n y2: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),\n\n /**\n * Constructor\n * @param {Array} [points] Array of points\n * @param {Object} [options] Options object\n * @return {fabric.Line} thisArg\n */\n initialize: function(points, options) {\n if (!points) {\n points = [0, 0, 0, 0];\n }\n\n this.callSuper('initialize', options);\n\n this.set('x1', points[0]);\n this.set('y1', points[1]);\n this.set('x2', points[2]);\n this.set('y2', points[3]);\n\n this._setWidthHeight(options);\n },\n\n /**\n * @private\n * @param {Object} [options] Options\n */\n _setWidthHeight: function(options) {\n options || (options = { });\n\n this.width = Math.abs(this.x2 - this.x1);\n this.height = Math.abs(this.y2 - this.y1);\n\n this.left = 'left' in options\n ? options.left\n : this._getLeftToOriginX();\n\n this.top = 'top' in options\n ? options.top\n : this._getTopToOriginY();\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n if (typeof coordProps[key] !== 'undefined') {\n this._setWidthHeight();\n }\n return this;\n },\n\n /**\n * @private\n * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.\n */\n _getLeftToOriginX: makeEdgeToOriginGetter(\n { // property names\n origin: 'originX',\n axis1: 'x1',\n axis2: 'x2',\n dimension: 'width'\n },\n { // possible values of origin\n nearest: 'left',\n center: 'center',\n farthest: 'right'\n }\n ),\n\n /**\n * @private\n * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.\n */\n _getTopToOriginY: makeEdgeToOriginGetter(\n { // property names\n origin: 'originY',\n axis1: 'y1',\n axis2: 'y2',\n dimension: 'height'\n },\n { // possible values of origin\n nearest: 'top',\n center: 'center',\n farthest: 'bottom'\n }\n ),\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n\n if (noTransform) {\n // Line coords are distances from left-top of canvas to origin of line.\n // To render line in a path-group, we need to translate them to\n // distances from center of path-group to center of line.\n var cp = this.getCenterPoint(),\n offset = this.strokeWidth / 2;\n ctx.translate(\n cp.x - (this.strokeLineCap === 'butt' && this.height === 0 ? 0 : offset),\n cp.y - (this.strokeLineCap === 'butt' && this.width === 0 ? 0 : offset)\n );\n }\n\n if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {\n // move from center (of virtual box) to its left/top corner\n // we can't assume x1, y1 is top left and x2, y2 is bottom right\n var p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\n }\n\n ctx.lineWidth = this.strokeWidth;\n\n // TODO: test this\n // make sure setting \"fill\" changes color of a line\n // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n var origStrokeStyle = ctx.strokeStyle;\n ctx.strokeStyle = this.stroke || ctx.fillStyle;\n this.stroke && this._renderStroke(ctx);\n ctx.strokeStyle = origStrokeStyle;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p = this.calcLinePoints();\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @methd toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());\n },\n\n /*\n * Calculate object dimensions from its properties\n * @private\n */\n _getNonTransformedDimensions: function() {\n var dim = this.callSuper('_getNonTransformedDimensions');\n if (this.strokeLineCap === 'butt') {\n if (this.width === 0) {\n dim.y -= this.strokeWidth;\n }\n if (this.height === 0) {\n dim.x -= this.strokeWidth;\n }\n }\n return dim;\n },\n\n /**\n * Recalculates line points given width and height\n * @private\n */\n calcLinePoints: function() {\n var xMult = this.x1 <= this.x2 ? -1 : 1,\n yMult = this.y1 <= this.y2 ? -1 : 1,\n x1 = (xMult * this.width * 0.5),\n y1 = (yMult * this.height * 0.5),\n x2 = (xMult * this.width * -0.5),\n y2 = (yMult * this.height * -0.5);\n\n return {\n x1: x1,\n x2: x2,\n y1: y1,\n y2: y2\n };\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(),\n p = { x1: this.x1, x2: this.x2, y1: this.y1, y2: this.y2 };\n\n if (!(this.group && this.group.type === 'path-group')) {\n p = this.calcLinePoints();\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})\n * @static\n * @memberOf fabric.Line\n * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\n */\n fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));\n\n /**\n * Returns fabric.Line instance from an SVG element\n * @static\n * @memberOf fabric.Line\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromElement = function(element, options) {\n options = options || { };\n var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),\n points = [\n parsedAttributes.x1 || 0,\n parsedAttributes.y1 || 0,\n parsedAttributes.x2 || 0,\n parsedAttributes.y2 || 0\n ];\n options.originX = 'left';\n options.originY = 'top';\n return new fabric.Line(points, extend(parsedAttributes, options));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Line instance from an object representation\n * @static\n * @memberOf fabric.Line\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Line} instance of fabric.Line\n */\n fabric.Line.fromObject = function(object, callback, forceAsync) {\n function _callback(instance) {\n delete instance.points;\n callback && callback(instance);\n };\n var options = clone(object, true);\n options.points = [object.x1, object.y1, object.x2, object.y2];\n var line = fabric.Object._fromObject('Line', options, _callback, forceAsync, 'points');\n if (line) {\n delete line.points;\n }\n return line;\n };\n\n /**\n * Produces a function that calculates distance from canvas edge to Line origin.\n */\n function makeEdgeToOriginGetter(propertyNames, originValues) {\n var origin = propertyNames.origin,\n axis1 = propertyNames.axis1,\n axis2 = propertyNames.axis2,\n dimension = propertyNames.dimension,\n nearest = originValues.nearest,\n center = originValues.center,\n farthest = originValues.farthest;\n\n return function() {\n switch (this.get(origin)) {\n case nearest:\n return Math.min(this.get(axis1), this.get(axis2));\n case center:\n return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));\n case farthest:\n return Math.max(this.get(axis1), this.get(axis2));\n }\n };\n\n }\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n pi = Math.PI,\n extend = fabric.util.object.extend;\n\n if (fabric.Circle) {\n fabric.warn('fabric.Circle is already defined.');\n return;\n }\n\n /**\n * Circle class\n * @class fabric.Circle\n * @extends fabric.Object\n * @see {@link fabric.Circle#initialize} for constructor definition\n */\n fabric.Circle = fabric.util.createClass(fabric.Object, /** @lends fabric.Circle.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'circle',\n\n /**\n * Radius of this circle\n * @type Number\n * @default\n */\n radius: 0,\n\n /**\n * Start angle of the circle, moving clockwise\n * @type Number\n * @default 0\n */\n startAngle: 0,\n\n /**\n * End angle of the circle\n * @type Number\n * @default 2Pi\n */\n endAngle: pi * 2,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Circle} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('radius', options && options.radius || 0);\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Circle} thisArg\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n\n if (key === 'radius') {\n this.setRadius(value);\n }\n\n return this;\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(), x = 0, y = 0,\n angle = (this.endAngle - this.startAngle) % ( 2 * pi);\n\n if (angle === 0) {\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.radius;\n y = this.top + this.radius;\n }\n markup.push(\n '\\n'\n );\n }\n else {\n var startX = Math.cos(this.startAngle) * this.radius,\n startY = Math.sin(this.startAngle) * this.radius,\n endX = Math.cos(this.endAngle) * this.radius,\n endY = Math.sin(this.endAngle) * this.radius,\n largeFlag = angle > pi ? '1' : '0';\n\n markup.push(\n '\\n'\n );\n }\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.arc(noTransform ? this.left + this.radius : 0,\n noTransform ? this.top + this.radius : 0,\n this.radius,\n this.startAngle,\n this.endAngle, false);\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * Returns horizontal radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusX: function() {\n return this.get('radius') * this.get('scaleX');\n },\n\n /**\n * Returns vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusY: function() {\n return this.get('radius') * this.get('scaleY');\n },\n\n /**\n * Sets radius of an object (and updates width accordingly)\n * @return {fabric.Circle} thisArg\n */\n setRadius: function(value) {\n this.radius = value;\n return this.set('width', value * 2).set('height', value * 2);\n },\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Circle.fromElement})\n * @static\n * @memberOf fabric.Circle\n * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\n */\n fabric.Circle.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy r'.split(' '));\n\n /**\n * Returns {@link fabric.Circle} instance from an SVG element\n * @static\n * @memberOf fabric.Circle\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @throws {Error} If value of `r` attribute is missing or invalid\n * @return {fabric.Circle} Instance of fabric.Circle\n */\n fabric.Circle.fromElement = function(element, options) {\n options || (options = { });\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Circle.ATTRIBUTE_NAMES);\n\n if (!isValidRadius(parsedAttributes)) {\n throw new Error('value of `r` attribute is required and can not be negative');\n }\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var obj = new fabric.Circle(extend(parsedAttributes, options));\n\n obj.left -= obj.radius;\n obj.top -= obj.radius;\n return obj;\n };\n\n /**\n * @private\n */\n function isValidRadius(attributes) {\n return (('radius' in attributes) && (attributes.radius >= 0));\n }\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Circle} instance from an object representation\n * @static\n * @memberOf fabric.Circle\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {Object} Instance of fabric.Circle\n */\n fabric.Circle.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Circle', object, callback, forceAsync);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { });\n\n if (fabric.Triangle) {\n fabric.warn('fabric.Triangle is already defined');\n return;\n }\n\n /**\n * Triangle class\n * @class fabric.Triangle\n * @extends fabric.Object\n * @return {fabric.Triangle} thisArg\n * @see {@link fabric.Triangle#initialize} for constructor definition\n */\n fabric.Triangle = fabric.util.createClass(fabric.Object, /** @lends fabric.Triangle.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'triangle',\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('width', options && options.width || 100)\n .set('height', options && options.height || 100);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n ctx.moveTo(-widthBy2, heightBy2);\n ctx.lineTo(0, -heightBy2);\n ctx.lineTo(widthBy2, heightBy2);\n ctx.closePath();\n\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);\n ctx.closePath();\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(),\n widthBy2 = this.width / 2,\n heightBy2 = this.height / 2,\n points = [\n -widthBy2 + ' ' + heightBy2,\n '0 ' + -heightBy2,\n widthBy2 + ' ' + heightBy2\n ]\n .join(',');\n\n markup.push(\n ''\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n });\n\n /**\n * Returns {@link fabric.Triangle} instance from an object representation\n * @static\n * @memberOf fabric.Triangle\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Triangle}\n */\n fabric.Triangle.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Triangle', object, callback, forceAsync);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n piBy2 = Math.PI * 2,\n extend = fabric.util.object.extend;\n\n if (fabric.Ellipse) {\n fabric.warn('fabric.Ellipse is already defined.');\n return;\n }\n\n /**\n * Ellipse class\n * @class fabric.Ellipse\n * @extends fabric.Object\n * @return {fabric.Ellipse} thisArg\n * @see {@link fabric.Ellipse#initialize} for constructor definition\n */\n fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @lends fabric.Ellipse.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'ellipse',\n\n /**\n * Horizontal radius\n * @type Number\n * @default\n */\n rx: 0,\n\n /**\n * Vertical radius\n * @type Number\n * @default\n */\n ry: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {fabric.Ellipse} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this.set('rx', options && options.rx || 0);\n this.set('ry', options && options.ry || 0);\n },\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {fabric.Ellipse} thisArg\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n switch (key) {\n\n case 'rx':\n this.rx = value;\n this.set('width', value * 2);\n break;\n\n case 'ry':\n this.ry = value;\n this.set('height', value * 2);\n break;\n\n }\n return this;\n },\n\n /**\n * Returns horizontal radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRx: function() {\n return this.get('rx') * this.get('scaleX');\n },\n\n /**\n * Returns Vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRy: function() {\n return this.get('ry') * this.get('scaleY');\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(), x = 0, y = 0;\n if (this.group && this.group.type === 'path-group') {\n x = this.left + this.rx;\n y = this.top + this.ry;\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _render: function(ctx, noTransform) {\n ctx.beginPath();\n ctx.save();\n ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n ctx.arc(\n noTransform ? this.left + this.rx : 0,\n noTransform ? (this.top + this.ry) * this.rx / this.ry : 0,\n this.rx,\n 0,\n piBy2,\n false);\n ctx.restore();\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement})\n * @static\n * @memberOf fabric.Ellipse\n * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\n */\n fabric.Ellipse.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('cx cy rx ry'.split(' '));\n\n /**\n * Returns {@link fabric.Ellipse} instance from an SVG element\n * @static\n * @memberOf fabric.Ellipse\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromElement = function(element, options) {\n options || (options = { });\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n\n var ellipse = new fabric.Ellipse(extend(parsedAttributes, options));\n\n ellipse.top -= ellipse.ry;\n ellipse.left -= ellipse.rx;\n return ellipse;\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Ellipse} instance from an object representation\n * @static\n * @memberOf fabric.Ellipse\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as first argument\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Ellipse}\n */\n fabric.Ellipse.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Ellipse', object, callback, forceAsync);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend;\n\n if (fabric.Rect) {\n fabric.warn('fabric.Rect is already defined');\n return;\n }\n\n /**\n * Rectangle class\n * @class fabric.Rect\n * @extends fabric.Object\n * @return {fabric.Rect} thisArg\n * @see {@link fabric.Rect#initialize} for constructor definition\n */\n fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {\n\n /**\n * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'rect',\n\n /**\n * Horizontal border radius\n * @type Number\n * @default\n */\n rx: 0,\n\n /**\n * Vertical border radius\n * @type Number\n * @default\n */\n ry: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @return {Object} thisArg\n */\n initialize: function(options) {\n this.callSuper('initialize', options);\n this._initRxRy();\n },\n\n /**\n * Initializes rx/ry attributes\n * @private\n */\n _initRxRy: function() {\n if (this.rx && !this.ry) {\n this.ry = this.rx;\n }\n else if (this.ry && !this.rx) {\n this.rx = this.ry;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n\n // optimize 1x1 case (used in spray brush)\n if (this.width === 1 && this.height === 1) {\n ctx.fillRect(-0.5, -0.5, 1, 1);\n return;\n }\n\n var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,\n ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,\n w = this.width,\n h = this.height,\n x = noTransform ? this.left : -this.width / 2,\n y = noTransform ? this.top : -this.height / 2,\n isRounded = rx !== 0 || ry !== 0,\n /* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\n k = 1 - 0.5522847498;\n ctx.beginPath();\n\n ctx.moveTo(x + rx, y);\n\n ctx.lineTo(x + w - rx, y);\n isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);\n\n ctx.lineTo(x + w, y + h - ry);\n isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);\n\n ctx.lineTo(x + rx, y + h);\n isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);\n\n ctx.lineTo(x, y + ry);\n isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);\n\n ctx.closePath();\n\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n ctx.closePath();\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;\n if (!(this.group && this.group.type === 'path-group')) {\n x = -this.width / 2;\n y = -this.height / 2;\n }\n markup.push(\n '\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)\n * @static\n * @memberOf fabric.Rect\n * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\n */\n fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));\n\n /**\n * Returns {@link fabric.Rect} instance from an SVG element\n * @static\n * @memberOf fabric.Rect\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Rect} Instance of fabric.Rect\n */\n fabric.Rect.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options = options || { };\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);\n\n parsedAttributes.left = parsedAttributes.left || 0;\n parsedAttributes.top = parsedAttributes.top || 0;\n var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n rect.visible = rect.visible && rect.width > 0 && rect.height > 0;\n return rect;\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns {@link fabric.Rect} instance from an object representation\n * @static\n * @memberOf fabric.Rect\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {Object} instance of fabric.Rect\n */\n fabric.Rect.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Rect', object, callback, forceAsync);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n if (fabric.Polyline) {\n fabric.warn('fabric.Polyline is already defined');\n return;\n }\n\n /**\n * Polyline class\n * @class fabric.Polyline\n * @extends fabric.Object\n * @see {@link fabric.Polyline#initialize} for constructor definition\n */\n fabric.Polyline = fabric.util.createClass(fabric.Object, /** @lends fabric.Polyline.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'polyline',\n\n /**\n * Points array\n * @type Array\n * @default\n */\n points: null,\n\n /**\n * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),\n\n /**\n * Constructor\n * @param {Array} points Array of points (where each point is an object with x and y)\n * @param {Object} [options] Options object\n * @return {fabric.Polyline} thisArg\n * @example\n * var poly = new fabric.Polyline([\n * { x: 10, y: 10 },\n * { x: 50, y: 30 },\n * { x: 40, y: 70 },\n * { x: 60, y: 50 },\n * { x: 100, y: 150 },\n * { x: 40, y: 100 }\n * ], {\n * stroke: 'red',\n * left: 100,\n * top: 100\n * });\n */\n initialize: function(points, options) {\n options = options || {};\n this.points = points || [];\n this.callSuper('initialize', options);\n this._calcDimensions();\n if (!('top' in options)) {\n this.top = this.minY;\n }\n if (!('left' in options)) {\n this.left = this.minX;\n }\n this.pathOffset = {\n x: this.minX + this.width / 2,\n y: this.minY + this.height / 2\n };\n },\n\n /**\n * @private\n */\n _calcDimensions: function() {\n\n var points = this.points,\n minX = min(points, 'x'),\n minY = min(points, 'y'),\n maxX = max(points, 'x'),\n maxY = max(points, 'y');\n\n this.width = (maxX - minX) || 0;\n this.height = (maxY - minY) || 0;\n this.minX = minX || 0;\n this.minY = minY || 0;\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return extend(this.callSuper('toObject', propertiesToInclude), {\n points: this.points.concat()\n });\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var points = [],\n diffX = 0,\n diffY = 0,\n markup = this._createBaseSVGMarkup();\n\n if (!(this.group && this.group.type === 'path-group')) {\n diffX = this.pathOffset.x;\n diffY = this.pathOffset.y;\n }\n\n for (var i = 0, len = this.points.length; i < len; i++) {\n points.push(\n toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',',\n toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' '\n );\n }\n markup.push(\n '<', this.type, ' ', this.getSvgId(),\n 'points=\"', points.join(''),\n '\" style=\"', this.getSvgStyles(),\n '\" transform=\"', this.getSvgTransform(),\n ' ', this.getSvgTransformMatrix(),\n '\"/>\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n commonRender: function(ctx, noTransform) {\n var point, len = this.points.length,\n x = noTransform ? 0 : this.pathOffset.x,\n y = noTransform ? 0 : this.pathOffset.y;\n\n if (!len || isNaN(this.points[len - 1].y)) {\n // do not draw if no points or odd points\n // NaN comes from parseFloat of a empty string in parser\n return false;\n }\n ctx.beginPath();\n ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\n for (var i = 0; i < len; i++) {\n point = this.points[i];\n ctx.lineTo(point.x - x, point.y - y);\n }\n return true;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n if (!this.commonRender(ctx, noTransform)) {\n return;\n }\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var p1, p2;\n\n ctx.beginPath();\n for (var i = 0, len = this.points.length; i < len; i++) {\n p1 = this.points[i];\n p2 = this.points[i + 1] || p1;\n fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);\n }\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.get('points').length;\n }\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement})\n * @static\n * @memberOf fabric.Polyline\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n */\n fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n /**\n * Returns fabric.Polyline instance from an SVG element\n * @static\n * @memberOf fabric.Polyline\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polyline.ATTRIBUTE_NAMES);\n\n return new fabric.Polyline(points, fabric.util.object.extend(parsedAttributes, options));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Polyline instance from an object representation\n * @static\n * @memberOf fabric.Polyline\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Polyline} Instance of fabric.Polyline\n */\n fabric.Polyline.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Polyline', object, callback, forceAsync, 'points');\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend;\n\n if (fabric.Polygon) {\n fabric.warn('fabric.Polygon is already defined');\n return;\n }\n\n /**\n * Polygon class\n * @class fabric.Polygon\n * @extends fabric.Polyline\n * @see {@link fabric.Polygon#initialize} for constructor definition\n */\n fabric.Polygon = fabric.util.createClass(fabric.Polyline, /** @lends fabric.Polygon.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'polygon',\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n if (!this.commonRender(ctx, noTransform)) {\n return;\n }\n ctx.closePath();\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n this.callSuper('_renderDashedStroke', ctx);\n ctx.closePath();\n },\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`)\n * @static\n * @memberOf fabric.Polygon\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement\n */\n fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat();\n\n /**\n * Returns {@link fabric.Polygon} instance from an SVG element\n * @static\n * @memberOf fabric.Polygon\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n options || (options = { });\n\n var points = fabric.parsePointsAttribute(element.getAttribute('points')),\n parsedAttributes = fabric.parseAttributes(element, fabric.Polygon.ATTRIBUTE_NAMES);\n\n return new fabric.Polygon(points, extend(parsedAttributes, options));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Polygon instance from an object representation\n * @static\n * @memberOf fabric.Polygon\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Polygon} Instance of fabric.Polygon\n */\n fabric.Polygon.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Polygon', object, callback, forceAsync, 'points');\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n min = fabric.util.array.min,\n max = fabric.util.array.max,\n extend = fabric.util.object.extend,\n _toString = Object.prototype.toString,\n drawArc = fabric.util.drawArc,\n commandLengths = {\n m: 2,\n l: 2,\n h: 1,\n v: 1,\n c: 6,\n s: 4,\n q: 4,\n t: 2,\n a: 7\n },\n repeatedCommands = {\n m: 'l',\n M: 'L'\n };\n\n if (fabric.Path) {\n fabric.warn('fabric.Path is already defined');\n return;\n }\n\n /**\n * Path class\n * @class fabric.Path\n * @extends fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n * @see {@link fabric.Path#initialize} for constructor definition\n */\n fabric.Path = fabric.util.createClass(fabric.Object, /** @lends fabric.Path.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'path',\n\n /**\n * Array of path points\n * @type Array\n * @default\n */\n path: null,\n\n /**\n * Minimum X from points values, necessary to offset points\n * @type Number\n * @default\n */\n minX: 0,\n\n /**\n * Minimum Y from points values, necessary to offset points\n * @type Number\n * @default\n */\n minY: 0,\n\n cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),\n\n stateProperties: fabric.Object.prototype.stateProperties.concat('path'),\n\n /**\n * Constructor\n * @param {Array|String} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Object} [options] Options object\n * @return {fabric.Path} thisArg\n */\n initialize: function(path, options) {\n options = options || { };\n this.callSuper('initialize', options);\n\n if (!path) {\n path = [];\n }\n\n var fromArray = _toString.call(path) === '[object Array]';\n\n this.path = fromArray\n ? path\n // one of commands (m,M,l,L,q,Q,c,C,etc.) followed by non-command characters (i.e. command values)\n : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);\n\n if (!this.path) {\n return;\n }\n\n if (!fromArray) {\n this.path = this._parsePath();\n }\n\n this._setPositionDimensions(options);\n },\n\n /**\n * @private\n * @param {Object} options Options object\n */\n _setPositionDimensions: function(options) {\n var calcDim = this._parseDimensions();\n\n this.minX = calcDim.left;\n this.minY = calcDim.top;\n this.width = calcDim.width;\n this.height = calcDim.height;\n\n if (typeof options.left === 'undefined') {\n this.left = calcDim.left + (this.originX === 'center'\n ? this.width / 2\n : this.originX === 'right'\n ? this.width\n : 0);\n }\n\n if (typeof options.top === 'undefined') {\n this.top = calcDim.top + (this.originY === 'center'\n ? this.height / 2\n : this.originY === 'bottom'\n ? this.height\n : 0);\n }\n\n this.pathOffset = this.pathOffset || {\n x: this.minX + this.width / 2,\n y: this.minY + this.height / 2\n };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _renderPathCommands: function(ctx) {\n var current, // current instruction\n previous = null,\n subpathStartX = 0,\n subpathStartY = 0,\n x = 0, // current x\n y = 0, // current y\n controlX = 0, // current control point x\n controlY = 0, // current control point y\n tempX,\n tempY,\n l = -this.pathOffset.x,\n t = -this.pathOffset.y;\n\n if (this.group && this.group.type === 'path-group') {\n l = 0;\n t = 0;\n }\n\n ctx.beginPath();\n\n for (var i = 0, len = this.path.length; i < len; ++i) {\n\n current = this.path[i];\n\n switch (current[0]) { // first letter\n\n case 'l': // lineto, relative\n x += current[1];\n y += current[2];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'h': // horizontal lineto, relative\n x += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n ctx.lineTo(x + l, y + t);\n break;\n\n case 'm': // moveTo, relative\n x += current[1];\n y += current[2];\n subpathStartX = x;\n subpathStartY = y;\n ctx.moveTo(x + l, y + t);\n break;\n\n case 'M': // moveTo, absolute\n x = current[1];\n y = current[2];\n subpathStartX = x;\n subpathStartY = y;\n ctx.moveTo(x + l, y + t);\n break;\n\n case 'c': // bezierCurveTo, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n ctx.bezierCurveTo(\n x + current[1] + l, // x1\n y + current[2] + t, // y1\n controlX + l, // x2\n controlY + t, // y2\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'C': // bezierCurveTo, absolute\n x = current[5];\n y = current[6];\n controlX = current[3];\n controlY = current[4];\n ctx.bezierCurveTo(\n current[1] + l,\n current[2] + t,\n controlX + l,\n controlY + t,\n x + l,\n y + t\n );\n break;\n\n case 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n x + current[1] + l,\n y + current[2] + t,\n tempX + l,\n tempY + t\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.bezierCurveTo(\n controlX + l,\n controlY + t,\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n controlX = x + current[1];\n controlY = y + current[2];\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n\n ctx.quadraticCurveTo(\n current[1] + l,\n current[2] + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n ctx.quadraticCurveTo(\n controlX + l,\n controlY + t,\n tempX + l,\n tempY + t\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x + l,\n current[7] + y + t\n ]);\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n drawArc(ctx, x + l, y + t, [\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + l,\n current[7] + t\n ]);\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n ctx.closePath();\n break;\n }\n previous = current;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _render: function(ctx) {\n this._renderPathCommands(ctx);\n this._renderFill(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} string representation of an instance\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var o = extend(this.callSuper('toObject', ['sourcePath', 'pathOffset'].concat(propertiesToInclude)), {\n path: this.path.map(function(item) { return item.slice(); }),\n top: this.top,\n left: this.left,\n });\n return o;\n },\n\n /**\n * Returns dataless object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var o = this.toObject(propertiesToInclude);\n if (this.sourcePath) {\n o.path = this.sourcePath;\n }\n delete o.sourcePath;\n return o;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var chunks = [],\n markup = this._createBaseSVGMarkup(), addTransform = '';\n\n for (var i = 0, len = this.path.length; i < len; i++) {\n chunks.push(this.path[i].join(' '));\n }\n var path = chunks.join(' ');\n if (!(this.group && this.group.type === 'path-group')) {\n addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') ';\n }\n markup.push(\n '\\n'\n );\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns number representation of an instance complexity\n * @return {Number} complexity of this instance\n */\n complexity: function() {\n return this.path.length;\n },\n\n /**\n * @private\n */\n _parsePath: function() {\n var result = [],\n coords = [],\n currentPath,\n parsed,\n re = /([-+]?((\\d+\\.\\d+)|((\\d+)|(\\.\\d+)))(?:e[-+]?\\d+)?)/ig,\n match,\n coordsStr;\n\n for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) {\n currentPath = this.path[i];\n\n coordsStr = currentPath.slice(1).trim();\n coords.length = 0;\n\n while ((match = re.exec(coordsStr))) {\n coords.push(match[0]);\n }\n\n coordsParsed = [currentPath.charAt(0)];\n\n for (var j = 0, jlen = coords.length; j < jlen; j++) {\n parsed = parseFloat(coords[j]);\n if (!isNaN(parsed)) {\n coordsParsed.push(parsed);\n }\n }\n\n var command = coordsParsed[0],\n commandLength = commandLengths[command.toLowerCase()],\n repeatedCommand = repeatedCommands[command] || command;\n\n if (coordsParsed.length - 1 > commandLength) {\n for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {\n result.push([command].concat(coordsParsed.slice(k, k + commandLength)));\n command = repeatedCommand;\n }\n }\n else {\n result.push(coordsParsed);\n }\n }\n\n return result;\n },\n\n /**\n * @private\n */\n _parseDimensions: function() {\n\n var aX = [],\n aY = [],\n current, // current instruction\n previous = null,\n subpathStartX = 0,\n subpathStartY = 0,\n x = 0, // current x\n y = 0, // current y\n controlX = 0, // current control point x\n controlY = 0, // current control point y\n tempX,\n tempY,\n bounds;\n\n for (var i = 0, len = this.path.length; i < len; ++i) {\n\n current = this.path[i];\n\n switch (current[0]) { // first letter\n\n case 'l': // lineto, relative\n x += current[1];\n y += current[2];\n bounds = [];\n break;\n\n case 'L': // lineto, absolute\n x = current[1];\n y = current[2];\n bounds = [];\n break;\n\n case 'h': // horizontal lineto, relative\n x += current[1];\n bounds = [];\n break;\n\n case 'H': // horizontal lineto, absolute\n x = current[1];\n bounds = [];\n break;\n\n case 'v': // vertical lineto, relative\n y += current[1];\n bounds = [];\n break;\n\n case 'V': // verical lineto, absolute\n y = current[1];\n bounds = [];\n break;\n\n case 'm': // moveTo, relative\n x += current[1];\n y += current[2];\n subpathStartX = x;\n subpathStartY = y;\n bounds = [];\n break;\n\n case 'M': // moveTo, absolute\n x = current[1];\n y = current[2];\n subpathStartX = x;\n subpathStartY = y;\n bounds = [];\n break;\n\n case 'c': // bezierCurveTo, relative\n tempX = x + current[5];\n tempY = y + current[6];\n controlX = x + current[3];\n controlY = y + current[4];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n x + current[1], // x1\n y + current[2], // y1\n controlX, // x2\n controlY, // y2\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'C': // bezierCurveTo, absolute\n controlX = current[3];\n controlY = current[4];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n current[1],\n current[2],\n controlX,\n controlY,\n current[5],\n current[6]\n );\n x = current[5];\n y = current[6];\n break;\n\n case 's': // shorthand cubic bezierCurveTo, relative\n\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n\n if (previous[0].match(/[CcSs]/) === null) {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n x + current[1],\n y + current[2],\n tempX,\n tempY\n );\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = x + current[1];\n controlY = y + current[2];\n x = tempX;\n y = tempY;\n break;\n\n case 'S': // shorthand cubic bezierCurveTo, absolute\n tempX = current[3];\n tempY = current[4];\n if (previous[0].match(/[CcSs]/) === null) {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n current[1],\n current[2],\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n // set control point to 2nd one of this command\n // \"... the first control point is assumed to be\n // the reflection of the second control point on\n // the previous command relative to the current point.\"\n controlX = current[1];\n controlY = current[2];\n break;\n\n case 'q': // quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[3];\n tempY = y + current[4];\n controlX = x + current[1];\n controlY = y + current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n controlX = current[1];\n controlY = current[2];\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n current[3],\n current[4]\n );\n x = current[3];\n y = current[4];\n break;\n\n case 't': // shorthand quadraticCurveTo, relative\n // transform to absolute x,y\n tempX = x + current[1];\n tempY = y + current[2];\n if (previous[0].match(/[QqTt]/) === null) {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n\n break;\n\n case 'T':\n tempX = current[1];\n tempY = current[2];\n\n if (previous[0].match(/[QqTt]/) === null) {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n else {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n }\n bounds = fabric.util.getBoundsOfCurve(x, y,\n controlX,\n controlY,\n controlX,\n controlY,\n tempX,\n tempY\n );\n x = tempX;\n y = tempY;\n break;\n\n case 'a':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6] + x,\n current[7] + y\n );\n x += current[6];\n y += current[7];\n break;\n\n case 'A':\n // TODO: optimize this\n bounds = fabric.util.getBoundsOfArc(x, y,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6],\n current[7]\n );\n x = current[6];\n y = current[7];\n break;\n\n case 'z':\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n break;\n }\n previous = current;\n bounds.forEach(function (point) {\n aX.push(point.x);\n aY.push(point.y);\n });\n aX.push(x);\n aY.push(y);\n }\n\n var minX = min(aX) || 0,\n minY = min(aY) || 0,\n maxX = max(aX) || 0,\n maxY = max(aY) || 0,\n deltaX = maxX - minX,\n deltaY = maxY - minY,\n\n o = {\n left: minX,\n top: minY,\n width: deltaX,\n height: deltaY\n };\n\n return o;\n }\n });\n\n /**\n * Creates an instance of fabric.Path from an object\n * @static\n * @memberOf fabric.Path\n * @param {Object} object\n * @param {Function} [callback] Callback to invoke when an fabric.Path instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n */\n fabric.Path.fromObject = function(object, callback, forceAsync) {\n // remove this pattern rom 2.0, accept just object.\n var path;\n if (typeof object.path === 'string') {\n fabric.loadSVGFromURL(object.path, function (elements) {\n var pathUrl = object.path;\n path = elements[0];\n delete object.path;\n\n path.setOptions(object);\n path.setSourcePath(pathUrl);\n\n callback && callback(path);\n });\n }\n else {\n return fabric.Object._fromObject('Path', object, callback, forceAsync, 'path');\n }\n };\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by `fabric.Path.fromElement`)\n * @static\n * @memberOf fabric.Path\n * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n */\n fabric.Path.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(['d']);\n\n /**\n * Creates an instance of fabric.Path from an SVG element\n * @static\n * @memberOf fabric.Path\n * @param {SVGElement} element to parse\n * @param {Function} callback Callback to invoke when an fabric.Path instance is created\n * @param {Object} [options] Options object\n */\n fabric.Path.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES);\n callback && callback(new fabric.Path(parsedAttributes.d, extend(parsedAttributes, options)));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Path\n * @type Boolean\n * @default\n */\n fabric.Path.async = true;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend;\n\n if (fabric.PathGroup) {\n fabric.warn('fabric.PathGroup is already defined');\n return;\n }\n\n /**\n * Path group class\n * @class fabric.PathGroup\n * @extends fabric.Path\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#path_and_pathgroup}\n * @see {@link fabric.PathGroup#initialize} for constructor definition\n */\n fabric.PathGroup = fabric.util.createClass(fabric.Object, /** @lends fabric.PathGroup.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'path-group',\n\n /**\n * Fill value\n * @type String\n * @default\n */\n fill: '',\n\n /**\n * Pathgroups are container, do not render anything on theyr own, ence no cache properties\n * @type Boolean\n * @default\n */\n cacheProperties: [],\n\n /**\n * Constructor\n * @param {Array} paths\n * @param {Object} [options] Options object\n * @return {fabric.PathGroup} thisArg\n */\n initialize: function(paths, options) {\n\n options = options || { };\n this.paths = paths || [];\n\n for (var i = this.paths.length; i--;) {\n this.paths[i].group = this;\n }\n\n if (options.toBeParsed) {\n this.parseDimensionsFromPaths(options);\n delete options.toBeParsed;\n }\n this.setOptions(options);\n this.setCoords();\n },\n\n /**\n * Calculate width and height based on paths contained\n */\n parseDimensionsFromPaths: function(options) {\n var points, p, xC = [], yC = [], path, height, width,\n m;\n for (var j = this.paths.length; j--;) {\n path = this.paths[j];\n height = path.height + path.strokeWidth;\n width = path.width + path.strokeWidth;\n points = [\n { x: path.left, y: path.top },\n { x: path.left + width, y: path.top },\n { x: path.left, y: path.top + height },\n { x: path.left + width, y: path.top + height }\n ];\n m = this.paths[j].transformMatrix;\n for (var i = 0; i < points.length; i++) {\n p = points[i];\n if (m) {\n p = fabric.util.transformPoint(p, m, false);\n }\n xC.push(p.x);\n yC.push(p.y);\n }\n }\n options.width = Math.max.apply(null, xC);\n options.height = Math.max.apply(null, yC);\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx) {\n ctx.save();\n ctx.translate(-this.width / 2, -this.height / 2);\n for (var i = 0, l = this.paths.length; i < l; ++i) {\n this.paths[i].render(ctx, true);\n }\n ctx.restore();\n },\n\n /**\n * Decide if the object should cache or not.\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * @return {Boolean}\n */\n shouldCache: function() {\n var parentCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\n this.caching = parentCache;\n if (parentCache) {\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[i].willDrawShadow()) {\n this.caching = false;\n return false;\n }\n }\n }\n return parentCache;\n },\n\n /**\n * Check if this object or a child object will cast a shadow\n * @return {Boolean}\n */\n willDrawShadow: function() {\n if (this.shadow) {\n return true;\n }\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[i].willDrawShadow()) {\n return true;\n }\n }\n return false;\n },\n\n /**\n * Check if this group or its parent group are caching, recursively up\n * @return {Boolean}\n */\n isCaching: function() {\n return this.caching || this.group && this.group.isCaching();\n },\n\n /**\n * Check if cache is dirty\n */\n isCacheDirty: function() {\n if (this.callSuper('isCacheDirty')) {\n return true;\n }\n if (!this.statefullCache) {\n return false;\n }\n for (var i = 0, len = this.paths.length; i < len; i++) {\n if (this.paths[i].isCacheDirty(true)) {\n if (this._cacheCanvas) {\n var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;\n this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\n }\n return true;\n }\n }\n return false;\n },\n\n /**\n * Sets certain property to a certain value\n * @param {String} prop\n * @param {*} value\n * @return {fabric.PathGroup} thisArg\n */\n _set: function(prop, value) {\n\n if (prop === 'fill' && value && this.isSameColor()) {\n var i = this.paths.length;\n while (i--) {\n this.paths[i]._set(prop, value);\n }\n }\n\n return this.callSuper('_set', prop, value);\n },\n\n /**\n * Returns object representation of this path group\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var pathsToObject = this.paths.map(function(path) {\n var originalDefaults = path.includeDefaultValues;\n path.includeDefaultValues = path.group.includeDefaultValues;\n var obj = path.toObject(propertiesToInclude);\n path.includeDefaultValues = originalDefaults;\n return obj;\n });\n var o = extend(this.callSuper('toObject', ['sourcePath'].concat(propertiesToInclude)), {\n paths: pathsToObject\n });\n return o;\n },\n\n /**\n * Returns dataless object representation of this path group\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} dataless object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var o = this.toObject(propertiesToInclude);\n if (this.sourcePath) {\n o.paths = this.sourcePath;\n }\n return o;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var objects = this.getObjects(),\n p = this.getPointByOrigin('left', 'top'),\n translatePart = 'translate(' + p.x + ' ' + p.y + ')',\n markup = this._createBaseSVGMarkup();\n markup.push(\n '\\n'\n );\n\n for (var i = 0, len = objects.length; i < len; i++) {\n markup.push('\\t', objects[i].toSVG(reviver));\n }\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns a string representation of this path group\n * @return {String} string representation of an object\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Returns true if all paths in this group are of same color\n * @return {Boolean} true if all paths are of the same color (`fill`)\n */\n isSameColor: function() {\n var firstPathFill = this.getObjects()[0].get('fill') || '';\n if (typeof firstPathFill !== 'string') {\n return false;\n }\n firstPathFill = firstPathFill.toLowerCase();\n return this.getObjects().every(function(path) {\n var pathFill = path.get('fill') || '';\n return typeof pathFill === 'string' && (pathFill).toLowerCase() === firstPathFill;\n });\n },\n\n /**\n * Returns number representation of object's complexity\n * @return {Number} complexity\n */\n complexity: function() {\n return this.paths.reduce(function(total, path) {\n return total + ((path && path.complexity) ? path.complexity() : 0);\n }, 0);\n },\n\n /**\n * Returns all paths in this path group\n * @return {Array} array of path objects included in this path group\n */\n getObjects: function() {\n return this.paths;\n }\n });\n\n /**\n * Creates fabric.PathGroup instance from an object representation\n * @static\n * @memberOf fabric.PathGroup\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.PathGroup instance is created\n */\n fabric.PathGroup.fromObject = function(object, callback) {\n var originalPaths = object.paths;\n delete object.paths;\n if (typeof originalPaths === 'string') {\n fabric.loadSVGFromURL(originalPaths, function (elements) {\n var pathUrl = originalPaths;\n var pathGroup = fabric.util.groupSVGElements(elements, object, pathUrl);\n object.paths = originalPaths;\n callback(pathGroup);\n });\n }\n else {\n fabric.util.enlivenObjects(originalPaths, function(enlivenedObjects) {\n var pathGroup = new fabric.PathGroup(enlivenedObjects, object);\n object.paths = originalPaths;\n callback(pathGroup);\n });\n }\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.PathGroup\n * @type Boolean\n * @default\n */\n fabric.PathGroup.async = true;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n min = fabric.util.array.min,\n max = fabric.util.array.max;\n\n if (fabric.Group) {\n return;\n }\n\n // lock-related properties, for use in fabric.Group#get\n // to enable locking behavior on group\n // when one of its objects has lock-related properties set\n var _lockProperties = {\n lockMovementX: true,\n lockMovementY: true,\n lockRotation: true,\n lockScalingX: true,\n lockScalingY: true,\n lockUniScaling: true\n };\n\n /**\n * Group class\n * @class fabric.Group\n * @extends fabric.Object\n * @mixes fabric.Collection\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}\n * @see {@link fabric.Group#initialize} for constructor definition\n */\n fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, /** @lends fabric.Group.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'group',\n\n /**\n * Width of stroke\n * @type Number\n * @default\n */\n strokeWidth: 0,\n\n /**\n * Indicates if click events should also check for subtargets\n * @type Boolean\n * @default\n */\n subTargetCheck: false,\n\n /**\n * Groups are container, do not render anything on theyr own, ence no cache properties\n * @type Boolean\n * @default\n */\n cacheProperties: [],\n\n /**\n * Constructor\n * @param {Object} objects Group objects\n * @param {Object} [options] Options object\n * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.\n * @return {Object} thisArg\n */\n initialize: function(objects, options, isAlreadyGrouped) {\n options = options || { };\n\n this._objects = [];\n // if objects enclosed in a group have been grouped already,\n // we cannot change properties of objects.\n // Thus we need to set options to group without objects,\n // because delegatedProperties propagate to objects.\n isAlreadyGrouped && this.callSuper('initialize', options);\n\n this._objects = objects || [];\n for (var i = this._objects.length; i--; ) {\n this._objects[i].group = this;\n }\n\n if (options.originX) {\n this.originX = options.originX;\n }\n if (options.originY) {\n this.originY = options.originY;\n }\n\n if (isAlreadyGrouped) {\n // do not change coordinate of objects enclosed in a group,\n // because objects coordinate system have been group coodinate system already.\n this._updateObjectsCoords(true);\n this._updateObjectsACoords();\n }\n else {\n this._calcBounds();\n this._updateObjectsCoords();\n this.callSuper('initialize', options);\n }\n\n this.setCoords();\n this.saveCoords();\n },\n\n _updateObjectsACoords: function() {\n var ignoreZoom = true, skipAbsolute = true;\n for (var i = this._objects.length; i--; ){\n this._objects[i].setCoords(ignoreZoom, skipAbsolute);\n }\n },\n\n /**\n * @private\n * @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change\n */\n _updateObjectsCoords: function(skipCoordsChange) {\n var center = this.getCenterPoint();\n for (var i = this._objects.length; i--; ){\n this._updateObjectCoords(this._objects[i], center, skipCoordsChange);\n }\n },\n\n /**\n * @private\n * @param {Object} object\n * @param {fabric.Point} center, current center of group.\n * @param {Boolean} [skipCoordsChange] if true, coordinates of object dose not change\n */\n _updateObjectCoords: function(object, center, skipCoordsChange) {\n // do not display corners of objects enclosed in a group\n object.__origHasControls = object.hasControls;\n object.hasControls = false;\n\n if (skipCoordsChange) {\n return;\n }\n\n var objectLeft = object.getLeft(),\n objectTop = object.getTop(),\n ignoreZoom = true, skipAbsolute = true;\n\n object.set({\n left: objectLeft - center.x,\n top: objectTop - center.y\n });\n object.setCoords(ignoreZoom, skipAbsolute);\n },\n\n /**\n * Returns string represenation of a group\n * @return {String}\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Adds an object to a group; Then recalculates group's dimension, position.\n * @param {Object} object\n * @return {fabric.Group} thisArg\n * @chainable\n */\n addWithUpdate: function(object) {\n this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n if (object) {\n this._objects.push(object);\n object.group = this;\n object._set('canvas', this.canvas);\n }\n // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, this);\n this._calcBounds();\n this._updateObjectsCoords();\n this.setCoords();\n this.dirty = true;\n return this;\n },\n\n /**\n * @private\n */\n _setObjectActive: function(object) {\n object.set('active', true);\n object.group = this;\n },\n\n /**\n * Removes an object from a group; Then recalculates group's dimension, position.\n * @param {Object} object\n * @return {fabric.Group} thisArg\n * @chainable\n */\n removeWithUpdate: function(object) {\n this._restoreObjectsState();\n fabric.util.resetObjectTransform(this);\n // since _restoreObjectsState set objects inactive\n this.forEachObject(this._setObjectActive, this);\n\n this.remove(object);\n this._calcBounds();\n this._updateObjectsCoords();\n this.setCoords();\n this.dirty = true;\n return this;\n },\n\n /**\n * @private\n */\n _onObjectAdded: function(object) {\n this.dirty = true;\n object.group = this;\n object._set('canvas', this.canvas);\n },\n\n /**\n * @private\n */\n _onObjectRemoved: function(object) {\n this.dirty = true;\n delete object.group;\n object.set('active', false);\n },\n\n /**\n * Properties that are delegated to group objects when reading/writing\n * @param {Object} delegatedProperties\n */\n delegatedProperties: {\n fill: true,\n stroke: true,\n strokeWidth: true,\n fontFamily: true,\n fontWeight: true,\n fontSize: true,\n fontStyle: true,\n lineHeight: true,\n textDecoration: true,\n textAlign: true,\n backgroundColor: true\n },\n\n /**\n * @private\n */\n _set: function(key, value) {\n var i = this._objects.length;\n\n if (this.delegatedProperties[key] || key === 'canvas') {\n while (i--) {\n this._objects[i].set(key, value);\n }\n }\n else {\n while (i--) {\n this._objects[i].setOnGroup(key, value);\n }\n }\n\n this.callSuper('_set', key, value);\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var objsToObject = this.getObjects().map(function(obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = obj.group.includeDefaultValues;\n var _obj = obj.toObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n return extend(this.callSuper('toObject', propertiesToInclude), {\n objects: objsToObject\n });\n },\n\n /**\n * Returns object representation of an instance, in dataless mode.\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject: function(propertiesToInclude) {\n var objsToObject = this.getObjects().map(function(obj) {\n var originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = obj.group.includeDefaultValues;\n var _obj = obj.toDatalessObject(propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n return _obj;\n });\n return extend(this.callSuper('toDatalessObject', propertiesToInclude), {\n objects: objsToObject\n });\n },\n\n /**\n * Renders instance on a given context\n * @param {CanvasRenderingContext2D} ctx context to render instance on\n */\n render: function(ctx) {\n this._transformDone = true;\n this.callSuper('render', ctx);\n this._transformDone = false;\n },\n\n /**\n * Decide if the object should cache or not.\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step. None of the fabric classes requires it.\n * Generally you do not cache objects in groups because the group outside is cached.\n * @return {Boolean}\n */\n shouldCache: function() {\n var parentCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isCaching());\n this.caching = parentCache;\n if (parentCache) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].willDrawShadow()) {\n this.caching = false;\n return false;\n }\n }\n }\n return parentCache;\n },\n\n /**\n * Check if this object or a child object will cast a shadow\n * @return {Boolean}\n */\n willDrawShadow: function() {\n if (this.callSuper('willDrawShadow')) {\n return true;\n }\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].willDrawShadow()) {\n return true;\n }\n }\n return false;\n },\n\n /**\n * Check if this group or its parent group are caching, recursively up\n * @return {Boolean}\n */\n isCaching: function() {\n return this.caching || this.group && this.group.isCaching();\n },\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n drawObject: function(ctx) {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._renderObject(this._objects[i], ctx);\n }\n },\n\n /**\n * Check if cache is dirty\n */\n isCacheDirty: function() {\n if (this.callSuper('isCacheDirty')) {\n return true;\n }\n if (!this.statefullCache) {\n return false;\n }\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i].isCacheDirty(true)) {\n if (this._cacheCanvas) {\n // if this group has not a cache canvas there is nothing to clean\n var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;\n this._cacheContext.clearRect(-x / 2, -y / 2, x, y);\n }\n return true;\n }\n }\n return false;\n },\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} [noTransform] When true, context is not transformed\n */\n _renderControls: function(ctx, noTransform) {\n ctx.save();\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n this.callSuper('_renderControls', ctx, noTransform);\n for (var i = 0, len = this._objects.length; i < len; i++) {\n this._objects[i]._renderControls(ctx);\n }\n ctx.restore();\n },\n\n /**\n * @private\n */\n _renderObject: function(object, ctx) {\n // do not render if object is not visible\n if (!object.visible) {\n return;\n }\n\n var originalHasRotatingPoint = object.hasRotatingPoint;\n object.hasRotatingPoint = false;\n object.render(ctx);\n object.hasRotatingPoint = originalHasRotatingPoint;\n },\n\n /**\n * Retores original state of each of group objects (original state is that which was before group was created).\n * @private\n * @return {fabric.Group} thisArg\n * @chainable\n */\n _restoreObjectsState: function() {\n this._objects.forEach(this._restoreObjectState, this);\n return this;\n },\n\n /**\n * Realises the transform from this group onto the supplied object\n * i.e. it tells you what would happen if the supplied object was in\n * the group, and then the group was destroyed. It mutates the supplied\n * object.\n * @param {fabric.Object} object\n * @return {fabric.Object} transformedObject\n */\n realizeTransform: function(object) {\n var matrix = object.calcTransformMatrix(),\n options = fabric.util.qrDecompose(matrix),\n center = new fabric.Point(options.translateX, options.translateY);\n object.flipX = false;\n object.flipY = false;\n object.set('scaleX', options.scaleX);\n object.set('scaleY', options.scaleY);\n object.skewX = options.skewX;\n object.skewY = options.skewY;\n object.angle = options.angle;\n object.setPositionByOrigin(center, 'center', 'center');\n return object;\n },\n\n /**\n * Restores original state of a specified object in group\n * @private\n * @param {fabric.Object} object\n * @return {fabric.Group} thisArg\n */\n _restoreObjectState: function(object) {\n this.realizeTransform(object);\n object.setCoords();\n object.hasControls = object.__origHasControls;\n delete object.__origHasControls;\n object.set('active', false);\n delete object.group;\n\n return this;\n },\n\n /**\n * Destroys a group (restoring state of its objects)\n * @return {fabric.Group} thisArg\n * @chainable\n */\n destroy: function() {\n // when group is destroyed objects needs to get a repaint to be eventually\n // displayed on canvas.\n this._objects.forEach(function(object) {\n object.set('dirty', true);\n });\n return this._restoreObjectsState();\n },\n\n /**\n * Saves coordinates of this instance (to be used together with `hasMoved`)\n * @saveCoords\n * @return {fabric.Group} thisArg\n * @chainable\n */\n saveCoords: function() {\n this._originalLeft = this.get('left');\n this._originalTop = this.get('top');\n return this;\n },\n\n /**\n * Checks whether this group was moved (since `saveCoords` was called last)\n * @return {Boolean} true if an object was moved (since fabric.Group#saveCoords was called)\n */\n hasMoved: function() {\n return this._originalLeft !== this.get('left') ||\n this._originalTop !== this.get('top');\n },\n\n /**\n * Sets coordinates of all objects inside group\n * @return {fabric.Group} thisArg\n * @chainable\n */\n setObjectsCoords: function() {\n var ignoreZoom = true, skipAbsolute = true;\n this.forEachObject(function(object) {\n object.setCoords(ignoreZoom, skipAbsolute);\n });\n return this;\n },\n\n /**\n * @private\n */\n _calcBounds: function(onlyWidthHeight) {\n var aX = [],\n aY = [],\n o, prop,\n props = ['tr', 'br', 'bl', 'tl'],\n i = 0, iLen = this._objects.length,\n j, jLen = props.length,\n ignoreZoom = true;\n\n for ( ; i < iLen; ++i) {\n o = this._objects[i];\n o.setCoords(ignoreZoom);\n for (j = 0; j < jLen; j++) {\n prop = props[j];\n aX.push(o.oCoords[prop].x);\n aY.push(o.oCoords[prop].y);\n }\n }\n\n this.set(this._getBounds(aX, aY, onlyWidthHeight));\n },\n\n /**\n * @private\n */\n _getBounds: function(aX, aY, onlyWidthHeight) {\n var minXY = new fabric.Point(min(aX), min(aY)),\n maxXY = new fabric.Point(max(aX), max(aY)),\n obj = {\n width: (maxXY.x - minXY.x) || 0,\n height: (maxXY.y - minXY.y) || 0\n };\n\n if (!onlyWidthHeight) {\n obj.left = minXY.x || 0;\n obj.top = minXY.y || 0;\n if (this.originX === 'center') {\n obj.left += obj.width / 2;\n }\n if (this.originX === 'right') {\n obj.left += obj.width;\n }\n if (this.originY === 'center') {\n obj.top += obj.height / 2;\n }\n if (this.originY === 'bottom') {\n obj.top += obj.height;\n }\n }\n return obj;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup();\n markup.push(\n '\\n'\n );\n\n for (var i = 0, len = this._objects.length; i < len; i++) {\n markup.push('\\t', this._objects[i].toSVG(reviver));\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns requested property\n * @param {String} prop Property to get\n * @return {*}\n */\n get: function(prop) {\n if (prop in _lockProperties) {\n if (this[prop]) {\n return this[prop];\n }\n else {\n for (var i = 0, len = this._objects.length; i < len; i++) {\n if (this._objects[i][prop]) {\n return true;\n }\n }\n return false;\n }\n }\n else {\n if (prop in this.delegatedProperties) {\n return this._objects[0] && this._objects[0].get(prop);\n }\n return this[prop];\n }\n }\n });\n\n /**\n * Returns {@link fabric.Group} instance from an object representation\n * @static\n * @memberOf fabric.Group\n * @param {Object} object Object to create a group from\n * @param {Function} [callback] Callback to invoke when an group instance is created\n */\n fabric.Group.fromObject = function(object, callback) {\n fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {\n var options = fabric.util.object.clone(object, true);\n delete options.objects;\n callback && callback(new fabric.Group(enlivenedObjects, options, true));\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @memberOf fabric.Group\n * @type Boolean\n * @default\n */\n fabric.Group.async = true;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var extend = fabric.util.object.extend;\n\n if (!global.fabric) {\n global.fabric = { };\n }\n\n if (global.fabric.Image) {\n fabric.warn('fabric.Image is already defined.');\n return;\n }\n\n /**\n * Image class\n * @class fabric.Image\n * @extends fabric.Object\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\n * @see {@link fabric.Image#initialize} for constructor definition\n */\n fabric.Image = fabric.util.createClass(fabric.Object, /** @lends fabric.Image.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'image',\n\n /**\n * crossOrigin value (one of \"\", \"anonymous\", \"use-credentials\")\n * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes\n * @type String\n * @default\n */\n crossOrigin: '',\n\n /**\n * AlignX value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element width differs from image width.\n * @type String\n * @default\n */\n alignX: 'none',\n\n /**\n * AlignY value, part of preserveAspectRatio (one of \"none\", \"mid\", \"min\", \"max\")\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * This parameter defines how the picture is aligned to its viewport when image element height differs from image height.\n * @type String\n * @default\n */\n alignY: 'none',\n\n /**\n * meetOrSlice value, part of preserveAspectRatio (one of \"meet\", \"slice\").\n * if meet the image is always fully visibile, if slice the viewport is always filled with image.\n * @see http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n * @type String\n * @default\n */\n meetOrSlice: 'meet',\n\n /**\n * Width of a stroke.\n * For image quality a stroke multiple of 2 gives better results.\n * @type Number\n * @default\n */\n strokeWidth: 0,\n\n /**\n * private\n * contains last value of scaleX to detect\n * if the Image got resized after the last Render\n * @type Number\n */\n _lastScaleX: 1,\n\n /**\n * private\n * contains last value of scaleY to detect\n * if the Image got resized after the last Render\n * @type Number\n */\n _lastScaleY: 1,\n\n /**\n * minimum scale factor under which any resizeFilter is triggered to resize the image\n * 0 will disable the automatic resize. 1 will trigger automatically always.\n * number bigger than 1 can be used in case we want to scale with some filter above\n * the natural image dimensions\n * @type Number\n */\n minimumScaleTrigger: 0.5,\n\n /**\n * List of properties to consider when checking if\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat(\n 'alignX',\n 'alignY',\n 'meetOrSlice'),\n\n /**\n * When `true`, object is cached on an additional canvas.\n * default to false for images\n * since 1.7.0\n * @type Boolean\n * @default\n */\n objectCaching: false,\n\n /**\n * Constructor\n * @param {HTMLImageElement | String} element Image element\n * @param {Object} [options] Options object\n * @param {function} [callback] callback function to call after eventual filters applied.\n * @return {fabric.Image} thisArg\n */\n initialize: function(element, options, callback) {\n options || (options = { });\n this.filters = [];\n this.resizeFilters = [];\n this.callSuper('initialize', options);\n this._initElement(element, options, callback);\n },\n\n /**\n * Returns image element which this instance if based on\n * @return {HTMLImageElement} Image element\n */\n getElement: function() {\n return this._element;\n },\n\n /**\n * Sets image element for this instance to a specified one.\n * If filters defined they are applied to new image.\n * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\n * @param {HTMLImageElement} element\n * @param {Function} [callback] Callback is invoked when all filters have been applied and new image is generated\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setElement: function(element, callback, options) {\n\n var _callback, _this;\n\n this._element = element;\n this._originalElement = element;\n this._initConfig(options);\n\n if (this.resizeFilters.length === 0) {\n _callback = callback;\n }\n else {\n _this = this;\n _callback = function() {\n _this.applyFilters(callback, _this.resizeFilters, _this._filteredEl || _this._originalElement, true);\n };\n }\n\n if (this.filters.length !== 0) {\n this.applyFilters(_callback);\n }\n else if (_callback) {\n _callback(this);\n }\n\n return this;\n },\n\n /**\n * Sets crossOrigin value (on an instance and corresponding image element)\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setCrossOrigin: function(value) {\n this.crossOrigin = value;\n this._element.crossOrigin = value;\n\n return this;\n },\n\n /**\n * Returns original size of an image\n * @return {Object} Object with \"width\" and \"height\" properties\n */\n getOriginalSize: function() {\n var element = this.getElement();\n return {\n width: element.width,\n height: element.height\n };\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _stroke: function(ctx) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n var w = this.width / 2, h = this.height / 2;\n ctx.beginPath();\n ctx.moveTo(-w, -h);\n ctx.lineTo(w, -h);\n ctx.lineTo(w, h);\n ctx.lineTo(-w, h);\n ctx.lineTo(-w, -h);\n ctx.closePath();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderDashedStroke: function(ctx) {\n var x = -this.width / 2,\n y = -this.height / 2,\n w = this.width,\n h = this.height;\n\n ctx.save();\n this._setStrokeStyles(ctx);\n\n ctx.beginPath();\n fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);\n fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);\n ctx.closePath();\n ctx.restore();\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var filters = [], resizeFilters = [],\n scaleX = 1, scaleY = 1;\n\n this.filters.forEach(function(filterObj) {\n if (filterObj) {\n if (filterObj.type === 'Resize') {\n scaleX *= filterObj.scaleX;\n scaleY *= filterObj.scaleY;\n }\n filters.push(filterObj.toObject());\n }\n });\n\n this.resizeFilters.forEach(function(filterObj) {\n filterObj && resizeFilters.push(filterObj.toObject());\n });\n var object = extend(\n this.callSuper(\n 'toObject',\n ['crossOrigin', 'alignX', 'alignY', 'meetOrSlice'].concat(propertiesToInclude)\n ), {\n src: this.getSrc(),\n filters: filters,\n resizeFilters: resizeFilters,\n });\n\n object.width /= scaleX;\n object.height /= scaleY;\n\n return object;\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2,\n preserveAspectRatio = 'none', filtered = true;\n if (this.group && this.group.type === 'path-group') {\n x = this.left;\n y = this.top;\n }\n if (this.alignX !== 'none' && this.alignY !== 'none') {\n preserveAspectRatio = 'x' + this.alignX + 'Y' + this.alignY + ' ' + this.meetOrSlice;\n }\n markup.push(\n '\\n',\n ' element with actual transformation, then offsetting object to the top/left\n // so that object's center aligns with container's left/top\n '\" width=\"', this.width,\n '\" height=\"', this.height,\n '\" preserveAspectRatio=\"', preserveAspectRatio, '\"',\n '>\\n'\n );\n\n if (this.stroke || this.strokeDashArray) {\n var origFill = this.fill;\n this.fill = null;\n markup.push(\n '\\n'\n );\n this.fill = origFill;\n }\n\n markup.push('\\n');\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n /* _TO_SVG_END_ */\n\n /**\n * Returns source of an image\n * @param {Boolean} filtered indicates if the src is needed for svg\n * @return {String} Source of an image\n */\n getSrc: function(filtered) {\n var element = filtered ? this._element : this._originalElement;\n if (element) {\n return fabric.isLikelyNode ? element._src : element.src;\n }\n else {\n return this.src || '';\n }\n },\n\n /**\n * Sets source of an image\n * @param {String} src Source string (URL)\n * @param {Function} [callback] Callback is invoked when image has been loaded (and all filters have been applied)\n * @param {Object} [options] Options object\n * @return {fabric.Image} thisArg\n * @chainable\n */\n setSrc: function(src, callback, options) {\n fabric.util.loadImage(src, function(img) {\n return this.setElement(img, callback, options);\n }, this, options && options.crossOrigin);\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of an instance\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Applies filters assigned to this image (from \"filters\" array)\n * @method applyFilters\n * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated\n * @param {Array} filters to be applied\n * @param {fabric.Image} imgElement image to filter ( default to this._element )\n * @param {Boolean} forResizing\n * @return {CanvasElement} canvasEl to be drawn immediately\n * @chainable\n */\n applyFilters: function(callback, filters, imgElement, forResizing) {\n\n filters = filters || this.filters;\n imgElement = imgElement || this._originalElement;\n\n if (!imgElement) {\n return;\n }\n\n var replacement = fabric.util.createImage(),\n retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : fabric.devicePixelRatio,\n minimumScale = this.minimumScaleTrigger / retinaScaling,\n _this = this, scaleX, scaleY;\n\n if (filters.length === 0) {\n this._element = imgElement;\n callback && callback(this);\n return imgElement;\n }\n\n var canvasEl = fabric.util.createCanvasElement();\n canvasEl.width = imgElement.width;\n canvasEl.height = imgElement.height;\n canvasEl.getContext('2d').drawImage(imgElement, 0, 0, imgElement.width, imgElement.height);\n\n filters.forEach(function(filter) {\n if (!filter) {\n return;\n }\n if (forResizing) {\n scaleX = _this.scaleX < minimumScale ? _this.scaleX : 1;\n scaleY = _this.scaleY < minimumScale ? _this.scaleY : 1;\n if (scaleX * retinaScaling < 1) {\n scaleX *= retinaScaling;\n }\n if (scaleY * retinaScaling < 1) {\n scaleY *= retinaScaling;\n }\n }\n else {\n scaleX = filter.scaleX;\n scaleY = filter.scaleY;\n }\n filter.applyTo(canvasEl, scaleX, scaleY);\n if (!forResizing && filter.type === 'Resize') {\n _this.width *= filter.scaleX;\n _this.height *= filter.scaleY;\n }\n });\n\n /** @ignore */\n replacement.width = canvasEl.width;\n replacement.height = canvasEl.height;\n if (fabric.isLikelyNode) {\n replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);\n // onload doesn't fire in some node versions, so we invoke callback manually\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback(_this);\n }\n else {\n replacement.onload = function() {\n _this._element = replacement;\n !forResizing && (_this._filteredEl = replacement);\n callback && callback(_this);\n replacement.onload = canvasEl = null;\n };\n replacement.src = canvasEl.toDataURL('image/png');\n }\n return canvasEl;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n _render: function(ctx, noTransform) {\n var x, y, imageMargins = this._findMargins(), elementToDraw;\n\n x = (noTransform ? this.left : -this.width / 2);\n y = (noTransform ? this.top : -this.height / 2);\n\n if (this.meetOrSlice === 'slice') {\n ctx.beginPath();\n ctx.rect(x, y, this.width, this.height);\n ctx.clip();\n }\n\n if (this.isMoving === false && this.resizeFilters.length && this._needsResize()) {\n this._lastScaleX = this.scaleX;\n this._lastScaleY = this.scaleY;\n elementToDraw = this.applyFilters(null, this.resizeFilters, this._filteredEl || this._originalElement, true);\n }\n else {\n elementToDraw = this._element;\n }\n elementToDraw && ctx.drawImage(elementToDraw,\n x + imageMargins.marginX,\n y + imageMargins.marginY,\n imageMargins.width,\n imageMargins.height\n );\n\n this._stroke(ctx);\n this._renderStroke(ctx);\n },\n\n /**\n * @private, needed to check if image needs resize\n */\n _needsResize: function() {\n return (this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY);\n },\n\n /**\n * @private\n */\n _findMargins: function() {\n var width = this.width, height = this.height, scales,\n scale, marginX = 0, marginY = 0;\n\n if (this.alignX !== 'none' || this.alignY !== 'none') {\n scales = [this.width / this._element.width, this.height / this._element.height];\n scale = this.meetOrSlice === 'meet'\n ? Math.min.apply(null, scales) : Math.max.apply(null, scales);\n width = this._element.width * scale;\n height = this._element.height * scale;\n if (this.alignX === 'Mid') {\n marginX = (this.width - width) / 2;\n }\n if (this.alignX === 'Max') {\n marginX = this.width - width;\n }\n if (this.alignY === 'Mid') {\n marginY = (this.height - height) / 2;\n }\n if (this.alignY === 'Max') {\n marginY = this.height - height;\n }\n }\n return {\n width: width,\n height: height,\n marginX: marginX,\n marginY: marginY\n };\n },\n\n /**\n * @private\n */\n _resetWidthHeight: function() {\n var element = this.getElement();\n\n this.set('width', element.width);\n this.set('height', element.height);\n },\n\n /**\n * The Image class's initialization method. This method is automatically\n * called by the constructor.\n * @private\n * @param {HTMLImageElement|String} element The element representing the image\n * @param {Object} [options] Options object\n */\n _initElement: function(element, options, callback) {\n this.setElement(fabric.util.getById(element), callback, options);\n fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);\n },\n\n /**\n * @private\n * @param {Object} [options] Options object\n */\n _initConfig: function(options) {\n options || (options = { });\n this.setOptions(options);\n this._setWidthHeight(options);\n if (this._element && this.crossOrigin) {\n this._element.crossOrigin = this.crossOrigin;\n }\n },\n\n /**\n * @private\n * @param {Array} filters to be initialized\n * @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created\n */\n _initFilters: function(filters, callback) {\n if (filters && filters.length) {\n fabric.util.enlivenObjects(filters, function(enlivenedObjects) {\n callback && callback(enlivenedObjects);\n }, 'fabric.Image.filters');\n }\n else {\n callback && callback();\n }\n },\n\n /**\n * @private\n * @param {Object} [options] Object with width/height properties\n */\n _setWidthHeight: function(options) {\n this.width = 'width' in options\n ? options.width\n : (this.getElement()\n ? this.getElement().width || 0\n : 0);\n\n this.height = 'height' in options\n ? options.height\n : (this.getElement()\n ? this.getElement().height || 0\n : 0);\n },\n });\n\n /**\n * Default CSS class name for canvas\n * @static\n * @type String\n * @default\n */\n fabric.Image.CSS_CANVAS = 'canvas-img';\n\n /**\n * Alias for getSrc\n * @static\n */\n fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;\n\n /**\n * Creates an instance of fabric.Image from its object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} callback Callback to invoke when an image instance is created\n */\n fabric.Image.fromObject = function(object, callback) {\n fabric.util.loadImage(object.src, function(img, error) {\n if (error) {\n callback && callback(null, error);\n return;\n }\n fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {\n object.filters = filters || [];\n fabric.Image.prototype._initFilters.call(object, object.resizeFilters, function(resizeFilters) {\n object.resizeFilters = resizeFilters || [];\n return new fabric.Image(img, object, callback);\n });\n });\n }, null, object.crossOrigin);\n };\n\n /**\n * Creates an instance of fabric.Image from an URL string\n * @static\n * @param {String} url URL to create an image from\n * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument)\n * @param {Object} [imgOptions] Options object\n */\n fabric.Image.fromURL = function(url, callback, imgOptions) {\n fabric.util.loadImage(url, function(img) {\n callback && callback(new fabric.Image(img, imgOptions));\n }, null, imgOptions && imgOptions.crossOrigin);\n };\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})\n * @static\n * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n */\n fabric.Image.ATTRIBUTE_NAMES =\n fabric.SHARED_ATTRIBUTES.concat('x y width height preserveAspectRatio xlink:href crossOrigin'.split(' '));\n\n /**\n * Returns {@link fabric.Image} instance from an SVG element\n * @static\n * @param {SVGElement} element Element to parse\n * @param {Function} callback Callback to execute when fabric.Image object is created\n * @param {Object} [options] Options object\n * @return {fabric.Image} Instance of fabric.Image\n */\n fabric.Image.fromElement = function(element, callback, options) {\n var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES),\n preserveAR;\n\n if (parsedAttributes.preserveAspectRatio) {\n preserveAR = fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio);\n extend(parsedAttributes, preserveAR);\n }\n\n fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,\n extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.async = true;\n\n /**\n * Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9\n * @static\n * @type Number\n * @default\n */\n fabric.Image.pngCompression = 1;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\nfabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {\n\n /**\n * @private\n * @return {Number} angle value\n */\n _getAngleValueForStraighten: function() {\n var angle = this.getAngle() % 360;\n if (angle > 0) {\n return Math.round((angle - 1) / 90) * 90;\n }\n return Math.round(angle / 90) * 90;\n },\n\n /**\n * Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)\n * @return {fabric.Object} thisArg\n * @chainable\n */\n straighten: function() {\n this.setAngle(this._getAngleValueForStraighten());\n return this;\n },\n\n /**\n * Same as {@link fabric.Object.prototype.straighten} but with animation\n * @param {Object} callbacks Object with callback functions\n * @param {Function} [callbacks.onComplete] Invoked on completion\n * @param {Function} [callbacks.onChange] Invoked on every step of animation\n * @return {fabric.Object} thisArg\n * @chainable\n */\n fxStraighten: function(callbacks) {\n callbacks = callbacks || { };\n\n var empty = function() { },\n onComplete = callbacks.onComplete || empty,\n onChange = callbacks.onChange || empty,\n _this = this;\n\n fabric.util.animate({\n startValue: this.get('angle'),\n endValue: this._getAngleValueForStraighten(),\n duration: this.FX_DURATION,\n onChange: function(value) {\n _this.setAngle(value);\n onChange();\n },\n onComplete: function() {\n _this.setCoords();\n onComplete();\n },\n onStart: function() {\n _this.set('active', false);\n }\n });\n\n return this;\n }\n});\n\nfabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {\n\n /**\n * Straightens object, then rerenders canvas\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n straightenObject: function (object) {\n object.straighten();\n this.renderAll();\n return this;\n },\n\n /**\n * Same as {@link fabric.Canvas.prototype.straightenObject}, but animated\n * @param {fabric.Object} object Object to straighten\n * @return {fabric.Canvas} thisArg\n * @chainable\n */\n fxStraightenObject: function (object) {\n object.fxStraighten({\n onChange: this.renderAll.bind(this)\n });\n return this;\n }\n});\n\n\n/**\n * @namespace fabric.Image.filters\n * @memberOf fabric.Image\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#image_filters}\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n */\nfabric.Image.filters = fabric.Image.filters || { };\n\n/**\n * Root filter class from which all filter classes inherit from\n * @class fabric.Image.filters.BaseFilter\n * @memberOf fabric.Image.filters\n */\nfabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Image.filters.BaseFilter.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'BaseFilter',\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n initialize: function(options) {\n if (options) {\n this.setOptions(options);\n }\n },\n\n /**\n * Sets filter's properties from options\n * @param {Object} [options] Options object\n */\n setOptions: function(options) {\n for (var prop in options) {\n this[prop] = options[prop];\n }\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return { type: this.type };\n },\n\n /**\n * Returns a JSON representation of an instance\n * @return {Object} JSON\n */\n toJSON: function() {\n // delegate, not alias\n return this.toObject();\n }\n});\n\nfabric.Image.filters.BaseFilter.fromObject = function(object, callback) {\n var filter = new fabric.Image.filters[object.type](object);\n callback && callback(filter);\n return filter;\n};\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Brightness filter class\n * @class fabric.Image.filters.Brightness\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Brightness#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Brightness({\n * brightness: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Brightness = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Brightness.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Brightness',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Brightness.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.brightness=0] Value to brighten the image up (-255..255)\n */\n initialize: function(options) {\n options = options || { };\n this.brightness = options.brightness || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n brightness = this.brightness;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i] += brightness;\n data[i + 1] += brightness;\n data[i + 2] += brightness;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n brightness: this.brightness\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Brightness} Instance of fabric.Image.filters.Brightness\n */\n fabric.Image.filters.Brightness.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Adapted from html5rocks article\n * @class fabric.Image.filters.Convolute\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Convolute#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example Sharpen filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 0, -1, 0,\n * -1, 5, -1,\n * 0, -1, 0 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Blur filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Emboss filter\n * var filter = new fabric.Image.filters.Convolute({\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Emboss filter with opaqueness\n * var filter = new fabric.Image.filters.Convolute({\n * opaque: true,\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Convolute = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Convolute.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Convolute',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Convolute.prototype\n * @param {Object} [options] Options object\n * @param {Boolean} [options.opaque=false] Opaque value (true/false)\n * @param {Array} [options.matrix] Filter matrix\n */\n initialize: function(options) {\n options = options || { };\n\n this.opaque = options.opaque;\n this.matrix = options.matrix || [\n 0, 0, 0,\n 0, 1, 0,\n 0, 0, 0\n ];\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n\n var weights = this.matrix,\n context = canvasEl.getContext('2d'),\n pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n\n side = Math.round(Math.sqrt(weights.length)),\n halfSide = Math.floor(side / 2),\n src = pixels.data,\n sw = pixels.width,\n sh = pixels.height,\n output = context.createImageData(sw, sh),\n dst = output.data,\n // go through the destination image pixels\n alphaFac = this.opaque ? 1 : 0,\n r, g, b, a, dstOff,\n scx, scy, srcOff, wt;\n\n for (var y = 0; y < sh; y++) {\n for (var x = 0; x < sw; x++) {\n dstOff = (y * sw + x) * 4;\n // calculate the weighed sum of the source image pixels that\n // fall under the convolution matrix\n r = 0; g = 0; b = 0; a = 0;\n\n for (var cy = 0; cy < side; cy++) {\n for (var cx = 0; cx < side; cx++) {\n scy = y + cy - halfSide;\n scx = x + cx - halfSide;\n\n // eslint-disable-next-line max-depth\n if (scy < 0 || scy > sh || scx < 0 || scx > sw) {\n continue;\n }\n\n srcOff = (scy * sw + scx) * 4;\n wt = weights[cy * side + cx];\n\n r += src[srcOff] * wt;\n g += src[srcOff + 1] * wt;\n b += src[srcOff + 2] * wt;\n a += src[srcOff + 3] * wt;\n }\n }\n dst[dstOff] = r;\n dst[dstOff + 1] = g;\n dst[dstOff + 2] = b;\n dst[dstOff + 3] = a + alphaFac * (255 - a);\n }\n }\n\n context.putImageData(output, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n opaque: this.opaque,\n matrix: this.matrix\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Convolute} Instance of fabric.Image.filters.Convolute\n */\n fabric.Image.filters.Convolute.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * GradientTransparency filter class\n * @class fabric.Image.filters.GradientTransparency\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.GradientTransparency#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.GradientTransparency({\n * threshold: 200\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n // eslint-disable-next-line max-len\n filters.GradientTransparency = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.GradientTransparency.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'GradientTransparency',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.GradientTransparency.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=100] Threshold value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 100;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n total = data.length;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i + 3] = threshold + 255 * (total - i) / total;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n threshold: this.threshold\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.GradientTransparency} Instance of fabric.Image.filters.GradientTransparency\n */\n fabric.Image.filters.GradientTransparency.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Grayscale image filter class\n * @class fabric.Image.filters.Grayscale\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Grayscale();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Grayscale = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Grayscale.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Grayscale',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Grayscale.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n len = imageData.width * imageData.height * 4,\n index = 0,\n average;\n\n while (index < len) {\n average = (data[index] + data[index + 1] + data[index + 2]) / 3;\n data[index] = average;\n data[index + 1] = average;\n data[index + 2] = average;\n index += 4;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale\n */\n fabric.Image.filters.Grayscale.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Grayscale';\n return fabric.Image.filters.BaseFilter.fromObject(object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Invert filter class\n * @class fabric.Image.filters.Invert\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Invert();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Invert = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Invert.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Invert',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Invert.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i;\n\n for (i = 0; i < iLen; i += 4) {\n data[i] = 255 - data[i];\n data[i + 1] = 255 - data[i + 1];\n data[i + 2] = 255 - data[i + 2];\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Invert} Instance of fabric.Image.filters.Invert\n */\n fabric.Image.filters.Invert.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Invert';\n return fabric.Image.filters.BaseFilter.fromObject(object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Mask filter class\n * See http://resources.aleph-1.com/mask/\n * @class fabric.Image.filters.Mask\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Mask#initialize} for constructor definition\n */\n filters.Mask = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Mask',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Mask.prototype\n * @param {Object} [options] Options object\n * @param {fabric.Image} [options.mask] Mask image object\n * @param {Number} [options.channel=0] Rgb channel (0, 1, 2 or 3)\n */\n initialize: function(options) {\n options = options || { };\n\n this.mask = options.mask;\n this.channel = [0, 1, 2, 3].indexOf(options.channel) > -1 ? options.channel : 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n if (!this.mask) {\n return;\n }\n\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n maskEl = this.mask.getElement(),\n maskCanvasEl = fabric.util.createCanvasElement(),\n channel = this.channel,\n i,\n iLen = imageData.width * imageData.height * 4;\n\n maskCanvasEl.width = canvasEl.width;\n maskCanvasEl.height = canvasEl.height;\n\n maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, canvasEl.width, canvasEl.height);\n\n var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, canvasEl.width, canvasEl.height),\n maskData = maskImageData.data;\n\n for (i = 0; i < iLen; i += 4) {\n data[i + 3] = maskData[i + channel];\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n mask: this.mask.toObject(),\n channel: this.channel\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when a mask filter instance is created\n */\n fabric.Image.filters.Mask.fromObject = function(object, callback) {\n fabric.util.loadImage(object.mask.src, function(img) {\n object.mask = new fabric.Image(img, object.mask);\n return fabric.Image.filters.BaseFilter.fromObject(object, callback);\n });\n };\n\n /**\n * Indicates that instances of this type are async\n * @static\n * @type Boolean\n * @default\n */\n fabric.Image.filters.Mask.async = true;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Noise filter class\n * @class fabric.Image.filters.Noise\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Noise#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Noise({\n * noise: 700\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Noise = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Noise.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Noise',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Noise.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.noise=0] Noise value\n */\n initialize: function(options) {\n options = options || { };\n this.noise = options.noise || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n noise = this.noise, rand;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n\n rand = (0.5 - Math.random()) * noise;\n\n data[i] += rand;\n data[i + 1] += rand;\n data[i + 2] += rand;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n noise: this.noise\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Noise} Instance of fabric.Image.filters.Noise\n */\n fabric.Image.filters.Noise.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Pixelate filter class\n * @class fabric.Image.filters.Pixelate\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Pixelate#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Pixelate({\n * blocksize: 8\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Pixelate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Pixelate.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Pixelate',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Pixelate.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.blocksize=4] Blocksize for pixelate\n */\n initialize: function(options) {\n options = options || { };\n this.blocksize = options.blocksize || 4;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = imageData.height,\n jLen = imageData.width,\n index, i, j, r, g, b, a;\n\n for (i = 0; i < iLen; i += this.blocksize) {\n for (j = 0; j < jLen; j += this.blocksize) {\n\n index = (i * 4) * jLen + (j * 4);\n\n r = data[index];\n g = data[index + 1];\n b = data[index + 2];\n a = data[index + 3];\n\n /*\n blocksize: 4\n\n [1,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [x,x,x,x,1]\n [1,1,1,1,1]\n */\n\n for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) {\n for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) {\n index = (_i * 4) * jLen + (_j * 4);\n data[index] = r;\n data[index + 1] = g;\n data[index + 2] = b;\n data[index + 3] = a;\n }\n }\n }\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n blocksize: this.blocksize\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Pixelate} Instance of fabric.Image.filters.Pixelate\n */\n fabric.Image.filters.Pixelate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Remove white filter class\n * @class fabric.Image.filters.RemoveWhite\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.RemoveWhite#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.RemoveWhite({\n * threshold: 40,\n * distance: 140\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.RemoveWhite = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.RemoveWhite.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'RemoveWhite',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.RemoveWhite.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.threshold=30] Threshold value\n * @param {Number} [options.distance=20] Distance value\n */\n initialize: function(options) {\n options = options || { };\n this.threshold = options.threshold || 30;\n this.distance = options.distance || 20;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n threshold = this.threshold,\n distance = this.distance,\n limit = 255 - threshold,\n abs = Math.abs,\n r, g, b;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (r > limit &&\n g > limit &&\n b > limit &&\n abs(r - g) < distance &&\n abs(r - b) < distance &&\n abs(g - b) < distance\n ) {\n data[i + 3] = 0;\n }\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n threshold: this.threshold,\n distance: this.distance\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.RemoveWhite\n */\n fabric.Image.filters.RemoveWhite.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Sepia filter class\n * @class fabric.Image.filters.Sepia\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Sepia();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Sepia = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Sepia.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, avg;\n\n for (i = 0; i < iLen; i += 4) {\n avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2];\n data[i] = avg + 100;\n data[i + 1] = avg + 50;\n data[i + 2] = avg + 255;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Sepia} Instance of fabric.Image.filters.Sepia\n */\n fabric.Image.filters.Sepia.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Sepia';\n return new fabric.Image.filters.BaseFilter.fromObject(object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Sepia2 filter class\n * @class fabric.Image.filters.Sepia2\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Sepia2();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Sepia2 = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Sepia2.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Sepia2',\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Sepia.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i, r, g, b;\n\n for (i = 0; i < iLen; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351;\n data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203;\n data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140;\n }\n\n context.putImageData(imageData, 0, 0);\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Sepia2} Instance of fabric.Image.filters.Sepia2\n */\n fabric.Image.filters.Sepia2.fromObject = function(object, callback) {\n object = object || { };\n object.type = 'Sepia2';\n return new fabric.Image.filters.BaseFilter.fromObject(object, callback);\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Tint filter class\n * Adapted from https://github.com/mezzoblue/PaintbrushJS\n * @class fabric.Image.filters.Tint\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example Tint filter with hex color and opacity\n * var filter = new fabric.Image.filters.Tint({\n * color: '#3513B0',\n * opacity: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Tint filter with rgba color\n * var filter = new fabric.Image.filters.Tint({\n * color: 'rgba(53, 21, 176, 0.5)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Tint = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Tint',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Tint.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to tint the image with\n * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1)\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n this.opacity = typeof options.opacity !== 'undefined'\n ? options.opacity\n : new fabric.Color(this.color).getAlpha();\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n tintR, tintG, tintB,\n r, g, b, alpha1,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n tintR = source[0] * this.opacity;\n tintG = source[1] * this.opacity;\n tintB = source[2] * this.opacity;\n\n alpha1 = 1 - this.opacity;\n\n for (i = 0; i < iLen; i += 4) {\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n // alpha compositing\n data[i] = tintR + r * alpha1;\n data[i + 1] = tintG + g * alpha1;\n data[i + 2] = tintB + b * alpha1;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n color: this.color,\n opacity: this.opacity\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Tint} Instance of fabric.Image.filters.Tint\n */\n fabric.Image.filters.Tint.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Multiply filter class\n * Adapted from http://www.laurenscorijn.com/articles/colormath-basics\n * @class fabric.Image.filters.Multiply\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example Multiply filter with hex color\n * var filter = new fabric.Image.filters.Multiply({\n * color: '#F0F'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n * @example Multiply filter with rgb color\n * var filter = new fabric.Image.filters.Multiply({\n * color: 'rgb(53, 21, 176)'\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Multiply = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Multiply.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Multiply',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Multiply.prototype\n * @param {Object} [options] Options object\n * @param {String} [options.color=#000000] Color to multiply the image pixels with\n */\n initialize: function(options) {\n options = options || { };\n\n this.color = options.color || '#000000';\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n iLen = data.length, i,\n source;\n\n source = new fabric.Color(this.color).getSource();\n\n for (i = 0; i < iLen; i += 4) {\n data[i] *= source[0] / 255;\n data[i + 1] *= source[1] / 255;\n data[i + 2] *= source[2] / 255;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n color: this.color\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Multiply} Instance of fabric.Image.filters.Multiply\n */\n fabric.Image.filters.Multiply.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n 'use strict';\n\n var fabric = global.fabric,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Color Blend filter class\n * @class fabric.Image.filter.Blend\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @example\n * var filter = new fabric.Image.filters.Blend({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * var filter = new fabric.Image.filters.Blend({\n * image: fabricImageObject,\n * mode: 'multiply',\n * alpha: 0.5\n * });\n\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n\n filters.Blend = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blend.prototype */ {\n type: 'Blend',\n\n initialize: function(options) {\n options = options || {};\n this.color = options.color || '#000';\n this.image = options.image || false;\n this.mode = options.mode || 'multiply';\n this.alpha = options.alpha || 1;\n },\n\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n tr, tg, tb,\n r, g, b,\n _r, _g, _b,\n source,\n isImage = false;\n\n if (this.image) {\n // Blend images\n isImage = true;\n\n var _el = fabric.util.createCanvasElement();\n _el.width = this.image.width;\n _el.height = this.image.height;\n\n var tmpCanvas = new fabric.StaticCanvas(_el);\n tmpCanvas.add(this.image);\n var context2 = tmpCanvas.getContext('2d');\n source = context2.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height).data;\n }\n else {\n // Blend color\n source = new fabric.Color(this.color).getSource();\n\n tr = source[0] * this.alpha;\n tg = source[1] * this.alpha;\n tb = source[2] * this.alpha;\n }\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n\n r = data[i];\n g = data[i + 1];\n b = data[i + 2];\n\n if (isImage) {\n tr = source[i] * this.alpha;\n tg = source[i + 1] * this.alpha;\n tb = source[i + 2] * this.alpha;\n }\n\n switch (this.mode) {\n case 'multiply':\n data[i] = r * tr / 255;\n data[i + 1] = g * tg / 255;\n data[i + 2] = b * tb / 255;\n break;\n case 'screen':\n data[i] = 1 - (1 - r) * (1 - tr);\n data[i + 1] = 1 - (1 - g) * (1 - tg);\n data[i + 2] = 1 - (1 - b) * (1 - tb);\n break;\n case 'add':\n data[i] = Math.min(255, r + tr);\n data[i + 1] = Math.min(255, g + tg);\n data[i + 2] = Math.min(255, b + tb);\n break;\n case 'diff':\n case 'difference':\n data[i] = Math.abs(r - tr);\n data[i + 1] = Math.abs(g - tg);\n data[i + 2] = Math.abs(b - tb);\n break;\n case 'subtract':\n _r = r - tr;\n _g = g - tg;\n _b = b - tb;\n\n data[i] = (_r < 0) ? 0 : _r;\n data[i + 1] = (_g < 0) ? 0 : _g;\n data[i + 2] = (_b < 0) ? 0 : _b;\n break;\n case 'darken':\n data[i] = Math.min(r, tr);\n data[i + 1] = Math.min(g, tg);\n data[i + 2] = Math.min(b, tb);\n break;\n case 'lighten':\n data[i] = Math.max(r, tr);\n data[i + 1] = Math.max(g, tg);\n data[i + 2] = Math.max(b, tb);\n break;\n }\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return {\n color: this.color,\n image: this.image,\n mode: this.mode,\n alpha: this.alpha\n };\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Blend} Instance of fabric.Image.filters.Blend\n */\n fabric.Image.filters.Blend.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }), pow = Math.pow, floor = Math.floor,\n sqrt = Math.sqrt, abs = Math.abs, max = Math.max, round = Math.round, sin = Math.sin,\n ceil = Math.ceil,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Resize image filter class\n * @class fabric.Image.filters.Resize\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Resize();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Resize = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Resize.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Resize',\n\n /**\n * Resize type\n * @param {String} resizeType\n * @default\n */\n resizeType: 'hermite',\n\n /**\n * Scale factor for resizing, x axis\n * @param {Number} scaleX\n * @default\n */\n scaleX: 0,\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n * @default\n */\n scaleY: 0,\n\n /**\n * LanczosLobes parameter for lanczos filter\n * @param {Number} lanczosLobes\n * @default\n */\n lanczosLobes: 3,\n\n /**\n * Applies filter to canvas element\n * @memberOf fabric.Image.filters.Resize.prototype\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} scaleX\n * @param {Number} scaleY\n */\n applyTo: function(canvasEl, scaleX, scaleY) {\n if (scaleX === 1 && scaleY === 1) {\n return;\n }\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n var oW = canvasEl.width, oH = canvasEl.height,\n dW = round(oW * scaleX), dH = round(oH * scaleY),\n imageData;\n\n if (this.resizeType === 'sliceHack') {\n imageData = this.sliceByTwo(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'hermite') {\n imageData = this.hermiteFastResize(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'bilinear') {\n imageData = this.bilinearFiltering(canvasEl, oW, oH, dW, dH);\n }\n if (this.resizeType === 'lanczos') {\n imageData = this.lanczosResize(canvasEl, oW, oH, dW, dH);\n }\n canvasEl.width = dW;\n canvasEl.height = dH;\n canvasEl.getContext('2d').putImageData(imageData, 0, 0);\n },\n\n /**\n * Filter sliceByTwo\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n sliceByTwo: function(canvasEl, oW, oH, dW, dH) {\n var context = canvasEl.getContext('2d'), imageData,\n multW = 0.5, multH = 0.5, signW = 1, signH = 1,\n doneW = false, doneH = false, stepW = oW, stepH = oH,\n tmpCanvas = fabric.util.createCanvasElement(),\n tmpCtx = tmpCanvas.getContext('2d');\n dW = floor(dW);\n dH = floor(dH);\n tmpCanvas.width = max(dW, oW);\n tmpCanvas.height = max(dH, oH);\n\n if (dW > oW) {\n multW = 2;\n signW = -1;\n }\n if (dH > oH) {\n multH = 2;\n signH = -1;\n }\n imageData = context.getImageData(0, 0, oW, oH);\n canvasEl.width = max(dW, oW);\n canvasEl.height = max(dH, oH);\n context.putImageData(imageData, 0, 0);\n\n while (!doneW || !doneH) {\n oW = stepW;\n oH = stepH;\n if (dW * signW < floor(stepW * multW * signW)) {\n stepW = floor(stepW * multW);\n }\n else {\n stepW = dW;\n doneW = true;\n }\n if (dH * signH < floor(stepH * multH * signH)) {\n stepH = floor(stepH * multH);\n }\n else {\n stepH = dH;\n doneH = true;\n }\n imageData = context.getImageData(0, 0, oW, oH);\n tmpCtx.putImageData(imageData, 0, 0);\n context.clearRect(0, 0, stepW, stepH);\n context.drawImage(tmpCanvas, 0, 0, oW, oH, 0, 0, stepW, stepH);\n }\n return context.getImageData(0, 0, dW, dH);\n },\n\n /**\n * Filter lanczosResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n lanczosResize: function(canvasEl, oW, oH, dW, dH) {\n\n function lanczosCreate(lobes) {\n return function(x) {\n if (x > lobes) {\n return 0;\n }\n x *= Math.PI;\n if (abs(x) < 1e-16) {\n return 1;\n }\n var xx = x / lobes;\n return sin(x) * sin(xx) / x / xx;\n };\n }\n\n function process(u) {\n var v, i, weight, idx, a, red, green,\n blue, alpha, fX, fY;\n center.x = (u + 0.5) * ratioX;\n icenter.x = floor(center.x);\n for (v = 0; v < dH; v++) {\n center.y = (v + 0.5) * ratioY;\n icenter.y = floor(center.y);\n a = 0; red = 0; green = 0; blue = 0; alpha = 0;\n for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n if (i < 0 || i >= oW) {\n continue;\n }\n fX = floor(1000 * abs(i - center.x));\n if (!cacheLanc[fX]) {\n cacheLanc[fX] = { };\n }\n for (var j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n if (j < 0 || j >= oH) {\n continue;\n }\n fY = floor(1000 * abs(j - center.y));\n if (!cacheLanc[fX][fY]) {\n cacheLanc[fX][fY] = lanczos(sqrt(pow(fX * rcpRatioX, 2) + pow(fY * rcpRatioY, 2)) / 1000);\n }\n weight = cacheLanc[fX][fY];\n if (weight > 0) {\n idx = (j * oW + i) * 4;\n a += weight;\n red += weight * srcData[idx];\n green += weight * srcData[idx + 1];\n blue += weight * srcData[idx + 2];\n alpha += weight * srcData[idx + 3];\n }\n }\n }\n idx = (v * dW + u) * 4;\n destData[idx] = red / a;\n destData[idx + 1] = green / a;\n destData[idx + 2] = blue / a;\n destData[idx + 3] = alpha / a;\n }\n\n if (++u < dW) {\n return process(u);\n }\n else {\n return destImg;\n }\n }\n\n var context = canvasEl.getContext('2d'),\n srcImg = context.getImageData(0, 0, oW, oH),\n destImg = context.getImageData(0, 0, dW, dH),\n srcData = srcImg.data, destData = destImg.data,\n lanczos = lanczosCreate(this.lanczosLobes),\n ratioX = this.rcpScaleX, ratioY = this.rcpScaleY,\n rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY,\n range2X = ceil(ratioX * this.lanczosLobes / 2),\n range2Y = ceil(ratioY * this.lanczosLobes / 2),\n cacheLanc = { }, center = { }, icenter = { };\n\n return process(0);\n },\n\n /**\n * bilinearFiltering\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n bilinearFiltering: function(canvasEl, oW, oH, dW, dH) {\n var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl,\n color, offset = 0, origPix, ratioX = this.rcpScaleX,\n ratioY = this.rcpScaleY, context = canvasEl.getContext('2d'),\n w4 = 4 * (oW - 1), img = context.getImageData(0, 0, oW, oH),\n pixels = img.data, destImage = context.getImageData(0, 0, dW, dH),\n destPixels = destImage.data;\n for (i = 0; i < dH; i++) {\n for (j = 0; j < dW; j++) {\n x = floor(ratioX * j);\n y = floor(ratioY * i);\n xDiff = ratioX * j - x;\n yDiff = ratioY * i - y;\n origPix = 4 * (y * oW + x);\n\n for (chnl = 0; chnl < 4; chnl++) {\n a = pixels[origPix + chnl];\n b = pixels[origPix + 4 + chnl];\n c = pixels[origPix + w4 + chnl];\n d = pixels[origPix + w4 + 4 + chnl];\n color = a * (1 - xDiff) * (1 - yDiff) + b * xDiff * (1 - yDiff) +\n c * yDiff * (1 - xDiff) + d * xDiff * yDiff;\n destPixels[offset++] = color;\n }\n }\n }\n return destImage;\n },\n\n /**\n * hermiteFastResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n hermiteFastResize: function(canvasEl, oW, oH, dW, dH) {\n var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,\n ratioWHalf = ceil(ratioW / 2),\n ratioHHalf = ceil(ratioH / 2),\n context = canvasEl.getContext('2d'),\n img = context.getImageData(0, 0, oW, oH), data = img.data,\n img2 = context.getImageData(0, 0, dW, dH), data2 = img2.data;\n for (var j = 0; j < dH; j++) {\n for (var i = 0; i < dW; i++) {\n var x2 = (i + j * dW) * 4, weight = 0, weights = 0, weightsAlpha = 0,\n gxR = 0, gxG = 0, gxB = 0, gxA = 0, centerY = (j + 0.5) * ratioH;\n for (var yy = floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n var dy = abs(centerY - (yy + 0.5)) / ratioHHalf,\n centerX = (i + 0.5) * ratioW, w0 = dy * dy;\n for (var xx = floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n var dx = abs(centerX - (xx + 0.5)) / ratioWHalf,\n w = sqrt(w0 + dx * dx);\n /* eslint-disable max-depth */\n if (w > 1 && w < -1) {\n continue;\n }\n //hermite filter\n weight = 2 * w * w * w - 3 * w * w + 1;\n if (weight > 0) {\n dx = 4 * (xx + yy * oW);\n //alpha\n gxA += weight * data[dx + 3];\n weightsAlpha += weight;\n //colors\n if (data[dx + 3] < 255) {\n weight = weight * data[dx + 3] / 250;\n }\n gxR += weight * data[dx];\n gxG += weight * data[dx + 1];\n gxB += weight * data[dx + 2];\n weights += weight;\n }\n /* eslint-enable max-depth */\n }\n }\n data2[x2] = gxR / weights;\n data2[x2 + 1] = gxG / weights;\n data2[x2 + 2] = gxB / weights;\n data2[x2 + 3] = gxA / weightsAlpha;\n }\n }\n return img2;\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return {\n type: this.type,\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n resizeType: this.resizeType,\n lanczosLobes: this.lanczosLobes\n };\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Resize} Instance of fabric.Image.filters.Resize\n */\n fabric.Image.filters.Resize.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Color Matrix filter class\n * @class fabric.Image.filters.ColorMatrix\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.ColorMatrix#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @see {@Link http://www.webwasp.co.uk/tutorials/219/Color_Matrix_Filter.php}\n * @see {@Link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl}\n * @example Kodachrome filter\n * var filter = new fabric.Image.filters.ColorMatrix({\n * matrix: [\n 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\n -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\n -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\n 0, 0, 0, 1, 0\n ]\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.ColorMatrix = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.ColorMatrix.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'ColorMatrix',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.ColorMatrix.prototype\n * @param {Object} [options] Options object\n * @param {Array} [options.matrix] Color Matrix to modify the image data with\n */\n initialize: function( options ) {\n options || ( options = {} );\n this.matrix = options.matrix || [\n 1, 0, 0, 0, 0,\n 0, 1, 0, 0, 0,\n 0, 0, 1, 0, 0,\n 0, 0, 0, 1, 0\n ];\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function( canvasEl ) {\n var context = canvasEl.getContext( '2d' ),\n imageData = context.getImageData( 0, 0, canvasEl.width, canvasEl.height ),\n data = imageData.data,\n iLen = data.length,\n i,\n r,\n g,\n b,\n a,\n m = this.matrix;\n\n for ( i = 0; i < iLen; i += 4 ) {\n r = data[ i ];\n g = data[ i + 1 ];\n b = data[ i + 2 ];\n a = data[ i + 3 ];\n\n data[ i ] = r * m[ 0 ] + g * m[ 1 ] + b * m[ 2 ] + a * m[ 3 ] + m[ 4 ];\n data[ i + 1 ] = r * m[ 5 ] + g * m[ 6 ] + b * m[ 7 ] + a * m[ 8 ] + m[ 9 ];\n data[ i + 2 ] = r * m[ 10 ] + g * m[ 11 ] + b * m[ 12 ] + a * m[ 13 ] + m[ 14 ];\n data[ i + 3 ] = r * m[ 15 ] + g * m[ 16 ] + b * m[ 17 ] + a * m[ 18 ] + m[ 19 ];\n }\n\n context.putImageData( imageData, 0, 0 );\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n type: this.type,\n matrix: this.matrix\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] function to invoke after filter creation\n * @return {fabric.Image.filters.ColorMatrix} Instance of fabric.Image.filters.ColorMatrix\n */\n fabric.Image.filters.ColorMatrix.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Contrast filter class\n * @class fabric.Image.filters.Contrast\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Contrast({\n * contrast: 40\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Contrast = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Contrast.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Contrast',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Contrast.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.contrast=0] Value to contrast the image up (-255...255)\n */\n initialize: function(options) {\n options = options || { };\n this.contrast = options.contrast || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n contrastF = 259 * (this.contrast + 255) / (255 * (259 - this.contrast));\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n data[i] = contrastF * (data[i] - 128) + 128;\n data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\n data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n contrast: this.contrast\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast\n */\n fabric.Image.filters.Contrast.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n extend = fabric.util.object.extend,\n filters = fabric.Image.filters,\n createClass = fabric.util.createClass;\n\n /**\n * Saturate filter class\n * @class fabric.Image.filters.Saturate\n * @memberOf fabric.Image.filters\n * @extends fabric.Image.filters.BaseFilter\n * @see {@link fabric.Image.filters.Saturate#initialize} for constructor definition\n * @see {@link http://fabricjs.com/image-filters|ImageFilters demo}\n * @example\n * var filter = new fabric.Image.filters.Saturate({\n * saturate: 100\n * });\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\n filters.Saturate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturate.prototype */ {\n\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n type: 'Saturate',\n\n /**\n * Constructor\n * @memberOf fabric.Image.filters.Saturate.prototype\n * @param {Object} [options] Options object\n * @param {Number} [options.saturate=0] Value to saturate the image (-100...100)\n */\n initialize: function(options) {\n options = options || { };\n this.saturate = options.saturate || 0;\n },\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo: function(canvasEl) {\n var context = canvasEl.getContext('2d'),\n imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),\n data = imageData.data,\n max, adjust = -this.saturate * 0.01;\n\n for (var i = 0, len = data.length; i < len; i += 4) {\n max = Math.max(data[i], data[i + 1], data[i + 2]);\n data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;\n data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;\n data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;\n }\n\n context.putImageData(imageData, 0, 0);\n },\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject: function() {\n return extend(this.callSuper('toObject'), {\n saturate: this.saturate\n });\n }\n });\n\n /**\n * Returns filter instance from an object representation\n * @static\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] to be invoked after filter creation\n * @return {fabric.Image.filters.Saturate} Instance of fabric.Image.filters.Saturate\n */\n fabric.Image.filters.Saturate.fromObject = fabric.Image.filters.BaseFilter.fromObject;\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = { }),\n toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,\n MIN_TEXT_WIDTH = 2;\n\n if (fabric.Text) {\n fabric.warn('fabric.Text is already defined');\n return;\n }\n\n /**\n * Text class\n * @class fabric.Text\n * @extends fabric.Object\n * @return {fabric.Text} thisArg\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}\n * @see {@link fabric.Text#initialize} for constructor definition\n */\n fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {\n\n /**\n * Properties which when set cause object to change dimensions\n * @type Object\n * @private\n */\n _dimensionAffectingProps: [\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n 'lineHeight',\n 'text',\n 'charSpacing',\n 'textAlign'\n ],\n\n /**\n * @private\n */\n _reNewline: /\\r?\\n/,\n\n /**\n * Use this regular expression to filter for whitespace that is not a new line.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n _reSpacesAndTabs: /[ \\t\\r]+/g,\n\n /**\n * Retrieves object's fontSize\n * @method getFontSize\n * @memberOf fabric.Text.prototype\n * @return {String} Font size (in pixels)\n */\n\n /**\n * Sets object's fontSize\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontSize\n * @memberOf fabric.Text.prototype\n * @param {Number} fontSize Font size (in pixels)\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontWeight\n * @method getFontWeight\n * @memberOf fabric.Text.prototype\n * @return {(String|Number)} Font weight\n */\n\n /**\n * Sets object's fontWeight\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontWeight\n * @memberOf fabric.Text.prototype\n * @param {(Number|String)} fontWeight Font weight\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontFamily\n * @method getFontFamily\n * @memberOf fabric.Text.prototype\n * @return {String} Font family\n */\n\n /**\n * Sets object's fontFamily\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontFamily\n * @memberOf fabric.Text.prototype\n * @param {String} fontFamily Font family\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's text\n * @method getText\n * @memberOf fabric.Text.prototype\n * @return {String} text\n */\n\n /**\n * Sets object's text\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setText\n * @memberOf fabric.Text.prototype\n * @param {String} text Text\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textDecoration\n * @method getTextDecoration\n * @memberOf fabric.Text.prototype\n * @return {String} Text decoration\n */\n\n /**\n * Sets object's textDecoration\n * @method setTextDecoration\n * @memberOf fabric.Text.prototype\n * @param {String} textDecoration Text decoration\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's fontStyle\n * @method getFontStyle\n * @memberOf fabric.Text.prototype\n * @return {String} Font style\n */\n\n /**\n * Sets object's fontStyle\n * Does not update the object .width and .height,\n * call ._initDimensions() to update the values.\n * @method setFontStyle\n * @memberOf fabric.Text.prototype\n * @param {String} fontStyle Font style\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's lineHeight\n * @method getLineHeight\n * @memberOf fabric.Text.prototype\n * @return {Number} Line height\n */\n\n /**\n * Sets object's lineHeight\n * @method setLineHeight\n * @memberOf fabric.Text.prototype\n * @param {Number} lineHeight Line height\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textAlign\n * @method getTextAlign\n * @memberOf fabric.Text.prototype\n * @return {String} Text alignment\n */\n\n /**\n * Sets object's textAlign\n * @method setTextAlign\n * @memberOf fabric.Text.prototype\n * @param {String} textAlign Text alignment\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Retrieves object's textBackgroundColor\n * @method getTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @return {String} Text background color\n */\n\n /**\n * Sets object's textBackgroundColor\n * @method setTextBackgroundColor\n * @memberOf fabric.Text.prototype\n * @param {String} textBackgroundColor Text background color\n * @return {fabric.Text}\n * @chainable\n */\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'text',\n\n /**\n * Font size (in pixels)\n * @type Number\n * @default\n */\n fontSize: 40,\n\n /**\n * Font weight (e.g. bold, normal, 400, 600, 800)\n * @type {(Number|String)}\n * @default\n */\n fontWeight: 'normal',\n\n /**\n * Font family\n * @type String\n * @default\n */\n fontFamily: 'Times New Roman',\n\n /**\n * Text decoration Possible values: \"\", \"underline\", \"overline\" or \"line-through\".\n * @type String\n * @default\n */\n textDecoration: '',\n\n /**\n * Text alignment. Possible values: \"left\", \"center\", \"right\" or \"justify\".\n * @type String\n * @default\n */\n textAlign: 'left',\n\n /**\n * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n * @type String\n * @default\n */\n fontStyle: '',\n\n /**\n * Line height\n * @type Number\n * @default\n */\n lineHeight: 1.16,\n\n /**\n * Background color of text lines\n * @type String\n * @default\n */\n textBackgroundColor: '',\n\n /**\n * List of properties to consider when checking if\n * state of an object is changed ({@link fabric.Object#hasStateChanged})\n * as well as for history (undo/redo) purposes\n * @type Array\n */\n stateProperties: fabric.Object.prototype.stateProperties.concat(\n 'fontFamily',\n 'fontWeight',\n 'fontSize',\n 'text',\n 'textDecoration',\n 'textAlign',\n 'fontStyle',\n 'lineHeight',\n 'textBackgroundColor',\n 'charSpacing'),\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * @type Array\n */\n cacheProperties: fabric.Object.prototype.cacheProperties.concat(\n 'fontFamily',\n 'fontWeight',\n 'fontSize',\n 'text',\n 'textDecoration',\n 'textAlign',\n 'fontStyle',\n 'lineHeight',\n 'textBackgroundColor',\n 'charSpacing',\n 'styles'),\n\n /**\n * When defined, an object is rendered via stroke and this property specifies its color.\n * Backwards incompatibility note: This property was named \"strokeStyle\" until v1.1.6\n * @type String\n * @default\n */\n stroke: null,\n\n /**\n * Shadow object representing shadow of this shape.\n * Backwards incompatibility note: This property was named \"textShadow\" (String) until v1.2.11\n * @type fabric.Shadow\n * @default\n */\n shadow: null,\n\n /**\n * @private\n */\n _fontSizeFraction: 0.25,\n\n /**\n * Text Line proportion to font Size (in pixels)\n * @type Number\n * @default\n */\n _fontSizeMult: 1.13,\n\n /**\n * additional space between characters\n * expressed in thousands of em unit\n * @type Number\n * @default\n */\n charSpacing: 0,\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Text} thisArg\n */\n initialize: function(text, options) {\n options = options || { };\n this.text = text;\n this.__skipDimension = true;\n this.callSuper('initialize', options);\n this.__skipDimension = false;\n this._initDimensions();\n this.setCoords();\n this.setupState({ propertySet: '_dimensionAffectingProps' });\n },\n\n /**\n * Initialize text dimensions. Render all text on given context\n * or on a offscreen canvas to get the text width with measureText.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n * @param {CanvasRenderingContext2D} [ctx] Context to render on\n * @private\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n }\n this._textLines = this._splitTextIntoLines();\n this._clearCache();\n this.width = this._getTextWidth(ctx) || this.cursorWidth || MIN_TEXT_WIDTH;\n this.height = this._getTextHeight(ctx);\n this.setCoords();\n },\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of text object\n */\n toString: function() {\n return '#';\n },\n\n /**\n * Return the dimension and the zoom level needed to create a cache canvas\n * big enough to host the object to be cached.\n * @private\n * @param {Object} dim.x width of object to be cached\n * @param {Object} dim.y height of object to be cached\n * @return {Object}.width width of canvas\n * @return {Object}.height height of canvas\n * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n */\n _getCacheCanvasDimensions: function() {\n var dims = this.callSuper('_getCacheCanvasDimensions');\n var fontSize = this.fontSize;\n dims.width += fontSize * dims.zoomX;\n dims.height += fontSize * dims.zoomY;\n return dims;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n this._setTextStyles(ctx);\n if (this.group && this.group.type === 'path-group') {\n ctx.translate(this.left, this.top);\n }\n this._renderTextLinesBackground(ctx);\n this._renderText(ctx);\n this._renderTextDecoration(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderText: function(ctx) {\n this._renderTextFill(ctx);\n this._renderTextStroke(ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setTextStyles: function(ctx) {\n ctx.textBaseline = 'alphabetic';\n ctx.font = this._getFontDeclaration();\n },\n\n /**\n * @private\n * @return {Number} Height of fabric.Text object\n */\n _getTextHeight: function() {\n return this._getHeightOfSingleLine() + (this._textLines.length - 1) * this._getHeightOfLine();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Maximum width of fabric.Text object\n */\n _getTextWidth: function(ctx) {\n var maxWidth = this._getLineWidth(ctx, 0);\n\n for (var i = 1, len = this._textLines.length; i < len; i++) {\n var currentLineWidth = this._getLineWidth(ctx, i);\n if (currentLineWidth > maxWidth) {\n maxWidth = currentLineWidth;\n }\n }\n return maxWidth;\n },\n\n /**\n * @private\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} chars Chars to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n */\n _renderChars: function(method, ctx, chars, left, top) {\n // remove Text word from method var\n var shortM = method.slice(0, -4), _char, width;\n if (this[shortM].toLive) {\n var offsetX = -this.width / 2 + this[shortM].offsetX || 0,\n offsetY = -this.height / 2 + this[shortM].offsetY || 0;\n ctx.save();\n ctx.translate(offsetX, offsetY);\n left -= offsetX;\n top -= offsetY;\n }\n if (this.charSpacing !== 0) {\n var additionalSpace = this._getWidthOfCharSpacing();\n chars = chars.split('');\n for (var i = 0, len = chars.length; i < len; i++) {\n _char = chars[i];\n width = ctx.measureText(_char).width + additionalSpace;\n ctx[method](_char, left, top);\n left += width > 0 ? width : 0;\n }\n }\n else {\n ctx[method](chars, left, top);\n }\n this[shortM].toLive && ctx.restore();\n },\n\n /**\n * @private\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Text to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n * @param {Number} lineIndex Index of a line in a text\n */\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n // lift the line by quarter of fontSize\n top -= this.fontSize * this._fontSizeFraction;\n\n // short-circuit\n var lineWidth = this._getLineWidth(ctx, lineIndex);\n if (this.textAlign !== 'justify' || this.width < lineWidth) {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n return;\n }\n\n // stretch the line\n var words = line.split(/\\s+/),\n charOffset = 0,\n wordsWidth = this._getWidthOfWords(ctx, words.join(' '), lineIndex, 0),\n widthDiff = this.width - wordsWidth,\n numSpaces = words.length - 1,\n spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,\n leftOffset = 0, word;\n\n for (var i = 0, len = words.length; i < len; i++) {\n while (line[charOffset] === ' ' && charOffset < line.length) {\n charOffset++;\n }\n word = words[i];\n this._renderChars(method, ctx, word, left + leftOffset, top, lineIndex, charOffset);\n leftOffset += this._getWidthOfWords(ctx, word, lineIndex, charOffset) + spaceWidth;\n charOffset += word.length;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} word\n */\n _getWidthOfWords: function (ctx, word) {\n var width = ctx.measureText(word).width, charCount, additionalSpace;\n if (this.charSpacing !== 0) {\n charCount = word.split('').length;\n additionalSpace = charCount * this._getWidthOfCharSpacing();\n width += additionalSpace;\n }\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @return {Number} Left offset\n */\n _getLeftOffset: function() {\n return -this.width / 2;\n },\n\n /**\n * @private\n * @return {Number} Top offset\n */\n _getTopOffset: function() {\n return -this.height / 2;\n },\n\n /**\n * Returns true because text has no style\n */\n isEmptyStyles: function() {\n return true;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n */\n _renderTextCommon: function(ctx, method) {\n\n var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n var heightOfLine = this._getHeightOfLine(ctx, i),\n maxHeight = heightOfLine / this.lineHeight,\n lineWidth = this._getLineWidth(ctx, i),\n leftOffset = this._getLineLeftOffset(lineWidth);\n this._renderTextLine(\n method,\n ctx,\n this._textLines[i],\n left + leftOffset,\n top + lineHeights + maxHeight,\n i\n );\n lineHeights += heightOfLine;\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextFill: function(ctx) {\n if (!this.fill && this.isEmptyStyles()) {\n return;\n }\n\n this._renderTextCommon(ctx, 'fillText');\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextStroke: function(ctx) {\n if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n this._setLineDash(ctx, this.strokeDashArray);\n ctx.beginPath();\n this._renderTextCommon(ctx, 'strokeText');\n ctx.closePath();\n ctx.restore();\n },\n\n /**\n * @private\n * @return {Number} height of line\n */\n _getHeightOfLine: function() {\n return this._getHeightOfSingleLine() * this.lineHeight;\n },\n\n /**\n * @private\n * @return {Number} height of line without lineHeight\n */\n _getHeightOfSingleLine: function() {\n return this.fontSize * this._fontSizeMult;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n if (!this.textBackgroundColor) {\n return;\n }\n var lineTopOffset = 0, heightOfLine,\n lineWidth, lineLeftOffset, originalFill = ctx.fillStyle;\n\n ctx.fillStyle = this.textBackgroundColor;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this._getHeightOfLine(ctx, i);\n lineWidth = this._getLineWidth(ctx, i);\n if (lineWidth > 0) {\n lineLeftOffset = this._getLineLeftOffset(lineWidth);\n ctx.fillRect(\n this._getLeftOffset() + lineLeftOffset,\n this._getTopOffset() + lineTopOffset,\n lineWidth,\n heightOfLine / this.lineHeight\n );\n }\n lineTopOffset += heightOfLine;\n }\n ctx.fillStyle = originalFill;\n // if there is text background color no\n // other shadows should be casted\n this._removeShadow(ctx);\n },\n\n /**\n * @private\n * @param {Number} lineWidth Width of text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset: function(lineWidth) {\n if (this.textAlign === 'center') {\n return (this.width - lineWidth) / 2;\n }\n if (this.textAlign === 'right') {\n return this.width - lineWidth;\n }\n return 0;\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.__lineWidths = [];\n this.__lineHeights = [];\n },\n\n /**\n * @private\n */\n _shouldClearDimensionCache: function() {\n var shouldClear = this._forceClearCache;\n shouldClear || (shouldClear = this.hasStateChanged('_dimensionAffectingProps'));\n if (shouldClear) {\n this.saveState({ propertySet: '_dimensionAffectingProps' });\n this.dirty = true;\n }\n return shouldClear;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _getLineWidth: function(ctx, lineIndex) {\n if (this.__lineWidths[lineIndex]) {\n return this.__lineWidths[lineIndex] === -1 ? this.width : this.__lineWidths[lineIndex];\n }\n\n var width, wordCount, line = this._textLines[lineIndex];\n\n if (line === '') {\n width = 0;\n }\n else {\n width = this._measureLine(ctx, lineIndex);\n }\n this.__lineWidths[lineIndex] = width;\n\n if (width && this.textAlign === 'justify') {\n wordCount = line.split(/\\s+/);\n if (wordCount.length > 1) {\n this.__lineWidths[lineIndex] = -1;\n }\n }\n return width;\n },\n\n _getWidthOfCharSpacing: function() {\n if (this.charSpacing !== 0) {\n return this.fontSize * this.charSpacing / 1000;\n }\n return 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _measureLine: function(ctx, lineIndex) {\n var line = this._textLines[lineIndex],\n width = ctx.measureText(line).width,\n additionalSpace = 0, charCount, finalWidth;\n if (this.charSpacing !== 0) {\n charCount = line.split('').length;\n additionalSpace = (charCount - 1) * this._getWidthOfCharSpacing();\n }\n finalWidth = width + additionalSpace;\n return finalWidth > 0 ? finalWidth : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (!this.textDecoration) {\n return;\n }\n var halfOfVerticalBox = this.height / 2,\n _this = this, offsets = [];\n\n /** @ignore */\n function renderLinesAtOffset(offsets) {\n var i, lineHeight = 0, len, j, oLen, lineWidth,\n lineLeftOffset, heightOfLine;\n\n for (i = 0, len = _this._textLines.length; i < len; i++) {\n\n lineWidth = _this._getLineWidth(ctx, i);\n lineLeftOffset = _this._getLineLeftOffset(lineWidth);\n heightOfLine = _this._getHeightOfLine(ctx, i);\n\n for (j = 0, oLen = offsets.length; j < oLen; j++) {\n ctx.fillRect(\n _this._getLeftOffset() + lineLeftOffset,\n lineHeight + (_this._fontSizeMult - 1 + offsets[j] ) * _this.fontSize - halfOfVerticalBox,\n lineWidth,\n _this.fontSize / 15);\n }\n lineHeight += heightOfLine;\n }\n }\n\n if (this.textDecoration.indexOf('underline') > -1) {\n offsets.push(0.85); // 1 - 3/16\n }\n if (this.textDecoration.indexOf('line-through') > -1) {\n offsets.push(0.43);\n }\n if (this.textDecoration.indexOf('overline') > -1) {\n offsets.push(-0.12);\n }\n if (offsets.length > 0) {\n renderLinesAtOffset(offsets);\n }\n },\n\n /**\n * return font declaration string for canvas context\n * @returns {String} font declaration formatted for canvas context.\n */\n _getFontDeclaration: function() {\n return [\n // node-canvas needs \"weight style\", while browsers need \"style weight\"\n (fabric.isLikelyNode ? this.fontWeight : this.fontStyle),\n (fabric.isLikelyNode ? this.fontStyle : this.fontWeight),\n this.fontSize + 'px',\n (fabric.isLikelyNode ? ('\"' + this.fontFamily + '\"') : this.fontFamily)\n ].join(' ');\n },\n\n /**\n * Renders text instance on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n render: function(ctx, noTransform) {\n // do not render if object is not visible\n if (!this.visible) {\n return;\n }\n if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {\n return;\n }\n if (this._shouldClearDimensionCache()) {\n this._setTextStyles(ctx);\n this._initDimensions(ctx);\n }\n this.callSuper('render', ctx, noTransform);\n },\n\n /**\n * Returns the text as an array of lines.\n * @returns {Array} Lines in the text\n */\n _splitTextIntoLines: function() {\n return this.text.split(this._reNewline);\n },\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n var additionalProperties = [\n 'text',\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n 'lineHeight',\n 'textDecoration',\n 'textAlign',\n 'textBackgroundColor',\n 'charSpacing'\n ].concat(propertiesToInclude);\n return this.callSuper('toObject', additionalProperties);\n },\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG: function(reviver) {\n if (!this.ctx) {\n this.ctx = fabric.util.createCanvasElement().getContext('2d');\n }\n var markup = this._createBaseSVGMarkup(),\n offsets = this._getSVGLeftTopOffsets(this.ctx),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n this._wrapSVGTextAndBg(markup, textAndBg);\n\n return reviver ? reviver(markup.join('')) : markup.join('');\n },\n\n /**\n * @private\n */\n _getSVGLeftTopOffsets: function(ctx) {\n var lineTop = this._getHeightOfLine(ctx, 0),\n textLeft = -this.width / 2,\n textTop = 0;\n\n return {\n textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0),\n textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0),\n lineTop: lineTop\n };\n },\n\n /**\n * @private\n */\n _wrapSVGTextAndBg: function(markup, textAndBg) {\n var noShadow = true, filter = this.getSvgFilter(),\n style = filter === '' ? '' : ' style=\"' + filter + '\"';\n\n markup.push(\n '\\t\\n',\n textAndBg.textBgRects.join(''),\n '\\t\\t\\n',\n textAndBg.textSpans.join(''),\n '\\t\\t\\n',\n '\\t\\n'\n );\n },\n\n getSvgStyles: function(skipShadow) {\n var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow);\n return svgStyle + ' white-space: pre;';\n },\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n _getSVGTextAndBg: function(textTopOffset, textLeftOffset) {\n var textSpans = [],\n textBgRects = [],\n height = 0;\n // bounding-box background\n this._setSVGBg(textBgRects);\n\n // text and text-background\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n if (this.textBackgroundColor) {\n this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height);\n }\n this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects);\n height += this._getHeightOfLine(this.ctx, i);\n }\n\n return {\n textSpans: textSpans,\n textBgRects: textBgRects\n };\n },\n\n _setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) {\n var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction)\n - textTopOffset + height - this.height / 2;\n if (this.textAlign === 'justify') {\n // i call from here to do not intefere with IText\n this._setSVGTextLineJustifed(i, textSpans, yPos, textLeftOffset);\n return;\n }\n textSpans.push(\n '\\t\\t\\t elements since setting opacity\n // on containing one doesn't work in Illustrator\n this._getFillAttributes(this.fill), '>',\n fabric.util.string.escapeXml(this._textLines[i]),\n '\\n'\n );\n },\n\n _setSVGTextLineJustifed: function(i, textSpans, yPos, textLeftOffset) {\n var ctx = fabric.util.createCanvasElement().getContext('2d');\n\n this._setTextStyles(ctx);\n\n var line = this._textLines[i],\n words = line.split(/\\s+/),\n wordsWidth = this._getWidthOfWords(ctx, words.join('')),\n widthDiff = this.width - wordsWidth,\n numSpaces = words.length - 1,\n spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,\n word, attributes = this._getFillAttributes(this.fill),\n len;\n\n textLeftOffset += this._getLineLeftOffset(this._getLineWidth(ctx, i));\n\n for (i = 0, len = words.length; i < len; i++) {\n word = words[i];\n textSpans.push(\n '\\t\\t\\t elements since setting opacity\n // on containing one doesn't work in Illustrator\n attributes, '>',\n fabric.util.string.escapeXml(word),\n '\\n'\n );\n textLeftOffset += this._getWidthOfWords(ctx, word) + spaceWidth;\n }\n },\n\n _setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) {\n textBgRects.push(\n '\\t\\t\\n');\n },\n\n _setSVGBg: function(textBgRects) {\n if (this.backgroundColor) {\n textBgRects.push(\n '\\t\\t\\n');\n }\n },\n\n /**\n * Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values\n * we work around it by \"moving\" alpha channel into opacity attribute and setting fill's alpha to 1\n *\n * @private\n * @param {*} value\n * @return {String}\n */\n _getFillAttributes: function(value) {\n var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';\n if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {\n return 'fill=\"' + value + '\"';\n }\n return 'opacity=\"' + fillColor.getAlpha() + '\" fill=\"' + fillColor.setAlpha(1).toRgb() + '\"';\n },\n /* _TO_SVG_END_ */\n\n /**\n * Sets specified property to a specified value\n * @param {String} key\n * @param {*} value\n * @return {fabric.Text} thisArg\n * @chainable\n */\n _set: function(key, value) {\n this.callSuper('_set', key, value);\n\n if (this._dimensionAffectingProps.indexOf(key) > -1) {\n this._initDimensions();\n this.setCoords();\n }\n },\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity\n */\n complexity: function() {\n return 1;\n }\n });\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})\n * @static\n * @memberOf fabric.Text\n * @see: http://www.w3.org/TR/SVG/text.html#TextElement\n */\n fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(\n 'x y dx dy font-family font-style font-weight font-size text-decoration text-anchor'.split(' '));\n\n /**\n * Default SVG font size\n * @static\n * @memberOf fabric.Text\n */\n fabric.Text.DEFAULT_SVG_FONT_SIZE = 16;\n\n /**\n * Returns fabric.Text instance from an SVG element (not yet implemented)\n * @static\n * @memberOf fabric.Text\n * @param {SVGElement} element Element to parse\n * @param {Object} [options] Options object\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromElement = function(element, options) {\n if (!element) {\n return null;\n }\n\n var parsedAttributes = fabric.parseAttributes(element, fabric.Text.ATTRIBUTE_NAMES);\n options = fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes);\n\n options.top = options.top || 0;\n options.left = options.left || 0;\n if ('dx' in parsedAttributes) {\n options.left += parsedAttributes.dx;\n }\n if ('dy' in parsedAttributes) {\n options.top += parsedAttributes.dy;\n }\n if (!('fontSize' in options)) {\n options.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n }\n\n if (!options.originX) {\n options.originX = 'left';\n }\n\n var textContent = '';\n\n // The XML is not properly parsed in IE9 so a workaround to get\n // textContent is through firstChild.data. Another workaround would be\n // to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n if (!('textContent' in element)) {\n if ('firstChild' in element && element.firstChild !== null) {\n if ('data' in element.firstChild && element.firstChild.data !== null) {\n textContent = element.firstChild.data;\n }\n }\n }\n else {\n textContent = element.textContent;\n }\n\n textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n\n var text = new fabric.Text(textContent, options),\n textHeightScaleFactor = text.getHeight() / text.height,\n lineHeightDiff = (text.height + text.strokeWidth) * text.lineHeight - text.height,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getHeight() + scaledDiff,\n offX = 0;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n top/left properties in Fabric correspond to center point of text bounding box\n */\n if (text.originX === 'left') {\n offX = text.getWidth() / 2;\n }\n if (text.originX === 'right') {\n offX = -text.getWidth() / 2;\n }\n text.set({\n left: text.getLeft() + offX,\n top: text.getTop() - textHeight / 2 + text.fontSize * (0.18 + text._fontSizeFraction) / text.lineHeight /* 0.3 is the old lineHeight */\n });\n\n return text;\n };\n /* _FROM_SVG_END_ */\n\n /**\n * Returns fabric.Text instance from an object representation\n * @static\n * @memberOf fabric.Text\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Text instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Text} Instance of fabric.Text\n */\n fabric.Text.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Text', object, callback, forceAsync, 'text');\n };\n\n fabric.util.createAccessors(fabric.Text);\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n var clone = fabric.util.object.clone;\n\n /**\n * IText class (introduced in v1.4) Events are also fired with \"text:\"\n * prefix when observing canvas.\n * @class fabric.IText\n * @extends fabric.Text\n * @mixes fabric.Observable\n *\n * @fires changed\n * @fires selection:changed\n * @fires editing:entered\n * @fires editing:exited\n *\n * @return {fabric.IText} thisArg\n * @see {@link fabric.IText#initialize} for constructor definition\n *\n *

Supported key combinations:

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

Supported mouse/touch combination

\n *
\n   *   Position cursor:                click/touch\n   *   Create selection:               click/touch & drag\n   *   Create selection:               click & shift + click\n   *   Select word:                    double click\n   *   Select line:                    triple click\n   * 
\n */\n fabric.IText = fabric.util.createClass(fabric.Text, fabric.Observable, /** @lends fabric.IText.prototype */ {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'i-text',\n\n /**\n * Index where text selection starts (or where cursor is when there is no selection)\n * @type Number\n * @default\n */\n selectionStart: 0,\n\n /**\n * Index where text selection ends\n * @type Number\n * @default\n */\n selectionEnd: 0,\n\n /**\n * Color of text selection\n * @type String\n * @default\n */\n selectionColor: 'rgba(17,119,255,0.3)',\n\n /**\n * Indicates whether text is in editing mode\n * @type Boolean\n * @default\n */\n isEditing: false,\n\n /**\n * Indicates whether a text can be edited\n * @type Boolean\n * @default\n */\n editable: true,\n\n /**\n * Border color of text object while it's in editing mode\n * @type String\n * @default\n */\n editingBorderColor: 'rgba(102,153,255,0.25)',\n\n /**\n * Width of cursor (in px)\n * @type Number\n * @default\n */\n cursorWidth: 2,\n\n /**\n * Color of default cursor (when not overwritten by character style)\n * @type String\n * @default\n */\n cursorColor: '#333',\n\n /**\n * Delay between cursor blink (in ms)\n * @type Number\n * @default\n */\n cursorDelay: 1000,\n\n /**\n * Duration of cursor fadein (in ms)\n * @type Number\n * @default\n */\n cursorDuration: 600,\n\n /**\n * Object containing character styles\n * (where top-level properties corresponds to line number and 2nd-level properties -- to char number in a line)\n * @type Object\n * @default\n */\n styles: null,\n\n /**\n * Indicates whether internal text char widths can be cached\n * @type Boolean\n * @default\n */\n caching: true,\n\n /**\n * @private\n */\n _reSpace: /\\s|\\n/,\n\n /**\n * @private\n */\n _currentCursorOpacity: 0,\n\n /**\n * @private\n */\n _selectionDirection: null,\n\n /**\n * @private\n */\n _abortCursorAnimation: false,\n\n /**\n * @private\n */\n __widthOfSpace: [],\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.IText} thisArg\n */\n initialize: function(text, options) {\n this.styles = options ? (options.styles || { }) : { };\n this.callSuper('initialize', text, options);\n this.initBehavior();\n },\n\n /**\n * @private\n */\n _clearCache: function() {\n this.callSuper('_clearCache');\n this.__widthOfSpace = [];\n },\n\n /**\n * Returns true if object has no styling\n */\n isEmptyStyles: function() {\n if (!this.styles) {\n return true;\n }\n var obj = this.styles;\n\n for (var p1 in obj) {\n for (var p2 in obj[p1]) {\n // eslint-disable-next-line no-unused-vars\n for (var p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n return true;\n },\n\n /**\n * Sets selection start (left boundary of a selection)\n * @param {Number} index Index to set selection start to\n */\n setSelectionStart: function(index) {\n index = Math.max(index, 0);\n this._updateAndFire('selectionStart', index);\n },\n\n /**\n * Sets selection end (right boundary of a selection)\n * @param {Number} index Index to set selection end to\n */\n setSelectionEnd: function(index) {\n index = Math.min(index, this.text.length);\n this._updateAndFire('selectionEnd', index);\n },\n\n /**\n * @private\n * @param {String} property 'selectionStart' or 'selectionEnd'\n * @param {Number} index new position of property\n */\n _updateAndFire: function(property, index) {\n if (this[property] !== index) {\n this._fireSelectionChanged();\n this[property] = index;\n }\n this._updateTextarea();\n },\n\n /**\n * Fires the even of selection changed\n * @private\n */\n _fireSelectionChanged: function() {\n this.fire('selection:changed');\n this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n },\n\n /**\n * Gets style of a current selection/cursor (at the start position)\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at\n * @return {Object} styles Style object at a specified (or current) index\n */\n getSelectionStyles: function(startIndex, endIndex) {\n\n if (arguments.length === 2) {\n var styles = [];\n for (var i = startIndex; i < endIndex; i++) {\n styles.push(this.getSelectionStyles(i));\n }\n return styles;\n }\n\n var loc = this.get2DCursorLocation(startIndex),\n style = this._getStyleDeclaration(loc.lineIndex, loc.charIndex);\n\n return style || {};\n },\n\n /**\n * Sets style of a current selection\n * @param {Object} [styles] Styles object\n * @return {fabric.IText} thisArg\n * @chainable\n */\n setSelectionStyles: function(styles) {\n if (this.selectionStart === this.selectionEnd) {\n this._extendStyles(this.selectionStart, styles);\n }\n else {\n for (var i = this.selectionStart; i < this.selectionEnd; i++) {\n this._extendStyles(i, styles);\n }\n }\n /* not included in _extendStyles to avoid clearing cache more than once */\n this._forceClearCache = true;\n return this;\n },\n\n /**\n * @private\n */\n _extendStyles: function(index, styles) {\n var loc = this.get2DCursorLocation(index);\n\n if (!this._getLineStyle(loc.lineIndex)) {\n this._setLineStyle(loc.lineIndex, {});\n }\n\n if (!this._getStyleDeclaration(loc.lineIndex, loc.charIndex)) {\n this._setStyleDeclaration(loc.lineIndex, loc.charIndex, {});\n }\n\n fabric.util.object.extend(this._getStyleDeclaration(loc.lineIndex, loc.charIndex), styles);\n },\n\n /**\n * Initialize text dimensions. Render all text on given context\n * or on a offscreen canvas to get the text width with measureText.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n * @param {CanvasRenderingContext2D} [ctx] Context to render on\n * @private\n */\n _initDimensions: function(ctx) {\n if (!ctx) {\n this.clearContextTop();\n }\n this.callSuper('_initDimensions', ctx);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Boolean} noTransform\n */\n render: function(ctx, noTransform) {\n this.clearContextTop();\n this.callSuper('render', ctx, noTransform);\n // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor\n // the correct position but not at every cursor animation.\n this.cursorOffsetCache = { };\n this.renderCursorOrSelection();\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render: function(ctx) {\n this.callSuper('_render', ctx);\n this.ctx = ctx;\n },\n\n /**\n * Prepare and clean the contextTop\n */\n clearContextTop: function() {\n if (!this.active || !this.isEditing) {\n return;\n }\n if (this.canvas && this.canvas.contextTop) {\n var ctx = this.canvas.contextTop;\n ctx.save();\n ctx.transform.apply(ctx, this.canvas.viewportTransform);\n this.transform(ctx);\n this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix);\n this._clearTextArea(ctx);\n ctx.restore();\n }\n },\n\n /**\n * Renders cursor or selection (depending on what exists)\n */\n renderCursorOrSelection: function() {\n if (!this.active || !this.isEditing) {\n return;\n }\n var chars = this.text.split(''),\n boundaries, ctx;\n if (this.canvas && this.canvas.contextTop) {\n ctx = this.canvas.contextTop;\n ctx.save();\n ctx.transform.apply(ctx, this.canvas.viewportTransform);\n this.transform(ctx);\n this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix);\n this._clearTextArea(ctx);\n }\n else {\n ctx = this.ctx;\n ctx.save();\n }\n if (this.selectionStart === this.selectionEnd) {\n boundaries = this._getCursorBoundaries(chars, 'cursor');\n this.renderCursor(boundaries, ctx);\n }\n else {\n boundaries = this._getCursorBoundaries(chars, 'selection');\n this.renderSelection(chars, boundaries, ctx);\n }\n ctx.restore();\n },\n\n _clearTextArea: function(ctx) {\n // we add 4 pixel, to be sure to do not leave any pixel out\n var width = this.width + 4, height = this.height + 4;\n ctx.clearRect(-width / 2, -height / 2, width, height);\n },\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n var len = this._textLines.length;\n for (var i = 0; i < len; i++) {\n if (selectionStart <= this._textLines[i].length) {\n return {\n lineIndex: i,\n charIndex: selectionStart\n };\n }\n selectionStart -= this._textLines[i].length + 1;\n }\n return {\n lineIndex: i - 1,\n charIndex: this._textLines[i - 1].length < selectionStart ? this._textLines[i - 1].length : selectionStart\n };\n },\n\n /**\n * Returns complete style of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Object} Character style\n */\n getCurrentCharStyle: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n\n return {\n fontSize: style && style.fontSize || this.fontSize,\n fill: style && style.fill || this.fill,\n textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor,\n textDecoration: style && style.textDecoration || this.textDecoration,\n fontFamily: style && style.fontFamily || this.fontFamily,\n fontWeight: style && style.fontWeight || this.fontWeight,\n fontStyle: style && style.fontStyle || this.fontStyle,\n stroke: style && style.stroke || this.stroke,\n strokeWidth: style && style.strokeWidth || this.strokeWidth\n };\n },\n\n /**\n * Returns fontSize of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {Number} Character font size\n */\n getCurrentCharFontSize: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * Returns color (fill) of char at the current cursor\n * @param {Number} lineIndex Line index\n * @param {Number} charIndex Char index\n * @return {String} Character color (fill)\n */\n getCurrentCharColor: function(lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex === 0 ? 0 : charIndex - 1);\n return style && style.fill ? style.fill : this.cursorColor;\n },\n\n /**\n * Returns cursor boundaries (left, top, leftOffset, topOffset)\n * @private\n * @param {Array} chars Array of characters\n * @param {String} typeOfBoundaries\n */\n _getCursorBoundaries: function(chars, typeOfBoundaries) {\n\n // left/top are left/top of entire text box\n // leftOffset/topOffset are offset from that left/top point of a text box\n\n var left = Math.round(this._getLeftOffset()),\n top = this._getTopOffset(),\n\n offsets = this._getCursorBoundariesOffsets(\n chars, typeOfBoundaries);\n\n return {\n left: left,\n top: top,\n leftOffset: offsets.left + offsets.lineLeft,\n topOffset: offsets.top\n };\n },\n\n /**\n * @private\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n return this.cursorOffsetCache;\n }\n var lineLeftOffset = 0,\n lineIndex = 0,\n charIndex = 0,\n topOffset = 0,\n leftOffset = 0,\n boundaries;\n\n for (var i = 0; i < this.selectionStart; i++) {\n if (chars[i] === '\\n') {\n leftOffset = 0;\n topOffset += this._getHeightOfLine(this.ctx, lineIndex);\n\n lineIndex++;\n charIndex = 0;\n }\n else {\n leftOffset += this._getWidthOfChar(this.ctx, chars[i], lineIndex, charIndex);\n charIndex++;\n }\n\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex));\n }\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight\n - this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction);\n }\n if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {\n leftOffset -= this._getWidthOfCharSpacing();\n }\n boundaries = {\n top: topOffset,\n left: leftOffset > 0 ? leftOffset : 0,\n lineLeft: lineLeftOffset\n };\n this.cursorOffsetCache = boundaries;\n return this.cursorOffsetCache;\n },\n\n /**\n * Renders cursor\n * @param {Object} boundaries\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderCursor: function(boundaries, ctx) {\n\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getCurrentCharFontSize(lineIndex, charIndex),\n leftOffset = boundaries.leftOffset,\n multiplier = this.scaleX * this.canvas.getZoom(),\n cursorWidth = this.cursorWidth / multiplier;\n\n ctx.fillStyle = this.getCurrentCharColor(lineIndex, charIndex);\n ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity;\n\n ctx.fillRect(\n boundaries.left + leftOffset - cursorWidth / 2,\n boundaries.top + boundaries.topOffset,\n cursorWidth,\n charHeight);\n },\n\n /**\n * Renders text selection\n * @param {Array} chars Array of characters\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderSelection: function(chars, boundaries, ctx) {\n\n ctx.fillStyle = this.selectionColor;\n\n var start = this.get2DCursorLocation(this.selectionStart),\n end = this.get2DCursorLocation(this.selectionEnd),\n startLine = start.lineIndex,\n endLine = end.lineIndex;\n for (var i = startLine; i <= endLine; i++) {\n var lineOffset = this._getLineLeftOffset(this._getLineWidth(ctx, i)) || 0,\n lineHeight = this._getHeightOfLine(this.ctx, i),\n realLineHeight = 0, boxWidth = 0, line = this._textLines[i];\n\n if (i === startLine) {\n for (var j = 0, len = line.length; j < len; j++) {\n if (j >= start.charIndex && (i !== endLine || j < end.charIndex)) {\n boxWidth += this._getWidthOfChar(ctx, line[j], i, j);\n }\n if (j < start.charIndex) {\n lineOffset += this._getWidthOfChar(ctx, line[j], i, j);\n }\n }\n if (j === line.length) {\n boxWidth -= this._getWidthOfCharSpacing();\n }\n }\n else if (i > startLine && i < endLine) {\n boxWidth += this._getLineWidth(ctx, i) || 5;\n }\n else if (i === endLine) {\n for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) {\n boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2);\n }\n if (end.charIndex === line.length) {\n boxWidth -= this._getWidthOfCharSpacing();\n }\n }\n realLineHeight = lineHeight;\n if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {\n lineHeight /= this.lineHeight;\n }\n ctx.fillRect(\n boundaries.left + lineOffset,\n boundaries.top + boundaries.topOffset,\n boxWidth > 0 ? boxWidth : 0,\n lineHeight);\n\n boundaries.topOffset += realLineHeight;\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Content of the line\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n * @param {Number} charOffset\n */\n _renderChars: function(method, ctx, line, left, top, lineIndex, charOffset) {\n\n if (this.isEmptyStyles()) {\n return this._renderCharsFast(method, ctx, line, left, top);\n }\n\n charOffset = charOffset || 0;\n\n // set proper line offset\n var lineHeight = this._getHeightOfLine(ctx, lineIndex),\n prevStyle,\n thisStyle,\n charsToRender = '';\n\n ctx.save();\n top -= lineHeight / this.lineHeight * this._fontSizeFraction;\n for (var i = charOffset, len = line.length + charOffset; i <= len; i++) {\n prevStyle = prevStyle || this.getCurrentCharStyle(lineIndex, i);\n thisStyle = this.getCurrentCharStyle(lineIndex, i + 1);\n\n if (this._hasStyleChanged(prevStyle, thisStyle) || i === len) {\n this._renderChar(method, ctx, lineIndex, i - 1, charsToRender, left, top, lineHeight);\n charsToRender = '';\n prevStyle = thisStyle;\n }\n charsToRender += line[i - charOffset];\n }\n ctx.restore();\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Content of the line\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n */\n _renderCharsFast: function(method, ctx, line, left, top) {\n\n if (method === 'fillText' && this.fill) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n if (method === 'strokeText' && ((this.stroke && this.strokeWidth > 0) || this.skipFillStrokeCheck)) {\n this.callSuper('_renderChars', method, ctx, line, left, top);\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} i\n * @param {String} _char\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n * @param {Number} lineHeight Height of the line\n */\n _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) {\n var charWidth, charHeight, shouldFill, shouldStroke,\n decl = this._getStyleDeclaration(lineIndex, i),\n offset, textDecoration, chars, additionalSpace, _charWidth;\n\n if (decl) {\n charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i);\n shouldStroke = decl.stroke;\n shouldFill = decl.fill;\n textDecoration = decl.textDecoration;\n }\n else {\n charHeight = this.fontSize;\n }\n\n shouldStroke = (shouldStroke || this.stroke) && method === 'strokeText';\n shouldFill = (shouldFill || this.fill) && method === 'fillText';\n\n decl && ctx.save();\n\n charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || null);\n textDecoration = textDecoration || this.textDecoration;\n\n if (decl && decl.textBackgroundColor) {\n this._removeShadow(ctx);\n }\n if (this.charSpacing !== 0) {\n additionalSpace = this._getWidthOfCharSpacing();\n chars = _char.split('');\n charWidth = 0;\n for (var j = 0, len = chars.length, jChar; j < len; j++) {\n jChar = chars[j];\n shouldFill && ctx.fillText(jChar, left + charWidth, top);\n shouldStroke && ctx.strokeText(jChar, left + charWidth, top);\n _charWidth = ctx.measureText(jChar).width + additionalSpace;\n charWidth += _charWidth > 0 ? _charWidth : 0;\n }\n }\n else {\n shouldFill && ctx.fillText(_char, left, top);\n shouldStroke && ctx.strokeText(_char, left, top);\n }\n\n if (textDecoration || textDecoration !== '') {\n offset = this._fontSizeFraction * lineHeight / this.lineHeight;\n this._renderCharDecoration(ctx, textDecoration, left, top, offset, charWidth, charHeight);\n }\n\n decl && ctx.restore();\n ctx.translate(charWidth, 0);\n },\n\n /**\n * @private\n * @param {Object} prevStyle\n * @param {Object} thisStyle\n */\n _hasStyleChanged: function(prevStyle, thisStyle) {\n return (prevStyle.fill !== thisStyle.fill ||\n prevStyle.fontSize !== thisStyle.fontSize ||\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.textDecoration !== thisStyle.textDecoration ||\n prevStyle.fontFamily !== thisStyle.fontFamily ||\n prevStyle.fontWeight !== thisStyle.fontWeight ||\n prevStyle.fontStyle !== thisStyle.fontStyle ||\n prevStyle.stroke !== thisStyle.stroke ||\n prevStyle.strokeWidth !== thisStyle.strokeWidth\n );\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderCharDecoration: function(ctx, textDecoration, left, top, offset, charWidth, charHeight) {\n\n if (!textDecoration) {\n return;\n }\n\n var decorationWeight = charHeight / 15,\n positions = {\n underline: top + charHeight / 10,\n 'line-through': top - charHeight * (this._fontSizeFraction + this._fontSizeMult - 1) + decorationWeight,\n overline: top - (this._fontSizeMult - this._fontSizeFraction) * charHeight\n },\n decorations = ['underline', 'line-through', 'overline'], i, decoration;\n\n for (i = 0; i < decorations.length; i++) {\n decoration = decorations[i];\n if (textDecoration.indexOf(decoration) > -1) {\n ctx.fillRect(left, positions[decoration], charWidth , decorationWeight);\n }\n }\n },\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n */\n _renderTextLine: function(method, ctx, line, left, top, lineIndex) {\n // to \"cancel\" this.fontSize subtraction in fabric.Text#_renderTextLine\n // the adding 0.03 is just to align text with itext by overlap test\n if (!this.isEmptyStyles()) {\n top += this.fontSize * (this._fontSizeFraction + 0.03);\n }\n this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex);\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration: function(ctx) {\n if (this.isEmptyStyles()) {\n return this.callSuper('_renderTextDecoration', ctx);\n }\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground: function(ctx) {\n this.callSuper('_renderTextLinesBackground', ctx);\n\n var lineTopOffset = 0, heightOfLine,\n lineWidth, lineLeftOffset,\n leftOffset = this._getLeftOffset(),\n topOffset = this._getTopOffset(),\n colorCache = '',\n line, _char, style, leftCache,\n topCache, widthCache, heightCache;\n ctx.save();\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n heightOfLine = this._getHeightOfLine(ctx, i);\n line = this._textLines[i];\n\n if (line === '' || !this.styles || !this._getLineStyle(i)) {\n lineTopOffset += heightOfLine;\n continue;\n }\n\n lineWidth = this._getLineWidth(ctx, i);\n lineLeftOffset = this._getLineLeftOffset(lineWidth);\n leftCache = topCache = widthCache = heightCache = 0;\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n style = this._getStyleDeclaration(i, j) || {};\n\n if (colorCache !== style.textBackgroundColor) {\n if (heightCache && widthCache) {\n ctx.fillStyle = colorCache;\n ctx.fillRect(leftCache, topCache, widthCache, heightCache);\n }\n leftCache = topCache = widthCache = heightCache = 0;\n colorCache = style.textBackgroundColor || '';\n }\n\n if (!style.textBackgroundColor) {\n colorCache = '';\n continue;\n }\n _char = line[j];\n\n if (colorCache === style.textBackgroundColor) {\n colorCache = style.textBackgroundColor;\n if (!leftCache) {\n leftCache = leftOffset + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j);\n }\n topCache = topOffset + lineTopOffset;\n widthCache += this._getWidthOfChar(ctx, _char, i, j);\n heightCache = heightOfLine / this.lineHeight;\n }\n }\n // if a textBackgroundColor ends on the last character of a line\n if (heightCache && widthCache) {\n ctx.fillStyle = colorCache;\n ctx.fillRect(leftCache, topCache, widthCache, heightCache);\n leftCache = topCache = widthCache = heightCache = 0;\n }\n lineTopOffset += heightOfLine;\n }\n ctx.restore();\n },\n\n /**\n * @private\n */\n _getCacheProp: function(_char, styleDeclaration) {\n return _char +\n styleDeclaration.fontSize +\n styleDeclaration.fontWeight +\n styleDeclaration.fontStyle;\n },\n\n /**\n * @private\n * @param {String} fontFamily name\n * @return {Object} reference to cache\n */\n _getFontCache: function(fontFamily) {\n if (!fabric.charWidthsCache[fontFamily]) {\n fabric.charWidthsCache[fontFamily] = { };\n }\n return fabric.charWidthsCache[fontFamily];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} _char\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} [decl]\n */\n _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) {\n var charDecl = decl || this._getStyleDeclaration(lineIndex, charIndex),\n styleDeclaration = clone(charDecl),\n width, cacheProp, charWidthsCache;\n\n this._applyFontStyles(styleDeclaration);\n charWidthsCache = this._getFontCache(styleDeclaration.fontFamily);\n cacheProp = this._getCacheProp(_char, styleDeclaration);\n\n // short-circuit if no styles for this char\n // global style from object is always applyed and handled by save and restore\n if (!charDecl && charWidthsCache[cacheProp] && this.caching) {\n return charWidthsCache[cacheProp];\n }\n\n if (typeof styleDeclaration.shadow === 'string') {\n styleDeclaration.shadow = new fabric.Shadow(styleDeclaration.shadow);\n }\n\n var fill = styleDeclaration.fill || this.fill;\n ctx.fillStyle = fill.toLive\n ? fill.toLive(ctx, this)\n : fill;\n\n if (styleDeclaration.stroke) {\n ctx.strokeStyle = (styleDeclaration.stroke && styleDeclaration.stroke.toLive)\n ? styleDeclaration.stroke.toLive(ctx, this)\n : styleDeclaration.stroke;\n }\n\n ctx.lineWidth = styleDeclaration.strokeWidth || this.strokeWidth;\n ctx.font = this._getFontDeclaration.call(styleDeclaration);\n\n //if we want this._setShadow.call to work with styleDeclarion\n //we have to add those references\n if (styleDeclaration.shadow) {\n styleDeclaration.scaleX = this.scaleX;\n styleDeclaration.scaleY = this.scaleY;\n styleDeclaration.canvas = this.canvas;\n styleDeclaration.getObjectScaling = this.getObjectScaling;\n this._setShadow.call(styleDeclaration, ctx);\n }\n\n if (!this.caching || !charWidthsCache[cacheProp]) {\n width = ctx.measureText(_char).width;\n this.caching && (charWidthsCache[cacheProp] = width);\n return width;\n }\n\n return charWidthsCache[cacheProp];\n },\n\n /**\n * @private\n * @param {Object} styleDeclaration\n */\n _applyFontStyles: function(styleDeclaration) {\n if (!styleDeclaration.fontFamily) {\n styleDeclaration.fontFamily = this.fontFamily;\n }\n if (!styleDeclaration.fontSize) {\n styleDeclaration.fontSize = this.fontSize;\n }\n if (!styleDeclaration.fontWeight) {\n styleDeclaration.fontWeight = this.fontWeight;\n }\n if (!styleDeclaration.fontStyle) {\n styleDeclaration.fontStyle = this.fontStyle;\n }\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (returnCloneOrEmpty) {\n return (this.styles[lineIndex] && this.styles[lineIndex][charIndex])\n ? clone(this.styles[lineIndex][charIndex])\n : { };\n }\n\n return this.styles[lineIndex] && this.styles[lineIndex][charIndex] ? this.styles[lineIndex][charIndex] : null;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n _setStyleDeclaration: function(lineIndex, charIndex, style) {\n this.styles[lineIndex][charIndex] = style;\n },\n\n /**\n *\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n _deleteStyleDeclaration: function(lineIndex, charIndex) {\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _getLineStyle: function(lineIndex) {\n return this.styles[lineIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n this.styles[lineIndex] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n delete this.styles[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) {\n if (!this._isMeasuring && this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) {\n return this._getWidthOfSpace(ctx, lineIndex);\n }\n ctx.save();\n var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex);\n if (this.charSpacing !== 0) {\n width += this._getWidthOfCharSpacing();\n }\n ctx.restore();\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n */\n _getHeightOfChar: function(ctx, lineIndex, charIndex) {\n var style = this._getStyleDeclaration(lineIndex, charIndex);\n return style && style.fontSize ? style.fontSize : this.fontSize;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n */\n _getWidthOfCharsAt: function(ctx, lineIndex, charIndex) {\n var width = 0, i, _char;\n for (i = 0; i < charIndex; i++) {\n _char = this._textLines[lineIndex][i];\n width += this._getWidthOfChar(ctx, _char, lineIndex, i);\n }\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n _measureLine: function(ctx, lineIndex) {\n this._isMeasuring = true;\n var width = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length);\n if (this.charSpacing !== 0) {\n width -= this._getWidthOfCharSpacing();\n }\n this._isMeasuring = false;\n return width > 0 ? width : 0;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n */\n _getWidthOfSpace: function (ctx, lineIndex) {\n if (this.__widthOfSpace[lineIndex]) {\n return this.__widthOfSpace[lineIndex];\n }\n var line = this._textLines[lineIndex],\n wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0),\n widthDiff = this.width - wordsWidth,\n numSpaces = line.length - line.replace(this._reSpacesAndTabs, '').length,\n width = Math.max(widthDiff / numSpaces, ctx.measureText(' ').width);\n this.__widthOfSpace[lineIndex] = width;\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line\n * @param {Number} lineIndex\n * @param {Number} charOffset\n */\n _getWidthOfWords: function (ctx, line, lineIndex, charOffset) {\n var width = 0;\n\n for (var charIndex = 0; charIndex < line.length; charIndex++) {\n var _char = line[charIndex];\n\n if (!_char.match(/\\s/)) {\n width += this._getWidthOfChar(ctx, _char, lineIndex, charIndex + charOffset);\n }\n }\n\n return width;\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getHeightOfLine: function(ctx, lineIndex) {\n if (this.__lineHeights[lineIndex]) {\n return this.__lineHeights[lineIndex];\n }\n\n var line = this._textLines[lineIndex],\n maxHeight = this._getHeightOfChar(ctx, lineIndex, 0);\n\n for (var i = 1, len = line.length; i < len; i++) {\n var currentCharHeight = this._getHeightOfChar(ctx, lineIndex, i);\n if (currentCharHeight > maxHeight) {\n maxHeight = currentCharHeight;\n }\n }\n this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;\n return this.__lineHeights[lineIndex];\n },\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _getTextHeight: function(ctx) {\n var lineHeight, height = 0;\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n lineHeight = this._getHeightOfLine(ctx, i);\n height += (i === len - 1 ? lineHeight / this.lineHeight : lineHeight);\n }\n return height;\n },\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {\n styles: clone(this.styles, true)\n });\n }\n });\n\n /**\n * Returns fabric.IText instance from an object representation\n * @static\n * @memberOf fabric.IText\n * @param {Object} object Object to create an instance from\n * @param {function} [callback] invoked with new instance as argument\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.IText} instance of fabric.IText\n */\n fabric.IText.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('IText', object, callback, forceAsync, 'text');\n };\n})();\n\n\n(function() {\n\n var clone = fabric.util.object.clone;\n\n fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * Initializes all the interactive behavior of IText\n */\n initBehavior: function() {\n this.initAddedHandler();\n this.initRemovedHandler();\n this.initCursorSelectionHandlers();\n this.initDoubleClickSimulation();\n this.mouseMoveHandler = this.mouseMoveHandler.bind(this);\n },\n\n onDeselect: function() {\n this.isEditing && this.exitEditing();\n this.selected = false;\n this.callSuper('onDeselect');\n },\n\n /**\n * Initializes \"added\" event handler\n */\n initAddedHandler: function() {\n var _this = this;\n this.on('added', function() {\n var canvas = _this.canvas;\n if (canvas) {\n if (!canvas._hasITextHandlers) {\n canvas._hasITextHandlers = true;\n _this._initCanvasHandlers(canvas);\n }\n canvas._iTextInstances = canvas._iTextInstances || [];\n canvas._iTextInstances.push(_this);\n }\n });\n },\n\n initRemovedHandler: function() {\n var _this = this;\n this.on('removed', function() {\n var canvas = _this.canvas;\n if (canvas) {\n canvas._iTextInstances = canvas._iTextInstances || [];\n fabric.util.removeFromArray(canvas._iTextInstances, _this);\n if (canvas._iTextInstances.length === 0) {\n canvas._hasITextHandlers = false;\n _this._removeCanvasHandlers(canvas);\n }\n }\n });\n },\n\n /**\n * register canvas event to manage exiting on other instances\n * @private\n */\n _initCanvasHandlers: function(canvas) {\n canvas._mouseUpITextHandler = (function() {\n if (canvas._iTextInstances) {\n canvas._iTextInstances.forEach(function(obj) {\n obj.__isMousedown = false;\n });\n }\n }).bind(this);\n canvas.on('mouse:up', canvas._mouseUpITextHandler);\n },\n\n /**\n * remove canvas event to manage exiting on other instances\n * @private\n */\n _removeCanvasHandlers: function(canvas) {\n canvas.off('mouse:up', canvas._mouseUpITextHandler);\n },\n\n /**\n * @private\n */\n _tick: function() {\n this._currentTickState = this._animateCursor(this, 1, this.cursorDuration, '_onTickComplete');\n },\n\n /**\n * @private\n */\n _animateCursor: function(obj, targetOpacity, duration, completeMethod) {\n\n var tickState;\n\n tickState = {\n isAborted: false,\n abort: function() {\n this.isAborted = true;\n },\n };\n\n obj.animate('_currentCursorOpacity', targetOpacity, {\n duration: duration,\n onComplete: function() {\n if (!tickState.isAborted) {\n obj[completeMethod]();\n }\n },\n onChange: function() {\n // we do not want to animate a selection, only cursor\n if (obj.canvas && obj.selectionStart === obj.selectionEnd) {\n obj.renderCursorOrSelection();\n }\n },\n abort: function() {\n return tickState.isAborted;\n }\n });\n return tickState;\n },\n\n /**\n * @private\n */\n _onTickComplete: function() {\n\n var _this = this;\n\n if (this._cursorTimeout1) {\n clearTimeout(this._cursorTimeout1);\n }\n this._cursorTimeout1 = setTimeout(function() {\n _this._currentTickCompleteState = _this._animateCursor(_this, 0, this.cursorDuration / 2, '_tick');\n }, 100);\n },\n\n /**\n * Initializes delayed cursor\n */\n initDelayedCursor: function(restart) {\n var _this = this,\n delay = restart ? 0 : this.cursorDelay;\n\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n this._cursorTimeout2 = setTimeout(function() {\n _this._tick();\n }, delay);\n },\n\n /**\n * Aborts cursor animation and clears all timeouts\n */\n abortCursorAnimation: function() {\n var shouldClear = this._currentTickState || this._currentTickCompleteState;\n this._currentTickState && this._currentTickState.abort();\n this._currentTickCompleteState && this._currentTickCompleteState.abort();\n\n clearTimeout(this._cursorTimeout1);\n clearTimeout(this._cursorTimeout2);\n\n this._currentCursorOpacity = 0;\n // to clear just itext area we need to transform the context\n // it may not be worth it\n if (shouldClear) {\n this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);\n }\n\n },\n\n /**\n * Selects entire text\n */\n selectAll: function() {\n this.selectionStart = 0;\n this.selectionEnd = this.text.length;\n this._fireSelectionChanged();\n this._updateTextarea();\n },\n\n /**\n * Returns selected text\n * @return {String}\n */\n getSelectedText: function() {\n return this.text.slice(this.selectionStart, this.selectionEnd);\n },\n\n /**\n * Find new selection index representing start of current word according to current selection index\n * @param {Number} startFrom Surrent selection index\n * @return {Number} New selection index\n */\n findWordBoundaryLeft: function(startFrom) {\n var offset = 0, index = startFrom - 1;\n\n // remove space before cursor first\n if (this._reSpace.test(this.text.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index--;\n }\n }\n while (/\\S/.test(this.text.charAt(index)) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n },\n\n /**\n * Find new selection index representing end of current word according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findWordBoundaryRight: function(startFrom) {\n var offset = 0, index = startFrom;\n\n // remove space after cursor first\n if (this._reSpace.test(this.text.charAt(index))) {\n while (this._reSpace.test(this.text.charAt(index))) {\n offset++;\n index++;\n }\n }\n while (/\\S/.test(this.text.charAt(index)) && index < this.text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Find new selection index representing start of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryLeft: function(startFrom) {\n var offset = 0, index = startFrom - 1;\n\n while (!/\\n/.test(this.text.charAt(index)) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n },\n\n /**\n * Find new selection index representing end of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryRight: function(startFrom) {\n var offset = 0, index = startFrom;\n\n while (!/\\n/.test(this.text.charAt(index)) && index < this.text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n },\n\n /**\n * Returns number of newlines in selected text\n * @return {Number} Number of newlines in selected text\n */\n getNumNewLinesInSelectedText: function() {\n var selectedText = this.getSelectedText(),\n numNewLines = 0;\n\n for (var i = 0, len = selectedText.length; i < len; i++) {\n if (selectedText[i] === '\\n') {\n numNewLines++;\n }\n }\n return numNewLines;\n },\n\n /**\n * Finds index corresponding to beginning or end of a word\n * @param {Number} selectionStart Index of a character\n * @param {Number} direction 1 or -1\n * @return {Number} Index of the beginning or end of a word\n */\n searchWordBoundary: function(selectionStart, direction) {\n var index = this._reSpace.test(this.text.charAt(selectionStart)) ? selectionStart - 1 : selectionStart,\n _char = this.text.charAt(index),\n reNonWord = /[ \\n\\.,;!\\?\\-]/;\n\n while (!reNonWord.test(_char) && index > 0 && index < this.text.length) {\n index += direction;\n _char = this.text.charAt(index);\n }\n if (reNonWord.test(_char) && _char !== '\\n') {\n index += direction === 1 ? 0 : 1;\n }\n return index;\n },\n\n /**\n * Selects a word based on the index\n * @param {Number} selectionStart Index of a character\n */\n selectWord: function(selectionStart) {\n selectionStart = selectionStart || this.selectionStart;\n var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */\n newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */\n\n this.selectionStart = newSelectionStart;\n this.selectionEnd = newSelectionEnd;\n this._fireSelectionChanged();\n this._updateTextarea();\n this.renderCursorOrSelection();\n },\n\n /**\n * Selects a line based on the index\n * @param {Number} selectionStart Index of a character\n */\n selectLine: function(selectionStart) {\n selectionStart = selectionStart || this.selectionStart;\n var newSelectionStart = this.findLineBoundaryLeft(selectionStart),\n newSelectionEnd = this.findLineBoundaryRight(selectionStart);\n\n this.selectionStart = newSelectionStart;\n this.selectionEnd = newSelectionEnd;\n this._fireSelectionChanged();\n this._updateTextarea();\n },\n\n /**\n * Enters editing state\n * @return {fabric.IText} thisArg\n * @chainable\n */\n enterEditing: function(e) {\n if (this.isEditing || !this.editable) {\n return;\n }\n\n if (this.canvas) {\n this.exitEditingOnOthers(this.canvas);\n }\n\n this.isEditing = true;\n this.selected = true;\n this.initHiddenTextarea(e);\n this.hiddenTextarea.focus();\n this._updateTextarea();\n this._saveEditingProps();\n this._setEditingProps();\n this._textBeforeEdit = this.text;\n\n this._tick();\n this.fire('editing:entered');\n this._fireSelectionChanged();\n if (!this.canvas) {\n return this;\n }\n this.canvas.fire('text:editing:entered', { target: this });\n this.initMouseMoveHandler();\n this.canvas.renderAll();\n return this;\n },\n\n exitEditingOnOthers: function(canvas) {\n if (canvas._iTextInstances) {\n canvas._iTextInstances.forEach(function(obj) {\n obj.selected = false;\n if (obj.isEditing) {\n obj.exitEditing();\n }\n });\n }\n },\n\n /**\n * Initializes \"mousemove\" event handler\n */\n initMouseMoveHandler: function() {\n this.canvas.on('mouse:move', this.mouseMoveHandler);\n },\n\n /**\n * @private\n */\n mouseMoveHandler: function(options) {\n if (!this.__isMousedown || !this.isEditing) {\n return;\n }\n\n var newSelectionStart = this.getSelectionStartFromPointer(options.e),\n currentStart = this.selectionStart,\n currentEnd = this.selectionEnd;\n if (\n (newSelectionStart !== this.__selectionStartOnMouseDown || currentStart === currentEnd)\n &&\n (currentStart === newSelectionStart || currentEnd === newSelectionStart)\n ) {\n return;\n }\n if (newSelectionStart > this.__selectionStartOnMouseDown) {\n this.selectionStart = this.__selectionStartOnMouseDown;\n this.selectionEnd = newSelectionStart;\n }\n else {\n this.selectionStart = newSelectionStart;\n this.selectionEnd = this.__selectionStartOnMouseDown;\n }\n if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) {\n this.restartCursorIfNeeded();\n this._fireSelectionChanged();\n this._updateTextarea();\n this.renderCursorOrSelection();\n }\n },\n\n /**\n * @private\n */\n _setEditingProps: function() {\n this.hoverCursor = 'text';\n\n if (this.canvas) {\n this.canvas.defaultCursor = this.canvas.moveCursor = 'text';\n }\n\n this.borderColor = this.editingBorderColor;\n\n this.hasControls = this.selectable = false;\n this.lockMovementX = this.lockMovementY = true;\n },\n\n /**\n * @private\n */\n _updateTextarea: function() {\n if (!this.hiddenTextarea || this.inCompositionMode) {\n return;\n }\n this.cursorOffsetCache = { };\n this.hiddenTextarea.value = this.text;\n this.hiddenTextarea.selectionStart = this.selectionStart;\n this.hiddenTextarea.selectionEnd = this.selectionEnd;\n if (this.selectionStart === this.selectionEnd) {\n var style = this._calcTextareaPosition();\n this.hiddenTextarea.style.left = style.left;\n this.hiddenTextarea.style.top = style.top;\n this.hiddenTextarea.style.fontSize = style.fontSize;\n }\n },\n\n /**\n * @private\n * @return {Object} style contains style for hiddenTextarea\n */\n _calcTextareaPosition: function() {\n if (!this.canvas) {\n return { x: 1, y: 1 };\n }\n var chars = this.text.split(''),\n boundaries = this._getCursorBoundaries(chars, 'cursor'),\n cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight = this.getCurrentCharFontSize(lineIndex, charIndex),\n leftOffset = boundaries.leftOffset,\n m = this.calcTransformMatrix(),\n p = {\n x: boundaries.left + leftOffset,\n y: boundaries.top + boundaries.topOffset + charHeight\n },\n upperCanvas = this.canvas.upperCanvasEl,\n maxWidth = upperCanvas.width - charHeight,\n maxHeight = upperCanvas.height - charHeight;\n\n p = fabric.util.transformPoint(p, m);\n p = fabric.util.transformPoint(p, this.canvas.viewportTransform);\n\n if (p.x < 0) {\n p.x = 0;\n }\n if (p.x > maxWidth) {\n p.x = maxWidth;\n }\n if (p.y < 0) {\n p.y = 0;\n }\n if (p.y > maxHeight) {\n p.y = maxHeight;\n }\n\n // add canvas offset on document\n p.x += this.canvas._offset.left;\n p.y += this.canvas._offset.top;\n\n return { left: p.x + 'px', top: p.y + 'px', fontSize: charHeight };\n },\n\n /**\n * @private\n */\n _saveEditingProps: function() {\n this._savedProps = {\n hasControls: this.hasControls,\n borderColor: this.borderColor,\n lockMovementX: this.lockMovementX,\n lockMovementY: this.lockMovementY,\n hoverCursor: this.hoverCursor,\n defaultCursor: this.canvas && this.canvas.defaultCursor,\n moveCursor: this.canvas && this.canvas.moveCursor\n };\n },\n\n /**\n * @private\n */\n _restoreEditingProps: function() {\n if (!this._savedProps) {\n return;\n }\n\n this.hoverCursor = this._savedProps.overCursor;\n this.hasControls = this._savedProps.hasControls;\n this.borderColor = this._savedProps.borderColor;\n this.lockMovementX = this._savedProps.lockMovementX;\n this.lockMovementY = this._savedProps.lockMovementY;\n\n if (this.canvas) {\n this.canvas.defaultCursor = this._savedProps.defaultCursor;\n this.canvas.moveCursor = this._savedProps.moveCursor;\n }\n },\n\n /**\n * Exits from editing state\n * @return {fabric.IText} thisArg\n * @chainable\n */\n exitEditing: function() {\n var isTextChanged = (this._textBeforeEdit !== this.text);\n this.selected = false;\n this.isEditing = false;\n this.selectable = true;\n\n this.selectionEnd = this.selectionStart;\n\n if (this.hiddenTextarea) {\n this.hiddenTextarea.blur && this.hiddenTextarea.blur();\n this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea);\n this.hiddenTextarea = null;\n }\n\n this.abortCursorAnimation();\n this._restoreEditingProps();\n this._currentCursorOpacity = 0;\n\n this.fire('editing:exited');\n isTextChanged && this.fire('modified');\n if (this.canvas) {\n this.canvas.off('mouse:move', this.mouseMoveHandler);\n this.canvas.fire('text:editing:exited', { target: this });\n isTextChanged && this.canvas.fire('object:modified', { target: this });\n }\n return this;\n },\n\n /**\n * @private\n */\n _removeExtraneousStyles: function() {\n for (var prop in this.styles) {\n if (!this._textLines[prop]) {\n delete this.styles[prop];\n }\n }\n },\n\n /**\n * @private\n */\n _removeCharsFromTo: function(start, end) {\n while (end !== start) {\n this._removeSingleCharAndStyle(start + 1);\n end--;\n }\n this.selectionStart = start;\n this.selectionEnd = start;\n },\n\n _removeSingleCharAndStyle: function(index) {\n var isBeginningOfLine = this.text[index - 1] === '\\n',\n indexStyle = isBeginningOfLine ? index : index - 1;\n this.removeStyleObject(isBeginningOfLine, indexStyle);\n this.text = this.text.slice(0, index - 1) +\n this.text.slice(index);\n\n this._textLines = this._splitTextIntoLines();\n },\n\n /**\n * Inserts characters where cursor is (replacing selection if one exists)\n * @param {String} _chars Characters to insert\n * @param {Boolean} useCopiedStyle use fabric.copiedTextStyle\n */\n insertChars: function(_chars, useCopiedStyle) {\n var style;\n\n if (this.selectionEnd - this.selectionStart > 1) {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n }\n //short circuit for block paste\n if (!useCopiedStyle && this.isEmptyStyles()) {\n this.insertChar(_chars, false);\n return;\n }\n for (var i = 0, len = _chars.length; i < len; i++) {\n if (useCopiedStyle) {\n style = fabric.util.object.clone(fabric.copiedTextStyle[i], true);\n }\n this.insertChar(_chars[i], i < len - 1, style);\n }\n },\n\n /**\n * Inserts a character where cursor is\n * @param {String} _char Characters to insert\n * @param {Boolean} skipUpdate trigger rendering and updates at the end of text insert\n * @param {Object} styleObject Style to be inserted for the new char\n */\n insertChar: function(_char, skipUpdate, styleObject) {\n var isEndOfLine = this.text[this.selectionStart] === '\\n';\n this.text = this.text.slice(0, this.selectionStart) +\n _char + this.text.slice(this.selectionEnd);\n this._textLines = this._splitTextIntoLines();\n this.insertStyleObjects(_char, isEndOfLine, styleObject);\n this.selectionStart += _char.length;\n this.selectionEnd = this.selectionStart;\n if (skipUpdate) {\n return;\n }\n this._updateTextarea();\n this.setCoords();\n this._fireSelectionChanged();\n this.fire('changed');\n this.restartCursorIfNeeded();\n if (this.canvas) {\n this.canvas.fire('text:changed', { target: this });\n this.canvas.renderAll();\n }\n },\n\n restartCursorIfNeeded: function() {\n if (!this._currentTickState || this._currentTickState.isAborted\n || !this._currentTickCompleteState || this._currentTickCompleteState.isAborted\n ) {\n this.initDelayedCursor();\n }\n },\n\n /**\n * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n\n this.shiftLineStyles(lineIndex, +1);\n\n var currentCharStyle = {},\n newLineStyles = {};\n\n if (this.styles[lineIndex] && this.styles[lineIndex][charIndex - 1]) {\n currentCharStyle = this.styles[lineIndex][charIndex - 1];\n }\n\n // if there's nothing after cursor,\n // we clone current char style onto the next (otherwise empty) line\n if (isEndOfLine && currentCharStyle) {\n newLineStyles[0] = clone(currentCharStyle);\n this.styles[lineIndex + 1] = newLineStyles;\n }\n // otherwise we clone styles of all chars\n // after cursor onto the next line, from the beginning\n else {\n var somethingAdded = false;\n for (var index in this.styles[lineIndex]) {\n var numIndex = parseInt(index, 10);\n if (numIndex >= charIndex) {\n somethingAdded = true;\n newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index];\n // remove lines from the previous line since they're on a new line now\n delete this.styles[lineIndex][index];\n }\n }\n somethingAdded && (this.styles[lineIndex + 1] = newLineStyles);\n }\n this._forceClearCache = true;\n },\n\n /**\n * Inserts style object for a given line/char index\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n\n var currentLineStyles = this.styles[lineIndex],\n currentLineStylesCloned = clone(currentLineStyles);\n\n if (charIndex === 0 && !style) {\n charIndex = 1;\n }\n\n // shift all char styles by 1 forward\n // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4\n for (var index in currentLineStylesCloned) {\n var numericIndex = parseInt(index, 10);\n\n if (numericIndex >= charIndex) {\n currentLineStyles[numericIndex + 1] = currentLineStylesCloned[numericIndex];\n\n // only delete the style if there was nothing moved there\n if (!currentLineStylesCloned[numericIndex - 1]) {\n delete currentLineStyles[numericIndex];\n }\n }\n }\n var newStyle = style || clone(currentLineStyles[charIndex - 1]);\n newStyle && (this.styles[lineIndex][charIndex] = newStyle);\n this._forceClearCache = true;\n },\n\n /**\n * Inserts style object(s)\n * @param {String} _chars Characters at the location where style is inserted\n * @param {Boolean} isEndOfLine True if it's end of line\n * @param {Object} [styleObject] Style to insert\n */\n insertStyleObjects: function(_chars, isEndOfLine, styleObject) {\n // removed shortcircuit over isEmptyStyles\n\n var cursorLocation = this.get2DCursorLocation(),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n if (!this._getLineStyle(lineIndex)) {\n this._setLineStyle(lineIndex, {});\n }\n\n if (_chars === '\\n') {\n this.insertNewlineStyleObject(lineIndex, charIndex, isEndOfLine);\n }\n else {\n this.insertCharStyleObject(lineIndex, charIndex, styleObject);\n }\n },\n\n /**\n * Shifts line styles up or down\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward or downward\n var clonedStyles = clone(this.styles);\n for (var line in clonedStyles) {\n var numericLine = parseInt(line, 10);\n if (numericLine <= lineIndex) {\n delete clonedStyles[numericLine];\n }\n }\n for (var line in this.styles) {\n var numericLine = parseInt(line, 10);\n if (numericLine > lineIndex) {\n this.styles[numericLine + offset] = clonedStyles[numericLine];\n if (!clonedStyles[numericLine - offset]) {\n delete this.styles[numericLine];\n }\n }\n }\n //TODO: evaluate if delete old style lines with offset -1\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex;\n\n this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex);\n },\n\n _getTextOnPreviousLine: function(lIndex) {\n return this._textLines[lIndex - 1];\n },\n\n _removeStyleObject: function(isBeginningOfLine, cursorLocation, lineIndex, charIndex) {\n\n if (isBeginningOfLine) {\n var textOnPreviousLine = this._getTextOnPreviousLine(cursorLocation.lineIndex),\n newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0;\n\n if (!this.styles[lineIndex - 1]) {\n this.styles[lineIndex - 1] = {};\n }\n for (charIndex in this.styles[lineIndex]) {\n this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]\n = this.styles[lineIndex][charIndex];\n }\n this.shiftLineStyles(cursorLocation.lineIndex, -1);\n }\n else {\n var currentLineStyles = this.styles[lineIndex];\n\n if (currentLineStyles) {\n delete currentLineStyles[charIndex];\n }\n var currentLineStylesCloned = clone(currentLineStyles);\n // shift all styles by 1 backwards\n for (var i in currentLineStylesCloned) {\n var numericIndex = parseInt(i, 10);\n if (numericIndex >= charIndex && numericIndex !== 0) {\n currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];\n delete currentLineStyles[numericIndex];\n }\n }\n }\n },\n\n /**\n * Inserts new line\n */\n insertNewline: function() {\n this.insertChars('\\n');\n },\n\n /**\n * Set the selectionStart and selectionEnd according to the ne postion of cursor\n * mimic the key - mouse navigation when shift is pressed.\n */\n setSelectionStartEndWithShift: function(start, end, newSelection) {\n if (newSelection <= start) {\n if (end === start) {\n this._selectionDirection = 'left';\n }\n else if (this._selectionDirection === 'right') {\n this._selectionDirection = 'left';\n this.selectionEnd = start;\n }\n this.selectionStart = newSelection;\n }\n else if (newSelection > start && newSelection < end) {\n if (this._selectionDirection === 'right') {\n this.selectionEnd = newSelection;\n }\n else {\n this.selectionStart = newSelection;\n }\n }\n else {\n // newSelection is > selection start and end\n if (end === start) {\n this._selectionDirection = 'right';\n }\n else if (this._selectionDirection === 'left') {\n this._selectionDirection = 'right';\n this.selectionStart = end;\n }\n this.selectionEnd = newSelection;\n }\n },\n\n setSelectionInBoundaries: function() {\n var length = this.text.length;\n if (this.selectionStart > length) {\n this.selectionStart = length;\n }\n else if (this.selectionStart < 0) {\n this.selectionStart = 0;\n }\n if (this.selectionEnd > length) {\n this.selectionEnd = length;\n }\n else if (this.selectionEnd < 0) {\n this.selectionEnd = 0;\n }\n }\n });\n})();\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n /**\n * Initializes \"dbclick\" event handler\n */\n initDoubleClickSimulation: function() {\n\n // for double click\n this.__lastClickTime = +new Date();\n\n // for triple click\n this.__lastLastClickTime = +new Date();\n\n this.__lastPointer = { };\n\n this.on('mousedown', this.onMouseDown.bind(this));\n },\n\n onMouseDown: function(options) {\n\n this.__newClickTime = +new Date();\n var newPointer = this.canvas.getPointer(options.e);\n\n if (this.isTripleClick(newPointer, options.e)) {\n this.fire('tripleclick', options);\n this._stopEvent(options.e);\n }\n else if (this.isDoubleClick(newPointer)) {\n this.fire('dblclick', options);\n this._stopEvent(options.e);\n }\n\n this.__lastLastClickTime = this.__lastClickTime;\n this.__lastClickTime = this.__newClickTime;\n this.__lastPointer = newPointer;\n this.__lastIsEditing = this.isEditing;\n this.__lastSelected = this.selected;\n },\n\n isDoubleClick: function(newPointer) {\n return this.__newClickTime - this.__lastClickTime < 500 &&\n this.__lastPointer.x === newPointer.x &&\n this.__lastPointer.y === newPointer.y && this.__lastIsEditing;\n },\n\n isTripleClick: function(newPointer) {\n return this.__newClickTime - this.__lastClickTime < 500 &&\n this.__lastClickTime - this.__lastLastClickTime < 500 &&\n this.__lastPointer.x === newPointer.x &&\n this.__lastPointer.y === newPointer.y;\n },\n\n /**\n * @private\n */\n _stopEvent: function(e) {\n e.preventDefault && e.preventDefault();\n e.stopPropagation && e.stopPropagation();\n },\n\n /**\n * Initializes event handlers related to cursor or selection\n */\n initCursorSelectionHandlers: function() {\n this.initMousedownHandler();\n this.initMouseupHandler();\n this.initClicks();\n },\n\n /**\n * Initializes double and triple click event handlers\n */\n initClicks: function() {\n this.on('dblclick', function(options) {\n this.selectWord(this.getSelectionStartFromPointer(options.e));\n });\n this.on('tripleclick', function(options) {\n this.selectLine(this.getSelectionStartFromPointer(options.e));\n });\n },\n\n /**\n * Initializes \"mousedown\" event handler\n */\n initMousedownHandler: function() {\n this.on('mousedown', function(options) {\n if (!this.editable || (options.e.button && options.e.button !== 1)) {\n return;\n }\n var pointer = this.canvas.getPointer(options.e);\n this.__mousedownX = pointer.x;\n this.__mousedownY = pointer.y;\n this.__isMousedown = true;\n\n if (this.selected) {\n this.setCursorByClick(options.e);\n }\n\n if (this.isEditing) {\n this.__selectionStartOnMouseDown = this.selectionStart;\n if (this.selectionStart === this.selectionEnd) {\n this.abortCursorAnimation();\n }\n this.renderCursorOrSelection();\n }\n });\n },\n\n /**\n * @private\n */\n _isObjectMoved: function(e) {\n var pointer = this.canvas.getPointer(e);\n\n return this.__mousedownX !== pointer.x ||\n this.__mousedownY !== pointer.y;\n },\n\n /**\n * Initializes \"mouseup\" event handler\n */\n initMouseupHandler: function() {\n this.on('mouseup', function(options) {\n this.__isMousedown = false;\n if (!this.editable || this._isObjectMoved(options.e) || (options.e.button && options.e.button !== 1)) {\n return;\n }\n\n if (this.__lastSelected && !this.__corner) {\n this.enterEditing(options.e);\n if (this.selectionStart === this.selectionEnd) {\n this.initDelayedCursor(true);\n }\n else {\n this.renderCursorOrSelection();\n }\n }\n this.selected = true;\n });\n },\n\n /**\n * Changes cursor location in a text depending on passed pointer (x/y) object\n * @param {Event} e Event object\n */\n setCursorByClick: function(e) {\n var newSelection = this.getSelectionStartFromPointer(e),\n start = this.selectionStart, end = this.selectionEnd;\n if (e.shiftKey) {\n this.setSelectionStartEndWithShift(start, end, newSelection);\n }\n else {\n this.selectionStart = newSelection;\n this.selectionEnd = newSelection;\n }\n if (this.isEditing) {\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Returns index of a character corresponding to where an object was clicked\n * @param {Event} e Event object\n * @return {Number} Index of a character\n */\n getSelectionStartFromPointer: function(e) {\n var mouseOffset = this.getLocalPointer(e),\n prevWidth = 0,\n width = 0,\n height = 0,\n charIndex = 0,\n newSelectionStart,\n line;\n\n for (var i = 0, len = this._textLines.length; i < len; i++) {\n line = this._textLines[i];\n height += this._getHeightOfLine(this.ctx, i) * this.scaleY;\n\n var widthOfLine = this._getLineWidth(this.ctx, i),\n lineLeftOffset = this._getLineLeftOffset(widthOfLine);\n\n width = lineLeftOffset * this.scaleX;\n\n for (var j = 0, jlen = line.length; j < jlen; j++) {\n\n prevWidth = width;\n\n width += this._getWidthOfChar(this.ctx, line[j], i, this.flipX ? jlen - j : j) *\n this.scaleX;\n\n if (height <= mouseOffset.y || width <= mouseOffset.x) {\n charIndex++;\n continue;\n }\n\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i, jlen);\n }\n\n if (mouseOffset.y < height) {\n //this happens just on end of lines.\n return this._getNewSelectionStartFromOffset(\n mouseOffset, prevWidth, width, charIndex + i - 1, jlen);\n }\n }\n\n // clicked somewhere after all chars, so set at the end\n if (typeof newSelectionStart === 'undefined') {\n return this.text.length;\n }\n },\n\n /**\n * @private\n */\n _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) {\n\n var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth,\n distanceBtwNextCharAndCursor = width - mouseOffset.x,\n offset = distanceBtwNextCharAndCursor > distanceBtwLastCharAndCursor ? 0 : 1,\n newSelectionStart = index + offset;\n\n // if object is horizontally flipped, mirror cursor location from the end\n if (this.flipX) {\n newSelectionStart = jlen - newSelectionStart;\n }\n\n if (newSelectionStart > this.text.length) {\n newSelectionStart = this.text.length;\n }\n\n return newSelectionStart;\n }\n});\n\n\nfabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * Initializes hidden textarea (needed to bring up keyboard in iOS)\n */\n initHiddenTextarea: function() {\n this.hiddenTextarea = fabric.document.createElement('textarea');\n this.hiddenTextarea.setAttribute('autocapitalize', 'off');\n this.hiddenTextarea.setAttribute('autocorrect', 'off');\n this.hiddenTextarea.setAttribute('autocomplete', 'off');\n this.hiddenTextarea.setAttribute('spellcheck', 'false');\n this.hiddenTextarea.setAttribute('data-fabric-hiddentextarea', '');\n this.hiddenTextarea.setAttribute('wrap', 'off');\n var style = this._calcTextareaPosition();\n this.hiddenTextarea.style.cssText = 'position: absolute; top: ' + style.top +\n '; left: ' + style.left + '; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;' +\n ' line-height: 1px; paddingーtop: ' + style.fontSize + ';';\n fabric.document.body.appendChild(this.hiddenTextarea);\n\n fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'keyup', this.onKeyUp.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'input', this.onInput.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'copy', this.copy.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'cut', this.cut.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'paste', this.paste.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionstart', this.onCompositionStart.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionupdate', this.onCompositionUpdate.bind(this));\n fabric.util.addListener(this.hiddenTextarea, 'compositionend', this.onCompositionEnd.bind(this));\n\n if (!this._clickHandlerInitialized && this.canvas) {\n fabric.util.addListener(this.canvas.upperCanvasEl, 'click', this.onClick.bind(this));\n this._clickHandlerInitialized = true;\n }\n },\n\n /**\n * For functionalities on keyDown\n * Map a special key to a function of the instance/prototype\n * If you need different behaviour for ESC or TAB or arrows, you have to change\n * this map setting the name of a function that you build on the fabric.Itext or\n * your prototype.\n * the map change will affect all Instances unless you need for only some text Instances\n * in that case you have to clone this object and assign your Instance.\n * this.keysMap = fabric.util.object.clone(this.keysMap);\n * The function must be in fabric.Itext.prototype.myFunction And will receive event as args[0]\n */\n keysMap: {\n 8: 'removeChars',\n 9: 'exitEditing',\n 27: 'exitEditing',\n 13: 'insertNewline',\n 33: 'moveCursorUp',\n 34: 'moveCursorDown',\n 35: 'moveCursorRight',\n 36: 'moveCursorLeft',\n 37: 'moveCursorLeft',\n 38: 'moveCursorUp',\n 39: 'moveCursorRight',\n 40: 'moveCursorDown',\n 46: 'forwardDelete'\n },\n\n /**\n * For functionalities on keyUp + ctrl || cmd\n */\n ctrlKeysMapUp: {\n 67: 'copy',\n 88: 'cut'\n },\n\n /**\n * For functionalities on keyDown + ctrl || cmd\n */\n ctrlKeysMapDown: {\n 65: 'selectAll'\n },\n\n onClick: function() {\n // No need to trigger click event here, focus is enough to have the keyboard appear on Android\n this.hiddenTextarea && this.hiddenTextarea.focus();\n },\n\n /**\n * Handles keyup event\n * @param {Event} e Event object\n */\n onKeyDown: function(e) {\n if (!this.isEditing) {\n return;\n }\n if (e.keyCode in this.keysMap) {\n this[this.keysMap[e.keyCode]](e);\n }\n else if ((e.keyCode in this.ctrlKeysMapDown) && (e.ctrlKey || e.metaKey)) {\n this[this.ctrlKeysMapDown[e.keyCode]](e);\n }\n else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n if (e.keyCode >= 33 && e.keyCode <= 40) {\n // if i press an arrow key just update selection\n this.clearContextTop();\n this.renderCursorOrSelection();\n }\n else {\n this.canvas && this.canvas.renderAll();\n }\n },\n\n /**\n * Handles keyup event\n * We handle KeyUp because ie11 and edge have difficulties copy/pasting\n * if a copy/cut event fired, keyup is dismissed\n * @param {Event} e Event object\n */\n onKeyUp: function(e) {\n if (!this.isEditing || this._copyDone) {\n this._copyDone = false;\n return;\n }\n if ((e.keyCode in this.ctrlKeysMapUp) && (e.ctrlKey || e.metaKey)) {\n this[this.ctrlKeysMapUp[e.keyCode]](e);\n }\n else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n this.canvas && this.canvas.renderAll();\n },\n\n /**\n * Handles onInput event\n * @param {Event} e Event object\n */\n onInput: function(e) {\n if (!this.isEditing || this.inCompositionMode) {\n return;\n }\n var offset = this.selectionStart || 0,\n offsetEnd = this.selectionEnd || 0,\n textLength = this.text.length,\n newTextLength = this.hiddenTextarea.value.length,\n diff, charsToInsert, start;\n if (newTextLength > textLength) {\n //we added some character\n start = this._selectionDirection === 'left' ? offsetEnd : offset;\n diff = newTextLength - textLength;\n charsToInsert = this.hiddenTextarea.value.slice(start, start + diff);\n }\n else {\n //we selected a portion of text and then input something else.\n //Internet explorer does not trigger this else\n diff = newTextLength - textLength + offsetEnd - offset;\n charsToInsert = this.hiddenTextarea.value.slice(offset, offset + diff);\n }\n this.insertChars(charsToInsert);\n e.stopPropagation();\n },\n\n /**\n * Composition start\n */\n onCompositionStart: function() {\n this.inCompositionMode = true;\n this.prevCompositionLength = 0;\n this.compositionStart = this.selectionStart;\n },\n\n /**\n * Composition end\n */\n onCompositionEnd: function() {\n this.inCompositionMode = false;\n },\n\n /**\n * Composition update\n */\n onCompositionUpdate: function(e) {\n var data = e.data;\n this.selectionStart = this.compositionStart;\n this.selectionEnd = this.selectionEnd === this.selectionStart ?\n this.compositionStart + this.prevCompositionLength : this.selectionEnd;\n this.insertChars(data, false);\n this.prevCompositionLength = data.length;\n },\n\n /**\n * Forward delete\n */\n forwardDelete: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n if (this.selectionStart === this.text.length) {\n return;\n }\n this.moveCursorRight(e);\n }\n this.removeChars(e);\n },\n\n /**\n * Copies selected text\n * @param {Event} e Event object\n */\n copy: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n //do not cut-copy if no selection\n return;\n }\n var selectedText = this.getSelectedText(),\n clipboardData = this._getClipboardData(e);\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n clipboardData.setData('text', selectedText);\n }\n\n fabric.copiedText = selectedText;\n fabric.copiedTextStyle = this.getSelectionStyles(this.selectionStart, this.selectionEnd);\n e.stopImmediatePropagation();\n e.preventDefault();\n this._copyDone = true;\n },\n\n /**\n * Pastes text\n * @param {Event} e Event object\n */\n paste: function(e) {\n var copiedText = null,\n clipboardData = this._getClipboardData(e),\n useCopiedStyle = true;\n\n // Check for backward compatibility with old browsers\n if (clipboardData) {\n copiedText = clipboardData.getData('text').replace(/\\r/g, '');\n if (!fabric.copiedTextStyle || fabric.copiedText !== copiedText) {\n useCopiedStyle = false;\n }\n }\n else {\n copiedText = fabric.copiedText;\n }\n\n if (copiedText) {\n this.insertChars(copiedText, useCopiedStyle);\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n },\n\n /**\n * Cuts text\n * @param {Event} e Event object\n */\n cut: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n return;\n }\n\n this.copy(e);\n this.removeChars(e);\n },\n\n /**\n * @private\n * @param {Event} e Event object\n * @return {Object} Clipboard data object\n */\n _getClipboardData: function(e) {\n return (e && e.clipboardData) || fabric.window.clipboardData;\n },\n\n /**\n * Finds the width in pixels before the cursor on the same line\n * @private\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {Number} widthBeforeCursor width before cursor\n */\n _getWidthBeforeCursor: function(lineIndex, charIndex) {\n var textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n widthOfLine = this._getLineWidth(this.ctx, lineIndex),\n widthBeforeCursor = this._getLineLeftOffset(widthOfLine), _char;\n\n for (var i = 0, len = textBeforeCursor.length; i < len; i++) {\n _char = textBeforeCursor[i];\n widthBeforeCursor += this._getWidthOfChar(this.ctx, _char, lineIndex, i);\n }\n return widthBeforeCursor;\n },\n\n /**\n * Gets start offset of a selection\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getDownCursorOffset: function(e, isRight) {\n var selectionProp = this._getSelectionForOffset(e, isRight),\n cursorLocation = this.get2DCursorLocation(selectionProp),\n lineIndex = cursorLocation.lineIndex;\n // if on last line, down cursor goes to end of line\n if (lineIndex === this._textLines.length - 1 || e.metaKey || e.keyCode === 34) {\n // move to the end of a text\n return this.text.length - selectionProp;\n }\n var charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor),\n textAfterCursor = this._textLines[lineIndex].slice(charIndex);\n\n return textAfterCursor.length + indexOnOtherLine + 2;\n },\n\n /**\n * private\n * Helps finding if the offset should be counted from Start or End\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n _getSelectionForOffset: function(e, isRight) {\n if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) {\n return this.selectionEnd;\n }\n else {\n return this.selectionStart;\n }\n },\n\n /**\n * @param {Event} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getUpCursorOffset: function(e, isRight) {\n var selectionProp = this._getSelectionForOffset(e, isRight),\n cursorLocation = this.get2DCursorLocation(selectionProp),\n lineIndex = cursorLocation.lineIndex;\n if (lineIndex === 0 || e.metaKey || e.keyCode === 33) {\n // if on first line, up cursor goes to start of line\n return -selectionProp;\n }\n var charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor),\n textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex);\n // return a negative offset\n return -this._textLines[lineIndex - 1].length + indexOnOtherLine - textBeforeCursor.length;\n },\n\n /**\n * find for a given width it founds the matching character.\n * @private\n */\n _getIndexOnLine: function(lineIndex, width) {\n\n var widthOfLine = this._getLineWidth(this.ctx, lineIndex),\n textOnLine = this._textLines[lineIndex],\n lineLeftOffset = this._getLineLeftOffset(widthOfLine),\n widthOfCharsOnLine = lineLeftOffset,\n indexOnLine = 0,\n foundMatch;\n\n for (var j = 0, jlen = textOnLine.length; j < jlen; j++) {\n\n var _char = textOnLine[j],\n widthOfChar = this._getWidthOfChar(this.ctx, _char, lineIndex, j);\n\n widthOfCharsOnLine += widthOfChar;\n\n if (widthOfCharsOnLine > width) {\n\n foundMatch = true;\n\n var leftEdge = widthOfCharsOnLine - widthOfChar,\n rightEdge = widthOfCharsOnLine,\n offsetFromLeftEdge = Math.abs(leftEdge - width),\n offsetFromRightEdge = Math.abs(rightEdge - width);\n\n indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : (j - 1);\n\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnLine = textOnLine.length - 1;\n }\n\n return indexOnLine;\n },\n\n\n /**\n * Moves cursor down\n * @param {Event} e Event object\n */\n moveCursorDown: function(e) {\n if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {\n return;\n }\n this._moveCursorUpOrDown('Down', e);\n },\n\n /**\n * Moves cursor up\n * @param {Event} e Event object\n */\n moveCursorUp: function(e) {\n if (this.selectionStart === 0 && this.selectionEnd === 0) {\n return;\n }\n this._moveCursorUpOrDown('Up', e);\n },\n\n /**\n * Moves cursor up or down, fires the events\n * @param {String} direction 'Up' or 'Down'\n * @param {Event} e Event object\n */\n _moveCursorUpOrDown: function(direction, e) {\n // getUpCursorOffset\n // getDownCursorOffset\n var action = 'get' + direction + 'CursorOffset',\n offset = this[action](e, this._selectionDirection === 'right');\n if (e.shiftKey) {\n this.moveCursorWithShift(offset);\n }\n else {\n this.moveCursorWithoutShift(offset);\n }\n if (offset !== 0) {\n this.setSelectionInBoundaries();\n this.abortCursorAnimation();\n this._currentCursorOpacity = 1;\n this.initDelayedCursor();\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Moves cursor with shift\n * @param {Number} offset\n */\n moveCursorWithShift: function(offset) {\n var newSelection = this._selectionDirection === 'left'\n ? this.selectionStart + offset\n : this.selectionEnd + offset;\n this.setSelectionStartEndWithShift(this.selectionStart, this.selectionEnd, newSelection);\n return offset !== 0;\n },\n\n /**\n * Moves cursor up without shift\n * @param {Number} offset\n */\n moveCursorWithoutShift: function(offset) {\n if (offset < 0) {\n this.selectionStart += offset;\n this.selectionEnd = this.selectionStart;\n }\n else {\n this.selectionEnd += offset;\n this.selectionStart = this.selectionEnd;\n }\n return offset !== 0;\n },\n\n /**\n * Moves cursor left\n * @param {Event} e Event object\n */\n moveCursorLeft: function(e) {\n if (this.selectionStart === 0 && this.selectionEnd === 0) {\n return;\n }\n this._moveCursorLeftOrRight('Left', e);\n },\n\n /**\n * @private\n * @return {Boolean} true if a change happened\n */\n _move: function(e, prop, direction) {\n var newValue;\n if (e.altKey) {\n newValue = this['findWordBoundary' + direction](this[prop]);\n }\n else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) {\n newValue = this['findLineBoundary' + direction](this[prop]);\n }\n else {\n this[prop] += direction === 'Left' ? -1 : 1;\n return true;\n }\n if (typeof newValue !== undefined && this[prop] !== newValue) {\n this[prop] = newValue;\n return true;\n }\n },\n\n /**\n * @private\n */\n _moveLeft: function(e, prop) {\n return this._move(e, prop, 'Left');\n },\n\n /**\n * @private\n */\n _moveRight: function(e, prop) {\n return this._move(e, prop, 'Right');\n },\n\n /**\n * Moves cursor left without keeping selection\n * @param {Event} e\n */\n moveCursorLeftWithoutShift: function(e) {\n var change = true;\n this._selectionDirection = 'left';\n\n // only move cursor when there is no selection,\n // otherwise we discard it, and leave cursor on same place\n if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {\n change = this._moveLeft(e, 'selectionStart');\n\n }\n this.selectionEnd = this.selectionStart;\n return change;\n },\n\n /**\n * Moves cursor left while keeping selection\n * @param {Event} e\n */\n moveCursorLeftWithShift: function(e) {\n if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {\n return this._moveLeft(e, 'selectionEnd');\n }\n else if (this.selectionStart !== 0){\n this._selectionDirection = 'left';\n return this._moveLeft(e, 'selectionStart');\n }\n },\n\n /**\n * Moves cursor right\n * @param {Event} e Event object\n */\n moveCursorRight: function(e) {\n if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {\n return;\n }\n this._moveCursorLeftOrRight('Right', e);\n },\n\n /**\n * Moves cursor right or Left, fires event\n * @param {String} direction 'Left', 'Right'\n * @param {Event} e Event object\n */\n _moveCursorLeftOrRight: function(direction, e) {\n var actionName = 'moveCursor' + direction + 'With';\n this._currentCursorOpacity = 1;\n\n if (e.shiftKey) {\n actionName += 'Shift';\n }\n else {\n actionName += 'outShift';\n }\n if (this[actionName](e)) {\n this.abortCursorAnimation();\n this.initDelayedCursor();\n this._fireSelectionChanged();\n this._updateTextarea();\n }\n },\n\n /**\n * Moves cursor right while keeping selection\n * @param {Event} e\n */\n moveCursorRightWithShift: function(e) {\n if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {\n return this._moveRight(e, 'selectionStart');\n }\n else if (this.selectionEnd !== this.text.length) {\n this._selectionDirection = 'right';\n return this._moveRight(e, 'selectionEnd');\n }\n },\n\n /**\n * Moves cursor right without keeping selection\n * @param {Event} e Event object\n */\n moveCursorRightWithoutShift: function(e) {\n var changed = true;\n this._selectionDirection = 'right';\n\n if (this.selectionStart === this.selectionEnd) {\n changed = this._moveRight(e, 'selectionStart');\n this.selectionEnd = this.selectionStart;\n }\n else {\n this.selectionStart = this.selectionEnd;\n }\n return changed;\n },\n\n /**\n * Removes characters selected by selection\n * @param {Event} e Event object\n */\n removeChars: function(e) {\n if (this.selectionStart === this.selectionEnd) {\n this._removeCharsNearCursor(e);\n }\n else {\n this._removeCharsFromTo(this.selectionStart, this.selectionEnd);\n }\n\n this.set('dirty', true);\n this.setSelectionEnd(this.selectionStart);\n\n this._removeExtraneousStyles();\n\n this.canvas && this.canvas.renderAll();\n\n this.setCoords();\n this.fire('changed');\n this.canvas && this.canvas.fire('text:changed', { target: this });\n },\n\n /**\n * @private\n * @param {Event} e Event object\n */\n _removeCharsNearCursor: function(e) {\n if (this.selectionStart === 0) {\n return;\n }\n if (e.metaKey) {\n // remove all till the start of current line\n var leftLineBoundary = this.findLineBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftLineBoundary, this.selectionStart);\n this.setSelectionStart(leftLineBoundary);\n }\n else if (e.altKey) {\n // remove all till the start of current word\n var leftWordBoundary = this.findWordBoundaryLeft(this.selectionStart);\n\n this._removeCharsFromTo(leftWordBoundary, this.selectionStart);\n this.setSelectionStart(leftWordBoundary);\n }\n else {\n this._removeSingleCharAndStyle(this.selectionStart);\n this.setSelectionStart(this.selectionStart - 1);\n }\n }\n});\n\n\n/* _TO_SVG_START_ */\n(function() {\n var toFixed = fabric.util.toFixed,\n NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;\n\n fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ {\n\n /**\n * @private\n */\n _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) {\n if (!this._getLineStyle(lineIndex)) {\n fabric.Text.prototype._setSVGTextLineText.call(this,\n lineIndex, textSpans, height, textLeftOffset, textTopOffset);\n }\n else {\n this._setSVGTextLineChars(\n lineIndex, textSpans, height, textLeftOffset, textBgRects);\n }\n },\n\n /**\n * @private\n */\n _setSVGTextLineChars: function(lineIndex, textSpans, height, textLeftOffset, textBgRects) {\n\n var chars = this._textLines[lineIndex],\n charOffset = 0,\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, lineIndex)) - this.width / 2,\n lineOffset = this._getSVGLineTopOffset(lineIndex),\n heightOfLine = this._getHeightOfLine(this.ctx, lineIndex);\n\n for (var i = 0, len = chars.length; i < len; i++) {\n var styleDecl = this._getStyleDeclaration(lineIndex, i) || { };\n\n textSpans.push(\n this._createTextCharSpan(\n chars[i], styleDecl, lineLeftOffset, lineOffset.lineTop + lineOffset.offset, charOffset));\n\n var charWidth = this._getWidthOfChar(this.ctx, chars[i], lineIndex, i);\n\n if (styleDecl.textBackgroundColor) {\n textBgRects.push(\n this._createTextCharBg(\n styleDecl, lineLeftOffset, lineOffset.lineTop, heightOfLine, charWidth, charOffset));\n }\n\n charOffset += charWidth;\n }\n },\n\n /**\n * @private\n */\n _getSVGLineTopOffset: function(lineIndex) {\n var lineTopOffset = 0, lastHeight = 0;\n for (var j = 0; j < lineIndex; j++) {\n lineTopOffset += this._getHeightOfLine(this.ctx, j);\n }\n lastHeight = this._getHeightOfLine(this.ctx, j);\n return {\n lineTop: lineTopOffset,\n offset: (this._fontSizeMult - this._fontSizeFraction) * lastHeight / (this.lineHeight * this._fontSizeMult)\n };\n },\n\n /**\n * @private\n */\n _createTextCharBg: function(styleDecl, lineLeftOffset, lineTopOffset, heightOfLine, charWidth, charOffset) {\n return [\n '\\t\\t\\n'\n ].join('');\n },\n\n /**\n * @private\n */\n _createTextCharSpan: function(_char, styleDecl, lineLeftOffset, lineTopOffset, charOffset) {\n\n var fillStyles = this.getSvgStyles.call(fabric.util.object.extend({\n visible: true,\n fill: this.fill,\n stroke: this.stroke,\n type: 'text',\n getSvgFilter: fabric.Object.prototype.getSvgFilter\n }, styleDecl));\n\n return [\n '\\t\\t\\t',\n fabric.util.string.escapeXml(_char),\n '\\n'\n ].join('');\n },\n });\n})();\n/* _TO_SVG_END_ */\n\n\n(function(global) {\n\n 'use strict';\n\n var fabric = global.fabric || (global.fabric = {});\n\n /**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n * @class fabric.Textbox\n * @extends fabric.IText\n * @mixes fabric.Observable\n * @return {fabric.Textbox} thisArg\n * @see {@link fabric.Textbox#initialize} for constructor definition\n */\n fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, {\n\n /**\n * Type of an object\n * @type String\n * @default\n */\n type: 'textbox',\n\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n * @default\n */\n minWidth: 20,\n\n /**\n * Minimum calculated width of a textbox, in pixels.\n * fixed to 2 so that an empty textbox cannot go to 0\n * and is still selectable without text.\n * @type Number\n * @default\n */\n dynamicMinWidth: 2,\n\n /**\n * Cached array of text wrapping.\n * @type Array\n */\n __cachedLines: null,\n\n /**\n * Override standard Object class values\n */\n lockScalingY: true,\n\n /**\n * Override standard Object class values\n */\n lockScalingFlip: true,\n\n /**\n * Override standard Object class values\n * Textbox needs this on false\n */\n noScaleCache: false,\n\n /**\n * Properties which when set cause object to change dimensions\n * @type Object\n * @private\n */\n _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),\n\n /**\n * Constructor. Some scaling related property values are forced. Visibility\n * of controls is also fixed; only the rotation and width controls are\n * made available.\n * @param {String} text Text string\n * @param {Object} [options] Options object\n * @return {fabric.Textbox} thisArg\n */\n initialize: function(text, options) {\n\n this.callSuper('initialize', text, options);\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n this.ctx = this.objectCaching ? this._cacheContext : fabric.util.createCanvasElement().getContext('2d');\n },\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @private\n * @override\n */\n _initDimensions: function(ctx) {\n if (this.__skipDimension) {\n return;\n }\n\n if (!ctx) {\n ctx = fabric.util.createCanvasElement().getContext('2d');\n this._setTextStyles(ctx);\n this.clearContextTop();\n }\n\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n\n // wrap lines\n this._textLines = this._splitTextIntoLines(ctx);\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n\n // clear cache and re-calculate height\n this._clearCache();\n this.height = this._getTextHeight(ctx);\n this.setCoords();\n },\n\n /**\n * Generate an object that translates the style object so that it is\n * broken up by visual lines (new lines and automatic wrapping).\n * The original text styles object is broken up by actual lines (new lines only),\n * which is only sufficient for Text / IText\n * @private\n */\n _generateStyleMap: function() {\n var realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0,\n map = {};\n\n for (var i = 0; i < this._textLines.length; i++) {\n if (this.text[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n }\n else if (this.text[charCount] === ' ' && i > 0) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += this._textLines[i].length;\n realLineCharCount += this._textLines[i].length;\n }\n\n return map;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Boolean} [returnCloneOrEmpty=false]\n * @private\n */\n _getStyleDeclaration: function(lineIndex, charIndex, returnCloneOrEmpty) {\n if (this._styleMap) {\n var map = this._styleMap[lineIndex];\n if (!map) {\n return returnCloneOrEmpty ? { } : null;\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return this.callSuper('_getStyleDeclaration', lineIndex, charIndex, returnCloneOrEmpty);\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n _setStyleDeclaration: function(lineIndex, charIndex, style) {\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n this.styles[lineIndex][charIndex] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n _deleteStyleDeclaration: function(lineIndex, charIndex) {\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n delete this.styles[lineIndex][charIndex];\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _getLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n return this.styles[map.line];\n },\n\n /**\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n _setLineStyle: function(lineIndex, style) {\n var map = this._styleMap[lineIndex];\n this.styles[map.line] = style;\n },\n\n /**\n * @param {Number} lineIndex\n * @private\n */\n _deleteLineStyle: function(lineIndex) {\n var map = this._styleMap[lineIndex];\n delete this.styles[map.line];\n },\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text that is split into lines\n * @returns {Array} Array of lines\n */\n _wrapText: function(ctx, text) {\n var lines = text.split(this._reNewline), wrapped = [], i;\n\n for (i = 0; i < lines.length; i++) {\n wrapped = wrapped.concat(this._wrapLine(ctx, lines[i], i));\n }\n\n return wrapped;\n },\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n * @private\n */\n _measureText: function(ctx, text, lineIndex, charOffset) {\n var width = 0;\n charOffset = charOffset || 0;\n for (var i = 0, len = text.length; i < len; i++) {\n width += this._getWidthOfChar(ctx, text[i], lineIndex, i + charOffset);\n }\n return width;\n },\n\n /**\n * Wraps a line of text using the width of the Textbox and a context.\n * @param {CanvasRenderingContext2D} ctx Context to use for measurements\n * @param {String} text The string of text to split into lines\n * @param {Number} lineIndex\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine: function(ctx, text, lineIndex) {\n var lineWidth = 0,\n lines = [],\n line = '',\n words = text.split(' '),\n word = '',\n offset = 0,\n infix = ' ',\n wordWidth = 0,\n infixWidth = 0,\n largestWordWidth = 0,\n lineJustStarted = true,\n additionalSpace = this._getWidthOfCharSpacing();\n\n for (var i = 0; i < words.length; i++) {\n word = words[i];\n wordWidth = this._measureText(ctx, word, lineIndex, offset);\n\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n\n if (lineWidth >= this.width && !lineJustStarted) {\n lines.push(line);\n line = '';\n lineWidth = wordWidth;\n lineJustStarted = true;\n }\n else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted) {\n line += infix;\n }\n line += word;\n\n infixWidth = this._measureText(ctx, infix, lineIndex, offset);\n offset++;\n lineJustStarted = false;\n // keep track of largest word\n if (wordWidth > largestWordWidth) {\n largestWordWidth = wordWidth;\n }\n }\n\n i && lines.push(line);\n\n if (largestWordWidth > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace;\n }\n\n return lines;\n },\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly everytime it is called.\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines: function(ctx) {\n ctx = ctx || this.ctx;\n var originalAlign = this.textAlign;\n this._styleMap = null;\n ctx.save();\n this._setTextStyles(ctx);\n this.textAlign = 'left';\n var lines = this._wrapText(ctx, this.text);\n this.textAlign = originalAlign;\n ctx.restore();\n this._textLines = lines;\n this._styleMap = this._generateStyleMap();\n return lines;\n },\n\n /**\n * When part of a group, we don't want the Textbox's scale to increase if\n * the group's increases. That's why we reduce the scale of the Textbox by\n * the amount that the group's increases. This is to maintain the effective\n * scale of the Textbox at 1, so that font-size values make sense. Otherwise\n * the same font-size value would result in different actual size depending\n * on the value of the scale.\n * @param {String} key\n * @param {*} value\n */\n setOnGroup: function(key, value) {\n if (key === 'scaleX') {\n this.set('scaleX', Math.abs(1 / value));\n this.set('width', (this.get('width') * value) /\n (typeof this.__oldScaleX === 'undefined' ? 1 : this.__oldScaleX));\n this.__oldScaleX = value;\n }\n },\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start).\n * Overrides the superclass function to take into account text wrapping.\n *\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n */\n get2DCursorLocation: function(selectionStart) {\n if (typeof selectionStart === 'undefined') {\n selectionStart = this.selectionStart;\n }\n\n var numLines = this._textLines.length,\n removed = 0;\n\n for (var i = 0; i < numLines; i++) {\n var line = this._textLines[i],\n lineLen = line.length;\n\n if (selectionStart <= removed + lineLen) {\n return {\n lineIndex: i,\n charIndex: selectionStart - removed\n };\n }\n\n removed += lineLen;\n\n if (this.text[removed] === '\\n' || this.text[removed] === ' ') {\n removed++;\n }\n }\n\n return {\n lineIndex: numLines - 1,\n charIndex: this._textLines[numLines - 1].length\n };\n },\n\n /**\n * Overrides superclass function and uses text wrapping data to get cursor\n * boundary offsets instead of the array of chars.\n * @param {Array} chars Unused\n * @param {String} typeOfBoundaries Can be 'cursor' or 'selection'\n * @returns {Object} Object with 'top', 'left', and 'lineLeft' properties set.\n */\n _getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {\n var topOffset = 0,\n leftOffset = 0,\n cursorLocation = this.get2DCursorLocation(),\n lineChars = this._textLines[cursorLocation.lineIndex].split(''),\n lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(this.ctx, cursorLocation.lineIndex));\n\n for (var i = 0; i < cursorLocation.charIndex; i++) {\n leftOffset += this._getWidthOfChar(this.ctx, lineChars[i], cursorLocation.lineIndex, i);\n }\n\n for (i = 0; i < cursorLocation.lineIndex; i++) {\n topOffset += this._getHeightOfLine(this.ctx, i);\n }\n\n if (typeOfBoundaries === 'cursor') {\n topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, cursorLocation.lineIndex)\n / this.lineHeight - this.getCurrentCharFontSize(cursorLocation.lineIndex, cursorLocation.charIndex)\n * (1 - this._fontSizeFraction);\n }\n\n return {\n top: topOffset,\n left: leftOffset,\n lineLeft: lineLeftOffset\n };\n },\n\n getMinWidth: function() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n },\n\n /**\n * Returns object representation of an instance\n * @method toObject\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject: function(propertiesToInclude) {\n return this.callSuper('toObject', ['minWidth'].concat(propertiesToInclude));\n }\n });\n\n /**\n * Returns fabric.Textbox instance from an object representation\n * @static\n * @memberOf fabric.Textbox\n * @param {Object} object Object to create an instance from\n * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created\n * @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first\n * @return {fabric.Textbox} instance of fabric.Textbox\n */\n fabric.Textbox.fromObject = function(object, callback, forceAsync) {\n return fabric.Object._fromObject('Textbox', object, callback, forceAsync, 'text');\n };\n\n /**\n * Returns the default controls visibility required for Textboxes.\n * @returns {Object}\n */\n fabric.Textbox.getTextboxControlVisibility = function() {\n return {\n tl: false,\n tr: false,\n br: false,\n bl: false,\n ml: true,\n mt: false,\n mr: true,\n mb: false,\n mtr: true\n };\n };\n\n})(typeof exports !== 'undefined' ? exports : this);\n\n\n(function() {\n\n /**\n * Override _setObjectScale and add Textbox specific resizing behavior. Resizing\n * a Textbox doesn't scale text, it only changes width and makes text wrap automatically.\n */\n var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;\n\n fabric.Canvas.prototype._setObjectScale = function(localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {\n\n var t = transform.target;\n if (t instanceof fabric.Textbox) {\n var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));\n if (w >= t.getMinWidth()) {\n t.set('width', w);\n return true;\n }\n }\n else {\n return setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,\n lockScalingX, lockScalingY, by, lockScalingFlip, _dim);\n }\n };\n\n /**\n * Sets controls of this group to the Textbox's special configuration if\n * one is present in the group. Deletes _controlsVisibility otherwise, so that\n * it gets initialized to default value at runtime.\n */\n fabric.Group.prototype._refreshControlsVisibility = function() {\n if (typeof fabric.Textbox === 'undefined') {\n return;\n }\n for (var i = this._objects.length; i--;) {\n if (this._objects[i] instanceof fabric.Textbox) {\n this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());\n return;\n }\n }\n };\n\n fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.IText.prototype */ {\n /**\n * @private\n */\n _removeExtraneousStyles: function() {\n for (var prop in this._styleMap) {\n if (!this._textLines[prop]) {\n delete this.styles[this._styleMap[prop].line];\n }\n }\n },\n\n /**\n * Inserts style object for a given line/char index\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Object} [style] Style object to insert, if given\n */\n insertCharStyleObject: function(lineIndex, charIndex, style) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertCharStyleObject.apply(this, [lineIndex, charIndex, style]);\n },\n\n /**\n * Inserts new style object\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Boolean} isEndOfLine True if it's end of line\n */\n insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {\n // adjust lineIndex and charIndex\n var map = this._styleMap[lineIndex];\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n\n fabric.IText.prototype.insertNewlineStyleObject.apply(this, [lineIndex, charIndex, isEndOfLine]);\n },\n\n /**\n * Shifts line styles up or down. This function is slightly different than the one in\n * itext_behaviour as it takes into account the styleMap.\n *\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can be -1 or +1\n */\n shiftLineStyles: function(lineIndex, offset) {\n // shift all line styles by 1 upward\n var map = this._styleMap[lineIndex];\n // adjust line index\n lineIndex = map.line;\n fabric.IText.prototype.shiftLineStyles.call(this, lineIndex, offset);\n },\n\n /**\n * Figure out programatically the text on previous actual line (actual = separated by \\n);\n *\n * @param {Number} lIndex\n * @returns {String}\n * @private\n */\n _getTextOnPreviousLine: function(lIndex) {\n var textOnPreviousLine = this._textLines[lIndex - 1];\n\n while (this._styleMap[lIndex - 2] && this._styleMap[lIndex - 2].line === this._styleMap[lIndex - 1].line) {\n textOnPreviousLine = this._textLines[lIndex - 2] + textOnPreviousLine;\n\n lIndex--;\n }\n\n return textOnPreviousLine;\n },\n\n /**\n * Removes style object\n * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line\n * @param {Number} [index] Optional index. When not given, current selectionStart is used.\n */\n removeStyleObject: function(isBeginningOfLine, index) {\n\n var cursorLocation = this.get2DCursorLocation(index),\n map = this._styleMap[cursorLocation.lineIndex],\n lineIndex = map.line,\n charIndex = map.offset + cursorLocation.charIndex;\n this._removeStyleObject(isBeginningOfLine, cursorLocation, lineIndex, charIndex);\n }\n });\n})();\n\n\n(function() {\n var override = fabric.IText.prototype._getNewSelectionStartFromOffset;\n /**\n * Overrides the IText implementation and adjusts character index as there is not always a linebreak\n *\n * @param {Number} mouseOffset\n * @param {Number} prevWidth\n * @param {Number} width\n * @param {Number} index\n * @param {Number} jlen\n * @returns {Number}\n */\n fabric.IText.prototype._getNewSelectionStartFromOffset = function(mouseOffset, prevWidth, width, index, jlen) {\n index = override.call(this, mouseOffset, prevWidth, width, index, jlen);\n\n // the index passed into the function is padded by the amount of lines from _textLines (to account for \\n)\n // we need to remove this padding, and pad it by actual lines, and / or spaces that are meant to be there\n var tmp = 0,\n removed = 0;\n\n // account for removed characters\n for (var i = 0; i < this._textLines.length; i++) {\n tmp += this._textLines[i].length;\n\n if (tmp + removed >= index) {\n break;\n }\n\n if (this.text[tmp + removed] === '\\n' || this.text[tmp + removed] === ' ') {\n removed++;\n }\n }\n\n return index - i + removed;\n };\n})();\n\n\n(function() {\n\n if (typeof document !== 'undefined' && typeof window !== 'undefined') {\n return;\n }\n\n var DOMParser = require('xmldom').DOMParser,\n URL = require('url'),\n HTTP = require('http'),\n HTTPS = require('https'),\n\n Canvas = require('canvas'),\n Image = require('canvas').Image;\n\n /** @private */\n function request(url, encoding, callback) {\n var oURL = URL.parse(url);\n\n // detect if http or https is used\n if ( !oURL.port ) {\n oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80;\n }\n\n // assign request handler based on protocol\n var reqHandler = (oURL.protocol.indexOf('https:') === 0 ) ? HTTPS : HTTP,\n req = reqHandler.request({\n hostname: oURL.hostname,\n port: oURL.port,\n path: oURL.path,\n method: 'GET'\n }, function(response) {\n var body = '';\n if (encoding) {\n response.setEncoding(encoding);\n }\n response.on('end', function () {\n callback(body);\n });\n response.on('data', function (chunk) {\n if (response.statusCode === 200) {\n body += chunk;\n }\n });\n });\n\n req.on('error', function(err) {\n if (err.errno === process.ECONNREFUSED) {\n fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port);\n }\n else {\n fabric.log(err.message);\n }\n callback(null);\n });\n\n req.end();\n }\n\n /** @private */\n function requestFs(path, callback) {\n var fs = require('fs');\n fs.readFile(path, function (err, data) {\n if (err) {\n fabric.log(err);\n throw err;\n }\n else {\n callback(data);\n }\n });\n }\n\n fabric.util.loadImage = function(url, callback, context) {\n function createImageAndCallBack(data) {\n if (data) {\n img.src = new Buffer(data, 'binary');\n // preserving original url, which seems to be lost in node-canvas\n img._src = url;\n callback && callback.call(context, img);\n }\n else {\n img = null;\n callback && callback.call(context, null, true);\n }\n }\n var img = new Image();\n if (url && (url instanceof Buffer || url.indexOf('data') === 0)) {\n img.src = img._src = url;\n callback && callback.call(context, img);\n }\n else if (url && url.indexOf('http') !== 0) {\n requestFs(url, createImageAndCallBack);\n }\n else if (url) {\n request(url, 'binary', createImageAndCallBack);\n }\n else {\n callback && callback.call(context, url);\n }\n };\n\n fabric.loadSVGFromURL = function(url, callback, reviver) {\n url = url.replace(/^\\n\\s*/, '').replace(/\\?.*$/, '').trim();\n if (url.indexOf('http') !== 0) {\n requestFs(url, function(body) {\n fabric.loadSVGFromString(body.toString(), callback, reviver);\n });\n }\n else {\n request(url, '', function(body) {\n fabric.loadSVGFromString(body, callback, reviver);\n });\n }\n };\n\n fabric.loadSVGFromString = function(string, callback, reviver) {\n var doc = new DOMParser().parseFromString(string);\n fabric.parseSVGDocument(doc.documentElement, function(results, options) {\n callback && callback(results, options);\n }, reviver);\n };\n\n fabric.util.getScript = function(url, callback) {\n request(url, '', function(body) {\n // eslint-disable-next-line no-eval\n eval(body);\n callback && callback();\n });\n };\n\n // fabric.util.createCanvasElement = function(_, width, height) {\n // return new Canvas(width, height);\n // }\n\n /**\n * Only available when running fabric on node.js\n * @param {Number} width Canvas width\n * @param {Number} height Canvas height\n * @param {Object} [options] Options to pass to FabricCanvas.\n * @param {Object} [nodeCanvasOptions] Options to pass to NodeCanvas.\n * @return {Object} wrapped canvas instance\n */\n fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) {\n nodeCanvasOptions = nodeCanvasOptions || options;\n\n var canvasEl = fabric.document.createElement('canvas'),\n nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions),\n nodeCacheCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions);\n\n // jsdom doesn't create style on canvas element, so here be temp. workaround\n canvasEl.style = { };\n\n canvasEl.width = nodeCanvas.width;\n canvasEl.height = nodeCanvas.height;\n options = options || { };\n options.nodeCanvas = nodeCanvas;\n options.nodeCacheCanvas = nodeCacheCanvas;\n var FabricCanvas = fabric.Canvas || fabric.StaticCanvas,\n fabricCanvas = new FabricCanvas(canvasEl, options);\n fabricCanvas.nodeCanvas = nodeCanvas;\n fabricCanvas.nodeCacheCanvas = nodeCacheCanvas;\n fabricCanvas.contextContainer = nodeCanvas.getContext('2d');\n fabricCanvas.contextCache = nodeCacheCanvas.getContext('2d');\n fabricCanvas.Font = Canvas.Font;\n return fabricCanvas;\n };\n\n var originaInitStatic = fabric.StaticCanvas.prototype._initStatic;\n fabric.StaticCanvas.prototype._initStatic = function(el, options) {\n el = el || fabric.document.createElement('canvas');\n this.nodeCanvas = new Canvas(el.width, el.height);\n this.nodeCacheCanvas = new Canvas(el.width, el.height);\n originaInitStatic.call(this, el, options);\n this.contextContainer = this.nodeCanvas.getContext('2d');\n this.contextCache = this.nodeCacheCanvas.getContext('2d');\n this.Font = Canvas.Font;\n };\n\n /** @ignore */\n fabric.StaticCanvas.prototype.createPNGStream = function() {\n return this.nodeCanvas.createPNGStream();\n };\n\n fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {\n return this.nodeCanvas.createJPEGStream(opts);\n };\n\n fabric.StaticCanvas.prototype._initRetinaScaling = function() {\n if (!this._isRetinaScaling()) {\n return;\n }\n\n this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);\n this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);\n this.nodeCanvas.width = this.width * fabric.devicePixelRatio;\n this.nodeCanvas.height = this.height * fabric.devicePixelRatio;\n this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype._initRetinaScaling = fabric.StaticCanvas.prototype._initRetinaScaling;\n }\n\n var origSetBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension;\n fabric.StaticCanvas.prototype._setBackstoreDimension = function(prop, value) {\n origSetBackstoreDimension.call(this, prop, value);\n this.nodeCanvas[prop] = value;\n return this;\n };\n if (fabric.Canvas) {\n fabric.Canvas.prototype._setBackstoreDimension = fabric.StaticCanvas.prototype._setBackstoreDimension;\n }\n\n})();\n\n"]}