fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 1.6 MB
Source Map (JSON)
{"version":3,"file":"index.min.mjs","sources":["../src/config.ts","../src/util/internals/console.ts","../src/filters/GLProbes/GLProbe.ts","../src/filters/GLProbes/WebGLProbe.ts","../src/env/browser.ts","../src/env/index.ts","../src/cache.ts","../src/constants.ts","../src/ClassRegistry.ts","../src/util/animation/AnimationRegistry.ts","../src/Observable.ts","../src/util/internals/removeFromArray.ts","../src/util/misc/cos.ts","../src/util/misc/sin.ts","../src/Point.ts","../src/Collection.ts","../src/CommonMethods.ts","../src/util/animation/AnimationFrameProvider.ts","../src/util/internals/uid.ts","../src/util/misc/dom.ts","../src/util/misc/radiansDegreesConversion.ts","../src/util/misc/matrix.ts","../src/util/misc/objectEnlive.ts","../src/util/misc/pick.ts","../src/util/misc/toFixed.ts","../src/util/misc/svgExport.ts","../src/util/typeAssertions.ts","../src/util/dom_misc.ts","../src/canvas/DOMManagers/util.ts","../src/canvas/DOMManagers/StaticCanvasDOMManager.ts","../src/canvas/StaticCanvasOptions.ts","../src/canvas/StaticCanvas.ts","../src/util/dom_event.ts","../src/util/misc/boundingBoxFromPoints.ts","../src/util/misc/objectTransforms.ts","../src/util/misc/planeChange.ts","../src/util/misc/resolveOrigin.ts","../src/util/misc/vectors.ts","../src/controls/util.ts","../src/util/internals/normalizeWhiteSpace.ts","../src/color/color_map.ts","../src/color/util.ts","../src/color/Color.ts","../src/color/constants.ts","../src/util/misc/svgParsing.ts","../src/shapes/Object/FabricObjectSVGExportMixin.ts","../src/parser/getSvgRegex.ts","../src/shapes/Text/constants.ts","../src/parser/constants.ts","../src/Shadow.ts","../src/util/misc/capValue.ts","../src/shapes/Object/defaultValues.ts","../src/util/animation/easing.ts","../src/util/animation/AnimationBase.ts","../src/util/animation/ValueAnimation.ts","../src/util/animation/ArrayAnimation.ts","../src/util/animation/ColorAnimation.ts","../src/util/animation/animate.ts","../src/Intersection.ts","../src/shapes/Object/ObjectGeometry.ts","../src/shapes/Object/Object.ts","../src/controls/fireEvent.ts","../src/controls/wrapWithFireEvent.ts","../src/controls/wrapWithFixedAnchor.ts","../src/controls/changeWidth.ts","../src/controls/controlRendering.ts","../src/controls/Control.ts","../src/controls/rotate.ts","../src/controls/scale.ts","../src/controls/skew.ts","../src/controls/scaleSkew.ts","../src/controls/commonControls.ts","../src/shapes/Object/InteractiveObject.ts","../src/util/applyMixins.ts","../src/shapes/Object/FabricObject.ts","../src/util/misc/isTransparent.ts","../src/util/misc/projectStroke/StrokeProjectionsBase.ts","../src/util/misc/projectStroke/StrokeLineJoinProjections.ts","../src/util/misc/projectStroke/StrokeLineCapProjections.ts","../src/util/misc/projectStroke/index.ts","../src/util/internals/findRight.ts","../src/util/internals/cloneStyles.ts","../src/util/lang_string.ts","../src/util/misc/textStyles.ts","../src/parser/attributes.ts","../src/parser/selectorMatches.ts","../src/parser/elementMatchesRule.ts","../src/parser/doesSomeParentMatch.ts","../src/parser/getGlobalStylesForElement.ts","../src/parser/normalizeAttr.ts","../src/util/internals/cleanupSvgAttribute.ts","../src/parser/parseTransformAttribute.ts","../src/parser/normalizeValue.ts","../src/parser/parseStyleString.ts","../src/parser/parseStyleAttribute.ts","../src/parser/parseStyleObject.ts","../src/parser/setStrokeFillOpacity.ts","../src/parser/parseAttributes.ts","../src/parser/parseFontDeclaration.ts","../src/shapes/Rect.ts","../src/LayoutManager/constants.ts","../src/LayoutManager/LayoutStrategies/utils.ts","../src/LayoutManager/LayoutStrategies/LayoutStrategy.ts","../src/LayoutManager/LayoutStrategies/FitContentLayout.ts","../src/LayoutManager/LayoutManager.ts","../src/shapes/Group.ts","../src/util/misc/groupSVGElements.ts","../src/util/misc/findScaleTo.ts","../src/util/path/regex.ts","../src/util/path/index.ts","../src/util/internals/getRandomInt.ts","../src/util/transform_matrix_removal.ts","../src/util/misc/mergeClipPaths.ts","../src/util/internals/dom_style.ts","../src/canvas/DOMManagers/CanvasDOMManager.ts","../src/canvas/CanvasOptions.ts","../src/controls/drag.ts","../src/controls/polyControl.ts","../src/controls/pathControl.ts","../src/canvas/SelectableCanvas.ts","../src/canvas/TextEditingManager.ts","../src/canvas/Canvas.ts","../src/gradient/constants.ts","../src/util/internals/ifNaN.ts","../src/parser/percent.ts","../src/gradient/parser/parseColorStops.ts","../src/gradient/parser/misc.ts","../src/gradient/parser/parseCoords.ts","../src/gradient/Gradient.ts","../src/Pattern/Pattern.ts","../src/brushes/BaseBrush.ts","../src/shapes/Path.ts","../src/brushes/PencilBrush.ts","../src/shapes/Circle.ts","../src/brushes/CircleBrush.ts","../src/brushes/SprayBrush.ts","../src/brushes/PatternBrush.ts","../src/shapes/Line.ts","../src/shapes/Triangle.ts","../src/shapes/Ellipse.ts","../src/shapes/Polyline.ts","../src/parser/parsePointsAttribute.ts","../src/shapes/Polygon.ts","../src/shapes/Text/StyledText.ts","../src/shapes/Text/TextSVGExportMixin.ts","../src/shapes/Text/Text.ts","../src/shapes/IText/DraggableTextDelegate.ts","../src/shapes/IText/ITextBehavior.ts","../src/shapes/IText/ITextKeyBehavior.ts","../src/shapes/IText/ITextClickBehavior.ts","../src/shapes/IText/constants.ts","../src/util/internals/applyCanvasTransform.ts","../src/shapes/IText/IText.ts","../src/shapes/Textbox.ts","../src/LayoutManager/LayoutStrategies/ClipPathLayout.ts","../src/LayoutManager/LayoutStrategies/FixedLayout.ts","../src/LayoutManager/ActiveSelectionLayoutManager.ts","../src/shapes/ActiveSelection.ts","../src/filters/Canvas2dFilterBackend.ts","../src/filters/WebGLFilterBackend.ts","../src/filters/FilterBackend.ts","../src/shapes/Image.ts","../src/parser/applyViewboxTransform.ts","../src/parser/getTagName.ts","../src/parser/hasInvalidAncestor.ts","../src/parser/getMultipleNodes.ts","../src/parser/recursivelyParseGradientsXlink.ts","../src/parser/getGradientDefs.ts","../src/parser/elements_parser.ts","../src/parser/getCSSRules.ts","../src/parser/parseSVGDocument.ts","../src/parser/parseUseDirectives.ts","../src/parser/loadSVGFromString.ts","../src/parser/loadSVGFromURL.ts","../src/filters/utils.ts","../src/filters/shaders/baseFilter.ts","../src/filters/BaseFilter.ts","../src/filters/shaders/blendColor.ts","../src/filters/BlendColor.ts","../src/filters/shaders/blendImage.ts","../src/filters/BlendImage.ts","../src/filters/Blur.ts","../src/filters/shaders/blur.ts","../src/filters/Brightness.ts","../src/filters/shaders/brightness.ts","../src/filters/shaders/colorMatrix.ts","../src/filters/ColorMatrix.ts","../src/filters/ColorMatrixFilters.ts","../src/filters/Composed.ts","../src/filters/Contrast.ts","../src/filters/shaders/constrast.ts","../src/filters/shaders/convolute.ts","../src/filters/Convolute.ts","../src/filters/shaders/gamma.ts","../src/filters/Gamma.ts","../src/filters/shaders/grayscale.ts","../src/filters/Grayscale.ts","../src/filters/HueRotation.ts","../src/filters/Invert.ts","../src/filters/shaders/invert.ts","../src/filters/Noise.ts","../src/filters/shaders/noise.ts","../src/filters/Pixelate.ts","../src/filters/shaders/pixelate.ts","../src/filters/RemoveColor.ts","../src/filters/shaders/removeColor.ts","../src/filters/Resize.ts","../src/filters/Saturation.ts","../src/filters/shaders/saturation.ts","../src/filters/Vibrance.ts","../src/filters/shaders/vibrance.ts"],"sourcesContent":["export type TConfiguration = Partial<BaseConfiguration>;\n\nclass BaseConfiguration {\n /**\n * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value,\n * which is unitless and not rendered equally across browsers.\n *\n * Values that work quite well (as of October 2017) are:\n * - Chrome: 1.5\n * - Edge: 1.75\n * - Firefox: 0.9\n * - Safari: 0.95\n *\n * @since 2.0.0\n * @type Number\n * @default 1\n */\n browserShadowBlurConstant = 1;\n\n /**\n * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.\n */\n DPI = 96;\n\n /**\n * Device Pixel Ratio\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n */\n devicePixelRatio =\n typeof window !== 'undefined' ? window.devicePixelRatio : 1; // eslint-disable-line no-restricted-globals\n\n /**\n * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine.\n * @since 1.7.14\n * @type Number\n */\n 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 */\n maxCacheSideLimit = 4096;\n\n /**\n * Lowest pixel limit for cache canvases, set at 256PX\n * @since 1.7.14\n * @type Number\n */\n minCacheSideLimit = 256;\n\n /**\n * When 'true', style information is not retained when copy/pasting text, making\n * pasted text use destination style.\n * Defaults to 'false'.\n * @type Boolean\n * @deprecated\n */\n disableStyleCopyPaste = false;\n\n /**\n * Enable webgl for filtering picture is available\n * A filtering backend will be initialized, this will both take memory and\n * time since a default 2048x2048 canvas will be created for the gl context\n * @since 2.0.0\n * @type Boolean\n */\n enableGLFiltering = true;\n\n /**\n * if webgl is enabled and available, textureSize will determine the size\n * of the canvas backend\n *\n * In order to support old hardware set to `2048` to avoid OOM\n *\n * @since 2.0.0\n * @type Number\n */\n textureSize = 4096;\n\n /**\n * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on\n * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true\n * this has to be set before instantiating the filtering backend ( before filtering the first image )\n * @type Boolean\n * @default false\n */\n forceGLPutImageData = false;\n\n /**\n * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better\n * With the standard behaviour of fabric to translate all curves in absolute commands and by not subtracting the starting point from\n * the curve is very hard to hit any cache.\n * Enable only if you know why it could be useful.\n * Candidate for removal/simplification\n * @default false\n */\n cachesBoundsOfCurve = false;\n\n /**\n * Map of font files\n * Map<fontFamily, pathToFile> of font files\n */\n fontPaths: Record</** fontFamily */ string, /** pathToFile */ string> = {};\n\n /**\n * Defines the number of fraction digits to use when serializing object values.\n * Used in exporting methods (`toObject`, `toJSON`, `toSVG`)\n * You can use it to increase/decrease precision of such values like left, top, scaleX, scaleY, etc.\n */\n NUM_FRACTION_DIGITS = 4;\n}\n\nexport class Configuration extends BaseConfiguration {\n constructor(config?: TConfiguration) {\n super();\n this.configure(config);\n }\n\n configure(config: TConfiguration = {}) {\n Object.assign(this, config);\n }\n\n /**\n * Map<fontFamily, pathToFile> of font files\n */\n addFonts(\n paths: Record</** fontFamily */ string, /** pathToFile */ string> = {},\n ) {\n this.fontPaths = {\n ...this.fontPaths,\n ...paths,\n };\n }\n\n removeFonts(fontFamilys: string[] = []) {\n fontFamilys.forEach((fontFamily) => {\n delete this.fontPaths[fontFamily];\n });\n }\n\n clearFonts() {\n this.fontPaths = {};\n }\n\n restoreDefaults<T extends BaseConfiguration>(keys?: (keyof T)[]) {\n const defaults = new BaseConfiguration() as T;\n const config =\n keys?.reduce((acc, key) => {\n acc[key] = defaults[key];\n return acc;\n }, {} as T) || defaults;\n this.configure(config);\n }\n}\n\nexport const config = new Configuration();\n","export const log = (\n severity: 'log' | 'warn' | 'error',\n ...optionalParams: any[]\n) =>\n // eslint-disable-next-line no-restricted-syntax\n console[severity]('fabric', ...optionalParams);\n\nexport class FabricError extends Error {\n constructor(message?: string, options?: ErrorOptions) {\n super(`fabric: ${message}`, options);\n }\n}\n\nexport class SignalAbortedError extends FabricError {\n constructor(context: string) {\n super(`${context} 'options.signal' is in 'aborted' state`);\n }\n}\n","export type GLPrecision = 'lowp' | 'mediump' | 'highp';\n\nexport abstract class GLProbe {\n declare GLPrecision: GLPrecision | undefined;\n abstract queryWebGL(canvas: HTMLCanvasElement): void;\n abstract isSupported(textureSize: number): boolean;\n}\n","import { log } from '../../util/internals/console';\nimport { GLProbe } from './GLProbe';\nimport type { GLPrecision } from './GLProbe';\n\n/**\n * Lazy initialize WebGL constants\n */\nexport class WebGLProbe extends GLProbe {\n declare maxTextureSize?: number;\n\n /**\n * Tests if webgl supports certain precision\n * @param {WebGL} Canvas WebGL context to test on\n * @param {GLPrecision} Precision to test can be any of following\n * @returns {Boolean} Whether the user's browser WebGL supports given precision.\n */\n private testPrecision(\n gl: WebGLRenderingContext,\n precision: GLPrecision,\n ): boolean {\n const fragmentSource = `precision ${precision} float;\\nvoid main(){}`;\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n if (!fragmentShader) {\n return false;\n }\n gl.shaderSource(fragmentShader, fragmentSource);\n gl.compileShader(fragmentShader);\n return !!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS);\n }\n\n /**\n * query browser for WebGL\n */\n queryWebGL(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext('webgl');\n if (gl) {\n this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n this.GLPrecision = (['highp', 'mediump', 'lowp'] as const).find(\n (precision) => this.testPrecision(gl, precision),\n );\n gl.getExtension('WEBGL_lose_context')!.loseContext();\n log('log', `WebGL: max texture size ${this.maxTextureSize}`);\n }\n }\n\n isSupported(textureSize: number) {\n return !!this.maxTextureSize && this.maxTextureSize >= textureSize;\n }\n}\n","/* eslint-disable no-restricted-globals */\nimport { WebGLProbe } from '../filters/GLProbes/WebGLProbe';\nimport type { TCopyPasteData, TFabricEnv } from './types';\n\nconst copyPasteData: TCopyPasteData = {};\n\nexport const getEnv = (): TFabricEnv => {\n return {\n document,\n window,\n isTouchSupported:\n 'ontouchstart' in window ||\n 'ontouchstart' in document ||\n (window && window.navigator && window.navigator.maxTouchPoints > 0),\n WebGLProbe: new WebGLProbe(),\n dispose() {\n // noop\n },\n copyPasteData,\n };\n};\n","/**\n * This file is consumed by fabric.\n * The `./node` and `./browser` files define the env variable that is used by this module.\n * The `./browser` module is defined to be the default env and doesn't set the env at all.\n * This is done in order to support isomorphic usage for browser and node applications\n * since window and document aren't defined at time of import in SSR, we can't set env so we avoid it by deferring to the default env.\n */\n\nimport { config } from '../config';\nimport { getEnv as getBrowserEnv } from './browser';\nimport type { TFabricEnv } from './types';\nimport type { DOMWindow } from 'jsdom';\n\nlet env: TFabricEnv;\n\n/**\n * Sets the environment variables used by fabric.\\\n * This is exposed for special cases, such as configuring a test environment, and should be used with care.\n *\n * **CAUTION**: Must be called before using the package.\n *\n * @example\n * <caption>Passing `window` and `document` objects to fabric (in case they are mocked or something)</caption>\n * import { getEnv, setEnv } from 'fabric';\n * // we want fabric to use the `window` and `document` objects exposed by the environment we are running in.\n * setEnv({ ...getEnv(), window, document });\n * // done with setup, using fabric is now safe\n */\nexport const setEnv = (value: TFabricEnv) => {\n env = value;\n};\n\n/**\n * In order to support SSR we **MUST** access the browser env only after the window has loaded\n */\nexport const getEnv = () => env || (env = getBrowserEnv());\n\nexport const getFabricDocument = (): Document => getEnv().document;\n\nexport const getFabricWindow = (): (Window & typeof globalThis) | DOMWindow =>\n getEnv().window;\n\n/**\n * @returns the config value if defined, fallbacks to the environment value\n */\nexport const getDevicePixelRatio = () =>\n Math.max(config.devicePixelRatio ?? getFabricWindow().devicePixelRatio, 1);\n","import { config } from './config';\nimport type { TRectBounds } from './typedefs';\n\ntype TextCouplesCache = Map</** char */ string, /** width */ number>;\n\ntype FamilyCache = Map</** fontStyleCacheKey */ string, TextCouplesCache>;\n\nexport class Cache {\n /**\n * Cache of widths of chars in text rendering.\n */\n declare charWidthsCache: Map</** fontFamily */ string, FamilyCache>;\n\n constructor() {\n this.charWidthsCache = new Map();\n }\n\n /**\n * @return {Object} reference to cache\n */\n getFontCache({\n fontFamily,\n fontStyle,\n fontWeight,\n }: {\n fontFamily: string;\n fontStyle: string;\n fontWeight: string | number;\n }): TextCouplesCache {\n fontFamily = fontFamily.toLowerCase();\n const cache = this.charWidthsCache;\n if (!cache.has(fontFamily)) {\n cache.set(fontFamily, new Map<string, TextCouplesCache>());\n }\n const fontCache = cache.get(fontFamily)!;\n const cacheKey = `${fontStyle.toLowerCase()}_${(\n fontWeight + ''\n ).toLowerCase()}`;\n if (!fontCache.has(cacheKey)) {\n fontCache.set(cacheKey, new Map<string, number>());\n }\n return fontCache.get(cacheKey)!;\n }\n\n /**\n * Clear char widths cache for the given font family or all the cache if no\n * fontFamily is specified.\n * Use it if you know you are loading fonts in a lazy way and you are not waiting\n * for custom fonts to load properly when adding text objects to the canvas.\n * If a text object is added when its own font is not loaded yet, you will get wrong\n * measurement and so wrong bounding boxes.\n * After the font cache is cleared, either change the textObject text content or call\n * initDimensions() to trigger a recalculation\n * @param {String} [fontFamily] font family to clear\n */\n clearFontCache(fontFamily?: string) {\n if (!fontFamily) {\n this.charWidthsCache = new Map();\n } else {\n this.charWidthsCache.delete((fontFamily || '').toLowerCase());\n }\n }\n\n /**\n * Given current aspect ratio, determines the max width and height that can\n * respect the total allowed area for the cache.\n * @param {number} ar aspect ratio\n * @return {number[]} Limited dimensions X and Y\n */\n limitDimsByArea(ar: number) {\n const { perfLimitSizeTotal } = config;\n const roughWidth = Math.sqrt(perfLimitSizeTotal * ar);\n // we are not returning a point on purpose, to avoid circular dependencies\n // this is an internal utility\n return [\n Math.floor(roughWidth),\n Math.floor(perfLimitSizeTotal / roughWidth),\n ];\n }\n\n /**\n * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.\n * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing\n * you do not get any speed benefit and you get a big object in memory.\n * The object was a private variable before, while now is appended to the lib so that you have access to it and you\n * can eventually clear it.\n * It was an internal variable, is accessible since version 2.3.4\n */\n boundsOfCurveCache: Record<string, TRectBounds> = {};\n}\n\nexport const cache = new Cache();\n","import type { TMat2D } from './typedefs';\n// use this syntax so babel plugin see this import here\nimport { version } from '../package.json';\n\nexport const VERSION = version;\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nexport function noop() {}\n\nexport const halfPI = Math.PI / 2;\nexport const quarterPI = Math.PI / 4;\nexport const twoMathPi = Math.PI * 2;\nexport const PiBy180 = Math.PI / 180;\n\nexport const iMatrix = Object.freeze([1, 0, 0, 1, 0, 0]) as TMat2D;\nexport const DEFAULT_SVG_FONT_SIZE = 16;\nexport const ALIASING_LIMIT = 2;\n\n/* \"magic number\" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */\nexport const kRect = 1 - 0.5522847498;\n\nexport const CENTER = 'center';\nexport const LEFT = 'left';\nexport const TOP = 'top';\nexport const BOTTOM = 'bottom';\nexport const RIGHT = 'right';\nexport const NONE = 'none';\nexport const HEIGHT = 'height';\n\nexport const reNewline = /\\r?\\n/;\n\nexport const MOVING = 'moving';\nexport const SCALING = 'scaling';\nexport const ROTATING = 'rotating';\nexport const ROTATE = 'rotate';\nexport const SKEWING = 'skewing';\nexport const RESIZING = 'resizing';\nexport const MODIFY_POLY = 'modifyPoly';\nexport const MODIFY_PATH = 'modifyPath';\nexport const CHANGED = 'changed';\nexport const SCALE = 'scale';\nexport const SCALE_X = 'scaleX';\nexport const SCALE_Y = 'scaleY';\nexport const SKEW_X = 'skewX';\nexport const SKEW_Y = 'skewY';\nexport const FILL = 'fill';\nexport const STROKE = 'stroke';\nexport const MODIFIED = 'modified';\n\nexport const LTR = 'ltr';\nexport const RTL = 'rtl';\n\nexport const NORMAL = 'normal';\n","import { FabricError } from './util/internals/console';\n\n/*\n * This Map connects the objects type value with their\n * class implementation. It used from any object to understand which are\n * the classes to enlive when requesting a object.type = 'path' for example.\n * Objects uses it for clipPath, Canvas uses it for everything.\n * This is necessary for generic code to run and enlive instances from serialized representation.\n * You can customize which classes get enlived from SVG parsing using this classRegistry.\n * The Registry start empty and gets filled in depending which files you import.\n * If you want to be able to parse arbitrary SVGs or JSON representation of canvases, coming from\n * different sources you will need to import all fabric because you may need all classes.\n */\n\nexport const JSON = 'json';\nexport const SVG = 'svg';\n\nexport class ClassRegistry {\n declare [JSON]: Map<string, any>;\n declare [SVG]: Map<string, any>;\n\n constructor() {\n this[JSON] = new Map();\n this[SVG] = new Map();\n }\n\n has(classType: string): boolean {\n return this[JSON].has(classType);\n }\n\n getClass<T>(classType: string): T {\n const constructor = this[JSON].get(classType);\n if (!constructor) {\n throw new FabricError(`No class registered for ${classType}`);\n }\n return constructor;\n }\n\n setClass(classConstructor: any, classType?: string) {\n if (classType) {\n this[JSON].set(classType, classConstructor);\n } else {\n this[JSON].set(classConstructor.type, classConstructor);\n // legacy\n // @TODO: needs to be removed in fabric 7 or 8\n this[JSON].set(classConstructor.type.toLowerCase(), classConstructor);\n }\n }\n\n getSVGClass(SVGTagName: string): any {\n return this[SVG].get(SVGTagName);\n }\n\n setSVGClass(classConstructor: any, SVGTagName?: string) {\n this[SVG].set(\n SVGTagName ?? classConstructor.type.toLowerCase(),\n classConstructor,\n );\n }\n}\n\nexport const classRegistry = new ClassRegistry();\n","import type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type { AnimationBase } from './AnimationBase';\n\n/**\n * Array holding all running animations\n */\nclass AnimationRegistry extends Array<AnimationBase> {\n /**\n * Remove a single animation using an animation context\n * @param {AnimationBase} context\n */\n remove(context: AnimationBase) {\n const index = this.indexOf(context);\n index > -1 && this.splice(index, 1);\n }\n\n /**\n * Cancel all running animations on the next frame\n */\n cancelAll() {\n const animations = this.splice(0);\n animations.forEach((animation) => animation.abort());\n return animations;\n }\n\n /**\n * Cancel all running animations attached to a canvas on the next frame\n * @param {StaticCanvas} canvas\n */\n cancelByCanvas(canvas: StaticCanvas) {\n if (!canvas) {\n return [];\n }\n const animations = this.filter(\n (animation) =>\n animation.target === canvas ||\n (typeof animation.target === 'object' &&\n (animation.target as FabricObject)?.canvas === canvas),\n );\n animations.forEach((animation) => animation.abort());\n return animations;\n }\n\n /**\n * Cancel all running animations for target on the next frame\n * @param target\n */\n cancelByTarget(target: AnimationBase['target']) {\n if (!target) {\n return [];\n }\n const animations = this.filter((animation) => animation.target === target);\n animations.forEach((animation) => animation.abort());\n return animations;\n }\n}\n\nexport const runningAnimations = new AnimationRegistry();\n","export type TEventCallback<T = any> = (options: T) => any;\n\ntype EventRegistryObject<E> = {\n [K in keyof E]?: TEventCallback<E[K]>;\n};\n\n/**\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#events}\n * @see {@link http://fabric5.fabricjs.com/events|Events demo}\n */\nexport class Observable<EventSpec> {\n private __eventListeners: Record<keyof EventSpec, TEventCallback[]> =\n {} as Record<keyof EventSpec, TEventCallback[]>;\n\n /**\n * Observes specified event\n * @alias on\n * @param {string} eventName Event name (eg. 'after:render')\n * @param {EventRegistryObject} handlers 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 {Function} disposer\n */\n on<K extends keyof EventSpec, E extends EventSpec[K]>(\n eventName: K,\n handler: TEventCallback<E>,\n ): VoidFunction;\n on(handlers: EventRegistryObject<EventSpec>): VoidFunction;\n on<K extends keyof EventSpec, E extends EventSpec[K]>(\n arg0: K | EventRegistryObject<EventSpec>,\n handler?: TEventCallback<E>,\n ): VoidFunction {\n if (!this.__eventListeners) {\n this.__eventListeners = {} as Record<keyof EventSpec, TEventCallback[]>;\n }\n if (typeof arg0 === 'object') {\n // one object with key/value pairs was passed\n Object.entries(arg0).forEach(([eventName, handler]) => {\n this.on(eventName as K, handler as TEventCallback);\n });\n return () => this.off(arg0);\n } else if (handler) {\n const eventName = arg0;\n if (!this.__eventListeners[eventName]) {\n this.__eventListeners[eventName] = [];\n }\n this.__eventListeners[eventName].push(handler);\n return () => this.off(eventName, handler);\n } else {\n // noop\n return () => false;\n }\n }\n\n /**\n * Observes specified event **once**\n * @alias once\n * @param {string} eventName Event name (eg. 'after:render')\n * @param {EventRegistryObject} handlers 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 {Function} disposer\n */\n once<K extends keyof EventSpec, E extends EventSpec[K]>(\n eventName: K,\n handler: TEventCallback<E>,\n ): VoidFunction;\n once(handlers: EventRegistryObject<EventSpec>): VoidFunction;\n once<K extends keyof EventSpec, E extends EventSpec[K]>(\n arg0: K | EventRegistryObject<EventSpec>,\n handler?: TEventCallback<E>,\n ): VoidFunction {\n if (typeof arg0 === 'object') {\n // one object with key/value pairs was passed\n const disposers: VoidFunction[] = [];\n Object.entries(arg0).forEach(([eventName, handler]) => {\n disposers.push(this.once(eventName as K, handler as TEventCallback));\n });\n return () => disposers.forEach((d) => d());\n } else if (handler) {\n const disposer = this.on<K, E>(\n arg0,\n function onceHandler(this: Observable<EventSpec>, ...args) {\n handler.call(this, ...args);\n disposer();\n },\n );\n return disposer;\n } else {\n // noop\n return () => false;\n }\n }\n\n /**\n * @private\n * @param {string} eventName\n * @param {Function} [handler]\n */\n private _removeEventListener<K extends keyof EventSpec>(\n eventName: K,\n handler?: TEventCallback,\n ) {\n if (!this.__eventListeners[eventName]) {\n return;\n }\n\n if (handler) {\n const eventListener = this.__eventListeners[eventName];\n const index = eventListener.indexOf(handler);\n index > -1 && eventListener.splice(index, 1);\n } else {\n this.__eventListeners[eventName] = [];\n }\n }\n\n /**\n * Unsubscribe all event listeners for eventname.\n * Do not use this pattern. You could kill internal fabricJS events.\n * We know we should have protected events for internal flows, but we don't have yet\n * @deprecated\n * @param {string} eventName event name (eg. 'after:render')\n */\n off<K extends keyof EventSpec>(eventName: K): void;\n /**\n * unsubscribe an event listener\n * @param {string} eventName event name (eg. 'after:render')\n * @param {TEventCallback} handler event listener to unsubscribe\n */\n off<K extends keyof EventSpec>(eventName: K, handler: TEventCallback): void;\n /**\n * unsubscribe event listeners\n * @param handlers handlers key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n */\n off(handlers: EventRegistryObject<EventSpec>): void;\n /**\n * unsubscribe all event listeners\n */\n off(): void;\n off<K extends keyof EventSpec>(\n arg0?: K | EventRegistryObject<EventSpec>,\n handler?: TEventCallback,\n ) {\n if (!this.__eventListeners) {\n return;\n }\n\n // remove all key/value pairs (event name -> event handler)\n if (typeof arg0 === 'undefined') {\n for (const eventName in this.__eventListeners) {\n this._removeEventListener(eventName);\n }\n }\n // one object with key/value pairs was passed\n else if (typeof arg0 === 'object') {\n Object.entries(arg0).forEach(([eventName, handler]) => {\n this._removeEventListener(eventName as K, handler as TEventCallback);\n });\n } else {\n this._removeEventListener(arg0, handler);\n }\n }\n\n /**\n * Fires event with an optional options object\n * @param {String} eventName Event name to fire\n * @param {Object} [options] Options object\n */\n fire<K extends keyof EventSpec>(eventName: K, options?: EventSpec[K]) {\n if (!this.__eventListeners) {\n return;\n }\n\n const listenersForEvent = this.__eventListeners[eventName]?.concat();\n if (listenersForEvent) {\n for (let i = 0; i < listenersForEvent.length; i++) {\n listenersForEvent[i].call(this, options || {});\n }\n }\n }\n}\n","/**\n * Removes value from an array.\n * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`\n * @param {Array} array\n * @param {*} value\n * @return {Array} original array\n */\nexport const removeFromArray = <T>(array: T[], value: T): T[] => {\n const idx = array.indexOf(value);\n if (idx !== -1) {\n array.splice(idx, 1);\n }\n return array;\n};\n","import type { TRadian } from '../../typedefs';\nimport { halfPI } from '../../constants';\n\n/**\n * Calculate the cos of an angle, avoiding returning floats for known results\n * This function is here just to avoid getting 0.999999999999999 when dealing\n * with numbers that are really 1 or 0.\n * @param {TRadian} angle the angle\n * @return {Number} the cosin value for angle.\n */\nexport const cos = (angle: TRadian): number => {\n if (angle === 0) {\n return 1;\n }\n const angleSlice = Math.abs(angle) / halfPI;\n switch (angleSlice) {\n case 1:\n case 3:\n return 0;\n case 2:\n return -1;\n }\n return Math.cos(angle);\n};\n","import type { TRadian } from '../../typedefs';\nimport { halfPI } from '../../constants';\n\n/**\n * Calculate the cos of an angle, avoiding returning floats for known results\n * This function is here just to avoid getting 0.999999999999999 when dealing\n * with numbers that are really 1 or 0.\n * @param {TRadian} angle the angle\n * @return {Number} the sin value for angle.\n */\nexport const sin = (angle: TRadian): number => {\n if (angle === 0) {\n return 0;\n }\n const angleSlice = angle / halfPI;\n const value = Math.sign(angle);\n switch (angleSlice) {\n case 1:\n return value;\n case 2:\n return 0;\n case 3:\n return -value;\n }\n return Math.sin(angle);\n};\n","import type { TMat2D, TRadian } from './typedefs';\nimport { cos } from './util/misc/cos';\nimport { sin } from './util/misc/sin';\n\nexport interface XY {\n x: number;\n y: number;\n}\n\n/**\n * Adaptation of work of Kevin Lindsey(kevin@kevlindev.com)\n */\nexport class Point implements XY {\n declare x: number;\n\n declare y: number;\n\n constructor();\n constructor(x: number, y: number);\n constructor(point?: XY);\n constructor(arg0: number | XY = 0, y = 0) {\n if (typeof arg0 === 'object') {\n this.x = arg0.x;\n this.y = arg0.y;\n } else {\n this.x = arg0;\n this.y = y;\n }\n }\n\n /**\n * Adds another point to this one and returns a new one with the sum\n * @param {XY} that\n * @return {Point} new Point instance with added values\n */\n add(that: XY): Point {\n return new Point(this.x + that.x, this.y + that.y);\n }\n\n /**\n * Adds another point to this one\n * @param {XY} that\n * @return {Point} thisArg\n * @deprecated\n */\n addEquals(that: XY): Point {\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 {Point} new Point with added value\n */\n scalarAdd(scalar: number): Point {\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 {Point} thisArg\n * @deprecated\n */\n scalarAddEquals(scalar: number): Point {\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 {XY} that\n * @return {Point} new Point object with subtracted values\n */\n subtract(that: XY): Point {\n return new Point(this.x - that.x, this.y - that.y);\n }\n\n /**\n * Subtracts another point from this point\n * @param {XY} that\n * @return {Point} thisArg\n * @deprecated\n */\n subtractEquals(that: XY): Point {\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 {Point}\n */\n scalarSubtract(scalar: number): Point {\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 {Point} thisArg\n * @deprecated\n */\n scalarSubtractEquals(scalar: number): Point {\n this.x -= scalar;\n this.y -= scalar;\n return this;\n }\n\n /**\n * Multiplies this point by another value and returns a new one\n * @param {XY} that\n * @return {Point}\n */\n multiply(that: XY): Point {\n return new Point(this.x * that.x, this.y * that.y);\n }\n\n /**\n * Multiplies this point by a value and returns a new one\n * @param {Number} scalar\n * @return {Point}\n */\n scalarMultiply(scalar: number): Point {\n return new Point(this.x * scalar, this.y * scalar);\n }\n\n /**\n * Multiplies this point by a value\n * @param {Number} scalar\n * @return {Point} thisArg\n * @deprecated\n */\n scalarMultiplyEquals(scalar: number): Point {\n this.x *= scalar;\n this.y *= scalar;\n return this;\n }\n\n /**\n * Divides this point by another and returns a new one\n * @param {XY} that\n * @return {Point}\n */\n divide(that: XY): Point {\n return new Point(this.x / that.x, this.y / that.y);\n }\n\n /**\n * Divides this point by a value and returns a new one\n * @param {Number} scalar\n * @return {Point}\n */\n scalarDivide(scalar: number): Point {\n return new Point(this.x / scalar, this.y / scalar);\n }\n\n /**\n * Divides this point by a value\n * @param {Number} scalar\n * @return {Point} thisArg\n * @deprecated\n */\n scalarDivideEquals(scalar: number): Point {\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 {XY} that\n * @return {Boolean}\n */\n eq(that: XY): boolean {\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 {XY} that\n * @return {Boolean}\n */\n lt(that: XY): boolean {\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 {XY} that\n * @return {Boolean}\n */\n lte(that: XY): boolean {\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 {XY} that\n * @return {Boolean}\n */\n gt(that: XY): boolean {\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 {XY} that\n * @return {Boolean}\n */\n gte(that: XY): boolean {\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 {XY} that\n * @param {Number} t , position of interpolation, between 0 and 1 default 0.5\n * @return {Point}\n */\n lerp(that: XY, t = 0.5): Point {\n t = Math.max(Math.min(1, t), 0);\n return new Point(\n this.x + (that.x - this.x) * t,\n this.y + (that.y - this.y) * t,\n );\n }\n\n /**\n * Returns distance from this point and another one\n * @param {XY} that\n * @return {Number}\n */\n distanceFrom(that: XY): number {\n const 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 {XY} that\n * @return {Point}\n */\n midPointFrom(that: XY): Point {\n return this.lerp(that);\n }\n\n /**\n * Returns a new point which is the min of this and another one\n * @param {XY} that\n * @return {Point}\n */\n min(that: XY): Point {\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 {XY} that\n * @return {Point}\n */\n max(that: XY): Point {\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(): string {\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 */\n setXY(x: number, y: number) {\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 */\n setX(x: number) {\n this.x = x;\n return this;\n }\n\n /**\n * Sets y of this point\n * @param {Number} y\n */\n setY(y: number) {\n this.y = y;\n return this;\n }\n\n /**\n * Sets x/y of this point from another point\n * @param {XY} that\n */\n setFromPoint(that: XY) {\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 {XY} that\n */\n swap(that: XY) {\n const 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 {Point}\n */\n clone(): Point {\n return new Point(this.x, this.y);\n }\n\n /**\n * Rotates `point` around `origin` with `radians`\n * @param {XY} origin The origin of the rotation\n * @param {TRadian} radians The radians of the angle for the rotation\n * @return {Point} The new rotated point\n */\n rotate(radians: TRadian, origin: XY = ZERO): Point {\n // TODO benchmark and verify the add and subtract how much cost\n // and then in case early return if no origin is passed\n const sinus = sin(radians),\n cosinus = cos(radians);\n const p = this.subtract(origin);\n const rotated = new Point(\n p.x * cosinus - p.y * sinus,\n p.x * sinus + p.y * cosinus,\n );\n return rotated.add(origin);\n }\n\n /**\n * Apply transform t to point p\n * @param {TMat2D} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {Point} The transformed point\n */\n transform(t: TMat2D, ignoreOffset = false): Point {\n return new Point(\n t[0] * this.x + t[2] * this.y + (ignoreOffset ? 0 : t[4]),\n t[1] * this.x + t[3] * this.y + (ignoreOffset ? 0 : t[5]),\n );\n }\n}\n\nexport const ZERO = new Point(0, 0);\n","import type { Constructor, TBBox } from './typedefs';\nimport { removeFromArray } from './util/internals/removeFromArray';\nimport { Point } from './Point';\nimport type { ActiveSelection } from './shapes/ActiveSelection';\nimport type { Group } from './shapes/Group';\nimport type { InteractiveFabricObject } from './shapes/Object/InteractiveObject';\nimport type { FabricObject } from './shapes/Object/FabricObject';\n\nexport const isCollection = (\n fabricObject?: FabricObject,\n): fabricObject is Group | ActiveSelection => {\n return !!fabricObject && Array.isArray((fabricObject as Group)._objects);\n};\n\nexport function createCollectionMixin<TBase extends Constructor>(Base: TBase) {\n class Collection extends Base {\n /**\n * @type {FabricObject[]}\n * @TODO needs to end up in the constructor too\n */\n _objects: FabricObject[] = [];\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onObjectAdded(object: FabricObject) {\n // subclasses should override this method\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onObjectRemoved(object: FabricObject) {\n // subclasses should override this method\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onStackOrderChanged(object: FabricObject) {\n // subclasses should override this method\n }\n\n /**\n * Adds objects to collection\n * Objects should be instances of (or inherit from) FabricObject\n * @param {...FabricObject[]} objects to add\n * @returns {number} new array length\n */\n add(...objects: FabricObject[]): number {\n const size = this._objects.push(...objects);\n objects.forEach((object) => this._onObjectAdded(object));\n return size;\n }\n\n /**\n * Inserts an object into collection at specified index\n * @param {number} index Index to insert object at\n * @param {...FabricObject[]} objects Object(s) to insert\n * @returns {number} new array length\n */\n insertAt(index: number, ...objects: FabricObject[]) {\n this._objects.splice(index, 0, ...objects);\n objects.forEach((object) => this._onObjectAdded(object));\n return this._objects.length;\n }\n\n /**\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * @private\n * @param {...FabricObject[]} objects objects to remove\n * @returns {FabricObject[]} removed objects\n */\n remove(...objects: FabricObject[]) {\n const array = this._objects,\n removed: FabricObject[] = [];\n objects.forEach((object) => {\n const index = array.indexOf(object);\n // only call onObjectRemoved if an object was actually removed\n if (index !== -1) {\n array.splice(index, 1);\n removed.push(object);\n this._onObjectRemoved(object);\n }\n });\n return removed;\n }\n\n /**\n * Executes given function for each object in this group\n * A simple shortcut for getObjects().forEach, before es6 was more complicated,\n * now is just a shortcut.\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 */\n forEachObject(\n callback: (\n object: FabricObject,\n index: number,\n array: FabricObject[],\n ) => any,\n ) {\n this.getObjects().forEach((object, index, objects) =>\n callback(object, index, objects),\n );\n }\n\n /**\n * Returns an array of children objects of this instance\n * @param {...String} [types] When specified, only objects of these types are returned\n * @return {Array}\n */\n getObjects(...types: string[]) {\n if (types.length === 0) {\n return [...this._objects];\n }\n return this._objects.filter((o) => o.isType(...types));\n }\n\n /**\n * Returns object at specified index\n * @param {Number} index\n * @return {Object} object at index\n */\n item(index: number) {\n return this._objects[index];\n }\n\n /**\n * Returns true if collection contains no objects\n * @return {Boolean} true if collection is empty\n */\n isEmpty() {\n return this._objects.length === 0;\n }\n\n /**\n * Returns a size of a collection (i.e: length of an array containing its objects)\n * @return {Number} Collection size\n */\n size() {\n return this._objects.length;\n }\n\n /**\n * Returns true if collection contains an object.\\\n * **Prefer using {@link FabricObject#isDescendantOf} for performance reasons**\n * instead of `a.contains(b)` use `b.isDescendantOf(a)`\n * @param {Object} object Object to check against\n * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`\n * @return {Boolean} `true` if collection contains an object\n */\n contains(object: FabricObject, deep?: boolean): boolean {\n if (this._objects.includes(object)) {\n return true;\n } else if (deep) {\n return this._objects.some(\n (obj) =>\n obj instanceof Collection &&\n (obj as unknown as Collection).contains(object, true),\n );\n }\n return false;\n }\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity() {\n return this._objects.reduce((memo, current) => {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\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 * @returns {boolean} true if change occurred\n */\n sendObjectToBack(object: FabricObject) {\n if (!object || object === this._objects[0]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.unshift(object);\n this._onStackOrderChanged(object);\n return true;\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 * @returns {boolean} true if change occurred\n */\n bringObjectToFront(object: FabricObject) {\n if (!object || object === this._objects[this._objects.length - 1]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.push(object);\n this._onStackOrderChanged(object);\n return true;\n }\n\n /**\n * Moves an object or a selection down in stack of drawn objects\n * An optional parameter, `intersecting` allows to move the object in behind\n * the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @returns {boolean} true if change occurred\n */\n sendObjectBackwards(object: FabricObject, intersecting?: boolean) {\n if (!object) {\n return false;\n }\n const idx = this._objects.indexOf(object);\n if (idx !== 0) {\n // if object is not on the bottom of stack\n const newIdx = this.findNewLowerIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n return false;\n }\n\n /**\n * Moves an object or a selection up in stack of drawn objects\n * An optional parameter, intersecting allows to move the object in front\n * of the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @returns {boolean} true if change occurred\n */\n bringObjectForward(object: FabricObject, intersecting?: boolean) {\n if (!object) {\n return false;\n }\n const 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 const newIdx = this.findNewUpperIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n return false;\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 * @returns {boolean} true if change occurred\n */\n moveObjectTo(object: FabricObject, index: number) {\n if (object === this._objects[index]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.splice(index, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n\n findNewLowerIndex(\n object: FabricObject,\n idx: number,\n intersecting?: boolean,\n ) {\n let newIdx;\n\n if (intersecting) {\n newIdx = idx;\n // traverse down the stack looking for the nearest intersecting object\n for (let i = idx - 1; i >= 0; --i) {\n if (object.isOverlapping(this._objects[i])) {\n newIdx = i;\n break;\n }\n }\n } else {\n newIdx = idx - 1;\n }\n\n return newIdx;\n }\n\n findNewUpperIndex(\n object: FabricObject,\n idx: number,\n intersecting?: boolean,\n ) {\n let newIdx;\n\n if (intersecting) {\n newIdx = idx;\n // traverse up the stack looking for the nearest intersecting object\n for (let i = idx + 1; i < this._objects.length; ++i) {\n if (object.isOverlapping(this._objects[i])) {\n newIdx = i;\n break;\n }\n }\n } else {\n newIdx = idx + 1;\n }\n\n return newIdx;\n }\n\n /**\n * Given a bounding box, return all the objects of the collection that are contained in the bounding box.\n * If `includeIntersecting` is true, return also the objects that intersect the bounding box as well.\n * This is meant to work with selection. Is not a generic method.\n * @param {TBBox} bbox a bounding box in scene coordinates\n * @param {{ includeIntersecting?: boolean }} options an object with includeIntersecting\n * @returns array of objects contained in the bounding box, ordered from top to bottom stacking wise\n */\n collectObjects(\n { left, top, width, height }: TBBox,\n { includeIntersecting = true }: { includeIntersecting?: boolean } = {},\n ) {\n const objects: InteractiveFabricObject[] = [],\n tl = new Point(left, top),\n br = tl.add(new Point(width, height));\n\n // we iterate reverse order to collect top first in case of click.\n for (let i = this._objects.length - 1; i >= 0; i--) {\n const object = this._objects[i] as unknown as InteractiveFabricObject;\n if (\n object.selectable &&\n object.visible &&\n ((includeIntersecting && object.intersectsWithRect(tl, br)) ||\n object.isContainedWithinRect(tl, br) ||\n (includeIntersecting && object.containsPoint(tl)) ||\n (includeIntersecting && object.containsPoint(br)))\n ) {\n objects.push(object);\n }\n }\n\n return objects;\n }\n }\n\n // https://github.com/microsoft/TypeScript/issues/32080\n return Collection;\n}\n","import { Observable } from './Observable';\n\nexport class CommonMethods<EventSpec> extends Observable<EventSpec> {\n /**\n * Sets object's properties from options, for initialization only\n * @protected\n * @param {Object} [options] Options object\n */\n protected _setOptions(options: any = {}) {\n for (const prop in options) {\n this.set(prop, options[prop]);\n }\n }\n\n /**\n * @private\n */\n _setObject(obj: Record<string, any>) {\n for (const 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 */\n set(key: string | Record<string, any>, value?: any) {\n if (typeof key === 'object') {\n this._setObject(key);\n } else {\n this._set(key, value);\n }\n return this;\n }\n\n _set(key: string, value: any) {\n this[key as keyof this] = 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 */\n toggle(property: string) {\n const 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(property: string): any {\n return this[property as keyof this];\n }\n}\n","import { getFabricWindow } from '../../env';\n\nexport function requestAnimFrame(callback: FrameRequestCallback): number {\n return getFabricWindow().requestAnimationFrame(callback);\n}\n\nexport function cancelAnimFrame(handle: number): void {\n return getFabricWindow().cancelAnimationFrame(handle);\n}\n","let id = 0;\n\nexport const uid = () => id++;\n","import { getFabricDocument } from '../../env';\nimport type { ImageFormat, TSize } from '../../typedefs';\nimport { FabricError } from '../internals/console';\n/**\n * Creates canvas element\n * @return {CanvasElement} initialized canvas element\n */\nexport const createCanvasElement = (): HTMLCanvasElement => {\n const element = getFabricDocument().createElement('canvas');\n if (!element || typeof element.getContext === 'undefined') {\n throw new FabricError('Failed to create `canvas` element');\n }\n return element;\n};\n\n/**\n * Creates image element (works on client and node)\n * @return {HTMLImageElement} HTML image element\n */\nexport const createImage = (): HTMLImageElement =>\n getFabricDocument().createElement('img');\n\n/**\n * Creates a canvas element that is a copy of another and is also painted\n * @param {CanvasElement} canvas to copy size and content of\n * @return {CanvasElement} initialized canvas element\n */\nexport const copyCanvasElement = (\n canvas: HTMLCanvasElement,\n): HTMLCanvasElement => {\n const newCanvas = createCanvasElementFor(canvas);\n newCanvas.getContext('2d')?.drawImage(canvas, 0, 0);\n return newCanvas;\n};\n\n/**\n * Creates a canvas element as big as another\n * @param {CanvasElement} canvas to copy size and content of\n * @return {CanvasElement} initialized canvas element\n */\nexport const createCanvasElementFor = (\n canvas: HTMLCanvasElement | ImageData | HTMLImageElement | TSize,\n): HTMLCanvasElement => {\n const newCanvas = createCanvasElement();\n newCanvas.width = canvas.width;\n newCanvas.height = canvas.height;\n return newCanvas;\n};\n\n/**\n * since 2.6.0 moved from canvas instance to utility.\n * possibly useless\n * @param {CanvasElement} canvasEl to copy size and content of\n * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too\n * @param {number} quality <= 1 and > 0\n * @return {String} data url\n */\nexport const toDataURL = (\n canvasEl: HTMLCanvasElement,\n format: ImageFormat,\n quality: number,\n) => canvasEl.toDataURL(`image/${format}`, quality);\n\nexport const isHTMLCanvas = (\n canvas?: HTMLCanvasElement | string,\n): canvas is HTMLCanvasElement => {\n return !!canvas && (canvas as HTMLCanvasElement).getContext !== undefined;\n};\n\nexport const toBlob = (\n canvasEl: HTMLCanvasElement,\n format?: ImageFormat,\n quality?: number,\n): Promise<Blob | null> =>\n new Promise((resolve, _) => {\n canvasEl.toBlob(resolve, `image/${format}`, quality);\n });\n","import type { TRadian, TDegree } from '../../typedefs';\nimport { PiBy180 } from '../../constants';\n\n/**\n * Transforms degrees to radians.\n * @param {TDegree} degrees value in degrees\n * @return {TRadian} value in radians\n */\nexport const degreesToRadians = (degrees: TDegree): TRadian =>\n (degrees * PiBy180) as TRadian;\n\n/**\n * Transforms radians to degrees.\n * @param {TRadian} radians value in radians\n * @return {TDegree} value in degrees\n */\nexport const radiansToDegrees = (radians: TRadian): TDegree =>\n (radians / PiBy180) as TDegree;\n","import { iMatrix } from '../../constants';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TDegree, TRadian, TMat2D } from '../../typedefs';\nimport { cos } from './cos';\nimport { degreesToRadians, radiansToDegrees } from './radiansDegreesConversion';\nimport { sin } from './sin';\n\nexport type TRotateMatrixArgs = {\n angle?: TDegree;\n};\n\nexport type TTranslateMatrixArgs = {\n translateX?: number;\n translateY?: number;\n};\n\nexport type TScaleMatrixArgs = {\n scaleX?: number;\n scaleY?: number;\n flipX?: boolean;\n flipY?: boolean;\n skewX?: TDegree;\n skewY?: TDegree;\n};\n\nexport type TComposeMatrixArgs = TTranslateMatrixArgs &\n TRotateMatrixArgs &\n TScaleMatrixArgs;\n\nexport type TQrDecomposeOut = Required<\n Omit<TComposeMatrixArgs, 'flipX' | 'flipY'>\n>;\n\nexport const isIdentityMatrix = (mat: TMat2D) =>\n mat.every((value, index) => value === iMatrix[index]);\n\n/**\n * Apply transform t to point p\n * @deprecated use {@link Point#transform}\n * @param {Point | XY} 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 {Point} The transformed point\n */\nexport const transformPoint = (\n p: XY,\n t: TMat2D,\n ignoreOffset?: boolean,\n): Point => new Point(p).transform(t, ignoreOffset);\n\n/**\n * Invert transformation t\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\nexport const invertTransform = (t: TMat2D): TMat2D => {\n const a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0] as TMat2D,\n { x, y } = new Point(t[4], t[5]).transform(r, true);\n r[4] = -x;\n r[5] = -y;\n return r;\n};\n\n/**\n * Multiply matrix A by matrix B to nest transformations\n * @param {TMat2D} a First transformMatrix\n * @param {TMat2D} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {TMat2D} The product of the two transform matrices\n */\nexport const multiplyTransformMatrices = (\n a: TMat2D,\n b: TMat2D,\n is2x2?: boolean,\n): TMat2D =>\n [\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 ] as TMat2D;\n\n/**\n * Multiplies the matrices array such that a matrix defines the plane for the rest of the matrices **after** it\n *\n * `multiplyTransformMatrixArray([A, B, C, D])` is equivalent to `A(B(C(D)))`\n *\n * @param matrices an array of matrices\n * @param [is2x2] flag to multiply matrices as 2x2 matrices\n * @returns the multiplication product\n */\nexport const multiplyTransformMatrixArray = (\n matrices: (TMat2D | undefined | null | false)[],\n is2x2?: boolean,\n) =>\n matrices.reduceRight(\n (product: TMat2D, curr) =>\n curr && product\n ? multiplyTransformMatrices(curr, product, is2x2)\n : curr || product,\n undefined as unknown as TMat2D,\n ) || iMatrix.concat();\n\nexport const calcPlaneRotation = ([a, b]: TMat2D) =>\n Math.atan2(b, a) as TRadian;\n\n/**\n * Decomposes standard 2x3 matrix into transform components\n * @param {TMat2D} a transformMatrix\n * @return {Object} Components of transform\n */\nexport const qrDecompose = (a: TMat2D): TQrDecomposeOut => {\n const angle = calcPlaneRotation(a),\n denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),\n scaleX = Math.sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);\n return {\n angle: radiansToDegrees(angle),\n scaleX,\n scaleY,\n skewX: radiansToDegrees(skewX),\n skewY: 0 as TDegree,\n translateX: a[4] || 0,\n translateY: a[5] || 0,\n };\n};\n\n/**\n * Generate a translation matrix\n *\n * A translation matrix in the form of\n * [ 1 0 x ]\n * [ 0 1 y ]\n * [ 0 0 1 ]\n *\n * See {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate} for more details\n *\n * @param {number} x translation on X axis\n * @param {number} [y] translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createTranslateMatrix = (x: number, y = 0): TMat2D => [\n 1,\n 0,\n 0,\n 1,\n x,\n y,\n];\n\n/**\n * Generate a rotation matrix around around a point (x,y), defaulting to (0,0)\n *\n * A matrix in the form of\n * [cos(a) -sin(a) -x*cos(a)+y*sin(a)+x]\n * [sin(a) cos(a) -x*sin(a)-y*cos(a)+y]\n * [0 0 1 ]\n *\n *\n * @param {TDegree} angle rotation in degrees\n * @param {XY} [pivotPoint] pivot point to rotate around\n * @returns {TMat2D} matrix\n */\nexport function createRotateMatrix(\n { angle = 0 }: TRotateMatrixArgs = {},\n { x = 0, y = 0 }: Partial<XY> = {},\n): TMat2D {\n const angleRadiant = degreesToRadians(angle),\n cosValue = cos(angleRadiant),\n sinValue = sin(angleRadiant);\n return [\n cosValue,\n sinValue,\n -sinValue,\n cosValue,\n x ? x - (cosValue * x - sinValue * y) : 0,\n y ? y - (sinValue * x + cosValue * y) : 0,\n ];\n}\n\n/**\n * Generate a scale matrix around the point (0,0)\n *\n * A matrix in the form of\n * [x 0 0]\n * [0 y 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale}\n *\n * @param {number} x scale on X axis\n * @param {number} [y] scale on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createScaleMatrix = (x: number, y: number = x): TMat2D => [\n x,\n 0,\n 0,\n y,\n 0,\n 0,\n];\n\nexport const angleToSkew = (angle: TDegree) =>\n Math.tan(degreesToRadians(angle));\n\nexport const skewToAngle = (value: TRadian) =>\n radiansToDegrees(Math.atan(value));\n\n/**\n * Generate a skew matrix for the X axis\n *\n * A matrix in the form of\n * [1 x 0]\n * [0 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx}\n *\n * @param {TDegree} skewValue translation on X axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewXMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n 0,\n angleToSkew(skewValue),\n 1,\n 0,\n 0,\n];\n\n/**\n * Generate a skew matrix for the Y axis\n *\n * A matrix in the form of\n * [1 0 0]\n * [y 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewy}\n *\n * @param {TDegree} skewValue translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewYMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n angleToSkew(skewValue),\n 0,\n 1,\n 0,\n 0,\n];\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\nexport const calcDimensionsMatrix = ({\n scaleX = 1,\n scaleY = 1,\n flipX = false,\n flipY = false,\n skewX = 0 as TDegree,\n skewY = 0 as TDegree,\n}: TScaleMatrixArgs) => {\n let matrix = createScaleMatrix(\n flipX ? -scaleX : scaleX,\n flipY ? -scaleY : scaleY,\n );\n if (skewX) {\n matrix = multiplyTransformMatrices(matrix, createSkewXMatrix(skewX), true);\n }\n if (skewY) {\n matrix = multiplyTransformMatrices(matrix, createSkewYMatrix(skewY), true);\n }\n return matrix;\n};\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * Before changing this function look at: src/benchmarks/calcTransformMatrix.mjs\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\nexport const composeMatrix = (options: TComposeMatrixArgs): TMat2D => {\n const { translateX = 0, translateY = 0, angle = 0 as TDegree } = options;\n let matrix = createTranslateMatrix(translateX, translateY);\n if (angle) {\n matrix = multiplyTransformMatrices(matrix, createRotateMatrix({ angle }));\n }\n const scaleMatrix = calcDimensionsMatrix(options);\n if (!isIdentityMatrix(scaleMatrix)) {\n matrix = multiplyTransformMatrices(matrix, scaleMatrix);\n }\n return matrix;\n};\n","import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T,\n ) => void;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.all(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal })\n .then((fabricInstance) => {\n reviver(obj, fabricInstance);\n instances.push(fabricInstance);\n return fabricInstance;\n }),\n ),\n )\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a classe registered for it, we enlive it.\n * If there is no class registered for it we return the value as is\n * */\n if (value.type && classRegistry.has(value.type)) {\n return enlivenObjects<FabricObject | Shadow | TFiller>([value], {\n signal,\n }).then(([enlived]) => {\n instances.push(enlived);\n return enlived;\n });\n }\n return value;\n });\n const keys = Object.keys(serializedObject);\n Promise.all(promises)\n .then((enlived) => {\n return enlived.reduce((acc, instance, index) => {\n acc[keys[index]] = instance;\n return acc;\n }, {});\n })\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance: any) => {\n instance.dispose && instance.dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n","/**\n * Populates an object with properties of another object\n * @param {Object} source Source object\n * @param {string[]} properties Properties names to include\n * @returns object populated with the picked keys\n */\nexport const pick = <T extends Record<string, any>>(\n source: T,\n keys: (keyof T)[] = [],\n) => {\n return keys.reduce((o, key) => {\n if (key in source) {\n o[key] = source[key];\n }\n return o;\n }, {} as Partial<T>);\n};\n\nexport const pickBy = <T extends Record<string, any>>(\n source: T,\n predicate: <K extends keyof T>(value: T[K], key: K, collection: T) => boolean,\n) => {\n return (Object.keys(source) as (keyof T)[]).reduce((o, key) => {\n if (predicate(source[key], key, source)) {\n o[key] = source[key];\n }\n return o;\n }, {} as Partial<T>);\n};\n","/**\n * A wrapper around Number#toFixed, which contrary to native method returns number, not string.\n * @param {number|string} number number to operate on\n * @param {number} fractionDigits number of fraction digits to \"leave\"\n * @return {number}\n */\nexport const toFixed = (number: number | string, fractionDigits: number) =>\n parseFloat(Number(number).toFixed(fractionDigits));\n","import type { TMat2D } from '../../typedefs';\nimport { toFixed } from './toFixed';\nimport { config } from '../../config';\n\n/**\n * given an array of 6 number returns something like `\"matrix(...numbers)\"`\n * @param {TMat2D} transform an array with 6 numbers\n * @return {String} transform matrix for svg\n */\nexport const matrixToSVG = (transform: TMat2D) =>\n 'matrix(' +\n transform\n .map((value) => toFixed(value, config.NUM_FRACTION_DIGITS))\n .join(' ') +\n ')';\n","import type { FabricObject } from '../shapes/Object/Object';\nimport type { TFiller } from '../typedefs';\nimport type { FabricText } from '../shapes/Text/Text';\nimport type { Pattern } from '../Pattern';\nimport type { Path } from '../shapes/Path';\nimport type { ActiveSelection } from '../shapes/ActiveSelection';\n\nexport const isFiller = (\n filler: TFiller | string | null,\n): filler is TFiller => {\n return !!filler && (filler as TFiller).toLive !== undefined;\n};\n\nexport const isSerializableFiller = (\n filler: TFiller | string | null,\n): filler is TFiller => {\n return !!filler && typeof (filler as TFiller).toObject === 'function';\n};\n\nexport const isPattern = (filler: TFiller): filler is Pattern => {\n return (\n !!filler && (filler as Pattern).offsetX !== undefined && 'source' in filler\n );\n};\n\nexport const isTextObject = (\n fabricObject?: FabricObject,\n): fabricObject is FabricText => {\n return (\n !!fabricObject &&\n typeof (fabricObject as FabricText)._renderText === 'function'\n );\n};\n\nexport const isPath = (fabricObject?: FabricObject): fabricObject is Path => {\n // we could use instanceof but that would mean pulling in Text code for a simple check\n // @todo discuss what to do and how to do\n return (\n !!fabricObject &&\n typeof (fabricObject as Path)._renderPathCommands === 'function'\n );\n};\n\nexport const isActiveSelection = (\n fabricObject?: FabricObject,\n): fabricObject is ActiveSelection =>\n !!fabricObject && 'multiSelectionStacking' in fabricObject;\n","/**\n * Returns element scroll offsets\n * @param {HTMLElement} element Element to operate on\n * @return {Object} Object with left/top values\n */\nexport function getScrollLeftTop(element: HTMLElement | null) {\n const doc = element && getDocumentFromElement(element);\n let left = 0,\n top = 0;\n if (!element || !doc) {\n return { left, top };\n }\n let elementLoop: HTMLElement | Document | ShadowRoot = element;\n const docElement = doc.documentElement,\n body = doc.body || {\n scrollLeft: 0,\n scrollTop: 0,\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 (\n elementLoop &&\n (elementLoop.parentNode || (elementLoop as unknown as ShadowRoot).host)\n ) {\n elementLoop = (elementLoop.parentNode ||\n (elementLoop as unknown as ShadowRoot).host) as\n | HTMLElement\n | Document\n | ShadowRoot;\n if (elementLoop === doc) {\n left = body.scrollLeft || docElement.scrollLeft || 0;\n top = body.scrollTop || docElement.scrollTop || 0;\n } else {\n left += (elementLoop as HTMLElement).scrollLeft || 0;\n top += (elementLoop as HTMLElement).scrollTop || 0;\n }\n\n if (\n elementLoop.nodeType === 1 &&\n (elementLoop as HTMLElement).style.position === 'fixed'\n ) {\n break;\n }\n }\n\n return { left, top };\n}\n\nexport const getDocumentFromElement = (el: HTMLElement) =>\n el.ownerDocument || null;\n\nexport const getWindowFromElement = (el: HTMLElement) =>\n el.ownerDocument?.defaultView || null;\n","import { NONE } from '../../constants';\nimport type { TSize } from '../../typedefs';\nimport {\n getDocumentFromElement,\n getWindowFromElement,\n getScrollLeftTop,\n} from '../../util/dom_misc';\n\nexport const setCanvasDimensions = (\n el: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n { width, height }: TSize,\n retinaScaling = 1,\n) => {\n el.width = width;\n el.height = height;\n if (retinaScaling > 1) {\n el.setAttribute('width', (width * retinaScaling).toString());\n el.setAttribute('height', (height * retinaScaling).toString());\n ctx.scale(retinaScaling, retinaScaling);\n }\n};\n\nexport type CSSDimensions = {\n width: number | string;\n height: number | string;\n};\n\nexport const setCSSDimensions = (\n el: HTMLElement,\n { width, height }: Partial<CSSDimensions>,\n) => {\n width && (el.style.width = typeof width === 'number' ? `${width}px` : width);\n height &&\n (el.style.height = typeof height === 'number' ? `${height}px` : height);\n};\n\n/**\n * Returns offset for a given element\n * @param {HTMLElement} element Element to get offset for\n * @return {Object} Object with \"left\" and \"top\" properties\n */\nexport function getElementOffset(element: HTMLElement) {\n const doc = element && getDocumentFromElement(element),\n offset = { left: 0, top: 0 };\n\n if (!doc) {\n return offset;\n }\n const elemStyle: CSSStyleDeclaration =\n getWindowFromElement(element)?.getComputedStyle(element, null) ||\n ({} as CSSStyleDeclaration);\n offset.left += parseInt(elemStyle.borderLeftWidth, 10) || 0;\n offset.top += parseInt(elemStyle.borderTopWidth, 10) || 0;\n offset.left += parseInt(elemStyle.paddingLeft, 10) || 0;\n offset.top += parseInt(elemStyle.paddingTop, 10) || 0;\n\n let box = { left: 0, top: 0 };\n\n const docElem = doc.documentElement;\n if (typeof element.getBoundingClientRect !== 'undefined') {\n box = element.getBoundingClientRect();\n }\n\n const scrollLeftTop = getScrollLeftTop(element);\n\n return {\n left:\n 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 * Makes element unselectable\n * @param {HTMLElement} element Element to make unselectable\n * @return {HTMLElement} Element that was passed in\n */\nexport function makeElementUnselectable(element: HTMLElement) {\n if (typeof element.onselectstart !== 'undefined') {\n element.onselectstart = () => false;\n }\n element.style.userSelect = NONE;\n return element;\n}\n","import { getEnv, getFabricDocument } from '../../env';\nimport type { TSize } from '../../typedefs';\nimport type { CSSDimensions } from './util';\nimport { setCSSDimensions, getElementOffset } from './util';\nimport { createCanvasElement, isHTMLCanvas } from '../../util/misc/dom';\nimport { setCanvasDimensions } from './util';\nimport { FabricError } from '../../util/internals/console';\n\nexport type CanvasItem = {\n el: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n};\n\nexport class StaticCanvasDOMManager {\n /**\n * Keeps a copy of the canvas style before setting retina scaling and other potions\n * in order to return it to original state on dispose\n * @type string\n */\n private _originalCanvasStyle?: string;\n\n lower: CanvasItem;\n\n constructor(arg0?: string | HTMLCanvasElement) {\n const el = this.createLowerCanvas(arg0);\n this.lower = { el, ctx: el.getContext('2d')! };\n }\n\n protected createLowerCanvas(arg0?: HTMLCanvasElement | string) {\n // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node\n const el = isHTMLCanvas(arg0)\n ? arg0\n : (arg0 &&\n (getFabricDocument().getElementById(arg0) as HTMLCanvasElement)) ||\n createCanvasElement();\n if (el.hasAttribute('data-fabric')) {\n throw new FabricError(\n 'Trying to initialize a canvas that has already been initialized. Did you forget to dispose the canvas?',\n );\n }\n this._originalCanvasStyle = el.style.cssText;\n el.setAttribute('data-fabric', 'main');\n el.classList.add('lower-canvas');\n return el;\n }\n\n cleanupDOM({ width, height }: TSize) {\n const { el } = this.lower;\n // restore canvas style and attributes\n el.classList.remove('lower-canvas');\n el.removeAttribute('data-fabric');\n // restore canvas size to original size in case retina scaling was applied\n el.setAttribute('width', `${width}`);\n el.setAttribute('height', `${height}`);\n el.style.cssText = this._originalCanvasStyle || '';\n this._originalCanvasStyle = undefined;\n }\n\n setDimensions(size: TSize, retinaScaling: number) {\n const { el, ctx } = this.lower;\n setCanvasDimensions(el, ctx, size, retinaScaling);\n }\n\n setCSSDimensions(size: Partial<CSSDimensions>) {\n setCSSDimensions(this.lower.el, size);\n }\n\n /**\n * Calculates canvas element offset relative to the document\n */\n calcOffset() {\n return getElementOffset(this.lower.el);\n }\n\n dispose() {\n getEnv().dispose(this.lower.el);\n // @ts-expect-error disposing\n delete this.lower;\n }\n}\n","import { iMatrix } from '../constants';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TFiller, TMat2D, TOptions } from '../typedefs';\n\ninterface CanvasDrawableOptions {\n /**\n * if set to false background image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @todo we should really find a different way to do this\n */\n backgroundVpt: boolean;\n\n /**\n * Background color of canvas instance.\n * @type {(String|TFiller)}\n */\n backgroundColor: TFiller | string;\n\n /**\n * Background image of canvas instance.\n * since 2.4.0 image caching is active, please when putting an image as background, add to the\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n * vale. As an alternative you can disable image objectCaching\n * @type FabricObject\n */\n backgroundImage?: FabricObject;\n\n /**\n * if set to false overlay image is not affected by viewport transform\n * @since 1.6.3\n * @type Boolean\n * @todo we should really find a different way to do this\n */\n overlayVpt: boolean;\n\n /**\n * Overlay color of canvas instance.\n * @since 1.3.9\n * @type {(String|TFiller)}\n */\n overlayColor: TFiller | string;\n\n /**\n * Overlay image of canvas instance.\n * since 2.4.0 image caching is active, please when putting an image as overlay, add to the\n * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom\n * vale. As an alternative you can disable image objectCaching\n * @type FabricObject\n */\n overlayImage?: FabricObject;\n}\n\ninterface CanvasRenderingOptions {\n /**\n * Indicates whether {@link StaticCanvas#add}, {@link StaticCanvas#insertAt} and {@link StaticCanvas#remove},\n * {@link StaticCanvas#moveTo}, {@link StaticCanvas#clear} and many more, should also re-render canvas.\n * Disabling this option will not give a performance boost when adding/removing a lot of objects to/from canvas at once\n * since the renders are queued and executed one per frame.\n * Disabling is suggested anyway and managing the renders of the app manually is not a big effort ( canvas.requestRenderAll() )\n * Left default to true to do not break documentation and old app, fiddles.\n * @type Boolean\n */\n renderOnAddRemove: boolean;\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 * @type Boolean\n * @default true\n */\n skipOffscreen: boolean;\n\n /**\n * When true, canvas is scaled by devicePixelRatio for better rendering on retina screens\n * @type Boolean\n */\n enableRetinaScaling: boolean;\n\n /**\n * Indicates whether this canvas will use image smoothing, this is on by default in browsers\n * @type Boolean\n */\n imageSmoothingEnabled: boolean;\n\n /**\n * a fabricObject that, without stroke define a clipping area with their shape. filled in black\n * the clipPath object gets used when the canvas has rendered, and the context is placed in the\n * top left corner of the canvas.\n * clipPath will clip away controls, if you do not want this to happen use controlsAboveOverlay = true\n * @type FabricObject\n */\n clipPath?: FabricObject;\n}\n\nexport interface CanvasExportOptions {\n /**\n * Indicates whether toObject/toDatalessObject should include default values\n * if set to false, takes precedence over the object value.\n * @type Boolean\n */\n includeDefaultValues: boolean;\n\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 */\n svgViewportTransformation: boolean;\n}\n\nexport interface StaticCanvasOptions\n extends CanvasDrawableOptions,\n CanvasRenderingOptions,\n CanvasExportOptions {\n /**\n * Width in virtual/logical pixels of the canvas.\n * The canvas can be larger than width if retina scaling is active\n * @type number\n */\n width: number;\n\n /**\n * Height in virtual/logical pixels of the canvas.\n * The canvas can be taller than width if retina scaling is active\n * @type height\n */\n height: number;\n\n /**\n * Indicates whether object controls (borders/controls) are rendered above overlay image\n * @type Boolean\n *\n * @todo move to Canvas\n */\n controlsAboveOverlay: boolean;\n\n /**\n * Indicates whether the browser can be scrolled when using a touchscreen and dragging on the canvas\n * It gives PRIORITY to DOM scrolling, it doesn't make it always possible.\n * If is true, when using a touch event on the canvas, the canvas will scroll if scroll is possible.\n * If we are in drawing mode or if we are selecting an object the canvas preventDefault and so it won't scroll\n * @type Boolean\n *\n * @todo move to Canvas\n */\n allowTouchScrolling: boolean;\n\n /**\n * The transformation (a Canvas 2D API transform matrix) which focuses the viewport\n * @type Array\n * @example <caption>Default transform</caption>\n * canvas.viewportTransform = [1, 0, 0, 1, 0, 0];\n * @example <caption>Scale by 70% and translate toward bottom-right by 50, without skewing</caption>\n * canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];\n */\n viewportTransform: TMat2D;\n}\n\nexport const staticCanvasDefaults: TOptions<StaticCanvasOptions> = {\n backgroundVpt: true,\n backgroundColor: '',\n overlayVpt: true,\n overlayColor: '',\n\n includeDefaultValues: true,\n svgViewportTransformation: true,\n\n renderOnAddRemove: true,\n skipOffscreen: true,\n enableRetinaScaling: true,\n imageSmoothingEnabled: true,\n\n /**\n * @todo move to Canvas\n */\n controlsAboveOverlay: false,\n /**\n * @todo move to Canvas\n */\n allowTouchScrolling: false,\n\n viewportTransform: [...iMatrix],\n patternQuality: 'best',\n};\n","import { config } from '../config';\nimport { CENTER, VERSION } from '../constants';\nimport type { CanvasEvents, StaticCanvasEvents } from '../EventTypeDefs';\nimport type { Gradient } from '../gradient/Gradient';\nimport { createCollectionMixin, isCollection } from '../Collection';\nimport { CommonMethods } from '../CommonMethods';\nimport type { Pattern } from '../Pattern';\nimport { Point } from '../Point';\nimport type { TCachedFabricObject } from '../shapes/Object/Object';\nimport type {\n Abortable,\n Constructor,\n TCornerPoint,\n TDataUrlOptions,\n TFiller,\n TMat2D,\n TSize,\n TSVGReviver,\n TToCanvasElementOptions,\n TValidToObjectMethod,\n TOptions,\n} from '../typedefs';\nimport {\n cancelAnimFrame,\n requestAnimFrame,\n} from '../util/animation/AnimationFrameProvider';\nimport { runningAnimations } from '../util/animation/AnimationRegistry';\nimport { uid } from '../util/internals/uid';\nimport { createCanvasElementFor, toBlob, toDataURL } from '../util/misc/dom';\nimport { invertTransform, transformPoint } from '../util/misc/matrix';\nimport type { EnlivenObjectOptions } from '../util/misc/objectEnlive';\nimport {\n enlivenObjectEnlivables,\n enlivenObjects,\n} from '../util/misc/objectEnlive';\nimport { pick } from '../util/misc/pick';\nimport { matrixToSVG } from '../util/misc/svgExport';\nimport { toFixed } from '../util/misc/toFixed';\nimport { isFiller, isPattern, isTextObject } from '../util/typeAssertions';\nimport { StaticCanvasDOMManager } from './DOMManagers/StaticCanvasDOMManager';\nimport type { CSSDimensions } from './DOMManagers/util';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { StaticCanvasOptions } from './StaticCanvasOptions';\nimport { staticCanvasDefaults } from './StaticCanvasOptions';\nimport { log, FabricError } from '../util/internals/console';\nimport { getDevicePixelRatio } from '../env';\n\n/**\n * Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset\n * Better try to restrict with types to avoid confusion.\n */\nexport type TCanvasSizeOptions =\n | {\n backstoreOnly?: true;\n cssOnly?: false;\n }\n | {\n backstoreOnly?: false;\n cssOnly?: true;\n };\n\nexport type TSVGExportOptions = {\n suppressPreamble?: boolean;\n viewBox?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n encoding?: 'UTF-8'; // test Encoding type and see what happens\n width?: string;\n height?: string;\n reviver?: TSVGReviver;\n};\n\nexport type PatternQuality = 'fast' | 'good' | 'best' | 'nearest' | 'bilinear';\n\n/**\n * Static canvas class\n * @see {@link http://fabric5.fabricjs.com/static_canvas|StaticCanvas demo}\n * @fires before:render\n * @fires after:render\n * @fires canvas:cleared\n * @fires object:added\n * @fires object:removed\n */\n// TODO: fix `EventSpec` inheritance https://github.com/microsoft/TypeScript/issues/26154#issuecomment-1366616260\nexport class StaticCanvas<\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n EventSpec extends StaticCanvasEvents = StaticCanvasEvents,\n >\n extends createCollectionMixin(CommonMethods<CanvasEvents>)\n implements StaticCanvasOptions\n{\n declare width: number;\n declare height: number;\n\n // background\n declare backgroundVpt: boolean;\n declare backgroundColor: TFiller | string;\n declare backgroundImage?: FabricObject;\n // overlay\n declare overlayVpt: boolean;\n declare overlayColor: TFiller | string;\n declare overlayImage?: FabricObject;\n\n declare clipPath?: FabricObject;\n\n declare includeDefaultValues: boolean;\n\n // rendering config\n declare renderOnAddRemove: boolean;\n declare skipOffscreen: boolean;\n declare enableRetinaScaling: boolean;\n declare imageSmoothingEnabled: boolean;\n\n /**\n * @todo move to Canvas\n */\n declare controlsAboveOverlay: boolean;\n\n /**\n * @todo move to Canvas\n */\n declare allowTouchScrolling: boolean;\n\n declare viewportTransform: TMat2D;\n\n /**\n * The viewport bounding box in scene plane coordinates, see {@link calcViewportBoundaries}\n */\n declare vptCoords: TCornerPoint;\n\n /**\n * A reference to the canvas actual HTMLCanvasElement.\n * Can be use to read the raw pixels, but never write or manipulate\n * @type HTMLCanvasElement\n */\n get lowerCanvasEl() {\n return this.elements.lower?.el;\n }\n\n get contextContainer() {\n return this.elements.lower?.ctx;\n }\n\n /**\n * If true the Canvas is in the process or has been disposed/destroyed.\n * No more rendering operation will be executed on this canvas.\n * @type boolean\n */\n declare destroyed?: boolean;\n\n /**\n * Started the process of disposing but not done yet.\n * WIll likely complete the render cycle already scheduled but stopping adding more.\n * @type boolean\n */\n declare disposed?: boolean;\n\n declare _offset: { left: number; top: number };\n declare protected hasLostContext: boolean;\n declare protected nextRenderHandle: number;\n\n declare elements: StaticCanvasDOMManager;\n\n /**\n * When true control drawing is skipped.\n * This boolean is used to avoid toDataURL to export controls.\n * Usage of this boolean to build up other flows and features is not supported\n * @type Boolean\n * @default false\n */\n declare protected skipControlsDrawing: boolean;\n\n /**\n * Controls the rendering of images under node-canvas.\n * Has no effects on the browser context.\n */\n declare patternQuality: PatternQuality;\n\n static ownDefaults = staticCanvasDefaults;\n\n // reference to\n declare protected __cleanupTask?: {\n (): void;\n kill: (reason?: any) => void;\n };\n\n static getDefaults(): Record<string, any> {\n return StaticCanvas.ownDefaults;\n }\n\n constructor(\n el?: string | HTMLCanvasElement,\n options: TOptions<StaticCanvasOptions> = {},\n ) {\n super();\n Object.assign(\n this,\n (this.constructor as typeof StaticCanvas).getDefaults(),\n );\n this.set(options);\n this.initElements(el);\n this._setDimensionsImpl({\n width: this.width || this.elements.lower.el.width || 0,\n height: this.height || this.elements.lower.el.height || 0,\n });\n this.skipControlsDrawing = false;\n this.viewportTransform = [...this.viewportTransform];\n this.calcViewportBoundaries();\n }\n\n protected initElements(el?: string | HTMLCanvasElement) {\n this.elements = new StaticCanvasDOMManager(el);\n }\n\n add(...objects: FabricObject[]) {\n const size = super.add(...objects);\n objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n return size;\n }\n\n insertAt(index: number, ...objects: FabricObject[]) {\n const size = super.insertAt(index, ...objects);\n objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n return size;\n }\n\n remove(...objects: FabricObject[]) {\n const removed = super.remove(...objects);\n removed.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n return removed;\n }\n\n _onObjectAdded(obj: FabricObject) {\n if (obj.canvas && (obj.canvas as StaticCanvas) !== this) {\n log(\n 'warn',\n 'Canvas is trying to add an object that belongs to a different canvas.\\n' +\n 'Resulting to default behavior: removing object from previous canvas and adding to new canvas',\n );\n obj.canvas.remove(obj);\n }\n obj._set('canvas', this);\n obj.setCoords();\n this.fire('object:added', { target: obj });\n obj.fire('added', { target: this });\n }\n\n _onObjectRemoved(obj: FabricObject) {\n obj._set('canvas', undefined);\n this.fire('object:removed', { target: obj });\n obj.fire('removed', { target: this });\n }\n\n _onStackOrderChanged() {\n this.renderOnAddRemove && this.requestRenderAll();\n }\n\n /**\n * @private\n * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n * @return {Number} retinaScaling if applied, otherwise 1;\n */\n getRetinaScaling() {\n return this.enableRetinaScaling ? getDevicePixelRatio() : 1;\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 */\n calcOffset() {\n return (this._offset = this.elements.calcOffset());\n }\n\n /**\n * Returns canvas width (in px)\n * @return {Number}\n */\n getWidth(): number {\n return this.width;\n }\n\n /**\n * Returns canvas height (in px)\n * @return {Number}\n */\n getHeight(): number {\n return this.height;\n }\n\n /**\n * Internal use only\n * @protected\n */\n protected _setDimensionsImpl(\n dimensions: Partial<TSize | CSSDimensions>,\n { cssOnly = false, backstoreOnly = false }: TCanvasSizeOptions = {},\n ) {\n if (!cssOnly) {\n const size = {\n width: this.width,\n height: this.height,\n ...(dimensions as Partial<TSize>),\n };\n this.elements.setDimensions(size, this.getRetinaScaling());\n this.hasLostContext = true;\n this.width = size.width;\n this.height = size.height;\n }\n if (!backstoreOnly) {\n this.elements.setCSSDimensions(dimensions);\n }\n\n this.calcOffset();\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 */\n setDimensions(\n dimensions: Partial<CSSDimensions>,\n options?: { cssOnly?: true; backstoreOnly?: false },\n ): void;\n setDimensions(\n dimensions: Partial<TSize>,\n options?: { backstoreOnly?: true; cssOnly?: false },\n ): void;\n setDimensions(dimensions: Partial<TSize>, options?: never): void;\n setDimensions(\n dimensions: Partial<TSize | CSSDimensions>,\n options?: TCanvasSizeOptions,\n ) {\n this._setDimensionsImpl(dimensions, options);\n if (!options || !options.cssOnly) {\n this.requestRenderAll();\n }\n }\n\n /**\n * Returns canvas zoom level\n * @return {Number}\n */\n getZoom() {\n return this.viewportTransform[0];\n }\n\n /**\n * Sets viewport transformation of this canvas instance\n * @param {Array} vpt a Canvas 2D API transform matrix\n */\n setViewportTransform(vpt: TMat2D) {\n this.viewportTransform = vpt;\n this.calcViewportBoundaries();\n this.renderOnAddRemove && this.requestRenderAll();\n }\n\n /**\n * Sets zoom level of this canvas instance, the zoom centered around point\n * meaning that following zoom to point with the same point will have the visual\n * effect of the zoom originating from that point. The point won't move.\n * It has nothing to do with canvas center or visual center of the viewport.\n * @param {Point} point to zoom with respect to\n * @param {Number} value to set zoom to, less than 1 zooms out\n */\n zoomToPoint(point: Point, value: number) {\n // TODO: just change the scale, preserve other transformations\n const before = point,\n vpt: TMat2D = [...this.viewportTransform];\n const newPoint = transformPoint(point, invertTransform(vpt));\n vpt[0] = value;\n vpt[3] = value;\n const after = transformPoint(newPoint, vpt);\n vpt[4] += before.x - after.x;\n vpt[5] += before.y - after.y;\n 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 */\n setZoom(value: number) {\n this.zoomToPoint(new Point(0, 0), value);\n }\n\n /**\n * Pan viewport so as to place point at top left corner of canvas\n * @param {Point} point to move to\n */\n absolutePan(point: Point) {\n const vpt: TMat2D = [...this.viewportTransform];\n vpt[4] = -point.x;\n vpt[5] = -point.y;\n return this.setViewportTransform(vpt);\n }\n\n /**\n * Pans viewpoint relatively\n * @param {Point} point (position vector) to move by\n */\n relativePan(point: Point) {\n return this.absolutePan(\n new Point(\n -point.x - this.viewportTransform[4],\n -point.y - this.viewportTransform[5],\n ),\n );\n }\n\n /**\n * Returns <canvas> element corresponding to this instance\n * @return {HTMLCanvasElement}\n */\n getElement(): HTMLCanvasElement {\n return this.elements.lower.el;\n }\n\n /**\n * Clears specified context of canvas element\n * @param {CanvasRenderingContext2D} ctx Context to clear\n */\n clearContext(ctx: CanvasRenderingContext2D) {\n ctx.clearRect(0, 0, this.width, this.height);\n }\n\n /**\n * Returns context of canvas where objects are drawn\n * @return {CanvasRenderingContext2D}\n */\n getContext(): CanvasRenderingContext2D {\n return this.elements.lower.ctx;\n }\n\n /**\n * Clears all contexts (background, main, top) of an instance\n */\n clear() {\n this.remove(...this.getObjects());\n this.backgroundImage = undefined;\n this.overlayImage = undefined;\n this.backgroundColor = '';\n this.overlayColor = '';\n this.clearContext(this.getContext());\n this.fire('canvas:cleared');\n this.renderOnAddRemove && this.requestRenderAll();\n }\n\n /**\n * Renders the canvas\n */\n renderAll() {\n this.cancelRequestedRender();\n if (this.destroyed) {\n return;\n }\n this.renderCanvas(this.getContext(), this._objects);\n }\n\n /**\n * Function created to be instance bound at initialization\n * used in requestAnimationFrame rendering\n * Let the fabricJS call it. If you call it manually you could have more\n * animationFrame stacking on to of each other\n * for an imperative rendering, use canvas.renderAll\n * @private\n */\n renderAndReset() {\n this.nextRenderHandle = 0;\n this.renderAll();\n }\n\n /**\n * Append a renderAll request to next animation frame.\n * unless one is already in progress, in that case nothing is done\n * a boolean flag will avoid appending more.\n */\n requestRenderAll() {\n if (!this.nextRenderHandle && !this.disposed && !this.destroyed) {\n this.nextRenderHandle = requestAnimFrame(() => this.renderAndReset());\n }\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\n */\n calcViewportBoundaries(): TCornerPoint {\n const width = this.width,\n height = this.height,\n iVpt = invertTransform(this.viewportTransform),\n a = transformPoint({ x: 0, y: 0 }, iVpt),\n b = transformPoint({ x: width, y: height }, iVpt),\n // we don't support vpt flipping\n // but the code is robust enough to mostly work with flipping\n min = a.min(b),\n max = a.max(b);\n return (this.vptCoords = {\n tl: min,\n tr: new Point(max.x, min.y),\n bl: new Point(min.x, max.y),\n br: max,\n });\n }\n\n cancelRequestedRender() {\n if (this.nextRenderHandle) {\n cancelAnimFrame(this.nextRenderHandle);\n this.nextRenderHandle = 0;\n }\n }\n\n drawControls(_ctx: CanvasRenderingContext2D) {\n // Static canvas has no controls\n }\n\n /**\n * Renders background, objects, overlay and controls.\n * @param {CanvasRenderingContext2D} ctx\n * @param {Array} objects to render\n */\n renderCanvas(ctx: CanvasRenderingContext2D, objects: FabricObject[]) {\n if (this.destroyed) {\n return;\n }\n\n const v = this.viewportTransform,\n path = this.clipPath;\n this.calcViewportBoundaries();\n this.clearContext(ctx);\n ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;\n // @ts-expect-error node-canvas stuff\n ctx.patternQuality = this.patternQuality;\n this.fire('before:render', { ctx });\n this._renderBackground(ctx);\n\n ctx.save();\n //apply viewport transform once for all rendering process\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n this._renderObjects(ctx, objects);\n ctx.restore();\n if (!this.controlsAboveOverlay && !this.skipControlsDrawing) {\n this.drawControls(ctx);\n }\n if (path) {\n path._set('canvas', this);\n // needed to setup a couple of variables\n // todo migrate to the newer one\n path.shouldCache();\n path._transformDone = true;\n (path as TCachedFabricObject).renderCache({ forClipping: true });\n this.drawClipPathOnCanvas(ctx, path as TCachedFabricObject);\n }\n this._renderOverlay(ctx);\n if (this.controlsAboveOverlay && !this.skipControlsDrawing) {\n this.drawControls(ctx);\n }\n this.fire('after:render', { ctx });\n\n if (this.__cleanupTask) {\n this.__cleanupTask();\n this.__cleanupTask = undefined;\n }\n }\n\n /**\n * Paint the cached clipPath on the lowerCanvasEl\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawClipPathOnCanvas(\n ctx: CanvasRenderingContext2D,\n clipPath: TCachedFabricObject,\n ) {\n const v = this.viewportTransform;\n ctx.save();\n ctx.transform(...v);\n // DEBUG: uncomment this line, comment the following\n // ctx.globalAlpha = 0.4;\n ctx.globalCompositeOperation = 'destination-in';\n clipPath.transform(ctx);\n ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);\n ctx.drawImage(\n clipPath._cacheCanvas,\n -clipPath.cacheTranslationX,\n -clipPath.cacheTranslationY,\n );\n ctx.restore();\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} objects to render\n */\n _renderObjects(ctx: CanvasRenderingContext2D, objects: FabricObject[]) {\n for (let i = 0, len = objects.length; i < len; ++i) {\n objects[i] && objects[i].render(ctx);\n }\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {string} property 'background' or 'overlay'\n */\n _renderBackgroundOrOverlay(\n ctx: CanvasRenderingContext2D,\n property: 'background' | 'overlay',\n ) {\n const fill = this[`${property}Color`],\n object = this[`${property}Image`],\n v = this.viewportTransform,\n needsVpt = this[`${property}Vpt`];\n if (!fill && !object) {\n return;\n }\n const isAFiller = isFiller(fill);\n if (fill) {\n ctx.save();\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(this.width, 0);\n ctx.lineTo(this.width, this.height);\n ctx.lineTo(0, this.height);\n ctx.closePath();\n ctx.fillStyle = isAFiller ? fill.toLive(ctx /* this */)! : fill;\n if (needsVpt) {\n ctx.transform(...v);\n }\n if (isAFiller) {\n ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\n const m = ((fill as Gradient<'linear'>).gradientTransform ||\n (fill as Pattern).patternTransform) as TMat2D;\n m && ctx.transform(...m);\n }\n ctx.fill();\n ctx.restore();\n }\n if (object) {\n ctx.save();\n const { skipOffscreen } = this;\n // if the object doesn't move with the viewport,\n // the offscreen concept does not apply;\n this.skipOffscreen = needsVpt;\n if (needsVpt) {\n ctx.transform(...v);\n }\n object.render(ctx);\n this.skipOffscreen = skipOffscreen;\n ctx.restore();\n }\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground(ctx: CanvasRenderingContext2D) {\n this._renderBackgroundOrOverlay(ctx, 'background');\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderOverlay(ctx: CanvasRenderingContext2D) {\n this._renderBackgroundOrOverlay(ctx, 'overlay');\n }\n\n /**\n * Returns coordinates of a center of canvas.\n * @return {Point}\n */\n getCenterPoint() {\n return new Point(this.width / 2, this.height / 2);\n }\n\n /**\n * Centers object horizontally in the canvas\n */\n centerObjectH(object: FabricObject) {\n return this._centerObject(\n object,\n new Point(this.getCenterPoint().x, object.getCenterPoint().y),\n );\n }\n\n /**\n * Centers object vertically in the canvas\n * @param {FabricObject} object Object to center vertically\n */\n centerObjectV(object: FabricObject) {\n return this._centerObject(\n object,\n new Point(object.getCenterPoint().x, this.getCenterPoint().y),\n );\n }\n\n /**\n * Centers object vertically and horizontally in the canvas\n * @param {FabricObject} object Object to center vertically and horizontally\n */\n centerObject(object: FabricObject) {\n return this._centerObject(object, this.getCenterPoint());\n }\n\n /**\n * Centers object vertically and horizontally in the viewport\n * @param {FabricObject} object Object to center vertically and horizontally\n */\n viewportCenterObject(object: FabricObject) {\n return this._centerObject(object, this.getVpCenter());\n }\n\n /**\n * Centers object horizontally in the viewport, object.top is unchanged\n * @param {FabricObject} object Object to center vertically and horizontally\n */\n viewportCenterObjectH(object: FabricObject) {\n return this._centerObject(\n object,\n new Point(this.getVpCenter().x, object.getCenterPoint().y),\n );\n }\n\n /**\n * Centers object Vertically in the viewport, object.top is unchanged\n * @param {FabricObject} object Object to center vertically and horizontally\n */\n viewportCenterObjectV(object: FabricObject) {\n return this._centerObject(\n object,\n new Point(object.getCenterPoint().x, this.getVpCenter().y),\n );\n }\n\n /**\n * Calculate the point in canvas that correspond to the center of actual viewport.\n * @return {Point} vpCenter, viewport center\n */\n getVpCenter(): Point {\n return transformPoint(\n this.getCenterPoint(),\n invertTransform(this.viewportTransform),\n );\n }\n\n /**\n * @private\n * @param {FabricObject} object Object to center\n * @param {Point} center Center point\n */\n _centerObject(object: FabricObject, center: Point) {\n object.setXY(center, CENTER, CENTER);\n object.setCoords();\n this.renderOnAddRemove && this.requestRenderAll();\n }\n\n /**\n * Returns dataless JSON representation of canvas\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {String} json string\n */\n toDatalessJSON(propertiesToInclude?: string[]) {\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(propertiesToInclude?: string[]) {\n return this._toObjectMethod('toObject', propertiesToInclude);\n }\n\n /**\n * Returns Object representation of canvas\n * this alias is provided because if you call JSON.stringify on an instance,\n * the toJSON object will be invoked if it exists.\n * Having a toJSON method means you can do JSON.stringify(myCanvas)\n * JSON does not support additional properties because toJSON has its own signature\n * @return {Object} JSON compatible object\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n * @example <caption>JSON representation of canvas </caption>\n * const json = canvas.toJSON();\n * @example <caption>JSON representation of canvas </caption>\n * const json = JSON.stringify(canvas);\n */\n toJSON() {\n return this.toObject();\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(propertiesToInclude?: string[]) {\n return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n }\n\n /**\n * @private\n */\n _toObjectMethod(\n methodName: TValidToObjectMethod,\n propertiesToInclude?: string[],\n ) {\n const clipPath = this.clipPath;\n const clipPathData =\n clipPath && !clipPath.excludeFromExport\n ? this._toObject(clipPath, methodName, propertiesToInclude)\n : null;\n return {\n version: VERSION,\n ...pick(this, propertiesToInclude as (keyof this)[]),\n objects: this._objects\n .filter((object) => !object.excludeFromExport)\n .map((instance) =>\n this._toObject(instance, methodName, propertiesToInclude),\n ),\n ...this.__serializeBgOverlay(methodName, propertiesToInclude),\n ...(clipPathData ? { clipPath: clipPathData } : null),\n };\n }\n\n /**\n * @private\n */\n protected _toObject(\n instance: FabricObject,\n methodName: TValidToObjectMethod,\n propertiesToInclude?: string[],\n ) {\n let originalValue;\n\n if (!this.includeDefaultValues) {\n originalValue = instance.includeDefaultValues;\n instance.includeDefaultValues = false;\n }\n\n const object = instance[methodName](propertiesToInclude);\n if (!this.includeDefaultValues) {\n instance.includeDefaultValues = !!originalValue;\n }\n return object;\n }\n\n /**\n * @private\n */\n __serializeBgOverlay(\n methodName: TValidToObjectMethod,\n propertiesToInclude?: string[],\n ) {\n const data: any = {},\n bgImage = this.backgroundImage,\n overlayImage = this.overlayImage,\n bgColor = this.backgroundColor,\n overlayColor = this.overlayColor;\n\n if (isFiller(bgColor)) {\n if (!bgColor.excludeFromExport) {\n data.background = bgColor.toObject(propertiesToInclude);\n }\n } else if (bgColor) {\n data.background = bgColor;\n }\n\n if (isFiller(overlayColor)) {\n if (!overlayColor.excludeFromExport) {\n data.overlay = overlayColor.toObject(propertiesToInclude);\n }\n } else if (overlayColor) {\n data.overlay = overlayColor;\n }\n\n if (bgImage && !bgImage.excludeFromExport) {\n data.backgroundImage = this._toObject(\n bgImage,\n methodName,\n propertiesToInclude,\n );\n }\n if (overlayImage && !overlayImage.excludeFromExport) {\n data.overlayImage = this._toObject(\n overlayImage,\n methodName,\n propertiesToInclude,\n );\n }\n\n return data;\n }\n\n /* _TO_SVG_START_ */\n\n declare svgViewportTransformation: boolean;\n\n /**\n * Returns SVG representation of canvas\n * @param {Object} [options] Options object for SVG output\n * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n * @param {Object} [options.viewBox] SVG viewbox object\n * @param {Number} [options.viewBox.x] x-coordinate of viewbox\n * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n * @param {Number} [options.viewBox.width] Width of viewbox\n * @param {Number} [options.viewBox.height] Height of viewbox\n * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n * @param {String} [options.width] desired width of svg with or without units\n * @param {String} [options.height] desired height of svg with or without units\n * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n * @return {String} SVG string\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#serialization}\n * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n * @example <caption>Normal SVG output</caption>\n * var svg = canvas.toSVG();\n * @example <caption>SVG output without preamble (without <?xml ../>)</caption>\n * var svg = canvas.toSVG({suppressPreamble: true});\n * @example <caption>SVG output with viewBox attribute</caption>\n * var svg = canvas.toSVG({\n * viewBox: {\n * x: 100,\n * y: 100,\n * width: 200,\n * height: 300\n * }\n * });\n * @example <caption>SVG output with different encoding (default: UTF-8)</caption>\n * var svg = canvas.toSVG({encoding: 'ISO-8859-1'});\n * @example <caption>Modify SVG output with reviver function</caption>\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(options: TSVGExportOptions = {}, reviver?: TSVGReviver) {\n options.reviver = reviver;\n const markup: string[] = [];\n\n this._setSVGPreamble(markup, options);\n this._setSVGHeader(markup, options);\n if (this.clipPath) {\n markup.push(`<g clip-path=\"url(#${this.clipPath.clipPathId})\" >\\n`);\n }\n this._setSVGBgOverlayColor(markup, 'background');\n this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);\n this._setSVGObjects(markup, reviver);\n if (this.clipPath) {\n markup.push('</g>\\n');\n }\n this._setSVGBgOverlayColor(markup, 'overlay');\n this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);\n\n markup.push('</svg>');\n\n return markup.join('');\n }\n\n /**\n * @private\n */\n _setSVGPreamble(markup: string[], options: TSVGExportOptions): void {\n if (options.suppressPreamble) {\n return;\n }\n markup.push(\n '<?xml version=\"1.0\" encoding=\"',\n options.encoding || 'UTF-8',\n '\" standalone=\"no\" ?>\\n',\n '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ',\n '\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\\n',\n );\n }\n\n /**\n * @private\n */\n _setSVGHeader(markup: string[], options: TSVGExportOptions): void {\n const width = options.width || `${this.width}`,\n height = options.height || `${this.height}`,\n NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,\n optViewBox = options.viewBox;\n let viewBox: string;\n if (optViewBox) {\n viewBox = `viewBox=\"${optViewBox.x} ${optViewBox.y} ${optViewBox.width} ${optViewBox.height}\" `;\n } else if (this.svgViewportTransformation) {\n const vpt = this.viewportTransform;\n viewBox = `viewBox=\"${toFixed(\n -vpt[4] / vpt[0],\n NUM_FRACTION_DIGITS,\n )} ${toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS)} ${toFixed(\n this.width / vpt[0],\n NUM_FRACTION_DIGITS,\n )} ${toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS)}\" `;\n } else {\n viewBox = `viewBox=\"0 0 ${this.width} ${this.height}\" `;\n }\n\n markup.push(\n '<svg ',\n 'xmlns=\"http://www.w3.org/2000/svg\" ',\n 'xmlns:xlink=\"http://www.w3.org/1999/xlink\" ',\n 'version=\"1.1\" ',\n 'width=\"',\n width,\n '\" ',\n 'height=\"',\n height,\n '\" ',\n viewBox,\n 'xml:space=\"preserve\">\\n',\n '<desc>Created with Fabric.js ',\n VERSION,\n '</desc>\\n',\n '<defs>\\n',\n this.createSVGFontFacesMarkup(),\n this.createSVGRefElementsMarkup(),\n this.createSVGClipPathMarkup(options),\n '</defs>\\n',\n );\n }\n\n createSVGClipPathMarkup(options: TSVGExportOptions): string {\n const clipPath = this.clipPath;\n if (clipPath) {\n clipPath.clipPathId = `CLIPPATH_${uid()}`;\n return `<clipPath id=\"${clipPath.clipPathId}\" >\\n${clipPath.toClipPathSVG(\n options.reviver,\n )}</clipPath>\\n`;\n }\n return '';\n }\n\n /**\n * Creates markup containing SVG referenced elements like patterns, gradients etc.\n * @return {String}\n */\n createSVGRefElementsMarkup(): string {\n return (['background', 'overlay'] as const)\n .map((prop) => {\n const fill = this[`${prop}Color`];\n if (isFiller(fill)) {\n const shouldTransform = this[`${prop}Vpt`],\n vpt = this.viewportTransform,\n object = {\n // otherwise circular dependency\n isType: () => false,\n width: this.width / (shouldTransform ? vpt[0] : 1),\n height: this.height / (shouldTransform ? vpt[3] : 1),\n };\n return fill.toSVG(object as FabricObject, {\n additionalTransform: shouldTransform ? matrixToSVG(vpt) : '',\n });\n }\n })\n .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(): string {\n const objects: FabricObject[] = [],\n fontList: Record<string, boolean> = {},\n fontPaths = config.fontPaths;\n\n this._objects.forEach(function add(object) {\n objects.push(object);\n if (isCollection(object)) {\n object._objects.forEach(add);\n }\n });\n\n objects.forEach((obj) => {\n if (!isTextObject(obj)) {\n return;\n }\n const { styles, fontFamily } = obj;\n if (fontList[fontFamily] || !fontPaths[fontFamily]) {\n return;\n }\n fontList[fontFamily] = true;\n if (!styles) {\n return;\n }\n Object.values(styles).forEach((styleRow) => {\n Object.values(styleRow).forEach(({ fontFamily = '' }) => {\n if (!fontList[fontFamily] && fontPaths[fontFamily]) {\n fontList[fontFamily] = true;\n }\n });\n });\n });\n\n const fontListMarkup = Object.keys(fontList)\n .map(\n (fontFamily) =>\n `\\t\\t@font-face {\\n\\t\\t\\tfont-family: '${fontFamily}';\\n\\t\\t\\tsrc: url('${fontPaths[fontFamily]}');\\n\\t\\t}\\n`,\n )\n .join('');\n\n if (fontListMarkup) {\n return `\\t<style type=\"text/css\"><![CDATA[\\n${fontListMarkup}]]></style>\\n`;\n }\n return '';\n }\n\n /**\n * @private\n */\n _setSVGObjects(markup: string[], reviver?: TSVGReviver) {\n this.forEachObject((fabricObject) => {\n if (fabricObject.excludeFromExport) {\n return;\n }\n this._setSVGObject(markup, fabricObject, reviver);\n });\n }\n\n /**\n * This is its own function because the Canvas ( non static ) requires extra code here\n * @private\n */\n _setSVGObject(\n markup: string[],\n instance: FabricObject,\n reviver?: TSVGReviver,\n ) {\n markup.push(instance.toSVG(reviver));\n }\n\n /**\n * @private\n */\n _setSVGBgOverlayImage(\n markup: string[],\n property: 'overlayImage' | 'backgroundImage',\n reviver?: TSVGReviver,\n ) {\n const bgOrOverlay = this[property];\n if (bgOrOverlay && !bgOrOverlay.excludeFromExport && bgOrOverlay.toSVG) {\n markup.push(bgOrOverlay.toSVG(reviver));\n }\n }\n\n /**\n * @TODO this seems to handle patterns but fail at gradients.\n * @private\n */\n _setSVGBgOverlayColor(markup: string[], property: 'background' | 'overlay') {\n const filler = this[`${property}Color`];\n if (!filler) {\n return;\n }\n if (isFiller(filler)) {\n const repeat = (filler as Pattern).repeat || '',\n finalWidth = this.width,\n finalHeight = this.height,\n shouldInvert = this[`${property}Vpt`],\n additionalTransform = shouldInvert\n ? matrixToSVG(invertTransform(this.viewportTransform))\n : '';\n markup.push(\n `<rect transform=\"${additionalTransform} translate(${finalWidth / 2},${\n finalHeight / 2\n })\" x=\"${filler.offsetX - finalWidth / 2}\" y=\"${\n filler.offsetY - finalHeight / 2\n }\" width=\"${\n (repeat === 'repeat-y' || repeat === 'no-repeat') && isPattern(filler)\n ? (filler.source as HTMLImageElement).width\n : finalWidth\n }\" height=\"${\n (repeat === 'repeat-x' || repeat === 'no-repeat') && isPattern(filler)\n ? (filler.source as HTMLImageElement).height\n : finalHeight\n }\" fill=\"url(#SVGID_${filler.id})\"></rect>\\n`,\n );\n } else {\n markup.push(\n '<rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" ',\n 'fill=\"',\n filler,\n '\"',\n '></rect>\\n',\n );\n }\n }\n /* _TO_SVG_END_ */\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 *\n * **IMPORTANT**: It is recommended to abort loading tasks before calling this method to prevent race conditions and unnecessary networking\n *\n * @param {String|Object} json JSON string or object\n * @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n * @param {Object} [options] options\n * @param {AbortSignal} [options.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @return {Promise<Canvas | StaticCanvas>} instance\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#deserialization}\n * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n * @example <caption>loadFromJSON</caption>\n * canvas.loadFromJSON(json).then((canvas) => canvas.requestRenderAll());\n * @example <caption>loadFromJSON with reviver</caption>\n * canvas.loadFromJSON(json, function(o, object) {\n * // `o` = json object\n * // `object` = fabric.Object instance\n * // ... do some stuff ...\n * }).then((canvas) => {\n * ... canvas is restored, add your code.\n * });\n *\n */\n loadFromJSON(\n json: string | Record<string, any>,\n reviver?: EnlivenObjectOptions['reviver'],\n { signal }: Abortable = {},\n ): Promise<this> {\n if (!json) {\n return Promise.reject(new FabricError('`json` is undefined'));\n }\n\n // parse json if it wasn't already\n const { objects = [], ...serialized } =\n typeof json === 'string' ? JSON.parse(json) : json;\n const { backgroundImage, background, overlayImage, overlay, clipPath } =\n serialized;\n const renderOnAddRemove = this.renderOnAddRemove;\n this.renderOnAddRemove = false;\n\n return Promise.all([\n enlivenObjects<FabricObject>(objects, {\n reviver,\n signal,\n }),\n enlivenObjectEnlivables(\n {\n backgroundImage,\n backgroundColor: background,\n overlayImage,\n overlayColor: overlay,\n clipPath,\n },\n { signal },\n ),\n ]).then(([enlived, enlivedMap]) => {\n this.clear();\n this.add(...enlived);\n this.set(serialized);\n this.set(enlivedMap);\n this.renderOnAddRemove = renderOnAddRemove;\n return this;\n });\n }\n\n /**\n * Clones canvas instance\n * @param {string[]} [properties] Array of properties to include in the cloned canvas and children\n */\n clone(properties: string[]) {\n const data = this.toObject(properties);\n const canvas = this.cloneWithoutData();\n return canvas.loadFromJSON(data);\n }\n\n /**\n * Clones canvas instance without cloning existing data.\n * This essentially copies canvas dimensions since loadFromJSON does not affect canvas size.\n */\n cloneWithoutData() {\n const el = createCanvasElementFor(this);\n return new (this.constructor as Constructor<this>)(el);\n }\n\n /**\n * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n * @param {Object} [options] Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\n * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n * @see {@link https://jsfiddle.net/xsjua1rd/ demo}\n * @example <caption>Generate jpeg dataURL with lower quality</caption>\n * var dataURL = canvas.toDataURL({\n * format: 'jpeg',\n * quality: 0.8\n * });\n * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * left: 100,\n * top: 100,\n * width: 200,\n * height: 200\n * });\n * @example <caption>Generate double scaled png dataURL</caption>\n * var dataURL = canvas.toDataURL({\n * format: 'png',\n * multiplier: 2\n * });\n * @example <caption>Generate dataURL with objects that overlap a specified object</caption>\n * var myObject;\n * var dataURL = canvas.toDataURL({\n * filter: (object) => object.isContainedWithinObject(myObject) || object.intersectsWithObject(myObject)\n * });\n */\n toDataURL(options = {} as TDataUrlOptions): string {\n const {\n format = 'png',\n quality = 1,\n multiplier = 1,\n enableRetinaScaling = false,\n } = options;\n const finalMultiplier =\n multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);\n\n return toDataURL(\n this.toCanvasElement(finalMultiplier, options),\n format,\n quality,\n );\n }\n toBlob(options = {} as TDataUrlOptions): Promise<Blob | null> {\n const {\n format = 'png',\n quality = 1,\n multiplier = 1,\n enableRetinaScaling = false,\n } = options;\n const finalMultiplier =\n multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);\n\n return toBlob(\n this.toCanvasElement(finalMultiplier, options),\n format,\n quality,\n );\n }\n\n /**\n * Create a new HTMLCanvas element painted with the current canvas content.\n * No need to resize the actual one or repaint it.\n * Will transfer object ownership to a new canvas, paint it, and set everything back.\n * This is an intermediary step used to get to a dataUrl but also it is useful to\n * create quick image copies of a canvas without passing for the dataUrl string\n * @param {Number} [multiplier] a zoom factor.\n * @param {Object} [options] Cropping informations\n * @param {Number} [options.left] Cropping left offset.\n * @param {Number} [options.top] Cropping top offset.\n * @param {Number} [options.width] Cropping width.\n * @param {Number} [options.height] Cropping height.\n * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.\n */\n toCanvasElement(\n multiplier = 1,\n { width, height, left, top, filter } = {} as TToCanvasElementOptions,\n ): HTMLCanvasElement {\n const scaledWidth = (width || this.width) * multiplier,\n scaledHeight = (height || this.height) * multiplier,\n zoom = this.getZoom(),\n originalWidth = this.width,\n originalHeight = this.height,\n originalSkipControlsDrawing = this.skipControlsDrawing,\n newZoom = zoom * multiplier,\n vp = this.viewportTransform,\n translateX = (vp[4] - (left || 0)) * multiplier,\n translateY = (vp[5] - (top || 0)) * multiplier,\n newVp = [newZoom, 0, 0, newZoom, translateX, translateY] as TMat2D,\n originalRetina = this.enableRetinaScaling,\n canvasEl = createCanvasElementFor({\n width: scaledWidth,\n height: scaledHeight,\n }),\n objectsToRender = filter\n ? this._objects.filter((obj) => filter(obj))\n : this._objects;\n this.enableRetinaScaling = false;\n this.viewportTransform = newVp;\n this.width = scaledWidth;\n this.height = scaledHeight;\n this.skipControlsDrawing = true;\n this.calcViewportBoundaries();\n this.renderCanvas(canvasEl.getContext('2d')!, objectsToRender);\n this.viewportTransform = vp;\n this.width = originalWidth;\n this.height = originalHeight;\n this.calcViewportBoundaries();\n this.enableRetinaScaling = originalRetina;\n this.skipControlsDrawing = originalSkipControlsDrawing;\n return canvasEl;\n }\n\n /**\n * Waits until rendering has settled to destroy the canvas\n * @returns {Promise<boolean>} a promise resolving to `true` once the canvas has been destroyed or to `false` if the canvas has was already destroyed\n * @throws if aborted by a consequent call\n */\n dispose() {\n !this.disposed &&\n this.elements.cleanupDOM({ width: this.width, height: this.height });\n runningAnimations.cancelByCanvas(this);\n this.disposed = true;\n return new Promise<boolean>((resolve, reject) => {\n const task = () => {\n this.destroy();\n resolve(true);\n };\n task.kill = reject;\n if (this.__cleanupTask) {\n this.__cleanupTask.kill('aborted');\n }\n\n if (this.destroyed) {\n resolve(false);\n } else if (this.nextRenderHandle) {\n this.__cleanupTask = task;\n } else {\n task();\n }\n });\n }\n\n /**\n * Clears the canvas element, disposes objects and frees resources.\n *\n * Invoked as part of the **async** operation of {@link dispose}.\n *\n * **CAUTION**:\n *\n * This method is **UNSAFE**.\n * You may encounter a race condition using it if there's a requested render.\n * Call this method only if you are sure rendering has settled.\n * Consider using {@link dispose} as it is **SAFE**\n *\n * @private\n */\n destroy() {\n this.destroyed = true;\n this.cancelRequestedRender();\n this.forEachObject((object) => object.dispose());\n this._objects = [];\n if (this.backgroundImage) {\n this.backgroundImage.dispose();\n }\n this.backgroundImage = undefined;\n if (this.overlayImage) {\n this.overlayImage.dispose();\n }\n this.overlayImage = undefined;\n this.elements.dispose();\n }\n\n /**\n * Returns a string representation of an instance\n * @return {String} string representation of an instance\n */\n toString() {\n return `#<Canvas (${this.complexity()}): { objects: ${\n this._objects.length\n } }>`;\n }\n}\n","import type { TPointerEvent } from '../EventTypeDefs';\nimport { Point } from '../Point';\nimport { getScrollLeftTop } from './dom_misc';\n\nconst touchEvents = ['touchstart', 'touchmove', 'touchend'];\n\nfunction getTouchInfo(event: TouchEvent | MouseEvent): MouseEvent | Touch {\n const touchProp = (event as TouchEvent).changedTouches;\n if (touchProp && touchProp[0]) {\n return touchProp[0];\n }\n return event as MouseEvent;\n}\n\nexport const getPointer = (event: TPointerEvent): Point => {\n const element = event.target as HTMLElement,\n scroll = getScrollLeftTop(element),\n _evt = getTouchInfo(event);\n return new Point(_evt.clientX + scroll.left, _evt.clientY + scroll.top);\n};\n\nexport const isTouchEvent = (event: TPointerEvent) =>\n touchEvents.includes(event.type) ||\n (event as PointerEvent).pointerType === 'touch';\n\nexport const stopEvent = (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n};\n","import type { XY } from '../../Point';\nimport type { TBBox } from '../../typedefs';\n\n/**\n * Calculates bounding box (left, top, width, height) from given `points`\n * @param {XY[]} points\n * @return {Object} Object with left, top, width, height properties\n */\nexport const makeBoundingBoxFromPoints = (points: XY[]): TBBox => {\n let left = 0,\n top = 0,\n width = 0,\n height = 0;\n\n for (let i = 0, len = points.length; i < len; i++) {\n const { x, y } = points[i];\n if (x > width || !i) width = x;\n if (x < left || !i) left = x;\n if (y > height || !i) height = y;\n if (y < top || !i) top = y;\n }\n\n return {\n left,\n top,\n width: width - left,\n height: height - top,\n };\n};\n","import { Point } from '../../Point';\nimport { CENTER } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/Object';\nimport type { TMat2D } from '../../typedefs';\nimport { makeBoundingBoxFromPoints } from './boundingBoxFromPoints';\nimport {\n invertTransform,\n multiplyTransformMatrices,\n qrDecompose,\n} from './matrix';\n\n/**\n * given an object and a transform, apply the inverse transform to the object,\n * this is equivalent to remove from that object that transformation, so that\n * added in a space with the removed transform, the object will be the same as before.\n * Removing from an object a transform that scale by 2 is like scaling it by 1/2.\n * Removing from an object a transform that rotate by 30deg is like rotating by 30deg\n * in the opposite direction.\n * This util is used to add objects inside transformed groups or nested groups.\n * @param {FabricObject} object the object you want to transform\n * @param {TMat2D} transform the destination transform\n */\nexport const removeTransformFromObject = (\n object: FabricObject,\n transform: TMat2D,\n) => {\n const inverted = invertTransform(transform),\n finalTransform = multiplyTransformMatrices(\n inverted,\n object.calcOwnMatrix(),\n );\n applyTransformToObject(object, finalTransform);\n};\n\n/**\n * given an object and a transform, apply the transform to the object.\n * this is equivalent to change the space where the object is drawn.\n * Adding to an object a transform that scale by 2 is like scaling it by 2.\n * This is used when removing an object from an active selection for example.\n * @param {FabricObject} object the object you want to transform\n * @param {Array} transform the destination transform\n */\nexport const addTransformToObject = (object: FabricObject, transform: TMat2D) =>\n applyTransformToObject(\n object,\n multiplyTransformMatrices(transform, object.calcOwnMatrix()),\n );\n\n/**\n * discard an object transform state and apply the one from the matrix.\n * @param {FabricObject} object the object you want to transform\n * @param {Array} transform the destination transform\n */\nexport const applyTransformToObject = (\n object: FabricObject,\n transform: TMat2D,\n) => {\n const { translateX, translateY, scaleX, scaleY, ...otherOptions } =\n qrDecompose(transform),\n center = new Point(translateX, translateY);\n object.flipX = false;\n object.flipY = false;\n Object.assign(object, otherOptions);\n object.set({ scaleX, scaleY });\n object.setPositionByOrigin(center, CENTER, CENTER);\n};\n/**\n * reset an object transform state to neutral. Top and left are not accounted for\n * @param {FabricObject} target object to transform\n */\nexport const resetObjectTransform = (target: FabricObject) => {\n target.scaleX = 1;\n target.scaleY = 1;\n target.skewX = 0;\n target.skewY = 0;\n target.flipX = false;\n target.flipY = false;\n target.rotate(0);\n};\n\n/**\n * Extract Object transform values\n * @param {FabricObject} target object to read from\n * @return {Object} Components of transform\n */\nexport const saveObjectTransform = (target: FabricObject) => ({\n scaleX: target.scaleX,\n scaleY: target.scaleY,\n skewX: target.skewX,\n skewY: target.skewY,\n angle: target.angle,\n left: target.left,\n flipX: target.flipX,\n flipY: target.flipY,\n top: target.top,\n});\n\n/**\n * given a width and height, return the size of the bounding box\n * that can contains the box with width/height with applied transform.\n * Use to calculate the boxes around objects for controls.\n * @param {Number} width\n * @param {Number} height\n * @param {TMat2D} t\n * @returns {Point} size\n */\nexport const sizeAfterTransform = (\n width: number,\n height: number,\n t: TMat2D,\n) => {\n const dimX = width / 2,\n dimY = height / 2,\n points = [\n new Point(-dimX, -dimY),\n new Point(dimX, -dimY),\n new Point(-dimX, dimY),\n new Point(dimX, dimY),\n ].map((p) => p.transform(t)),\n bbox = makeBoundingBoxFromPoints(points);\n return new Point(bbox.width, bbox.height);\n};\n","import { iMatrix } from '../../constants';\nimport type { Point } from '../../Point';\nimport type { FabricObject } from '../../shapes/Object/Object';\nimport type { TMat2D } from '../../typedefs';\nimport { invertTransform, multiplyTransformMatrices } from './matrix';\nimport { applyTransformToObject } from './objectTransforms';\n\n/**\n * We are actually looking for the transformation from the destination plane to the source plane (change of basis matrix)\\\n * The object will exist on the destination plane and we want it to seem unchanged by it so we invert the destination matrix (`to`) and then apply the source matrix (`from`)\n * @param [from]\n * @param [to]\n * @returns\n */\nexport const calcPlaneChangeMatrix = (\n from: TMat2D = iMatrix,\n to: TMat2D = iMatrix,\n) => multiplyTransformMatrices(invertTransform(to), from);\n\n/**\n * Sends a point from the source coordinate plane to the destination coordinate plane.\\\n * From the canvas/viewer's perspective the point remains unchanged.\n *\n * @example <caption>Send point from canvas plane to group plane</caption>\n * var obj = new Rect({ left: 20, top: 20, width: 60, height: 60, strokeWidth: 0 });\n * var group = new Group([obj], { strokeWidth: 0 });\n * var sentPoint1 = sendPointToPlane(new Point(50, 50), undefined, group.calcTransformMatrix());\n * var sentPoint2 = sendPointToPlane(new Point(50, 50), iMatrix, group.calcTransformMatrix());\n * console.log(sentPoint1, sentPoint2) // both points print (0,0) which is the center of group\n *\n * @param {Point} point\n * @param {TMat2D} [from] plane matrix containing object. Passing `undefined` is equivalent to passing the identity matrix, which means `point` exists in the canvas coordinate plane.\n * @param {TMat2D} [to] destination plane matrix to contain object. Passing `undefined` means `point` should be sent to the canvas coordinate plane.\n * @returns {Point} transformed point\n */\nexport const sendPointToPlane = (\n point: Point,\n from: TMat2D = iMatrix,\n to: TMat2D = iMatrix,\n): Point => point.transform(calcPlaneChangeMatrix(from, to));\n\n/**\n * See {@link sendPointToPlane}\n */\nexport const sendVectorToPlane = (\n point: Point,\n from: TMat2D = iMatrix,\n to: TMat2D = iMatrix,\n): Point => point.transform(calcPlaneChangeMatrix(from, to), true);\n\n/**\n *\n * A util that abstracts applying transform to objects.\\\n * Sends `object` to the destination coordinate plane by applying the relevant transformations.\\\n * Changes the space/plane where `object` is drawn.\\\n * From the canvas/viewer's perspective `object` remains unchanged.\n *\n * @example <caption>Move clip path from one object to another while preserving it's appearance as viewed by canvas/viewer</caption>\n * let obj, obj2;\n * let clipPath = new Circle({ radius: 50 });\n * obj.clipPath = clipPath;\n * // render\n * sendObjectToPlane(clipPath, obj.calcTransformMatrix(), obj2.calcTransformMatrix());\n * obj.clipPath = undefined;\n * obj2.clipPath = clipPath;\n * // render, clipPath now clips obj2 but seems unchanged from the eyes of the viewer\n *\n * @example <caption>Clip an object's clip path with an existing object</caption>\n * let obj, existingObj;\n * let clipPath = new Circle({ radius: 50 });\n * obj.clipPath = clipPath;\n * let transformTo = multiplyTransformMatrices(obj.calcTransformMatrix(), clipPath.calcTransformMatrix());\n * sendObjectToPlane(existingObj, existingObj.group?.calcTransformMatrix(), transformTo);\n * clipPath.clipPath = existingObj;\n *\n * @param {FabricObject} object\n * @param {Matrix} [from] plane matrix containing object. Passing `undefined` is equivalent to passing the identity matrix, which means `object` is a direct child of canvas.\n * @param {Matrix} [to] destination plane matrix to contain object. Passing `undefined` means `object` should be sent to the canvas coordinate plane.\n * @returns {Matrix} the transform matrix that was applied to `object`\n */\nexport const sendObjectToPlane = (\n object: FabricObject,\n from?: TMat2D,\n to?: TMat2D,\n): TMat2D => {\n const t = calcPlaneChangeMatrix(from, to);\n applyTransformToObject(\n object,\n multiplyTransformMatrices(t, object.calcOwnMatrix()),\n );\n return t;\n};\n","import type { TOriginX, TOriginY } from '../../typedefs';\n\nconst originOffset = {\n left: -0.5,\n top: -0.5,\n center: 0,\n bottom: 0.5,\n right: 0.5,\n};\n/**\n * Resolves origin value relative to center\n * @private\n * @param {TOriginX | TOriginY} originValue originX / originY\n * @returns number\n */\n\nexport const resolveOrigin = (\n originValue: TOriginX | TOriginY | number,\n): number =>\n typeof originValue === 'string'\n ? originOffset[originValue]\n : originValue - 0.5;\n","import type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TRadian } from '../../typedefs';\n\nconst unitVectorX = new Point(1, 0);\nconst zero = new Point();\n\n/**\n * Rotates `vector` with `radians`\n * @param {Point} vector The vector to rotate (x and y)\n * @param {Number} radians The radians of the angle for the rotation\n * @return {Point} The new rotated point\n */\nexport const rotateVector = (vector: Point, radians: TRadian) =>\n vector.rotate(radians);\n\n/**\n * Creates a vector from points represented as a point\n *\n * @param {Point} from\n * @param {Point} to\n * @returns {Point} vector\n */\nexport const createVector = (from: XY, to: XY): Point =>\n new Point(to).subtract(from);\n\n/**\n * return the magnitude of a vector\n * @return {number}\n */\nexport const magnitude = (point: Point) => point.distanceFrom(zero);\n\n/**\n * Calculates the angle between 2 vectors\n * @param {Point} a\n * @param {Point} b\n * @returns the angle in radians from `a` to `b`\n */\nexport const calcAngleBetweenVectors = (a: Point, b: Point): TRadian =>\n Math.atan2(crossProduct(a, b), dotProduct(a, b)) as TRadian;\n\n/**\n * Calculates the angle between the x axis and the vector\n * @param {Point} v\n * @returns the angle in radians of `v`\n */\nexport const calcVectorRotation = (v: Point) =>\n calcAngleBetweenVectors(unitVectorX, v);\n\n/**\n * @param {Point} v\n * @returns {Point} vector representing the unit vector pointing to the direction of `v`\n */\nexport const getUnitVector = (v: Point): Point =>\n v.eq(zero) ? v : v.scalarDivide(magnitude(v));\n\n/**\n * @param {Point} v\n * @param {Boolean} [counterClockwise] the direction of the orthogonal vector, defaults to `true`\n * @returns {Point} the unit orthogonal vector\n */\nexport const getOrthonormalVector = (\n v: Point,\n counterClockwise = true,\n): Point =>\n getUnitVector(new Point(-v.y, v.x).scalarMultiply(counterClockwise ? 1 : -1));\n\n/**\n * Cross product of two vectors in 2D\n * @param {Point} a\n * @param {Point} b\n * @returns {number} the magnitude of Z vector\n */\nexport const crossProduct = (a: Point, b: Point): number =>\n a.x * b.y - a.y * b.x;\n\n/**\n * Dot product of two vectors in 2D\n * @param {Point} a\n * @param {Point} b\n * @returns {number}\n */\nexport const dotProduct = (a: Point, b: Point): number => a.x * b.x + a.y * b.y;\n\n/**\n * Checks if the vector is between two others. It is considered\n * to be inside when the vector to be tested is between the\n * initial vector and the final vector (included) in a counterclockwise direction.\n * @param {Point} t vector to be tested\n * @param {Point} a initial vector\n * @param {Point} b final vector\n * @returns {boolean} true if the vector is among the others\n */\nexport const isBetweenVectors = (t: Point, a: Point, b: Point): boolean => {\n if (t.eq(a) || t.eq(b)) return true;\n const AxB = crossProduct(a, b),\n AxT = crossProduct(a, t),\n BxT = crossProduct(b, t);\n return AxB >= 0 ? AxT >= 0 && BxT <= 0 : !(AxT <= 0 && BxT >= 0);\n};\n","import type {\n TPointerEvent,\n Transform,\n TransformAction,\n BasicTransformEvent,\n} from '../EventTypeDefs';\nimport { resolveOrigin } from '../util/misc/resolveOrigin';\nimport { Point } from '../Point';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TOriginX, TOriginY } from '../typedefs';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\nimport type { Control } from './Control';\nimport { CENTER, quarterPI, twoMathPi } from '../constants';\nimport { calcVectorRotation, createVector } from '../util/misc/vectors';\nimport type { TOCoord } from '../shapes/Object/InteractiveObject';\nimport { sendPointToPlane } from '../util/misc/planeChange';\n\nexport const NOT_ALLOWED_CURSOR = 'not-allowed';\n\n/**\n * @param {Boolean} alreadySelected true if target is already selected\n * @param {String} corner a string representing the corner ml, mr, tl ...\n * @param {Event} e Event object\n * @param {FabricObject} [target] inserted back to help overriding. Unused\n */\nexport const getActionFromCorner = (\n alreadySelected: boolean,\n corner: string | undefined,\n e: TPointerEvent,\n target: FabricObject,\n) => {\n if (!corner || !alreadySelected) {\n return 'drag';\n }\n const control = target.controls[corner];\n return control.getActionName(e, control, target);\n};\n\n/**\n * Checks if transform is centered\n * @param {Object} transform transform data\n * @return {Boolean} true if transform is centered\n */\nexport function isTransformCentered(transform: Transform) {\n return (\n resolveOrigin(transform.originX) === resolveOrigin(CENTER) &&\n resolveOrigin(transform.originY) === resolveOrigin(CENTER)\n );\n}\n\nexport function invertOrigin(origin: TOriginX | TOriginY) {\n return -resolveOrigin(origin) + 0.5;\n}\n\nexport const isLocked = (\n target: FabricObject,\n lockingKey:\n | 'lockMovementX'\n | 'lockMovementY'\n | 'lockRotation'\n | 'lockScalingX'\n | 'lockScalingY'\n | 'lockSkewingX'\n | 'lockSkewingY'\n | 'lockScalingFlip',\n) => target[lockingKey];\n\nexport const commonEventInfo: TransformAction<\n Transform,\n BasicTransformEvent\n> = (eventData, transform, x, y) => {\n return {\n e: eventData,\n transform,\n pointer: new Point(x, y),\n };\n};\n\n/**\n * Combine control position and object angle to find the control direction compared\n * to the object center.\n * @param {FabricObject} fabricObject the fabric object for which we are rendering controls\n * @param {Control} control the control class\n * @return {Number} 0 - 7 a quadrant number\n */\nexport function findCornerQuadrant(\n fabricObject: FabricObject,\n control: Control,\n coord: TOCoord,\n): number {\n const target = coord;\n const center = sendPointToPlane(\n fabricObject.getCenterPoint(),\n fabricObject.canvas!.viewportTransform,\n undefined,\n );\n const angle = calcVectorRotation(createVector(center, target)) + twoMathPi;\n return Math.round((angle % twoMathPi) / quarterPI);\n}\n\n/**\n * @returns the normalized point (rotated relative to center) in local coordinates\n */\nfunction normalizePoint(\n target: FabricObject,\n point: Point,\n originX: TOriginX,\n originY: TOriginY,\n): Point {\n const center = target.getRelativeCenterPoint(),\n p =\n typeof originX !== 'undefined' && typeof originY !== 'undefined'\n ? target.translateToGivenOrigin(\n center,\n CENTER,\n CENTER,\n originX,\n originY,\n )\n : new Point(target.left, target.top),\n p2 = target.angle\n ? point.rotate(-degreesToRadians(target.angle), center)\n : point;\n return p2.subtract(p);\n}\n\n/**\n * Transforms a point to the offset from the given origin\n * @param {Object} transform\n * @param {String} originX\n * @param {String} originY\n * @param {number} x\n * @param {number} y\n * @return {Fabric.Point} the normalized point\n */\nexport function getLocalPoint(\n { target, corner }: Transform,\n originX: TOriginX,\n originY: TOriginY,\n x: number,\n y: number,\n) {\n const control = target.controls[corner],\n zoom = target.canvas?.getZoom() || 1,\n padding = target.padding / zoom,\n localPoint = normalizePoint(target, new Point(x, y), originX, originY);\n if (localPoint.x >= padding) {\n localPoint.x -= padding;\n }\n if (localPoint.x <= -padding) {\n localPoint.x += padding;\n }\n if (localPoint.y >= padding) {\n localPoint.y -= padding;\n }\n if (localPoint.y <= padding) {\n localPoint.y += padding;\n }\n localPoint.x -= control.offsetX;\n localPoint.y -= control.offsetY;\n return localPoint;\n}\n","export const normalizeWs = (value: string) => value.replace(/\\s+/g, ' ');\n","/**\n * Map of the 148 color names with HEX code\n * @see: https://www.w3.org/TR/css3-color/#svg-color\n */\nexport const ColorNameMap = {\n aliceblue: '#F0F8FF',\n antiquewhite: '#FAEBD7',\n aqua: '#0FF',\n aquamarine: '#7FFFD4',\n azure: '#F0FFFF',\n beige: '#F5F5DC',\n bisque: '#FFE4C4',\n black: '#000',\n blanchedalmond: '#FFEBCD',\n blue: '#00F',\n blueviolet: '#8A2BE2',\n brown: '#A52A2A',\n burlywood: '#DEB887',\n cadetblue: '#5F9EA0',\n chartreuse: '#7FFF00',\n chocolate: '#D2691E',\n coral: '#FF7F50',\n cornflowerblue: '#6495ED',\n cornsilk: '#FFF8DC',\n crimson: '#DC143C',\n cyan: '#0FF',\n darkblue: '#00008B',\n darkcyan: '#008B8B',\n darkgoldenrod: '#B8860B',\n darkgray: '#A9A9A9',\n darkgrey: '#A9A9A9',\n darkgreen: '#006400',\n darkkhaki: '#BDB76B',\n darkmagenta: '#8B008B',\n darkolivegreen: '#556B2F',\n darkorange: '#FF8C00',\n darkorchid: '#9932CC',\n darkred: '#8B0000',\n darksalmon: '#E9967A',\n darkseagreen: '#8FBC8F',\n darkslateblue: '#483D8B',\n darkslategray: '#2F4F4F',\n darkslategrey: '#2F4F4F',\n darkturquoise: '#00CED1',\n darkviolet: '#9400D3',\n deeppink: '#FF1493',\n deepskyblue: '#00BFFF',\n dimgray: '#696969',\n dimgrey: '#696969',\n dodgerblue: '#1E90FF',\n firebrick: '#B22222',\n floralwhite: '#FFFAF0',\n forestgreen: '#228B22',\n fuchsia: '#F0F',\n gainsboro: '#DCDCDC',\n ghostwhite: '#F8F8FF',\n gold: '#FFD700',\n goldenrod: '#DAA520',\n gray: '#808080',\n grey: '#808080',\n green: '#008000',\n greenyellow: '#ADFF2F',\n honeydew: '#F0FFF0',\n hotpink: '#FF69B4',\n indianred: '#CD5C5C',\n indigo: '#4B0082',\n ivory: '#FFFFF0',\n khaki: '#F0E68C',\n lavender: '#E6E6FA',\n lavenderblush: '#FFF0F5',\n lawngreen: '#7CFC00',\n lemonchiffon: '#FFFACD',\n lightblue: '#ADD8E6',\n lightcoral: '#F08080',\n lightcyan: '#E0FFFF',\n lightgoldenrodyellow: '#FAFAD2',\n lightgray: '#D3D3D3',\n lightgrey: '#D3D3D3',\n lightgreen: '#90EE90',\n lightpink: '#FFB6C1',\n lightsalmon: '#FFA07A',\n lightseagreen: '#20B2AA',\n lightskyblue: '#87CEFA',\n lightslategray: '#789',\n lightslategrey: '#789',\n lightsteelblue: '#B0C4DE',\n lightyellow: '#FFFFE0',\n lime: '#0F0',\n limegreen: '#32CD32',\n linen: '#FAF0E6',\n magenta: '#F0F',\n maroon: '#800000',\n mediumaquamarine: '#66CDAA',\n mediumblue: '#0000CD',\n mediumorchid: '#BA55D3',\n mediumpurple: '#9370DB',\n mediumseagreen: '#3CB371',\n mediumslateblue: '#7B68EE',\n mediumspringgreen: '#00FA9A',\n mediumturquoise: '#48D1CC',\n mediumvioletred: '#C71585',\n midnightblue: '#191970',\n mintcream: '#F5FFFA',\n mistyrose: '#FFE4E1',\n moccasin: '#FFE4B5',\n navajowhite: '#FFDEAD',\n navy: '#000080',\n oldlace: '#FDF5E6',\n olive: '#808000',\n olivedrab: '#6B8E23',\n orange: '#FFA500',\n orangered: '#FF4500',\n orchid: '#DA70D6',\n palegoldenrod: '#EEE8AA',\n palegreen: '#98FB98',\n paleturquoise: '#AFEEEE',\n palevioletred: '#DB7093',\n papayawhip: '#FFEFD5',\n peachpuff: '#FFDAB9',\n peru: '#CD853F',\n pink: '#FFC0CB',\n plum: '#DDA0DD',\n powderblue: '#B0E0E6',\n purple: '#800080',\n rebeccapurple: '#639',\n red: '#F00',\n rosybrown: '#BC8F8F',\n royalblue: '#4169E1',\n saddlebrown: '#8B4513',\n salmon: '#FA8072',\n sandybrown: '#F4A460',\n seagreen: '#2E8B57',\n seashell: '#FFF5EE',\n sienna: '#A0522D',\n silver: '#C0C0C0',\n skyblue: '#87CEEB',\n slateblue: '#6A5ACD',\n slategray: '#708090',\n slategrey: '#708090',\n snow: '#FFFAFA',\n springgreen: '#00FF7F',\n steelblue: '#4682B4',\n tan: '#D2B48C',\n teal: '#008080',\n thistle: '#D8BFD8',\n tomato: '#FF6347',\n turquoise: '#40E0D0',\n violet: '#EE82EE',\n wheat: '#F5DEB3',\n white: '#FFF',\n whitesmoke: '#F5F5F5',\n yellow: '#FF0',\n yellowgreen: '#9ACD32',\n};\n","import type { TRGBAColorSource } from './typedefs';\n\n/**\n * @param {Number} p\n * @param {Number} q\n * @param {Number} t\n * @return {Number}\n */\nexport const hue2rgb = (p: number, q: number, t: number): number => {\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 * Adapted from {@link https://gist.github.com/mjackson/5311256 https://gist.github.com/mjackson}\n * @param {Number} r Red color value\n * @param {Number} g Green color value\n * @param {Number} b Blue color value\n * @param {Number} a Alpha color value pass through\n * @return {TRGBColorSource} Hsl color\n */\nexport const rgb2Hsl = (\n r: number,\n g: number,\n b: number,\n a: number,\n): TRGBAColorSource => {\n r /= 255;\n g /= 255;\n b /= 255;\n const maxValue = Math.max(r, g, b),\n minValue = Math.min(r, g, b);\n\n let h!: number, s: number;\n const l = (maxValue + minValue) / 2;\n\n if (maxValue === minValue) {\n h = s = 0; // achromatic\n } else {\n const d = maxValue - minValue;\n s = l > 0.5 ? d / (2 - maxValue - minValue) : d / (maxValue + minValue);\n switch (maxValue) {\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 [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100), a];\n};\n\nexport const fromAlphaToFloat = (value = '1') =>\n parseFloat(value) / (value.endsWith('%') ? 100 : 1);\n\n/**\n * Convert a value in the inclusive range [0, 255] to hex\n */\nexport const hexify = (value: number) =>\n Math.min(Math.round(value), 255).toString(16).toUpperCase().padStart(2, '0');\n\n/**\n * Calculate the grey average value for rgb and pass through alpha\n */\nexport const greyAverage = ([\n r,\n g,\n b,\n a = 1,\n]: TRGBAColorSource): TRGBAColorSource => {\n const avg = Math.round(r * 0.3 + g * 0.59 + b * 0.11);\n return [avg, avg, avg, a];\n};\n","import { normalizeWs } from '../util/internals/normalizeWhiteSpace';\nimport { radiansToDegrees } from '../util/misc/radiansDegreesConversion';\nimport { ColorNameMap } from './color_map';\nimport { reHSLa, reHex, reRGBa } from './constants';\nimport type { TRGBAColorSource, TColorArg } from './typedefs';\nimport {\n hue2rgb,\n hexify,\n rgb2Hsl,\n fromAlphaToFloat,\n greyAverage,\n} from './util';\n\n/**\n * @class Color common color operations\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#colors colors}\n */\nexport class Color {\n declare private _source: TRGBAColorSource;\n isUnrecognised = false;\n\n /**\n *\n * @param {string} [color] optional in hex or rgb(a) or hsl format or from known color list\n */\n constructor(color?: TColorArg) {\n if (!color) {\n // we default to black as canvas does\n this.setSource([0, 0, 0, 1]);\n } else if (color instanceof Color) {\n this.setSource([...color._source]);\n } else if (Array.isArray(color)) {\n const [r, g, b, a = 1] = color;\n this.setSource([r, g, b, a]);\n } else {\n this.setSource(this._tryParsingColor(color));\n }\n }\n\n /**\n * @private\n * @param {string} [color] Color value to parse\n * @returns {TRGBAColorSource}\n */\n protected _tryParsingColor(color: string) {\n color = color.toLowerCase();\n if (color in ColorNameMap) {\n color = ColorNameMap[color as keyof typeof ColorNameMap];\n }\n return color === 'transparent'\n ? ([255, 255, 255, 0] as TRGBAColorSource)\n : Color.sourceFromHex(color) ||\n Color.sourceFromRgb(color) ||\n Color.sourceFromHsl(color) ||\n // color is not recognized\n // we default to black as canvas does\n // eslint-disable-next-line no-constant-binary-expression\n ((this.isUnrecognised = true) && ([0, 0, 0, 1] as TRGBAColorSource));\n }\n\n /**\n * Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])\n * @return {TRGBAColorSource}\n */\n getSource() {\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 {TRGBAColorSource} source\n */\n setSource(source: TRGBAColorSource) {\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() {\n const [r, g, b] = this.getSource();\n return `rgb(${r},${g},${b})`;\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() {\n return `rgba(${this.getSource().join(',')})`;\n }\n\n /**\n * Returns color representation in HSL format\n * @return {String} ex: hsl(0-360,0%-100%,0%-100%)\n */\n toHsl() {\n const [h, s, l] = rgb2Hsl(...this.getSource());\n return `hsl(${h},${s}%,${l}%)`;\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() {\n const [h, s, l, a] = rgb2Hsl(...this.getSource());\n return `hsla(${h},${s}%,${l}%,${a})`;\n }\n\n /**\n * Returns color representation in HEX format\n * @return {String} ex: FF5555\n */\n toHex() {\n const fullHex = this.toHexa();\n return fullHex.slice(0, 6);\n }\n\n /**\n * Returns color representation in HEXA format\n * @return {String} ex: FF5555CC\n */\n toHexa() {\n const [r, g, b, a] = this.getSource();\n return `${hexify(r)}${hexify(g)}${hexify(b)}${hexify(Math.round(a * 255))}`;\n }\n\n /**\n * Gets value of alpha channel for this color\n * @return {Number} 0-1\n */\n getAlpha() {\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 {Color} thisArg\n */\n setAlpha(alpha: number) {\n this._source[3] = alpha;\n return this;\n }\n\n /**\n * Transforms color to its grayscale representation\n * @return {Color} thisArg\n */\n toGrayscale() {\n this.setSource(greyAverage(this.getSource()));\n return this;\n }\n\n /**\n * Transforms color to its black and white representation\n * @param {Number} threshold\n * @return {Color} thisArg\n */\n toBlackWhite(threshold: number) {\n const [average, , , a] = greyAverage(this.getSource()),\n bOrW = average < (threshold || 127) ? 0 : 255;\n this.setSource([bOrW, bOrW, bOrW, a]);\n return this;\n }\n\n /**\n * Overlays color with another color\n * @param {String|Color} otherColor\n * @return {Color} thisArg\n */\n overlayWith(otherColor: string | Color) {\n if (!(otherColor instanceof Color)) {\n otherColor = new Color(otherColor);\n }\n\n const source = this.getSource(),\n otherAlpha = 0.5,\n otherSource = otherColor.getSource(),\n [R, G, B] = source.map((value, index) =>\n Math.round(value * (1 - otherAlpha) + otherSource[index] * otherAlpha),\n );\n\n this.setSource([R, G, B, source[3]]);\n return this;\n }\n\n /**\n * Returns new color object, when given a color in RGB format\n * @param {String} color Color value ex: rgb(0-255,0-255,0-255)\n * @return {Color}\n */\n static fromRgb(color: string): Color {\n return Color.fromRgba(color);\n }\n\n /**\n * Returns new color object, when given a color in RGBA format\n * @param {String} color\n * @return {Color}\n */\n static fromRgba(color: string): Color {\n return new Color(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 * @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)\n * @return {TRGBAColorSource | undefined} source\n */\n static sourceFromRgb(color: string): TRGBAColorSource | undefined {\n const match = normalizeWs(color).match(reRGBa());\n if (match) {\n const [r, g, b] = match.slice(1, 4).map((value) => {\n const parsedValue = parseFloat(value);\n return value.endsWith('%')\n ? Math.round(parsedValue * 2.55)\n : parsedValue;\n });\n return [r, g, b, fromAlphaToFloat(match[4])];\n }\n }\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 * @return {Color}\n */\n static fromHsl(color: string): Color {\n return Color.fromHsla(color);\n }\n\n /**\n * Returns new color object, when given a color in HSLA format\n * @param {String} color\n * @return {Color}\n */\n static fromHsla(color: string): Color {\n return new Color(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 <a href=\"https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html\">https://github.com/mjijackson</a>\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 {TRGBAColorSource | undefined} source\n * @see http://http://www.w3.org/TR/css3-color/#hsl-color\n */\n static sourceFromHsl(color: string): TRGBAColorSource | undefined {\n const match = normalizeWs(color).match(reHSLa());\n if (!match) {\n return;\n }\n const match1degrees = Color.parseAngletoDegrees(match[1]);\n\n const h = (((match1degrees % 360) + 360) % 360) / 360,\n s = parseFloat(match[2]) / 100,\n l = parseFloat(match[3]) / 100;\n let r: number, g: number, b: number;\n\n if (s === 0) {\n r = g = b = l;\n } else {\n const 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 fromAlphaToFloat(match[4]),\n ];\n }\n\n /**\n * Returns new color object, when given a color in HEX format\n * @param {String} color Color value ex: FF5555\n * @return {Color}\n */\n static fromHex(color: string): Color {\n return new Color(Color.sourceFromHex(color));\n }\n\n /**\n * Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format\n * @param {String} color ex: FF5555 or FF5544CC (RGBa)\n * @return {TRGBAColorSource | undefined} source\n */\n static sourceFromHex(color: string): TRGBAColorSource | undefined {\n if (color.match(reHex())) {\n const value = color.slice(color.indexOf('#') + 1),\n isShortNotation = value.length <= 4;\n let expandedValue: string[];\n if (isShortNotation) {\n expandedValue = value.split('').map((hex) => hex + hex);\n } else {\n expandedValue = value.match(/.{2}/g)!;\n }\n const [r, g, b, a = 255] = expandedValue.map((hexCouple) =>\n parseInt(hexCouple, 16),\n );\n return [r, g, b, a / 255];\n }\n }\n\n /**\n * Converts a string that could be any angle notation (50deg, 0.5turn, 2rad)\n * into degrees without the 'deg' suffix\n * @param {String} value ex: 0deg, 0.5turn, 2rad\n * @return {Number} number in degrees or NaN if inputs are invalid\n */\n static parseAngletoDegrees(value: string): number {\n const lowercase = value.toLowerCase();\n const numeric = parseFloat(lowercase);\n\n if (lowercase.includes('rad')) {\n return radiansToDegrees(numeric);\n }\n\n if (lowercase.includes('turn')) {\n return numeric * 360;\n }\n\n // Value is probably just a number already in degrees eg '50'\n return numeric;\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 * Also matching rgba(r g b / a) as per new specs\n * https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb\n *\n * In order to avoid performance issues, you have to clean the input string for this regex from multiple spaces before.\n * ex: colorString.replace(/\\s+/g, ' ');\n *\n * Formal syntax at the time of writing:\n * <rgb()> =\n * rgb( [ <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? ) |\n * rgb( [ <number> | none ]{3} [ / [ <alpha-value> | none ] ]? )\n * <alpha-value> = <number> | <percentage>\n *\n * For learners this is how you can read this regex\n * Regular expression for matching an rgba or rgb CSS color value\n *\n * /^ # Beginning of the string\n * rgba? # \"rgb\" or \"rgba\"\n * \\(\\s? # Opening parenthesis and zero or one whitespace character\n * (\\d{0,3} # 0 to three digits R channel\n * (?:\\.\\d+)? # Optional decimal with one or more digits\n * ) # End of capturing group for the first color component\n * %? # Optional percent sign after the first color component\n * \\s? # Zero or one whitespace character\n * [\\s|,] # Separator between color components can be a space or comma\n * \\s? # Zero or one whitespace character\n * (\\d{0,3} # 0 to three digits G channel\n * (?:\\.\\d+)? # Optional decimal with one or more digits\n * ) # End of capturing group for the second color component\n * %? # Optional percent sign after the second color component\n * \\s? # Zero or one whitespace character\n * [\\s|,] # Separator between color components can be a space or comma\n * \\s? # Zero or one whitespace character\n * (\\d{0,3} # 0 to three digits B channel\n * (?:\\.\\d+)? # Optional decimal with one or more digits\n * ) # End of capturing group for the third color component\n * %? # Optional percent sign after the third color component\n * \\s? # Zero or one whitespace character\n * (?: # Beginning of non-capturing group for alpha value\n * \\s? # Zero or one whitespace character\n * [,/] # Comma or slash separator for alpha value\n * \\s? # Zero or one whitespace character\n * (\\d{0,3} # Zero to three digits\n * (?:\\.\\d+)? # Optional decimal with one or more digits\n * ) # End of capturing group for alpha value\n * %? # Optional percent sign after alpha value\n * \\s? # Zero or one whitespace character\n * )? # End of non-capturing group for alpha value (optional)\n * \\) # Closing parenthesis\n * $ # End of the string\n *\n * The alpha channel can be in the format 0.4 .7 or 1 or 73%\n *\n * WARNING this regex doesn't fail on off spec colors. it matches everything that could be a color.\n * So the spec does not allow for `rgba(30 , 45% 35, 49%)` but this will work anyways for us\n */\nexport const reRGBa = () =>\n /^rgba?\\(\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?[\\s|,]\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?[\\s|,]\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?(?:\\s?[,/]\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?)?\\)$/i;\n\n/**\n * Regex matching color in HSL or HSLA formats (ex: hsl(0deg 0%, 0%), hsla(160, 100, 10, 0.5), hsla( 180 , 100 , 10 , 0.5 ), hsl(1,1,1))\n * Also matching hsla(h s l / a) as per new specs\n * https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl\n * In order to avoid performance issues, you have to clean the input string for this regex from multiple spaces before.\n * ex: colorString.replace(/\\s+/g, ' ');\n * Formal syntax at the time of writing:\n * <hsl()> =\n * hsl( [ <hue> | none ] [ <percentage> | none ] [ <percentage> | none ] [ / [ <alpha-value> | none ] ]? )\n *\n * <hue> =\n * <number> |\n * <angle>\n *\n * <alpha-value> =\n * <number> |\n * <percentage>\n *\n * For learners this is how you can read this regex\n * Regular expression for matching an hsla or hsl CSS color value\n *\n * /^hsla?\\( // Matches the beginning of the string and the opening parenthesis of \"hsl\" or \"hsla\"\n * \\s? // Matches any whitespace character (space, tab, etc.) zero or one time\n * (\\d{0,3} // Hue: 0 to three digits - start capture in a group\n * (?:\\.\\d+)? // Hue: Optional (non capture group) decimal with one or more digits.\n * (?:deg|turn|rad)? // Hue: Optionally include suffix deg or turn or rad\n * ) // Hue: End capture group\n * \\s? // Matches any whitespace character zero or one time\n * [\\s|,] // Matches a space, tab or comma\n * \\s? // Matches any whitespace character zero or one time\n * (\\d{0,3} // Saturation: 0 to three digits - start capture in a group\n * (?:\\.\\d+)? // Saturation: Optional decimal with one or more digits in a non-capturing group\n * %?) // Saturation: match optional % character and end capture group\n * \\s? // Matches any whitespace character zero or one time\n * [\\s|,] // Matches a space, tab or comma\n * \\s? // Matches any whitespace character zero or one time\n * (\\d{0,3} // Lightness: 0 to three digits - start capture in a group\n * (?:\\.\\d+)? // Lightness: Optional decimal with one or more digits in a non-capturing group\n * %?) // Lightness: match % character and end capture group\n * \\s? // Matches any whitespace character zero or one time\n * (?: // Alpha: Begins a non-capturing group for the alpha value\n * \\s? // Matches any whitespace character zero or one time\n * [,/] // Matches a comma or forward slash\n * \\s? // Matches any whitespace character zero or one time\n * (\\d*(?:\\.\\d+)?%?) // Matches zero or more digits, optionally followed by a decimal point and one or more digits, followed by an optional percentage sign and captures it in a group\n * \\s? // Matches any whitespace character zero or one time\n * )? // Makes the alpha value group optional\n * \\) // Matches the closing parenthesis\n * $/i // Matches the end of the string and sets the regular expression to case-insensitive mode\n *\n * WARNING this regex doesn't fail on off spec colors. It matches everything that could be a color.\n * So the spec does not allow `hsl(30 , 45% 35, 49%)` but this will work anyways for us.\n */\nexport const reHSLa = () =>\n /^hsla?\\(\\s?([+-]?\\d{0,3}(?:\\.\\d+)?(?:deg|turn|rad)?)\\s?[\\s|,]\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?[\\s|,]\\s?(\\d{0,3}(?:\\.\\d+)?%?)\\s?(?:\\s?[,/]\\s?(\\d*(?:\\.\\d+)?%?)\\s?)?\\)$/i;\n\n/**\n * Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)\n */\nexport const reHex = () => /^#?(([0-9a-f]){3,4}|([0-9a-f]{2}){3,4})$/i;\n","import { Color } from '../../color/Color';\nimport { config } from '../../config';\nimport { DEFAULT_SVG_FONT_SIZE, FILL, NONE } from '../../constants';\nimport type { TBBox, SVGElementName, SupportedSVGUnit } from '../../typedefs';\nimport { toFixed } from './toFixed';\n\n/**\n * Returns array of attributes for given svg that fabric parses\n * @param {SVGElementName} type Type of svg element (eg. 'circle')\n * @return {Array} string names of supported attributes\n */\nexport const getSvgAttributes = (type: SVGElementName) => {\n const commonAttributes = ['instantiated_by_use', 'style', 'id', 'class'];\n switch (type) {\n case 'linearGradient':\n return commonAttributes.concat([\n 'x1',\n 'y1',\n 'x2',\n 'y2',\n 'gradientUnits',\n 'gradientTransform',\n ]);\n case 'radialGradient':\n return commonAttributes.concat([\n 'gradientUnits',\n 'gradientTransform',\n 'cx',\n 'cy',\n 'r',\n 'fx',\n 'fy',\n 'fr',\n ]);\n case 'stop':\n return commonAttributes.concat(['offset', 'stop-color', 'stop-opacity']);\n }\n return commonAttributes;\n};\n\n/**\n * Converts from attribute value to pixel value if applicable.\n * Returns converted pixels or original value not converted.\n * @param {string} value number to operate on\n * @param {number} fontSize\n * @return {number}\n */\nexport const parseUnit = (value: string, fontSize = DEFAULT_SVG_FONT_SIZE) => {\n const unit = /\\D{0,2}$/.exec(value),\n number = parseFloat(value);\n const dpi = config.DPI;\n switch (unit?.[0] as SupportedSVGUnit) {\n case 'mm':\n return (number * dpi) / 25.4;\n\n case 'cm':\n return (number * dpi) / 2.54;\n\n case 'in':\n return number * dpi;\n\n case 'pt':\n return (number * dpi) / 72; // or * 4 / 3\n\n case 'pc':\n return ((number * dpi) / 72) * 12; // or * 16\n\n case 'em':\n return number * fontSize;\n\n default:\n return number;\n }\n};\n\nexport type MeetOrSlice = 'meet' | 'slice';\n\nexport type MinMidMax = 'Min' | 'Mid' | 'Max' | 'none';\n\nexport type TPreserveArParsed = {\n meetOrSlice: MeetOrSlice;\n alignX: MinMidMax;\n alignY: MinMidMax;\n};\n\n// align can be either none or undefined or a combination of mid/max\nconst parseAlign = (align: string): MinMidMax[] => {\n //divide align in alignX and alignY\n if (align && align !== NONE) {\n return [align.slice(1, 4) as MinMidMax, align.slice(5, 8) as MinMidMax];\n } else if (align === NONE) {\n return [align, align];\n }\n return ['Mid', 'Mid'];\n};\n\n/**\n * Parse preserveAspectRatio attribute from element\n * https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio\n * @param {string} attribute to be parsed\n * @return {Object} an object containing align and meetOrSlice attribute\n */\nexport const parsePreserveAspectRatioAttribute = (\n attribute: string,\n): TPreserveArParsed => {\n const [firstPart, secondPart] = attribute.trim().split(' ') as [\n MinMidMax,\n MeetOrSlice | undefined,\n ];\n const [alignX, alignY] = parseAlign(firstPart);\n return {\n meetOrSlice: secondPart || 'meet',\n alignX,\n alignY,\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 * @param prop\n * @param value\n * @param {boolean} inlineStyle The default is inline style, the separator used is \":\", The other is \"=\"\n * @returns\n */\nexport const colorPropToSVG = (\n prop: string,\n value?: any,\n inlineStyle = true,\n) => {\n let colorValue;\n let opacityValue;\n if (!value) {\n colorValue = 'none';\n } else if (value.toLive) {\n colorValue = `url(#SVGID_${value.id})`;\n } else {\n const color = new Color(value),\n opacity = color.getAlpha();\n\n colorValue = color.toRgb();\n if (opacity !== 1) {\n opacityValue = opacity.toString();\n }\n }\n if (inlineStyle) {\n return `${prop}: ${colorValue}; ${\n opacityValue ? `${prop}-opacity: ${opacityValue}; ` : ''\n }`;\n } else {\n return `${prop}=\"${colorValue}\" ${\n opacityValue ? `${prop}-opacity=\"${opacityValue}\" ` : ''\n }`;\n }\n};\n\nexport const createSVGRect = (\n color: string,\n { left, top, width, height }: TBBox,\n precision = config.NUM_FRACTION_DIGITS,\n) => {\n const svgColor = colorPropToSVG(FILL, color, false);\n const [x, y, w, h] = [left, top, width, height].map((value) =>\n toFixed(value, precision),\n );\n return `<rect ${svgColor} x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${h}\"></rect>`;\n};\n","import type { TSVGReviver } from '../../typedefs';\nimport { uid } from '../../util/internals/uid';\nimport { colorPropToSVG } from '../../util/misc/svgParsing';\nimport { FILL, NONE, STROKE } from '../../constants';\nimport type { FabricObject } from './FabricObject';\nimport { isFiller } from '../../util/typeAssertions';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nexport class FabricObjectSVGExportMixin {\n /**\n * When an object is being exported as SVG as a clippath, a reference inside the SVG is needed.\n * This reference is a UID in the fabric namespace and is temporary stored here.\n * @type {String}\n */\n declare clipPathId?: string;\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(\n this: FabricObjectSVGExportMixin & FabricObject,\n skipShadow?: boolean,\n ) {\n const fillRule = this.fillRule ? this.fillRule : 'nonzero',\n strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n strokeDashArray = this.strokeDashArray\n ? this.strokeDashArray.join(' ')\n : NONE,\n strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\n strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n visibility = this.visible ? '' : ' visibility: hidden;',\n filter = skipShadow ? '' : this.getSvgFilter(),\n fill = colorPropToSVG(FILL, this.fill),\n stroke = colorPropToSVG(STROKE, this.stroke);\n\n return [\n stroke,\n 'stroke-width: ',\n strokeWidth,\n '; ',\n 'stroke-dasharray: ',\n strokeDashArray,\n '; ',\n 'stroke-linecap: ',\n strokeLineCap,\n '; ',\n 'stroke-dashoffset: ',\n strokeDashOffset,\n '; ',\n 'stroke-linejoin: ',\n strokeLineJoin,\n '; ',\n 'stroke-miterlimit: ',\n strokeMiterLimit,\n '; ',\n fill,\n 'fill-rule: ',\n fillRule,\n '; ',\n 'opacity: ',\n opacity,\n ';',\n filter,\n visibility,\n ].join('');\n }\n\n /**\n * Returns filter for svg shadow\n * @return {String}\n */\n getSvgFilter(this: FabricObjectSVGExportMixin & FabricObject) {\n return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';\n }\n\n /**\n * Returns id attribute for svg output\n * @return {String}\n */\n getSvgCommons(\n this: FabricObjectSVGExportMixin & FabricObject & { id?: string },\n ) {\n return [\n this.id ? `id=\"${this.id}\" ` : '',\n this.clipPath\n ? `clip-path=\"url(#${\n (this.clipPath as FabricObjectSVGExportMixin & FabricObject)\n .clipPathId\n })\" `\n : '',\n ].join('');\n }\n\n /**\n * Returns transform-string for svg-export\n * @param {Boolean} use the full transform or the single object one.\n * @return {String}\n */\n getSvgTransform(\n this: FabricObjectSVGExportMixin & FabricObject,\n full?: boolean,\n additionalTransform = '',\n ) {\n const transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\n svgTransform = `transform=\"${matrixToSVG(transform)}`;\n return `${svgTransform}${additionalTransform}\" `;\n }\n\n /**\n * Returns svg representation of an instance\n * This function is implemented in each subclass\n * This is just because typescript otherwise cryies all the time\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG(_reviver?: TSVGReviver): string[] {\n return [''];\n }\n\n /**\n * Returns svg representation of an instance\n * @param {TSVGReviver} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toSVG(\n this: FabricObjectSVGExportMixin & FabricObject,\n reviver?: TSVGReviver,\n ) {\n return this._createBaseSVGMarkup(this._toSVG(reviver), {\n reviver,\n });\n }\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {TSVGReviver} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toClipPathSVG(\n this: FabricObjectSVGExportMixin & FabricObject,\n reviver?: TSVGReviver,\n ) {\n return (\n '\\t' +\n this._createBaseClipPathSVGMarkup(this._toSVG(reviver), {\n reviver,\n })\n );\n }\n\n /**\n * @private\n */\n _createBaseClipPathSVGMarkup(\n this: FabricObjectSVGExportMixin & FabricObject,\n objectMarkup: string[],\n {\n reviver,\n additionalTransform = '',\n }: { reviver?: TSVGReviver; additionalTransform?: string } = {},\n ) {\n const commonPieces = [\n this.getSvgTransform(true, additionalTransform),\n this.getSvgCommons(),\n ].join(''),\n // insert commons in the markup, style and svgCommons\n index = objectMarkup.indexOf('COMMON_PARTS');\n objectMarkup[index] = commonPieces;\n return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\n }\n\n /**\n * @private\n */\n _createBaseSVGMarkup(\n this: FabricObjectSVGExportMixin & FabricObject,\n objectMarkup: string[],\n {\n noStyle,\n reviver,\n withShadow,\n additionalTransform,\n }: {\n noStyle?: boolean;\n reviver?: TSVGReviver;\n withShadow?: boolean;\n additionalTransform?: string;\n } = {},\n ): string {\n const styleInfo = noStyle ? '' : `style=\"${this.getSvgStyles()}\" `,\n shadowInfo = withShadow ? `style=\"${this.getSvgFilter()}\" ` : '',\n clipPath = this.clipPath as FabricObjectSVGExportMixin & FabricObject,\n vectorEffect = this.strokeUniform\n ? 'vector-effect=\"non-scaling-stroke\" '\n : '',\n absoluteClipPath = clipPath && clipPath.absolutePositioned,\n stroke = this.stroke,\n fill = this.fill,\n shadow = this.shadow,\n markup = [],\n // insert commons in the markup, style and svgCommons\n index = objectMarkup.indexOf('COMMON_PARTS');\n let clipPathMarkup;\n if (clipPath) {\n clipPath.clipPathId = `CLIPPATH_${uid()}`;\n clipPathMarkup = `<clipPath id=\"${\n clipPath.clipPathId\n }\" >\\n${clipPath.toClipPathSVG(reviver)}</clipPath>\\n`;\n }\n if (absoluteClipPath) {\n markup.push('<g ', shadowInfo, this.getSvgCommons(), ' >\\n');\n }\n markup.push(\n '<g ',\n this.getSvgTransform(false),\n !absoluteClipPath ? shadowInfo + this.getSvgCommons() : '',\n ' >\\n',\n );\n const commonPieces = [\n styleInfo,\n vectorEffect,\n noStyle ? '' : this.addPaintOrder(),\n ' ',\n additionalTransform ? `transform=\"${additionalTransform}\" ` : '',\n ].join('');\n objectMarkup[index] = commonPieces;\n if (isFiller(fill)) {\n markup.push(fill.toSVG(this));\n }\n if (isFiller(stroke)) {\n markup.push(stroke.toSVG(this));\n }\n if (shadow) {\n markup.push(shadow.toSVG(this));\n }\n if (clipPath) {\n markup.push(clipPathMarkup);\n }\n markup.push(objectMarkup.join(''));\n markup.push('</g>\\n');\n absoluteClipPath && markup.push('</g>\\n');\n return reviver ? reviver(markup.join('')) : markup.join('');\n }\n\n addPaintOrder(this: FabricObjectSVGExportMixin & FabricObject) {\n return this.paintFirst !== FILL ? ` paint-order=\"${this.paintFirst}\" ` : '';\n }\n}\n","export function getSvgRegex(arr: string[]) {\n return new RegExp('^(' + arr.join('|') + ')\\\\b', 'i');\n}\n","import { FILL, LEFT, LTR, NORMAL, STROKE, reNewline } from '../../constants';\nimport type { TClassProperties } from '../../typedefs';\nimport type { FabricText } from './Text';\n\nexport const TEXT_DECORATION_THICKNESS = 'textDecorationThickness';\n\nconst fontProperties = [\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'fontStyle',\n] as const;\n\nexport const textDecorationProperties = [\n 'underline',\n 'overline',\n 'linethrough',\n] as const;\n\nexport const textLayoutProperties: string[] = [\n ...fontProperties,\n 'lineHeight',\n 'text',\n 'charSpacing',\n 'textAlign',\n 'styles',\n 'path',\n 'pathStartOffset',\n 'pathSide',\n 'pathAlign',\n];\n\nexport const additionalProps = [\n ...textLayoutProperties,\n ...textDecorationProperties,\n 'textBackgroundColor',\n 'direction',\n TEXT_DECORATION_THICKNESS,\n] as const;\n\nexport type StylePropertiesType =\n | 'fill'\n | 'stroke'\n | 'strokeWidth'\n | 'fontSize'\n | 'fontFamily'\n | 'fontWeight'\n | 'fontStyle'\n | 'textBackgroundColor'\n | 'deltaY'\n | 'overline'\n | 'underline'\n | 'linethrough'\n | typeof TEXT_DECORATION_THICKNESS;\n\nexport const styleProperties: Readonly<StylePropertiesType[]> = [\n ...fontProperties,\n ...textDecorationProperties,\n STROKE,\n 'strokeWidth',\n FILL,\n 'deltaY',\n 'textBackgroundColor',\n TEXT_DECORATION_THICKNESS,\n] as const;\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textDefaultValues: Partial<TClassProperties<FabricText>> = {\n _reNewline: reNewline,\n _reSpacesAndTabs: /[ \\t\\r]/g,\n _reSpaceAndTab: /[ \\t\\r]/,\n _reWords: /\\S+/g,\n fontSize: 40,\n fontWeight: NORMAL,\n fontFamily: 'Times New Roman',\n underline: false,\n overline: false,\n linethrough: false,\n textAlign: LEFT,\n fontStyle: NORMAL,\n lineHeight: 1.16,\n textBackgroundColor: '',\n stroke: null,\n shadow: null,\n path: undefined,\n pathStartOffset: 0,\n pathSide: LEFT,\n pathAlign: 'baseline',\n charSpacing: 0,\n deltaY: 0,\n direction: LTR,\n CACHE_FONT_SIZE: 400,\n MIN_TEXT_WIDTH: 2,\n // Text magic numbers\n superscript: {\n size: 0.6, // fontSize factor\n baseline: -0.35, // baseline-shift factor (upwards)\n },\n subscript: {\n size: 0.6, // fontSize factor\n baseline: 0.11, // baseline-shift factor (downwards)\n },\n _fontSizeFraction: 0.222,\n offsets: {\n underline: 0.1,\n linethrough: -0.28167, // added 1/30 to original number\n overline: -0.81333, // added 1/15 to original number\n },\n _fontSizeMult: 1.13,\n [TEXT_DECORATION_THICKNESS]: 66.667, // before implementation was 1/15\n};\n\nexport const JUSTIFY = 'justify';\nexport const JUSTIFY_LEFT = 'justify-left';\nexport const JUSTIFY_RIGHT = 'justify-right';\nexport const JUSTIFY_CENTER = 'justify-center';\n","import { getSvgRegex } from './getSvgRegex';\nimport { LEFT, TOP } from '../constants';\nimport { TEXT_DECORATION_THICKNESS } from '../shapes/Text/constants';\n\n// matches, e.g.: +14.56e-12, etc.\nexport const reNum = String.raw`[-+]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][-+]?\\d+)?`;\nexport const viewportSeparator = String.raw`(?:\\s*,?\\s+|\\s*,\\s*)`;\n\nexport const svgNS = 'http://www.w3.org/2000/svg';\n\nexport const 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 reNum +\n '(?:px|cm|mm|em|pt|pc|in)*)(?:\\\\/(normal|' +\n reNum +\n '))?\\\\s+(.*)',\n);\n\nexport const svgValidTagNames = [\n 'path',\n 'circle',\n 'polygon',\n 'polyline',\n 'ellipse',\n 'rect',\n 'line',\n 'image',\n 'text',\n ],\n svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],\n svgInvalidAncestors = [\n 'pattern',\n 'defs',\n 'symbol',\n 'metadata',\n 'clipPath',\n 'mask',\n 'desc',\n ],\n svgValidParents = ['symbol', 'g', 'a', 'svg', 'clipPath', 'defs'],\n attributesMap = {\n cx: LEFT,\n x: LEFT,\n r: 'radius',\n cy: TOP,\n y: TOP,\n display: 'visible',\n visibility: 'visible',\n transform: 'transformMatrix',\n 'fill-opacity': 'fillOpacity',\n 'fill-rule': 'fillRule',\n 'font-family': 'fontFamily',\n 'font-size': 'fontSize',\n 'font-style': 'fontStyle',\n 'font-weight': 'fontWeight',\n 'letter-spacing': 'charSpacing',\n 'paint-order': 'paintFirst',\n 'stroke-dasharray': 'strokeDashArray',\n 'stroke-dashoffset': 'strokeDashOffset',\n 'stroke-linecap': 'strokeLineCap',\n 'stroke-linejoin': 'strokeLineJoin',\n 'stroke-miterlimit': 'strokeMiterLimit',\n 'stroke-opacity': 'strokeOpacity',\n 'stroke-width': 'strokeWidth',\n 'text-decoration': 'textDecoration',\n 'text-anchor': 'textAnchor',\n opacity: 'opacity',\n 'clip-path': 'clipPath',\n 'clip-rule': 'clipRule',\n 'vector-effect': 'strokeUniform',\n 'image-rendering': 'imageSmoothing',\n 'text-decoration-thickness': TEXT_DECORATION_THICKNESS,\n },\n fSize = 'font-size',\n cPath = 'clip-path';\n\nexport const svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);\n\nexport const svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);\n\nexport const svgValidParentsRegEx = getSvgRegex(svgValidParents);\n\n// http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute\n\nexport const reViewBoxAttrValue = new RegExp(\n String.raw`^\\s*(${reNum})${viewportSeparator}(${reNum})${viewportSeparator}(${reNum})${viewportSeparator}(${reNum})\\s*$`,\n);\n","import { classRegistry } from './ClassRegistry';\nimport { Color } from './color/Color';\nimport { config } from './config';\nimport { reNum } from './parser/constants';\nimport { Point } from './Point';\nimport type { FabricObject } from './shapes/Object/FabricObject';\nimport type { TClassProperties } from './typedefs';\nimport { uid } from './util/internals/uid';\nimport { pickBy } from './util/misc/pick';\nimport { degreesToRadians } from './util/misc/radiansDegreesConversion';\nimport { toFixed } from './util/misc/toFixed';\nimport { rotateVector } from './util/misc/vectors';\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 * - (?:\\s|^): This part captures either a whitespace character (\\s) or the beginning of a line (^). It's non-capturing (due to (?:...)), meaning it doesn't create a capturing group.\n * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: This captures the first component of the shadow, which is the horizontal offset. Breaking it down:\n * - (-?\\d+): Captures an optional minus sign followed by one or more digits (integer part of the number).\n * - (?:\\.\\d*)?: Optionally captures a decimal point followed by zero or more digits (decimal part of the number).\n * - (?:px)?: Optionally captures the \"px\" unit.\n * - (?:\\s?|$): Captures either an optional whitespace or the end of the line. This whole part is wrapped in a non-capturing group and marked as optional with ?.\n * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: Similar to the previous step, this captures the vertical offset.\n\n(\\d+(?:\\.\\d*)?(?:px)?)?: This captures the blur radius. It's similar to the horizontal offset but without the optional minus sign.\n\n(?:\\s+(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?){0,1}: This captures an optional part for the color. It allows for whitespace followed by a component with an optional minus sign, digits, decimal point, and \"px\" unit.\n\n(?:$|\\s): This captures either the end of the line or a whitespace character. It ensures that the match ends either at the end of the string or with a whitespace character.\n */\n// eslint-disable-next-line max-len\n\nconst shadowOffsetRegex = '(-?\\\\d+(?:\\\\.\\\\d*)?(?:px)?(?:\\\\s?|$))?';\n\nconst reOffsetsAndBlur = new RegExp(\n '(?:\\\\s|^)' +\n shadowOffsetRegex +\n shadowOffsetRegex +\n '(' +\n reNum +\n '?(?:px)?)?(?:\\\\s?|$)(?:$|\\\\s)',\n);\n\nexport const shadowDefaultValues: Partial<TClassProperties<Shadow>> = {\n color: 'rgb(0,0,0)',\n blur: 0,\n offsetX: 0,\n offsetY: 0,\n affectStroke: false,\n includeDefaultValues: true,\n nonScaling: false,\n};\n\nexport type SerializedShadowOptions = {\n color: string;\n blur: number;\n offsetX: number;\n offsetY: number;\n affectStroke: boolean;\n nonScaling: boolean;\n type: string;\n};\n\nexport class Shadow {\n /**\n * Shadow color\n * @type String\n */\n declare color: string;\n\n /**\n * Shadow blur\n * @type Number\n */\n declare blur: number;\n\n /**\n * Shadow horizontal offset\n * @type Number\n */\n declare offsetX: number;\n\n /**\n * Shadow vertical offset\n * @type Number\n */\n declare offsetY: number;\n\n /**\n * Whether the shadow should affect stroke operations\n * @type Boolean\n */\n declare affectStroke: boolean;\n\n /**\n * Indicates whether toObject should include default values\n * @type Boolean\n */\n declare includeDefaultValues: boolean;\n\n /**\n * When `false`, the shadow will scale with the object.\n * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n * default to false\n * @type Boolean\n */\n declare nonScaling: boolean;\n\n declare id: number;\n\n static ownDefaults = shadowDefaultValues;\n\n static type = 'shadow';\n\n /**\n * @see {@link http://fabric5.fabricjs.com/shadows|Shadow demo}\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n */\n constructor(options?: Partial<TClassProperties<Shadow>>);\n constructor(svgAttribute: string);\n constructor(arg0: string | Partial<TClassProperties<Shadow>> = {}) {\n const options: Partial<TClassProperties<Shadow>> =\n typeof arg0 === 'string' ? Shadow.parseShadow(arg0) : arg0;\n Object.assign(this, Shadow.ownDefaults, options);\n this.id = uid();\n }\n\n /**\n * @param {String} value Shadow value to parse\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\n */\n static parseShadow(value: string) {\n const shadowStr = value.trim(),\n [, offsetX = 0, offsetY = 0, blur = 0] = (\n reOffsetsAndBlur.exec(shadowStr) || []\n ).map((value) => parseFloat(value) || 0),\n color = (shadowStr.replace(reOffsetsAndBlur, '') || 'rgb(0,0,0)').trim();\n\n return {\n color,\n offsetX,\n offsetY,\n blur,\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() {\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n }\n\n /**\n * Returns SVG representation of a shadow\n * @param {FabricObject} object\n * @return {String} SVG representation of a shadow\n */\n toSVG(object: FabricObject) {\n const offset = rotateVector(\n new Point(this.offsetX, this.offsetY),\n degreesToRadians(-object.angle),\n ),\n BLUR_BOX = 20,\n color = new Color(this.color);\n let fBoxX = 40,\n fBoxY = 40;\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 =\n toFixed(\n (Math.abs(offset.x) + this.blur) / object.width,\n config.NUM_FRACTION_DIGITS,\n ) *\n 100 +\n BLUR_BOX;\n fBoxY =\n toFixed(\n (Math.abs(offset.y) + this.blur) / object.height,\n config.NUM_FRACTION_DIGITS,\n ) *\n 100 +\n BLUR_BOX;\n }\n if (object.flipX) {\n offset.x *= -1;\n }\n if (object.flipY) {\n offset.y *= -1;\n }\n\n return `<filter id=\"SVGID_${this.id}\" y=\"-${fBoxY}%\" height=\"${\n 100 + 2 * fBoxY\n }%\" x=\"-${fBoxX}%\" width=\"${\n 100 + 2 * fBoxX\n }%\" >\\n\\t<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"${toFixed(\n this.blur ? this.blur / 2 : 0,\n config.NUM_FRACTION_DIGITS,\n )}\"></feGaussianBlur>\\n\\t<feOffset dx=\"${toFixed(\n offset.x,\n config.NUM_FRACTION_DIGITS,\n )}\" dy=\"${toFixed(\n offset.y,\n config.NUM_FRACTION_DIGITS,\n )}\" result=\"oBlur\" ></feOffset>\\n\\t<feFlood flood-color=\"${color.toRgb()}\" flood-opacity=\"${color.getAlpha()}\"/>\\n\\t<feComposite in2=\"oBlur\" operator=\"in\" />\\n\\t<feMerge>\\n\\t\\t<feMergeNode></feMergeNode>\\n\\t\\t<feMergeNode in=\"SourceGraphic\"></feMergeNode>\\n\\t</feMerge>\\n</filter>\\n`;\n }\n\n /**\n * Returns object representation of a shadow\n * @return {Object} Object representation of a shadow instance\n */\n toObject() {\n const data: SerializedShadowOptions = {\n color: this.color,\n blur: this.blur,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n affectStroke: this.affectStroke,\n nonScaling: this.nonScaling,\n type: (this.constructor as typeof Shadow).type,\n };\n const defaults = Shadow.ownDefaults as SerializedShadowOptions;\n return !this.includeDefaultValues\n ? pickBy(data, (value, key) => value !== defaults[key])\n : data;\n }\n\n static async fromObject(options: Partial<TClassProperties<Shadow>>) {\n return new this(options);\n }\n}\n\nclassRegistry.setClass(Shadow, 'shadow');\n","export const capValue = (min: number, value: number, max: number) =>\n Math.max(min, Math.min(value, max));\n","import {\n TOP,\n LEFT,\n SCALE_Y,\n SCALE_X,\n SKEW_X,\n SKEW_Y,\n FILL,\n STROKE,\n CENTER,\n} from '../../constants';\nimport type { TClassProperties } from '../../typedefs';\nimport type { InteractiveFabricObject } from './InteractiveObject';\nimport type { FabricObject } from './Object';\n\nexport const stateProperties = [\n TOP,\n LEFT,\n SCALE_X,\n SCALE_Y,\n 'flipX',\n 'flipY',\n 'originX',\n 'originY',\n 'angle',\n 'opacity',\n 'globalCompositeOperation',\n 'shadow',\n 'visible',\n SKEW_X,\n SKEW_Y,\n];\n\nexport const cacheProperties = [\n FILL,\n STROKE,\n 'strokeWidth',\n 'strokeDashArray',\n 'width',\n 'height',\n 'paintFirst',\n 'strokeUniform',\n 'strokeLineCap',\n 'strokeDashOffset',\n 'strokeLineJoin',\n 'strokeMiterLimit',\n 'backgroundColor',\n 'clipPath',\n];\n\nexport const fabricObjectDefaultValues: Partial<\n TClassProperties<FabricObject>\n> = {\n // see composeMatrix() to see order of transforms. First defaults listed based on this\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n angle: 0,\n flipX: false,\n flipY: false,\n scaleX: 1,\n scaleY: 1,\n minScaleLimit: 0,\n skewX: 0,\n skewY: 0,\n originX: CENTER,\n originY: CENTER,\n strokeWidth: 1,\n strokeUniform: false,\n padding: 0,\n opacity: 1,\n paintFirst: FILL,\n fill: 'rgb(0,0,0)',\n fillRule: 'nonzero',\n stroke: null,\n strokeDashArray: null,\n strokeDashOffset: 0,\n strokeLineCap: 'butt',\n strokeLineJoin: 'miter',\n strokeMiterLimit: 4,\n globalCompositeOperation: 'source-over',\n backgroundColor: '',\n shadow: null,\n visible: true,\n includeDefaultValues: true,\n excludeFromExport: false,\n objectCaching: true,\n clipPath: undefined,\n inverted: false,\n absolutePositioned: false,\n centeredRotation: true,\n centeredScaling: false,\n dirty: true,\n} as const;\n\nexport const interactiveObjectDefaultValues: Partial<\n TClassProperties<InteractiveFabricObject>\n> = {\n noScaleCache: true,\n lockMovementX: false,\n lockMovementY: false,\n lockRotation: false,\n lockScalingX: false,\n lockScalingY: false,\n lockSkewingX: false,\n lockSkewingY: false,\n lockScalingFlip: false,\n cornerSize: 13,\n touchCornerSize: 24,\n transparentCorners: true,\n cornerColor: 'rgb(178,204,255)',\n cornerStrokeColor: '',\n cornerStyle: 'rect',\n cornerDashArray: null,\n hasControls: true,\n borderColor: 'rgb(178,204,255)',\n borderDashArray: null,\n borderOpacityWhenMoving: 0.4,\n borderScaleFactor: 1,\n hasBorders: true,\n selectionBackgroundColor: '',\n selectable: true,\n evented: true,\n perPixelTargetFind: false,\n activeOn: 'down',\n hoverCursor: null,\n moveCursor: null,\n};\n","/**\n * Easing functions\n * @see {@link http://gizma.com/easing/ Easing Equations by Robert Penner}\n */\n\nimport { twoMathPi, halfPI } from '../../constants';\nimport type { TEasingFunction } from './types';\n\nconst normalize = (a: number, c: number, p: number, s: number) => {\n if (a < Math.abs(c)) {\n a = c;\n s = p / 4;\n } else {\n //handle the 0/0 case:\n if (c === 0 && a === 0) {\n s = (p / twoMathPi) * Math.asin(1);\n } else {\n s = (p / twoMathPi) * Math.asin(c / a);\n }\n }\n return { a, c, p, s };\n};\n\nconst elastic = (\n a: number,\n s: number,\n p: number,\n t: number,\n d: number,\n): number =>\n a * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t * d - s) * twoMathPi) / p);\n\n/**\n * Default sinusoidal easing\n */\nexport const defaultEasing: TEasingFunction = (t, b, c, d) =>\n -c * Math.cos((t / d) * halfPI) + c + b;\n\n/**\n * Cubic easing in\n */\nexport const easeInCubic: TEasingFunction = (t, b, c, d) =>\n c * (t / d) ** 3 + b;\n\n/**\n * Cubic easing out\n */\nexport const easeOutCubic: TEasingFunction = (t, b, c, d) =>\n c * ((t / d - 1) ** 3 + 1) + b;\n\n/**\n * Cubic easing in and out\n */\nexport const easeInOutCubic: TEasingFunction = (t, b, c, d) => {\n t /= d / 2;\n if (t < 1) {\n return (c / 2) * t ** 3 + b;\n }\n return (c / 2) * ((t - 2) ** 3 + 2) + b;\n};\n\n/**\n * Quartic easing in\n */\nexport const easeInQuart: TEasingFunction = (t, b, c, d) =>\n c * (t /= d) * t ** 3 + b;\n\n/**\n * Quartic easing out\n */\nexport const easeOutQuart: TEasingFunction = (t, b, c, d) =>\n -c * ((t = t / d - 1) * t ** 3 - 1) + b;\n\n/**\n * Quartic easing in and out\n */\nexport const easeInOutQuart: TEasingFunction = (t, b, c, d) => {\n t /= d / 2;\n if (t < 1) {\n return (c / 2) * t ** 4 + b;\n }\n return (-c / 2) * ((t -= 2) * t ** 3 - 2) + b;\n};\n\n/**\n * Quintic easing in\n */\nexport const easeInQuint: TEasingFunction = (t, b, c, d) =>\n c * (t / d) ** 5 + b;\n\n/**\n * Quintic easing out\n */\nexport const easeOutQuint: TEasingFunction = (t, b, c, d) =>\n c * ((t / d - 1) ** 5 + 1) + b;\n\n/**\n * Quintic easing in and out\n */\nexport const easeInOutQuint: TEasingFunction = (t, b, c, d) => {\n t /= d / 2;\n if (t < 1) {\n return (c / 2) * t ** 5 + b;\n }\n return (c / 2) * ((t - 2) ** 5 + 2) + b;\n};\n\n/**\n * Sinusoidal easing in\n */\nexport const easeInSine: TEasingFunction = (t, b, c, d) =>\n -c * Math.cos((t / d) * halfPI) + c + b;\n\n/**\n * Sinusoidal easing out\n */\nexport const easeOutSine: TEasingFunction = (t, b, c, d) =>\n c * Math.sin((t / d) * halfPI) + b;\n\n/**\n * Sinusoidal easing in and out\n */\nexport const easeInOutSine: TEasingFunction = (t, b, c, d) =>\n (-c / 2) * (Math.cos((Math.PI * t) / d) - 1) + b;\n\n/**\n * Exponential easing in\n */\nexport const easeInExpo: TEasingFunction = (t, b, c, d) =>\n t === 0 ? b : c * 2 ** (10 * (t / d - 1)) + b;\n\n/**\n * Exponential easing out\n */\nexport const easeOutExpo: TEasingFunction = (t, b, c, d) =>\n t === d ? b + c : c * -(2 ** ((-10 * t) / d) + 1) + b;\n\n/**\n * Exponential easing in and out\n */\nexport const easeInOutExpo: TEasingFunction = (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) * 2 ** (10 * (t - 1)) + b;\n }\n return (c / 2) * -(2 ** (-10 * --t) + 2) + b;\n};\n\n/**\n * Circular easing in\n */\nexport const easeInCirc: TEasingFunction = (t, b, c, d) =>\n -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;\n\n/**\n * Circular easing out\n */\nexport const easeOutCirc: TEasingFunction = (t, b, c, d) =>\n c * Math.sqrt(1 - (t = t / d - 1) * t) + b;\n\n/**\n * Circular easing in and out\n */\nexport const easeInOutCirc: TEasingFunction = (t, b, c, d) => {\n t /= d / 2;\n if (t < 1) {\n return (-c / 2) * (Math.sqrt(1 - t ** 2) - 1) + b;\n }\n return (c / 2) * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;\n};\n\n/**\n * Elastic easing in\n */\nexport const easeInElastic: TEasingFunction = (t, b, c, d) => {\n const s = 1.70158,\n a = c;\n let p = 0;\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 const { a: normA, s: normS, p: normP } = normalize(a, c, p, s);\n return -elastic(normA, normS, normP, t, d) + b;\n};\n\n/**\n * Elastic easing out\n */\nexport const easeOutElastic: TEasingFunction = (t, b, c, d) => {\n const s = 1.70158,\n a = c;\n let p = 0;\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 const { a: normA, s: normS, p: normP, c: normC } = normalize(a, c, p, s);\n return (\n normA * 2 ** (-10 * t) * Math.sin(((t * d - normS) * twoMathPi) / normP) +\n normC +\n b\n );\n};\n\n/**\n * Elastic easing in and out\n */\nexport const easeInOutElastic: TEasingFunction = (t, b, c, d) => {\n const s = 1.70158,\n a = c;\n let p = 0;\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 const { a: normA, s: normS, p: normP, c: normC } = normalize(a, c, p, s);\n if (t < 1) {\n return -0.5 * elastic(normA, normS, normP, t, d) + b;\n }\n return (\n normA *\n Math.pow(2, -10 * (t -= 1)) *\n Math.sin(((t * d - normS) * twoMathPi) / normP) *\n 0.5 +\n normC +\n b\n );\n};\n\n/**\n * Backwards easing in\n */\nexport const easeInBack: TEasingFunction = (t, b, c, d, s = 1.70158) =>\n c * (t /= d) * t * ((s + 1) * t - s) + b;\n\n/**\n * Backwards easing out\n */\nexport const easeOutBack: TEasingFunction = (t, b, c, d, s = 1.70158) =>\n c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\n\n/**\n * Backwards easing in and out\n */\nexport const easeInOutBack: TEasingFunction = (t, b, c, d, s = 1.70158) => {\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 out\n */\nexport const easeOutBounce: TEasingFunction = (t, b, c, d) => {\n if ((t /= d) < 1 / 2.75) {\n return c * (7.5625 * t * t) + b;\n } else if (t < 2 / 2.75) {\n return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;\n } else if (t < 2.5 / 2.75) {\n return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;\n } else {\n return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;\n }\n};\n\n/**\n * Bouncing easing in\n */\nexport const easeInBounce: TEasingFunction = (t, b, c, d) =>\n c - easeOutBounce(d - t, 0, c, d) + b;\n\n/**\n * Bouncing easing in and out\n */\nexport const easeInOutBounce: TEasingFunction = (t, b, c, d) =>\n t < d / 2\n ? easeInBounce(t * 2, 0, c, d) * 0.5 + b\n : easeOutBounce(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;\n\n/**\n * Quadratic easing in\n */\nexport const easeInQuad: TEasingFunction = (t, b, c, d) => c * (t /= d) * t + b;\n\n/**\n * Quadratic easing out\n */\nexport const easeOutQuad: TEasingFunction = (t, b, c, d) =>\n -c * (t /= d) * (t - 2) + b;\n\n/**\n * Quadratic easing in and out\n */\nexport const easeInOutQuad: TEasingFunction = (t, b, c, d) => {\n t /= d / 2;\n if (t < 1) {\n return (c / 2) * t ** 2 + b;\n }\n return (-c / 2) * (--t * (t - 2) - 1) + b;\n};\n","import { noop } from '../../constants';\nimport { requestAnimFrame } from './AnimationFrameProvider';\nimport { runningAnimations } from './AnimationRegistry';\nimport { defaultEasing } from './easing';\nimport type {\n AnimationState,\n TAbortCallback,\n TBaseAnimationOptions,\n TEasingFunction,\n TOnAnimationChangeCallback,\n} from './types';\n\nconst defaultAbort = () => false;\n\nexport abstract class AnimationBase<\n T extends number | number[] = number | number[],\n> {\n declare readonly startValue: T;\n declare readonly endValue: T;\n declare readonly duration: number;\n declare readonly delay: number;\n\n declare protected readonly byValue: T;\n declare protected readonly easing: TEasingFunction<T>;\n\n declare private readonly _onStart: VoidFunction;\n declare private readonly _onChange: TOnAnimationChangeCallback<T>;\n declare private readonly _onComplete: TOnAnimationChangeCallback<T>;\n declare private readonly _abort: TAbortCallback<T>;\n\n /**\n * Used to register the animation to a target object\n * so that it can be cancelled within the object context\n */\n declare readonly target?: unknown;\n\n private _state: AnimationState = 'pending';\n /**\n * Time %, or the ratio of `timeElapsed / duration`\n * @see tick\n */\n durationProgress = 0;\n /**\n * Value %, or the ratio of `(currentValue - startValue) / (endValue - startValue)`\n */\n valueProgress = 0;\n /**\n * Current value\n */\n declare value: T;\n /**\n * Animation start time ms\n */\n declare private startTime: number;\n\n constructor({\n startValue,\n byValue,\n duration = 500,\n delay = 0,\n easing = defaultEasing,\n onStart = noop,\n onChange = noop,\n onComplete = noop,\n abort = defaultAbort,\n target,\n }: TBaseAnimationOptions<T>) {\n this.tick = this.tick.bind(this);\n\n this.duration = duration;\n this.delay = delay;\n this.easing = easing;\n this._onStart = onStart;\n this._onChange = onChange;\n this._onComplete = onComplete;\n this._abort = abort;\n this.target = target;\n\n this.startValue = startValue;\n this.byValue = byValue;\n this.value = this.startValue;\n this.endValue = Object.freeze(this.calculate(this.duration).value);\n }\n\n get state() {\n return this._state;\n }\n\n isDone() {\n return this._state === 'aborted' || this._state === 'completed';\n }\n\n /**\n * Calculate the current value based on the easing parameters\n * @param timeElapsed in ms\n * @protected\n */\n protected abstract calculate(timeElapsed: number): {\n value: T;\n valueProgress: number;\n };\n\n start() {\n const firstTick: FrameRequestCallback = (timestamp) => {\n if (this._state !== 'pending') return;\n this.startTime = timestamp || +new Date();\n this._state = 'running';\n this._onStart();\n this.tick(this.startTime);\n };\n\n this.register();\n\n // setTimeout(cb, 0) will run cb on the next frame, causing a delay\n // we don't want that\n if (this.delay > 0) {\n setTimeout(() => requestAnimFrame(firstTick), this.delay);\n } else {\n requestAnimFrame(firstTick);\n }\n }\n\n private tick(t: number) {\n const durationMs = (t || +new Date()) - this.startTime;\n const boundDurationMs = Math.min(durationMs, this.duration);\n this.durationProgress = boundDurationMs / this.duration;\n const { value, valueProgress } = this.calculate(boundDurationMs);\n this.value = Object.freeze(value);\n this.valueProgress = valueProgress;\n\n if (this._state === 'aborted') {\n return;\n } else if (\n this._abort(this.value, this.valueProgress, this.durationProgress)\n ) {\n this._state = 'aborted';\n this.unregister();\n } else if (durationMs >= this.duration) {\n this.durationProgress = this.valueProgress = 1;\n this._onChange(this.endValue, this.valueProgress, this.durationProgress);\n this._state = 'completed';\n this._onComplete(\n this.endValue,\n this.valueProgress,\n this.durationProgress,\n );\n this.unregister();\n } else {\n this._onChange(this.value, this.valueProgress, this.durationProgress);\n requestAnimFrame(this.tick);\n }\n }\n\n private register() {\n runningAnimations.push(this as unknown as AnimationBase);\n }\n\n private unregister() {\n runningAnimations.remove(this as unknown as AnimationBase);\n }\n\n abort() {\n this._state = 'aborted';\n this.unregister();\n }\n}\n","import { AnimationBase } from './AnimationBase';\nimport type { ValueAnimationOptions } from './types';\n\nexport class ValueAnimation extends AnimationBase<number> {\n constructor({\n startValue = 0,\n endValue = 100,\n ...otherOptions\n }: ValueAnimationOptions) {\n super({\n ...otherOptions,\n startValue,\n byValue: endValue - startValue,\n });\n }\n\n protected calculate(timeElapsed: number) {\n const value = this.easing(\n timeElapsed,\n this.startValue,\n this.byValue,\n this.duration,\n );\n return {\n value,\n valueProgress: Math.abs((value - this.startValue) / this.byValue),\n };\n }\n}\n","import { AnimationBase } from './AnimationBase';\nimport type { ArrayAnimationOptions } from './types';\n\nexport class ArrayAnimation extends AnimationBase<number[]> {\n constructor({\n startValue = [0],\n endValue = [100],\n ...options\n }: ArrayAnimationOptions) {\n super({\n ...options,\n startValue,\n byValue: endValue.map((value, i) => value - startValue[i]),\n });\n }\n protected calculate(timeElapsed: number) {\n const values = this.startValue.map((value, i) =>\n this.easing(timeElapsed, value, this.byValue[i], this.duration, i),\n );\n return {\n value: values,\n valueProgress: Math.abs(\n (values[0] - this.startValue[0]) / this.byValue[0],\n ),\n };\n }\n}\n","import { Color } from '../../color/Color';\nimport type { TRGBAColorSource } from '../../color/typedefs';\nimport { halfPI } from '../../constants';\nimport { capValue } from '../misc/capValue';\nimport { AnimationBase } from './AnimationBase';\nimport type {\n ColorAnimationOptions,\n TEasingFunction,\n TOnAnimationChangeCallback,\n} from './types';\n\nconst defaultColorEasing: TEasingFunction = (\n timeElapsed,\n startValue,\n byValue,\n duration,\n) => {\n const durationProgress = 1 - Math.cos((timeElapsed / duration) * halfPI);\n return startValue + byValue * durationProgress;\n};\n\nconst wrapColorCallback = <R>(\n callback?: TOnAnimationChangeCallback<string, R>,\n) =>\n callback &&\n ((rgba: TRGBAColorSource, valueProgress: number, durationProgress: number) =>\n callback(new Color(rgba).toRgba(), valueProgress, durationProgress));\n\nexport class ColorAnimation extends AnimationBase<TRGBAColorSource> {\n constructor({\n startValue,\n endValue,\n easing = defaultColorEasing,\n onChange,\n onComplete,\n abort,\n ...options\n }: ColorAnimationOptions) {\n const startColor = new Color(startValue).getSource();\n const endColor = new Color(endValue).getSource();\n super({\n ...options,\n startValue: startColor,\n byValue: endColor.map(\n (value, i) => value - startColor[i],\n ) as TRGBAColorSource,\n easing,\n onChange: wrapColorCallback(onChange),\n onComplete: wrapColorCallback(onComplete),\n abort: wrapColorCallback(abort),\n });\n }\n protected calculate(timeElapsed: number) {\n const [r, g, b, a] = this.startValue.map((value, i) =>\n this.easing(timeElapsed, value, this.byValue[i], this.duration, i),\n ) as TRGBAColorSource;\n const value = [\n ...[r, g, b].map(Math.round),\n capValue(0, a, 1),\n ] as TRGBAColorSource;\n return {\n value,\n valueProgress:\n // to correctly calculate the change ratio we must find a changed value\n value\n .map((p, i) =>\n this.byValue[i] !== 0\n ? Math.abs((p - this.startValue[i]) / this.byValue[i])\n : 0,\n )\n .find((p) => p !== 0) || 0,\n };\n }\n}\n","import { ValueAnimation } from './ValueAnimation';\nimport { ArrayAnimation } from './ArrayAnimation';\nimport { ColorAnimation } from './ColorAnimation';\nimport type {\n ValueAnimationOptions,\n ArrayAnimationOptions,\n ColorAnimationOptions,\n} from './types';\nimport type { TColorArg } from '../../color/typedefs';\n\nexport type TAnimation<T extends number | number[] | TColorArg> =\n T extends TColorArg\n ? ColorAnimation\n : T extends number[]\n ? ArrayAnimation\n : ValueAnimation;\n\nconst isArrayAnimation = (\n options: ArrayAnimationOptions | ValueAnimationOptions,\n): options is ArrayAnimationOptions => {\n return Array.isArray(options.startValue) || Array.isArray(options.endValue);\n};\n\n/**\n * Changes value(s) from startValue to endValue within a certain period of time,\n * invoking callbacks as the value(s) change.\n *\n * @example\n * animate({\n * startValue: 1,\n * endValue: 0,\n * onChange: (v) => {\n * obj.set('opacity', v);\n * // since we are running in a requested frame we should call `renderAll` and not `requestRenderAll`\n * canvas.renderAll();\n * }\n * });\n *\n * @example Using lists:\n * animate({\n * startValue: [1, 2, 3],\n * endValue: [2, 4, 6],\n * onChange: ([x, y, zoom]) => {\n * canvas.zoomToPoint(new Point(x, y), zoom);\n * canvas.renderAll();\n * }\n * });\n *\n */\nexport function animate(options: ArrayAnimationOptions): ArrayAnimation;\nexport function animate(options: ValueAnimationOptions): ValueAnimation;\nexport function animate<\n T extends ValueAnimationOptions | ArrayAnimationOptions,\n>(\n options: T,\n): T extends ArrayAnimationOptions ? ArrayAnimation : ValueAnimation;\nexport function animate<\n T extends ValueAnimationOptions | ArrayAnimationOptions,\n R extends T extends ArrayAnimationOptions ? ArrayAnimation : ValueAnimation,\n>(options: T): R {\n const animation = (\n isArrayAnimation(options)\n ? new ArrayAnimation(options)\n : new ValueAnimation(options)\n ) as R;\n animation.start();\n return animation;\n}\n\nexport function animateColor(options: ColorAnimationOptions) {\n const animation = new ColorAnimation(options);\n animation.start();\n return animation;\n}\n","import { Point } from './Point';\nimport { createVector } from './util/misc/vectors';\n\n/* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */\n\nexport type IntersectionType = 'Intersection' | 'Coincident' | 'Parallel';\n\nexport class Intersection {\n declare points: Point[];\n\n declare status?: IntersectionType;\n\n constructor(status?: IntersectionType) {\n this.status = status;\n this.points = [];\n }\n\n /**\n * Used to verify if a point is alredy in the collection\n * @param {Point} point\n * @returns {boolean}\n */\n private includes(point: Point): boolean {\n return this.points.some((p) => p.eq(point));\n }\n\n /**\n * Appends points of intersection\n * @param {...Point[]} points\n * @return {Intersection} thisArg\n */\n private append(...points: Point[]): Intersection {\n this.points = this.points.concat(\n points.filter((point) => {\n return !this.includes(point);\n }),\n );\n return this;\n }\n\n /**\n * check if point T is on the segment or line defined between A and B\n *\n * @param {Point} T the point we are checking for\n * @param {Point} A one extremity of the segment\n * @param {Point} B the other extremity of the segment\n * @param [infinite] if true checks if `T` is on the line defined by `A` and `B`\n * @returns true if `T` is contained\n */\n static isPointContained(T: Point, A: Point, B: Point, infinite = false) {\n if (A.eq(B)) {\n // Edge case: the segment is a point, we check for coincidence,\n // infinite param has no meaning because there are infinite lines to consider\n return T.eq(A);\n } else if (A.x === B.x) {\n // Edge case: horizontal line.\n // we first check if T.x has the same value, and then if T.y is contained between A.y and B.y\n return (\n T.x === A.x &&\n (infinite || (T.y >= Math.min(A.y, B.y) && T.y <= Math.max(A.y, B.y)))\n );\n } else if (A.y === B.y) {\n // Edge case: vertical line.\n // we first check if T.y has the same value, and then if T.x is contained between A.x and B.x\n return (\n T.y === A.y &&\n (infinite || (T.x >= Math.min(A.x, B.x) && T.x <= Math.max(A.x, B.x)))\n );\n } else {\n // Generic case: sloped line.\n // we check that AT has the same slope as AB\n // for the segment case we need both the vectors to have the same direction and for AT to be lte AB in size\n // for the infinite case we check the absolute value of the slope, since direction is meaningless\n const AB = createVector(A, B);\n const AT = createVector(A, T);\n const s = AT.divide(AB);\n return infinite\n ? Math.abs(s.x) === Math.abs(s.y)\n : s.x === s.y && s.x >= 0 && s.x <= 1;\n }\n }\n\n /**\n * Use the ray casting algorithm to determine if point is in the polygon defined by points\n * @see https://en.wikipedia.org/wiki/Point_in_polygon\n * @param point\n * @param points polygon points\n * @returns\n */\n static isPointInPolygon(point: Point, points: Point[]) {\n const other = new Point(point).setX(\n Math.min(point.x - 1, ...points.map((p) => p.x)),\n );\n let hits = 0;\n for (let index = 0; index < points.length; index++) {\n const inter = this.intersectSegmentSegment(\n // polygon side\n points[index],\n points[(index + 1) % points.length],\n // ray\n point,\n other,\n );\n if (inter.includes(point)) {\n // point is on the polygon side\n return true;\n }\n hits += Number(inter.status === 'Intersection');\n }\n return hits % 2 === 1;\n }\n\n /**\n * Checks if a line intersects another\n * @see {@link https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection line intersection}\n * @see {@link https://en.wikipedia.org/wiki/Cramer%27s_rule Cramer's rule}\n * @param {Point} a1\n * @param {Point} a2\n * @param {Point} b1\n * @param {Point} b2\n * @param {boolean} [aInfinite=true] check segment intersection by passing `false`\n * @param {boolean} [bInfinite=true] check segment intersection by passing `false`\n * @return {Intersection}\n */\n static intersectLineLine(\n a1: Point,\n a2: Point,\n b1: Point,\n b2: Point,\n aInfinite = true,\n bInfinite = true,\n ): Intersection {\n const a2xa1x = a2.x - a1.x,\n a2ya1y = a2.y - a1.y,\n b2xb1x = b2.x - b1.x,\n b2yb1y = b2.y - b1.y,\n a1xb1x = a1.x - b1.x,\n a1yb1y = a1.y - b1.y,\n uaT = b2xb1x * a1yb1y - b2yb1y * a1xb1x,\n ubT = a2xa1x * a1yb1y - a2ya1y * a1xb1x,\n uB = b2yb1y * a2xa1x - b2xb1x * a2ya1y;\n if (uB !== 0) {\n const ua = uaT / uB,\n ub = ubT / uB;\n if (\n (aInfinite || (0 <= ua && ua <= 1)) &&\n (bInfinite || (0 <= ub && ub <= 1))\n ) {\n return new Intersection('Intersection').append(\n new Point(a1.x + ua * a2xa1x, a1.y + ua * a2ya1y),\n );\n } else {\n return new Intersection();\n }\n } else {\n if (uaT === 0 || ubT === 0) {\n const segmentsCoincide =\n aInfinite ||\n bInfinite ||\n Intersection.isPointContained(a1, b1, b2) ||\n Intersection.isPointContained(a2, b1, b2) ||\n Intersection.isPointContained(b1, a1, a2) ||\n Intersection.isPointContained(b2, a1, a2);\n return new Intersection(segmentsCoincide ? 'Coincident' : undefined);\n } else {\n return new Intersection('Parallel');\n }\n }\n }\n\n /**\n * Checks if a segment intersects a line\n * @see {@link intersectLineLine} for line intersection\n * @param {Point} s1 boundary point of segment\n * @param {Point} s2 other boundary point of segment\n * @param {Point} l1 point on line\n * @param {Point} l2 other point on line\n * @return {Intersection}\n */\n static intersectSegmentLine(\n s1: Point,\n s2: Point,\n l1: Point,\n l2: Point,\n ): Intersection {\n return Intersection.intersectLineLine(s1, s2, l1, l2, false, true);\n }\n\n /**\n * Checks if a segment intersects another\n * @see {@link intersectLineLine} for line intersection\n * @param {Point} a1 boundary point of segment\n * @param {Point} a2 other boundary point of segment\n * @param {Point} b1 boundary point of segment\n * @param {Point} b2 other boundary point of segment\n * @return {Intersection}\n */\n static intersectSegmentSegment(\n a1: Point,\n a2: Point,\n b1: Point,\n b2: Point,\n ): Intersection {\n return Intersection.intersectLineLine(a1, a2, b1, b2, false, false);\n }\n\n /**\n * Checks if line intersects polygon\n *\n * @todo account for stroke\n *\n * @see {@link intersectSegmentPolygon} for segment intersection\n * @param {Point} a1 point on line\n * @param {Point} a2 other point on line\n * @param {Point[]} points polygon points\n * @param {boolean} [infinite=true] check segment intersection by passing `false`\n * @return {Intersection}\n */\n static intersectLinePolygon(\n a1: Point,\n a2: Point,\n points: Point[],\n infinite = true,\n ): Intersection {\n const result = new Intersection();\n const length = points.length;\n\n for (let i = 0, b1, b2, inter; i < length; i++) {\n b1 = points[i];\n b2 = points[(i + 1) % length];\n inter = Intersection.intersectLineLine(a1, a2, b1, b2, infinite, false);\n if (inter.status === 'Coincident') {\n return inter;\n }\n result.append(...inter.points);\n }\n\n if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n\n return result;\n }\n\n /**\n * Checks if segment intersects polygon\n * @see {@link intersectLinePolygon} for line intersection\n * @param {Point} a1 boundary point of segment\n * @param {Point} a2 other boundary point of segment\n * @param {Point[]} points polygon points\n * @return {Intersection}\n */\n static intersectSegmentPolygon(\n a1: Point,\n a2: Point,\n points: Point[],\n ): Intersection {\n return Intersection.intersectLinePolygon(a1, a2, points, false);\n }\n\n /**\n * Checks if polygon intersects another polygon\n *\n * @todo account for stroke\n *\n * @param {Point[]} points1\n * @param {Point[]} points2\n * @return {Intersection}\n */\n static intersectPolygonPolygon(\n points1: Point[],\n points2: Point[],\n ): Intersection {\n const result = new Intersection(),\n length = points1.length;\n const coincidences: Intersection[] = [];\n\n for (let i = 0; i < length; i++) {\n const a1 = points1[i],\n a2 = points1[(i + 1) % length],\n inter = Intersection.intersectSegmentPolygon(a1, a2, points2);\n if (inter.status === 'Coincident') {\n coincidences.push(inter);\n result.append(a1, a2);\n } else {\n result.append(...inter.points);\n }\n }\n\n if (coincidences.length > 0 && coincidences.length === points1.length) {\n return new Intersection('Coincident');\n } else if (result.points.length > 0) {\n result.status = 'Intersection';\n }\n\n return result;\n }\n\n /**\n * Checks if polygon intersects rectangle\n * @see {@link intersectPolygonPolygon} for polygon intersection\n * @param {Point[]} points polygon points\n * @param {Point} r1 top left point of rect\n * @param {Point} r2 bottom right point of rect\n * @return {Intersection}\n */\n static intersectPolygonRectangle(\n points: Point[],\n r1: Point,\n r2: Point,\n ): Intersection {\n const min = r1.min(r2),\n max = r1.max(r2),\n topRight = new Point(max.x, min.y),\n bottomLeft = new Point(min.x, max.y);\n\n return Intersection.intersectPolygonPolygon(points, [\n min,\n topRight,\n max,\n bottomLeft,\n ]);\n }\n}\n","import type {\n TBBox,\n TCornerPoint,\n TDegree,\n TMat2D,\n TOriginX,\n TOriginY,\n} from '../../typedefs';\nimport { SCALE_X, SCALE_Y, iMatrix } from '../../constants';\nimport { Intersection } from '../../Intersection';\nimport { Point } from '../../Point';\nimport { makeBoundingBoxFromPoints } from '../../util/misc/boundingBoxFromPoints';\nimport {\n createRotateMatrix,\n createTranslateMatrix,\n composeMatrix,\n invertTransform,\n multiplyTransformMatrices,\n transformPoint,\n calcPlaneRotation,\n} from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport type { ObjectEvents } from '../../EventTypeDefs';\nimport type { ControlProps } from './types/ControlProps';\nimport { resolveOrigin } from '../../util/misc/resolveOrigin';\nimport type { Group } from '../Group';\nimport { calcDimensionsMatrix } from '../../util/misc/matrix';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport { degreesToRadians } from '../../util/misc/radiansDegreesConversion';\nimport { CommonMethods } from '../../CommonMethods';\nimport type { BaseProps } from './types/BaseProps';\nimport type { FillStrokeProps } from './types/FillStrokeProps';\nimport { CENTER, LEFT, TOP } from '../../constants';\n\ntype TMatrixCache = {\n key: number[];\n value: TMat2D;\n};\n\ntype TACoords = TCornerPoint;\n\nexport class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>\n extends CommonMethods<EventSpec>\n implements\n Pick<ControlProps, 'padding'>,\n BaseProps,\n Pick<FillStrokeProps, 'strokeWidth' | 'strokeUniform'>\n{\n // #region Geometry\n\n declare padding: number;\n\n /**\n * Describe object's corner position in scene coordinates.\n * The coordinates are derived from the following:\n * left, top, width, height, scaleX, scaleY, skewX, skewY, angle, strokeWidth.\n * The coordinates do not depend on viewport changes.\n * The coordinates get updated with {@link setCoords}.\n * You can calculate them without updating with {@link calcACoords()}\n */\n declare aCoords: TACoords;\n\n /**\n * storage cache for object transform matrix\n */\n declare ownMatrixCache?: TMatrixCache;\n\n /**\n * storage cache for object full transform matrix\n */\n declare matrixCache?: TMatrixCache;\n\n /**\n * A Reference of the Canvas where the object is actually added\n * @type StaticCanvas | Canvas;\n * @default undefined\n * @private\n */\n declare canvas?: StaticCanvas | Canvas;\n\n /**\n * @returns {number} x position according to object's originX property in canvas coordinate plane\n */\n getX(): number {\n return this.getXY().x;\n }\n\n /**\n * @param {number} value x position according to object's originX property in canvas coordinate plane\n */\n setX(value: number) {\n this.setXY(this.getXY().setX(value));\n }\n\n /**\n * @returns {number} y position according to object's originY property in canvas coordinate plane\n */\n getY(): number {\n return this.getXY().y;\n }\n\n /**\n * @param {number} value y position according to object's originY property in canvas coordinate plane\n */\n setY(value: number) {\n this.setXY(this.getXY().setY(value));\n }\n\n /**\n * @returns {number} x position according to object's originX property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link getX}\n */\n getRelativeX(): number {\n return this.left;\n }\n\n /**\n * @param {number} value x position according to object's originX property in parent's coordinate plane\\\n * if parent is canvas then this method is identical to {@link setX}\n */\n setRelativeX(value: number) {\n this.left = value;\n }\n\n /**\n * @returns {number} y position according to object's originY property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link getY}\n */\n getRelativeY(): number {\n return this.top;\n }\n\n /**\n * @param {number} value y position according to object's originY property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link setY}\n */\n setRelativeY(value: number) {\n this.top = value;\n }\n\n /**\n * @returns {Point} x position according to object's originX originY properties in canvas coordinate plane\n */\n getXY(): Point {\n const relativePosition = this.getRelativeXY();\n return this.group\n ? transformPoint(relativePosition, this.group.calcTransformMatrix())\n : relativePosition;\n }\n\n /**\n * Set an object position to a particular point, the point is intended in absolute ( canvas ) coordinate.\n * You can specify originX and originY values,\n * that otherwise are the object's current values.\n * @example <caption>Set object's bottom left corner to point (5,5) on canvas</caption>\n * object.setXY(new Point(5, 5), 'left', 'bottom').\n * @param {Point} point position in scene coordinate plane\n * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n */\n setXY(point: Point, originX?: TOriginX, originY?: TOriginY) {\n if (this.group) {\n point = transformPoint(\n point,\n invertTransform(this.group.calcTransformMatrix()),\n );\n }\n this.setRelativeXY(point, originX, originY);\n }\n\n /**\n * @returns {Point} x,y position according to object's originX originY properties in parent's coordinate plane\n */\n getRelativeXY(): Point {\n return new Point(this.left, this.top);\n }\n\n /**\n * As {@link setXY}, but in current parent's coordinate plane (the current group if any or the canvas)\n * @param {Point} point position according to object's originX originY properties in parent's coordinate plane\n * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n */\n setRelativeXY(\n point: Point,\n originX: TOriginX = this.originX,\n originY: TOriginY = this.originY,\n ) {\n this.setPositionByOrigin(point, originX, originY);\n }\n\n /**\n * @deprecated intermidiate method to be removed, do not use\n */\n protected isStrokeAccountedForInDimensions() {\n return false;\n }\n\n /**\n * @return {Point[]} [tl, tr, br, bl] in the scene plane\n */\n getCoords(): Point[] {\n const { tl, tr, br, bl } =\n this.aCoords || (this.aCoords = this.calcACoords());\n const coords = [tl, tr, br, bl];\n if (this.group) {\n const t = this.group.calcTransformMatrix();\n return coords.map((p) => transformPoint(p, t));\n }\n return coords;\n }\n\n /**\n * Checks if object intersects with the scene rect formed by tl and br\n */\n intersectsWithRect(tl: Point, br: Point): boolean {\n const intersection = Intersection.intersectPolygonRectangle(\n this.getCoords(),\n tl,\n br,\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 * @return {Boolean} true if object intersects with another object\n */\n intersectsWithObject(other: ObjectGeometry): boolean {\n const intersection = Intersection.intersectPolygonPolygon(\n this.getCoords(),\n other.getCoords(),\n );\n\n return (\n intersection.status === 'Intersection' ||\n intersection.status === 'Coincident' ||\n other.isContainedWithinObject(this) ||\n this.isContainedWithinObject(other)\n );\n }\n\n /**\n * Checks if object is fully contained within area of another object\n * @param {Object} other Object to test\n * @return {Boolean} true if object is fully contained within area of another object\n */\n isContainedWithinObject(other: ObjectGeometry): boolean {\n const points = this.getCoords();\n return points.every((point) => other.containsPoint(point));\n }\n\n /**\n * Checks if object is fully contained within the scene rect formed by tl and br\n */\n isContainedWithinRect(tl: Point, br: Point): boolean {\n const { left, top, width, height } = this.getBoundingRect();\n return (\n left >= tl.x &&\n left + width <= br.x &&\n top >= tl.y &&\n top + height <= br.y\n );\n }\n\n isOverlapping<T extends ObjectGeometry>(other: T): boolean {\n return (\n this.intersectsWithObject(other) ||\n this.isContainedWithinObject(other) ||\n other.isContainedWithinObject(this)\n );\n }\n\n /**\n * Checks if point is inside the object\n * @param {Point} point Point to check against\n * @return {Boolean} true if point is inside the object\n */\n containsPoint(point: Point): boolean {\n return Intersection.isPointInPolygon(point, this.getCoords());\n }\n\n /**\n * Checks if object is contained within the canvas with current viewportTransform\n * the check is done stopping at first point that appears on screen\n * @return {Boolean} true if object is fully or partially contained within canvas\n */\n isOnScreen(): boolean {\n if (!this.canvas) {\n return false;\n }\n const { tl, br } = this.canvas.vptCoords;\n const points = this.getCoords();\n // if some point is on screen, the object is on screen.\n if (\n points.some(\n (point) =>\n point.x <= br.x &&\n point.x >= tl.x &&\n point.y <= br.y &&\n point.y >= tl.y,\n )\n ) {\n return true;\n }\n // no points on screen, check intersection with absolute coordinates\n if (this.intersectsWithRect(tl, br)) {\n return true;\n }\n // check if the object is so big that it contains the entire viewport\n return this.containsPoint(tl.midPointFrom(br));\n }\n\n /**\n * Checks if object is partially contained within the canvas with current viewportTransform\n * @return {Boolean} true if object is partially contained within canvas\n */\n isPartiallyOnScreen(): boolean {\n if (!this.canvas) {\n return false;\n }\n const { tl, br } = this.canvas.vptCoords;\n if (this.intersectsWithRect(tl, br)) {\n return true;\n }\n const allPointsAreOutside = this.getCoords().every(\n (point) =>\n (point.x >= br.x || point.x <= tl.x) &&\n (point.y >= br.y || point.y <= tl.y),\n );\n // check if the object is so big that it contains the entire viewport\n return allPointsAreOutside && this.containsPoint(tl.midPointFrom(br));\n }\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * the box is intended as aligned to axis of canvas.\n * @return {Object} Object with left, top, width, height properties\n */\n getBoundingRect(): TBBox {\n return makeBoundingBoxFromPoints(this.getCoords());\n }\n\n /**\n * Returns width of an object's bounding box counting transformations\n * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n * @return {Number} width value\n */\n getScaledWidth(): number {\n return this._getTransformedDimensions().x;\n }\n\n /**\n * Returns height of an object bounding box counting transformations\n * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n * @return {Number} height value\n */\n getScaledHeight(): number {\n return this._getTransformedDimensions().y;\n }\n\n /**\n * Scales an object (equally by x and y)\n * @param {Number} value Scale factor\n * @return {void}\n */\n scale(value: number): void {\n this._set(SCALE_X, value);\n this._set(SCALE_Y, value);\n 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 {void}\n */\n scaleToWidth(value: number) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n const boundingRectFactor =\n this.getBoundingRect().width / this.getScaledWidth();\n return this.scale(value / this.width / boundingRectFactor);\n }\n\n /**\n * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New height value\n * @return {void}\n */\n scaleToHeight(value: number) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n const boundingRectFactor =\n this.getBoundingRect().height / this.getScaledHeight();\n return this.scale(value / this.height / boundingRectFactor);\n }\n\n getCanvasRetinaScaling() {\n return this.canvas?.getRetinaScaling() || 1;\n }\n\n /**\n * Returns the object angle relative to canvas counting also the group property\n * @returns {TDegree}\n */\n getTotalAngle(): TDegree {\n return this.group\n ? radiansToDegrees(calcPlaneRotation(this.calcTransformMatrix()))\n : this.angle;\n }\n\n /**\n * Retrieves viewportTransform from Object's canvas if available\n * @return {TMat2D}\n */\n getViewportTransform(): TMat2D {\n return this.canvas?.viewportTransform || (iMatrix.concat() as TMat2D);\n }\n\n /**\n * Calculates the coordinates of the 4 corner of the bbox, in absolute coordinates.\n * those never change with zoom or viewport changes.\n * @return {TCornerPoint}\n */\n calcACoords(): TCornerPoint {\n const rotateMatrix = createRotateMatrix({ angle: this.angle }),\n { x, y } = this.getRelativeCenterPoint(),\n tMatrix = createTranslateMatrix(x, y),\n finalMatrix = multiplyTransformMatrices(tMatrix, rotateMatrix),\n dim = this._getTransformedDimensions(),\n w = dim.x / 2,\n h = dim.y / 2;\n return {\n // corners\n tl: transformPoint({ x: -w, y: -h }, finalMatrix),\n tr: transformPoint({ x: w, y: -h }, finalMatrix),\n bl: transformPoint({ x: -w, y: h }, finalMatrix),\n br: transformPoint({ x: w, y: h }, finalMatrix),\n };\n }\n\n /**\n * Sets corner and controls position coordinates based on current angle, width and height, left and top.\n * aCoords are used to quickly find an object on the canvas.\n * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabric5.fabricjs.com/fabric-gotchas}\n */\n setCoords(): void {\n this.aCoords = this.calcACoords();\n }\n\n transformMatrixKey(skipGroup = false): number[] {\n let prefix: number[] = [];\n if (!skipGroup && this.group) {\n prefix = this.group.transformMatrixKey(skipGroup);\n }\n prefix.push(\n this.top,\n this.left,\n this.width,\n this.height,\n this.scaleX,\n this.scaleY,\n this.angle,\n this.strokeWidth,\n this.skewX,\n this.skewY,\n +this.flipX,\n +this.flipY,\n resolveOrigin(this.originX),\n resolveOrigin(this.originY),\n );\n\n return prefix;\n }\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties.\n * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n * There are some situation in which this is useful to avoid the fake rotation.\n * @return {TMat2D} transform matrix for the object\n */\n calcTransformMatrix(skipGroup = false): TMat2D {\n let matrix = this.calcOwnMatrix();\n if (skipGroup || !this.group) {\n return matrix;\n }\n const key = this.transformMatrixKey(skipGroup),\n cache = this.matrixCache;\n if (cache && cache.key.every((x, i) => x === key[i])) {\n return cache.value;\n }\n if (this.group) {\n matrix = multiplyTransformMatrices(\n this.group.calcTransformMatrix(false),\n matrix,\n );\n }\n this.matrixCache = {\n key,\n value: matrix,\n };\n return matrix;\n }\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties, this matrix does not include the group transformation\n * @return {TMat2D} transform matrix for the object\n */\n calcOwnMatrix(): TMat2D {\n const key = this.transformMatrixKey(true),\n cache = this.ownMatrixCache;\n if (cache && cache.key.every((x, i) => x === key[i])) {\n return cache.value;\n }\n const center = this.getRelativeCenterPoint(),\n options = {\n angle: this.angle,\n translateX: center.x,\n translateY: center.y,\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n flipX: this.flipX,\n flipY: this.flipY,\n },\n value = composeMatrix(options);\n this.ownMatrixCache = {\n key,\n value,\n };\n return value;\n }\n\n /**\n * Calculate object dimensions from its properties\n * @private\n * @returns {Point} dimensions\n */\n _getNonTransformedDimensions(): Point {\n return new Point(this.width, this.height).scalarAdd(this.strokeWidth);\n }\n\n /**\n * Calculate object dimensions for controls box, including padding and canvas zoom.\n * and active selection\n * @private\n * @param {object} [options] transform options\n * @returns {Point} dimensions\n */\n _calculateCurrentDimensions(options?: any): Point {\n return this._getTransformedDimensions(options)\n .transform(this.getViewportTransform(), true)\n .scalarAdd(2 * this.padding);\n }\n\n // #region Origin\n\n declare top: number;\n declare left: number;\n declare width: number;\n declare height: number;\n declare flipX: boolean;\n declare flipY: boolean;\n declare scaleX: number;\n declare scaleY: number;\n declare skewX: number;\n declare skewY: number;\n /**\n * @deprecated please use 'center' as value in new projects\n * */\n declare originX: TOriginX;\n /**\n * @deprecated please use 'center' as value in new projects\n * */\n declare originY: TOriginY;\n declare angle: TDegree;\n declare strokeWidth: number;\n declare strokeUniform: boolean;\n\n /**\n * Object containing this object.\n * can influence its size and position\n */\n declare group?: Group;\n\n /**\n * Calculate object bounding box dimensions from its properties scale, skew.\n * This bounding box is aligned with object angle and not with canvas axis or screen.\n * @param {Object} [options]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @private\n * @returns {Point} dimensions\n */\n _getTransformedDimensions(options: any = {}): Point {\n const dimOptions = {\n // if scaleX or scaleY are negative numbers,\n // this will return dimensions that are negative.\n // and this will break assumptions around the codebase\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n width: this.width,\n height: this.height,\n strokeWidth: this.strokeWidth,\n // TODO remove this spread. is visible in the performance inspection\n ...options,\n };\n // stroke is applied before/after transformations are applied according to `strokeUniform`\n const strokeWidth = dimOptions.strokeWidth;\n let preScalingStrokeValue = strokeWidth,\n postScalingStrokeValue = 0;\n\n if (this.strokeUniform) {\n preScalingStrokeValue = 0;\n postScalingStrokeValue = strokeWidth;\n }\n const dimX = dimOptions.width + preScalingStrokeValue,\n dimY = dimOptions.height + preScalingStrokeValue,\n noSkew = dimOptions.skewX === 0 && dimOptions.skewY === 0;\n let finalDimensions;\n if (noSkew) {\n finalDimensions = new Point(\n dimX * dimOptions.scaleX,\n dimY * dimOptions.scaleY,\n );\n } else {\n finalDimensions = sizeAfterTransform(\n dimX,\n dimY,\n calcDimensionsMatrix(dimOptions),\n );\n }\n\n return finalDimensions.scalarAdd(postScalingStrokeValue);\n }\n\n /**\n * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n * @param {Point} point The point which corresponds to the originX and originY params\n * @param {TOriginX} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @param {TOriginX} toOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToGivenOrigin(\n point: Point,\n fromOriginX: TOriginX,\n fromOriginY: TOriginY,\n toOriginX: TOriginX,\n toOriginY: TOriginY,\n ): Point {\n let x = point.x,\n y = point.y;\n const offsetX = resolveOrigin(toOriginX) - resolveOrigin(fromOriginX),\n offsetY = resolveOrigin(toOriginY) - resolveOrigin(fromOriginY);\n\n if (offsetX || offsetY) {\n const dim = this._getTransformedDimensions();\n x += offsetX * dim.x;\n y += offsetY * dim.y;\n }\n\n return new Point(x, y);\n }\n\n /**\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n * @param {Point} point The point which corresponds to the originX and originY params\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToCenterPoint(\n point: Point,\n originX: TOriginX,\n originY: TOriginY,\n ): Point {\n if (originX === CENTER && originY === CENTER) {\n return point;\n }\n const p = this.translateToGivenOrigin(\n point,\n originX,\n originY,\n CENTER,\n CENTER,\n );\n if (this.angle) {\n return p.rotate(degreesToRadians(this.angle), point);\n }\n return p;\n }\n\n /**\n * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n * @param {Point} center The point which corresponds to center of the object\n * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToOriginPoint(\n center: Point,\n originX: TOriginX,\n originY: TOriginY,\n ): Point {\n const p = this.translateToGivenOrigin(\n center,\n CENTER,\n CENTER,\n originX,\n originY,\n );\n if (this.angle) {\n return p.rotate(degreesToRadians(this.angle), center);\n }\n return p;\n }\n\n /**\n * Returns the center coordinates of the object relative to canvas\n * @return {Point}\n */\n getCenterPoint(): Point {\n const relCenter = this.getRelativeCenterPoint();\n return this.group\n ? transformPoint(relCenter, this.group.calcTransformMatrix())\n : relCenter;\n }\n\n /**\n * Returns the center coordinates of the object relative to it's parent\n * @return {Point}\n */\n getRelativeCenterPoint(): Point {\n return this.translateToCenterPoint(\n new Point(this.left, this.top),\n this.originX,\n this.originY,\n );\n }\n\n /**\n * Alias of {@link getPositionByOrigin}\n * @deprecated use {@link getPositionByOrigin} instead\n */\n getPointByOrigin(originX: TOriginX, originY: TOriginY): Point {\n return this.getPositionByOrigin(originX, originY);\n }\n\n /**\n * This function is the mirror of {@link setPositionByOrigin}\n * Returns the position of the object based on specified origin.\n * Take an object that has left, top set to 100, 100 with origin 'left', 'top'.\n * Return the values of left top ( wrapped in a point ) that you would need to keep\n * the same position if origin where different ( ex: center, bottom )\n * Alternatively you can use this to also find which point in the parent plane is a specific origin\n * ( where is the bottom right corner of my object? )\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n getPositionByOrigin(originX: TOriginX, originY: TOriginY) {\n return this.translateToOriginPoint(\n this.getRelativeCenterPoint(),\n originX,\n originY,\n );\n }\n\n /**\n * Sets the position of the object taking into consideration the object's origin\n * @param {Point} pos The new position of the object\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {void}\n */\n setPositionByOrigin(pos: Point, originX: TOriginX, originY: TOriginY) {\n const center = this.translateToCenterPoint(pos, originX, originY),\n position = this.translateToOriginPoint(\n center,\n this.originX,\n this.originY,\n );\n this.set({ left: position.x, top: position.y });\n }\n\n /**\n * @private\n */\n _getLeftTopCoords() {\n return this.getPositionByOrigin(LEFT, TOP);\n }\n\n /**\n * An utility method to position the object by its left top corner.\n * Useful to reposition objects since now the default origin is center/center\n * Places the left/top corner of the object bounding box in p.\n */\n positionByLeftTop(p: Point) {\n return this.setPositionByOrigin(p, LEFT, TOP);\n }\n}\n","import { cache } from '../../cache';\nimport { config } from '../../config';\nimport {\n ALIASING_LIMIT,\n CENTER,\n iMatrix,\n LEFT,\n SCALE_X,\n SCALE_Y,\n STROKE,\n FILL,\n TOP,\n VERSION,\n} from '../../constants';\nimport type { ObjectEvents } from '../../EventTypeDefs';\nimport { Point } from '../../Point';\nimport { Shadow } from '../../Shadow';\nimport type {\n TDegree,\n TFiller,\n TSize,\n TCacheCanvasDimensions,\n Abortable,\n TOptions,\n ImageFormat,\n} from '../../typedefs';\nimport { classRegistry } from '../../ClassRegistry';\nimport { runningAnimations } from '../../util/animation/AnimationRegistry';\nimport { capValue } from '../../util/misc/capValue';\nimport {\n createCanvasElement,\n createCanvasElementFor,\n toDataURL,\n toBlob,\n} from '../../util/misc/dom';\nimport { invertTransform, qrDecompose } from '../../util/misc/matrix';\nimport { enlivenObjectEnlivables } from '../../util/misc/objectEnlive';\nimport {\n resetObjectTransform,\n saveObjectTransform,\n} from '../../util/misc/objectTransforms';\nimport { sendObjectToPlane } from '../../util/misc/planeChange';\nimport { pick, pickBy } from '../../util/misc/pick';\nimport { toFixed } from '../../util/misc/toFixed';\nimport type { Group } from '../Group';\nimport { StaticCanvas } from '../../canvas/StaticCanvas';\nimport { isFiller, isSerializableFiller } from '../../util/typeAssertions';\nimport type { FabricImage } from '../Image';\nimport {\n cacheProperties,\n fabricObjectDefaultValues,\n stateProperties,\n} from './defaultValues';\nimport type { Gradient } from '../../gradient/Gradient';\nimport type { Pattern } from '../../Pattern';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { SerializedObjectProps } from './types/SerializedObjectProps';\nimport type { ObjectProps } from './types/ObjectProps';\nimport { getDevicePixelRatio, getEnv } from '../../env';\nimport { log } from '../../util/internals/console';\nimport type { TColorArg } from '../../color/typedefs';\nimport type { TAnimation } from '../../util/animation/animate';\nimport { animate, animateColor } from '../../util/animation/animate';\nimport type {\n AnimationOptions,\n ArrayAnimationOptions,\n ColorAnimationOptions,\n ValueAnimationOptions,\n} from '../../util/animation/types';\nimport { ObjectGeometry } from './ObjectGeometry';\n\ntype TAncestor = FabricObject;\ntype TCollection = Group;\n\nexport type Ancestors =\n | [FabricObject | Group]\n | [FabricObject | Group, ...Group[]]\n | Group[];\n\nexport type AncestryComparison = {\n /**\n * common ancestors of `this` and`other`(may include`this` | `other`)\n */\n common: Ancestors;\n /**\n * ancestors that are of `this` only\n */\n fork: Ancestors;\n /**\n * ancestors that are of `other` only\n */\n otherFork: Ancestors;\n};\n\nexport type TCachedFabricObject<T extends FabricObject = FabricObject> = T &\n Required<\n Pick<\n T,\n | 'zoomX'\n | 'zoomY'\n | '_cacheCanvas'\n | '_cacheContext'\n | 'cacheTranslationX'\n | 'cacheTranslationY'\n >\n > & {\n _cacheContext: CanvasRenderingContext2D;\n };\n\nexport type ObjectToCanvasElementOptions = {\n format?: ImageFormat;\n /** Multiplier to scale by */\n multiplier?: number;\n /** Cropping left offset. Introduced in v1.2.14 */\n left?: number;\n /** Cropping top offset. Introduced in v1.2.14 */\n top?: number;\n /** Cropping width. Introduced in v1.2.14 */\n width?: number;\n /** Cropping height. Introduced in v1.2.14 */\n height?: number;\n /** Enable retina scaling for clone image. Introduce in 1.6.4 */\n enableRetinaScaling?: boolean;\n /** Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4 */\n withoutTransform?: boolean;\n /** Remove current object shadow. Introduced in 2.4.2 */\n withoutShadow?: boolean;\n /** Account for canvas viewport transform */\n viewportTransform?: boolean;\n /** Function to create the output canvas to export onto */\n canvasProvider?: <T extends StaticCanvas>(el?: HTMLCanvasElement) => T;\n};\n\ntype toDataURLOptions = ObjectToCanvasElementOptions & {\n quality?: number;\n};\n\nexport type DrawContext =\n | {\n parentClipPaths: FabricObject[];\n width: number;\n height: number;\n cacheTranslationX: number;\n cacheTranslationY: number;\n zoomX: number;\n zoomY: number;\n }\n | Record<string, never>;\n\n/**\n * Root object class from which all 2d shape classes inherit from\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-1#objects}\n *\n * @fires added\n * @fires removed\n *\n * @fires selected\n * @fires deselected\n *\n * @fires rotating\n * @fires scaling\n * @fires moving\n * @fires skewing\n * @fires modified\n *\n * @fires mousedown\n * @fires mouseup\n * @fires mouseover\n * @fires mouseout\n * @fires mousewheel\n * @fires mousedblclick\n *\n * @fires dragover\n * @fires dragenter\n * @fires dragleave\n * @fires drop\n */\nexport class FabricObject<\n Props extends TOptions<ObjectProps> = Partial<ObjectProps>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n SProps extends SerializedObjectProps = SerializedObjectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends ObjectGeometry<EventSpec>\n implements ObjectProps\n{\n declare minScaleLimit: number;\n\n declare opacity: number;\n\n declare paintFirst: 'fill' | 'stroke';\n declare fill: string | TFiller | null;\n declare fillRule: CanvasFillRule;\n declare stroke: string | TFiller | null;\n declare strokeDashArray: number[] | null;\n declare strokeDashOffset: number;\n declare strokeLineCap: CanvasLineCap;\n declare strokeLineJoin: CanvasLineJoin;\n declare strokeMiterLimit: number;\n\n declare globalCompositeOperation: GlobalCompositeOperation;\n declare backgroundColor: string;\n\n declare shadow: Shadow | null;\n\n declare visible: boolean;\n\n declare includeDefaultValues: boolean;\n declare excludeFromExport: boolean;\n\n declare objectCaching: boolean;\n\n declare clipPath?: FabricObject;\n declare inverted: boolean;\n declare absolutePositioned: boolean;\n declare centeredRotation: boolean;\n declare centeredScaling: boolean;\n\n /**\n * This list of properties is used to check if the state of an object is changed.\n * This state change now is only used for children of groups to understand if a group\n * needs its cache regenerated during a .set call\n * @type Array\n */\n static stateProperties: string[] = stateProperties;\n\n /**\n * List of properties to consider when checking if cache needs refresh\n * Those properties are checked by\n * calls to Object.set(key, value). If the key is in this list, the object is marked as dirty\n * and refreshed at the next render\n * @type Array\n */\n static cacheProperties: string[] = cacheProperties;\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 declare dirty: boolean;\n\n /**\n * Quick access for the _cacheCanvas rendering context\n * This is part of the objectCaching feature\n * since 1.7.0\n * @type boolean\n * @default undefined\n * @private\n */\n _cacheContext: CanvasRenderingContext2D | null = null;\n\n /**\n * A reference to the HTMLCanvasElement that is used to contain the cache of the object\n * this canvas element is resized and cleared as needed\n * Is marked private, you can read it, don't use it since it is handled by fabric\n * since 1.7.0\n * @type HTMLCanvasElement\n * @default undefined\n * @private\n */\n declare _cacheCanvas?: HTMLCanvasElement;\n\n /**\n * zoom level used on the cacheCanvas to draw the cache, X axe\n * since 1.7.0\n * @type number\n * @default undefined\n * @private\n */\n declare zoomX?: number;\n\n /**\n * zoom level used on the cacheCanvas to draw the cache, Y axe\n * since 1.7.0\n * @type number\n * @default undefined\n * @private\n */\n declare zoomY?: number;\n\n /**\n * zoom level used on the cacheCanvas to draw the cache, Y axe\n * since 1.7.0\n * @type number\n * @default undefined\n * @private\n */\n declare cacheTranslationX?: number;\n\n /**\n * translation of the cacheCanvas away from the center, for subpixel accuracy and crispness\n * since 1.7.0\n * @type number\n * @default undefined\n * @private\n */\n declare cacheTranslationY?: number;\n\n /**\n * A reference to the parent of the object, usually a Group\n * @type number\n * @default undefined\n * @private\n */\n declare group?: Group;\n\n /**\n * Indicate if the object is sitting on a cache dedicated to it\n * or is part of a larger cache for many object ( a group for example)\n * @type number\n * @default undefined\n * @private\n */\n declare ownCaching?: boolean;\n\n /**\n * Private. indicates if the object inside a group is on a transformed context or not\n * or is part of a larger cache for many object ( a group for example)\n * @type boolean\n * @default undefined\n * @private\n */\n declare _transformDone?: boolean;\n\n static ownDefaults = fabricObjectDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return FabricObject.ownDefaults;\n }\n\n /**\n * The class type.\n * This is used for serialization and deserialization purposes and internally it can be used\n * to identify classes.\n * When we transform a class in a plain JS object we need a way to recognize which class it was,\n * and the type is the way we do that. It has no other purposes and you should not give one.\n * Hard to reach on instances and please do not use to drive instance's logic (this.constructor.type).\n * To idenfity a class use instanceof class ( instanceof Rect ).\n * We do not do that in fabricJS code because we want to try to have code splitting possible.\n */\n static type = 'FabricObject';\n\n /**\n * Legacy identifier of the class. Prefer using utils like isType or instanceOf\n * Will be removed in fabric 7 or 8.\n * The setter exists to avoid type errors in old code and possibly current deserialization code.\n * DO NOT build new code around this type value\n * @TODO add sustainable warning message\n * @type string\n * @deprecated\n */\n get type() {\n const name = (this.constructor as typeof FabricObject).type;\n if (name === 'FabricObject') {\n return 'object';\n }\n return name.toLowerCase();\n }\n\n set type(value) {\n log('warn', 'Setting type has no effect', value);\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(this, FabricObject.ownDefaults);\n this.setOptions(options);\n }\n\n /**\n * Create a the canvas used to keep the cached copy of the object\n * @private\n */\n _createCacheCanvas() {\n this._cacheCanvas = createCanvasElement();\n this._cacheContext = this._cacheCanvas.getContext('2d');\n this._updateCacheCanvas();\n // if canvas gets created, is empty, so dirty.\n this.dirty = true;\n }\n\n /**\n * Limit the cache dimensions so that X * Y do not cross config.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 * It mutates the input object dims.\n * @param {TCacheCanvasDimensions} dims\n * @return {TCacheCanvasDimensions} dims\n */\n _limitCacheSize(\n dims: TCacheCanvasDimensions & { capped?: boolean },\n ): TCacheCanvasDimensions & { capped?: boolean } {\n const width = dims.width,\n height = dims.height,\n max = config.maxCacheSideLimit,\n min = config.minCacheSideLimit;\n if (\n width <= max &&\n height <= max &&\n width * height <= config.perfLimitSizeTotal\n ) {\n if (width < min) {\n dims.width = min;\n }\n if (height < min) {\n dims.height = min;\n }\n return dims;\n }\n const ar = width / height,\n [limX, limY] = cache.limitDimsByArea(ar),\n x = capValue(min, limX, max),\n y = capValue(min, limY, max);\n if (width > x) {\n dims.zoomX /= width / x;\n dims.width = x;\n dims.capped = true;\n }\n if (height > y) {\n dims.zoomY /= height / y;\n dims.height = y;\n dims.capped = true;\n }\n return dims;\n }\n\n /**\n * Return the dimension and the zoom level needed to create a cache canvas\n * big enough to host the object to be cached.\n * @private\n * @return {TCacheCanvasDimensions} Informations about the object to be cached\n */\n _getCacheCanvasDimensions(): TCacheCanvasDimensions {\n const objectScale = this.getTotalObjectScaling(),\n // calculate dimensions without skewing\n dim = this._getTransformedDimensions({ skewX: 0, skewY: 0 }),\n neededX = (dim.x * objectScale.x) / this.scaleX,\n neededY = (dim.y * objectScale.y) / this.scaleY;\n return {\n // for sure this ALIASING_LIMIT is slightly creating problem\n // in situation in which the cache canvas gets an upper limit\n // also objectScale contains already scaleX and scaleY\n width: Math.ceil(neededX + ALIASING_LIMIT),\n height: Math.ceil(neededY + ALIASING_LIMIT),\n zoomX: objectScale.x,\n zoomY: objectScale.y,\n x: neededX,\n y: neededY,\n };\n }\n\n /**\n * Update width and height of the canvas for cache\n * returns true or false if canvas needed resize.\n * @private\n * @return {Boolean} true if the canvas has been resized\n */\n _updateCacheCanvas() {\n const canvas = this._cacheCanvas!,\n context = this._cacheContext,\n { width, height, zoomX, zoomY, x, y } = this._limitCacheSize(\n this._getCacheCanvasDimensions(),\n ),\n dimensionsChanged = width !== canvas.width || height !== canvas.height,\n zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY;\n\n if (!canvas || !context) {\n return false;\n }\n\n const shouldRedraw = dimensionsChanged || zoomChanged;\n\n if (shouldRedraw) {\n if (width !== canvas.width || height !== canvas.height) {\n canvas.width = width;\n canvas.height = height;\n } else {\n context.setTransform(1, 0, 0, 1, 0, 0);\n context.clearRect(0, 0, canvas.width, canvas.height);\n }\n const drawingWidth = x / 2;\n const drawingHeight = y / 2;\n this.cacheTranslationX =\n Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;\n this.cacheTranslationY =\n Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;\n context.translate(this.cacheTranslationX, this.cacheTranslationY);\n context.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, for class constructor only.\n * Needs to be overridden for different defaults.\n * @protected\n * @param {Object} [options] Options object\n */\n protected setOptions(options: Record<string, any> = {}) {\n this._setOptions(options);\n }\n\n /**\n * Transforms context when rendering an object\n * @param {CanvasRenderingContext2D} ctx Context\n */\n transform(ctx: CanvasRenderingContext2D) {\n const needFullTransform =\n (this.group && !this.group._transformDone) ||\n (this.group && this.canvas && ctx === (this.canvas as Canvas).contextTop);\n const m = this.calcTransformMatrix(!needFullTransform);\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n }\n\n /**\n * Return the object scale factor counting also the group scaling\n * @return {Point}\n */\n getObjectScaling() {\n // if the object is a top level one, on the canvas, we go for simple aritmetic\n // otherwise the complex method with angles will return approximations and decimals\n // and will likely kill the cache when not needed\n // https://github.com/fabricjs/fabric.js/issues/7157\n if (!this.group) {\n return new Point(Math.abs(this.scaleX), Math.abs(this.scaleY));\n }\n // if we are inside a group total zoom calculation is complex, we defer to generic matrices\n const options = qrDecompose(this.calcTransformMatrix());\n return new Point(Math.abs(options.scaleX), Math.abs(options.scaleY));\n }\n\n /**\n * Return the object scale factor counting also the group scaling, zoom and retina\n * @return {Object} object with scaleX and scaleY properties\n */\n getTotalObjectScaling() {\n const scale = this.getObjectScaling();\n if (this.canvas) {\n const zoom = this.canvas.getZoom();\n const retina = this.getCanvasRetinaScaling();\n return scale.scalarMultiply(zoom * retina);\n }\n return scale;\n }\n\n /**\n * Return the object opacity counting also the group property\n * @return {Number}\n */\n getObjectOpacity() {\n let opacity = this.opacity;\n if (this.group) {\n opacity *= this.group.getObjectOpacity();\n }\n return opacity;\n }\n\n /**\n * Makes sure the scale is valid and modifies it if necessary\n * @todo: this is a control action issue, not a geometry one\n * @private\n * @param {Number} value, unconstrained\n * @return {Number} constrained value;\n */\n _constrainScale(value: number): number {\n if (Math.abs(value) < this.minScaleLimit) {\n if (value < 0) {\n return -this.minScaleLimit;\n } else {\n return this.minScaleLimit;\n }\n } else if (value === 0) {\n return 0.0001;\n }\n return value;\n }\n\n /**\n * Handles setting values on the instance and handling internal side effects\n * @protected\n * @param {String} key\n * @param {*} value\n */\n _set(key: string, value: any) {\n if (key === SCALE_X || key === SCALE_Y) {\n value = this._constrainScale(value);\n }\n if (key === SCALE_X && value < 0) {\n this.flipX = !this.flipX;\n value *= -1;\n } else if (key === 'scaleY' && value < 0) {\n this.flipY = !this.flipY;\n value *= -1;\n // i don't like this automatic initialization here\n } else if (key === 'shadow' && value && !(value instanceof Shadow)) {\n value = new Shadow(value);\n }\n\n const isChanged = this[key as keyof this] !== value;\n this[key as keyof this] = value;\n\n // invalidate caches\n if (\n isChanged &&\n (this.constructor as typeof FabricObject).cacheProperties.includes(key)\n ) {\n this.dirty = true;\n }\n // a dirty child makes the parent dirty.\n // but a non dirty child does not make the parent not dirty.\n // the parent could be dirty for some other reason.\n this.parent &&\n (this.dirty ||\n (isChanged &&\n (this.constructor as typeof FabricObject).stateProperties.includes(\n key,\n ))) &&\n this.parent._set('dirty', true);\n\n return this;\n }\n\n /**\n * return if the object would be visible in rendering\n * @return {Boolean}\n */\n isNotVisible() {\n return (\n this.opacity === 0 ||\n (!this.width && !this.height && this.strokeWidth === 0) ||\n !this.visible\n );\n }\n\n /**\n * Renders an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render(ctx: CanvasRenderingContext2D) {\n // do not render if width/height are zeros or object is not visible\n if (this.isNotVisible()) {\n return;\n }\n if (\n this.canvas &&\n this.canvas.skipOffscreen &&\n !this.group &&\n !this.isOnScreen()\n ) {\n return;\n }\n ctx.save();\n this._setupCompositeOperation(ctx);\n this.drawSelectionBackground(ctx);\n this.transform(ctx);\n this._setOpacity(ctx);\n this._setShadow(ctx);\n if (this.shouldCache()) {\n (this as TCachedFabricObject).renderCache();\n (this as TCachedFabricObject).drawCacheOnCanvas(ctx);\n } else {\n this._removeCacheCanvas();\n this.drawObject(ctx, false, {});\n this.dirty = false;\n }\n ctx.restore();\n }\n\n drawSelectionBackground(_ctx: CanvasRenderingContext2D) {\n /* no op */\n }\n\n renderCache(this: TCachedFabricObject, options?: any) {\n options = options || {};\n if (!this._cacheCanvas || !this._cacheContext) {\n this._createCacheCanvas();\n }\n if (this.isCacheDirty() && this._cacheContext) {\n const { zoomX, zoomY, cacheTranslationX, cacheTranslationY } = this;\n const { width, height } = this._cacheCanvas;\n this.drawObject(this._cacheContext, options.forClipping, {\n zoomX,\n zoomY,\n cacheTranslationX,\n cacheTranslationY,\n width,\n height,\n parentClipPaths: [],\n });\n this.dirty = false;\n }\n }\n\n /**\n * Remove cacheCanvas and its dimensions from the objects\n */\n _removeCacheCanvas() {\n this._cacheCanvas = undefined;\n this._cacheContext = null;\n }\n\n /**\n * return true if the object will draw a stroke\n * Does not consider text styles. This is just a shortcut used at rendering time\n * We want it to be an approximation and be fast.\n * wrote to avoid extra caching, it has to return true when stroke happens,\n * can guess when it will not happen at 100% chance, does not matter if it misses\n * some use case where the stroke is invisible.\n * @since 3.0.0\n * @returns Boolean\n */\n hasStroke(): boolean {\n return (\n !!this.stroke && this.stroke !== 'transparent' && this.strokeWidth !== 0\n );\n }\n\n /**\n * return true if the object will draw a fill\n * Does not consider text styles. This is just a shortcut used at rendering time\n * We want it to be an approximation and be fast.\n * wrote to avoid extra caching, it has to return true when fill happens,\n * can guess when it will not happen at 100% chance, does not matter if it misses\n * some use case where the fill is invisible.\n * @since 3.0.0\n * @returns Boolean\n */\n hasFill(): boolean {\n return !!this.fill && this.fill !== 'transparent';\n }\n\n /**\n * When returns `true`, force the object to have its own cache, even if it is inside a group\n * it may be needed when your object behave in a particular way on the cache and always needs\n * its own isolated canvas to render correctly.\n * Created to be overridden\n * since 1.7.12\n * @returns Boolean\n */\n needsItsOwnCache() {\n // TODO re-evaluate this shadow condition\n if (\n this.paintFirst === STROKE &&\n this.hasFill() &&\n this.hasStroke() &&\n !!this.shadow\n ) {\n return true;\n }\n if (this.clipPath) {\n return true;\n }\n return false;\n }\n\n /**\n * Decide if the object should cache or not. Create its own cache level\n * objectCaching is a global flag, wins over everything\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step.\n * Generally you do not cache objects in groups because the group outside is cached.\n * Read as: cache if is needed, or if the feature is enabled but we are not already caching.\n * @return {Boolean}\n */\n shouldCache() {\n this.ownCaching =\n (this.objectCaching && (!this.parent || !this.parent.isOnACache())) ||\n this.needsItsOwnCache();\n return this.ownCaching;\n }\n\n /**\n * Check if this object will cast a shadow with an offset.\n * used by Group.shouldCache to know if child has a shadow recursively\n * @return {Boolean}\n * @deprecated\n */\n willDrawShadow() {\n return (\n !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0)\n );\n }\n\n /**\n * Execute the drawing operation for an object clipPath\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {FabricObject} clipPath\n */\n drawClipPathOnCache(\n ctx: CanvasRenderingContext2D,\n clipPath: FabricObject,\n canvasWithClipPath: HTMLCanvasElement,\n ) {\n ctx.save();\n // DEBUG: uncomment this line, comment the following\n // ctx.globalAlpha = 0.4\n if (clipPath.inverted) {\n ctx.globalCompositeOperation = 'destination-out';\n } else {\n ctx.globalCompositeOperation = 'destination-in';\n }\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(canvasWithClipPath, 0, 0);\n ctx.restore();\n }\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {boolean} forClipping apply clipping styles\n * @param {DrawContext} context additional context for rendering\n */\n drawObject(\n ctx: CanvasRenderingContext2D,\n forClipping: boolean | undefined,\n context: DrawContext,\n ) {\n const originalFill = this.fill,\n originalStroke = this.stroke;\n if (forClipping) {\n this.fill = 'black';\n this.stroke = '';\n this._setClippingProperties(ctx);\n } else {\n this._renderBackground(ctx);\n }\n this._render(ctx);\n this._drawClipPath(ctx, this.clipPath, context);\n this.fill = originalFill;\n this.stroke = originalStroke;\n }\n\n private createClipPathLayer(\n this: TCachedFabricObject,\n clipPath: FabricObject,\n context: DrawContext,\n ) {\n const canvas = createCanvasElementFor(context as TSize);\n const ctx = canvas.getContext('2d')!;\n ctx.translate(context.cacheTranslationX, context.cacheTranslationY);\n ctx.scale(context.zoomX, context.zoomY);\n clipPath._cacheCanvas = canvas;\n context.parentClipPaths.forEach((prevClipPath) => {\n prevClipPath.transform(ctx);\n });\n context.parentClipPaths.push(clipPath);\n if (clipPath.absolutePositioned) {\n const m = invertTransform(this.calcTransformMatrix());\n ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n }\n clipPath.transform(ctx);\n clipPath.drawObject(ctx, true, context);\n return canvas;\n }\n\n /**\n * Prepare clipPath state and cache and draw it on instance's cache\n * @param {CanvasRenderingContext2D} ctx\n * @param {FabricObject} clipPath\n */\n _drawClipPath(\n ctx: CanvasRenderingContext2D,\n clipPath: FabricObject | undefined,\n context: DrawContext,\n ) {\n if (!clipPath) {\n return;\n }\n // needed to setup _transformDone\n // TODO find a better solution?\n clipPath._transformDone = true;\n const canvas = (this as TCachedFabricObject).createClipPathLayer(\n clipPath,\n context,\n );\n this.drawClipPathOnCache(ctx, clipPath, canvas);\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(this: TCachedFabricObject, ctx: CanvasRenderingContext2D) {\n ctx.scale(1 / this.zoomX, 1 / this.zoomY);\n ctx.drawImage(\n this._cacheCanvas,\n -this.cacheTranslationX,\n -this.cacheTranslationY,\n );\n }\n\n /**\n * Check if cache is dirty and if is dirty clear the context.\n * This check has a big side effect, it changes the underlying cache canvas if necessary.\n * Do not call this method on your own to check if the cache is dirty, because if it is,\n * it is also going to wipe the cache. This is badly designed and needs to be fixed.\n * @param {Boolean} skipCanvas skip canvas checks because this object is painted\n * on parent canvas.\n */\n isCacheDirty(skipCanvas = false) {\n if (this.isNotVisible()) {\n return false;\n }\n const canvas = this._cacheCanvas;\n const ctx = this._cacheContext;\n if (canvas && ctx && !skipCanvas && this._updateCacheCanvas()) {\n // in this case the context is already cleared.\n return true;\n } else {\n if (this.dirty || (this.clipPath && this.clipPath.absolutePositioned)) {\n if (canvas && ctx && !skipCanvas) {\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.restore();\n }\n return true;\n }\n }\n return false;\n }\n\n /**\n * Draws a background for the object big as its untransformed dimensions\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderBackground(ctx: CanvasRenderingContext2D) {\n if (!this.backgroundColor) {\n return;\n }\n const dim = this._getNonTransformedDimensions();\n ctx.fillStyle = this.backgroundColor;\n\n ctx.fillRect(-dim.x / 2, -dim.y / 2, dim.x, dim.y);\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(ctx: CanvasRenderingContext2D) {\n if (this.group && !this.group._transformDone) {\n ctx.globalAlpha = this.getObjectOpacity();\n } else {\n ctx.globalAlpha *= this.opacity;\n }\n }\n\n _setStrokeStyles(\n ctx: CanvasRenderingContext2D,\n decl: Pick<\n this,\n | 'stroke'\n | 'strokeWidth'\n | 'strokeLineCap'\n | 'strokeDashOffset'\n | 'strokeLineJoin'\n | 'strokeMiterLimit'\n >,\n ) {\n const stroke = decl.stroke;\n if (stroke) {\n ctx.lineWidth = decl.strokeWidth;\n ctx.lineCap = decl.strokeLineCap;\n ctx.lineDashOffset = decl.strokeDashOffset;\n ctx.lineJoin = decl.strokeLineJoin;\n ctx.miterLimit = decl.strokeMiterLimit;\n if (isFiller(stroke)) {\n if (\n (stroke as Gradient<'linear'>).gradientUnits === 'percentage' ||\n (stroke as Gradient<'linear'>).gradientTransform ||\n (stroke as Pattern).patternTransform\n ) {\n // need to transform gradient in a pattern.\n // this is a slow process. If you are hitting this codepath, and the object\n // is not using caching, you should consider switching it on.\n // we need a canvas as big as the current object caching canvas.\n this._applyPatternForTransformedGradient(ctx, stroke);\n } else {\n // is a simple gradient or pattern\n ctx.strokeStyle = stroke.toLive(ctx)!;\n this._applyPatternGradientTransform(ctx, stroke);\n }\n } else {\n // is a color\n ctx.strokeStyle = decl.stroke as string;\n }\n }\n }\n\n _setFillStyles(ctx: CanvasRenderingContext2D, { fill }: Pick<this, 'fill'>) {\n if (fill) {\n if (isFiller(fill)) {\n ctx.fillStyle = fill.toLive(ctx)!;\n this._applyPatternGradientTransform(ctx, fill);\n } else {\n ctx.fillStyle = fill;\n }\n }\n }\n\n _setClippingProperties(ctx: CanvasRenderingContext2D) {\n ctx.globalAlpha = 1;\n ctx.strokeStyle = 'transparent';\n ctx.fillStyle = '#000000';\n }\n\n /**\n * @private\n * Sets line dash\n * @param {CanvasRenderingContext2D} ctx Context to set the dash line on\n * @param {Array} dashArray array representing dashes\n */\n _setLineDash(ctx: CanvasRenderingContext2D, dashArray?: number[] | null) {\n if (!dashArray || dashArray.length === 0) {\n return;\n }\n ctx.setLineDash(dashArray);\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _setShadow(ctx: CanvasRenderingContext2D) {\n if (!this.shadow) {\n return;\n }\n\n const shadow = this.shadow,\n canvas = this.canvas,\n retinaScaling = this.getCanvasRetinaScaling(),\n [sx, , , sy] = canvas?.viewportTransform || iMatrix,\n multX = sx * retinaScaling,\n multY = sy * retinaScaling,\n scaling = shadow.nonScaling ? new Point(1, 1) : this.getObjectScaling();\n ctx.shadowColor = shadow.color;\n ctx.shadowBlur =\n (shadow.blur *\n config.browserShadowBlurConstant *\n (multX + multY) *\n (scaling.x + scaling.y)) /\n 4;\n ctx.shadowOffsetX = shadow.offsetX * multX * scaling.x;\n ctx.shadowOffsetY = shadow.offsetY * multY * scaling.y;\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _removeShadow(ctx: CanvasRenderingContext2D) {\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 {TFiller} filler {@link Pattern} or {@link Gradient}\n */\n _applyPatternGradientTransform(\n ctx: CanvasRenderingContext2D,\n filler: TFiller,\n ) {\n if (!isFiller(filler)) {\n return { offsetX: 0, offsetY: 0 };\n }\n const t =\n (filler as Gradient<'linear'>).gradientTransform ||\n (filler as Pattern).patternTransform;\n const offsetX = -this.width / 2 + filler.offsetX || 0,\n offsetY = -this.height / 2 + filler.offsetY || 0;\n\n if ((filler as Gradient<'linear'>).gradientUnits === 'percentage') {\n ctx.transform(this.width, 0, 0, this.height, offsetX, offsetY);\n } else {\n ctx.transform(1, 0, 0, 1, offsetX, offsetY);\n }\n if (t) {\n ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);\n }\n return { offsetX: offsetX, offsetY: offsetY };\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderPaintInOrder(ctx: CanvasRenderingContext2D) {\n if (this.paintFirst === STROKE) {\n this._renderStroke(ctx);\n this._renderFill(ctx);\n } else {\n this._renderFill(ctx);\n this._renderStroke(ctx);\n }\n }\n\n /**\n * @private\n * function that actually render something on the context.\n * empty here to allow Obects to work on tests to benchmark fabric functionalites\n * not related to rendering\n * @param {CanvasRenderingContext2D} _ctx Context to render on\n */\n _render(_ctx: CanvasRenderingContext2D) {\n // placeholder to be overridden\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderFill(ctx: CanvasRenderingContext2D) {\n if (!this.fill) {\n return;\n }\n\n ctx.save();\n this._setFillStyles(ctx, this);\n if (this.fillRule === 'evenodd') {\n ctx.fill('evenodd');\n } else {\n ctx.fill();\n }\n ctx.restore();\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderStroke(ctx: CanvasRenderingContext2D) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n if (this.strokeUniform) {\n const scaling = this.getObjectScaling();\n ctx.scale(1 / scaling.x, 1 / scaling.y);\n }\n this._setLineDash(ctx, this.strokeDashArray);\n this._setStrokeStyles(ctx, this);\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * This function try to patch the missing gradientTransform on canvas gradients.\n * transforming a context to transform the gradient, is going to transform the stroke too.\n * we want to transform the gradient but not the stroke operation, so we create\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size\n * is limited.\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Gradient} filler\n */\n _applyPatternForTransformedGradient(\n ctx: CanvasRenderingContext2D,\n filler: TFiller,\n ) {\n const dims = this._limitCacheSize(this._getCacheCanvasDimensions()),\n retinaScaling = this.getCanvasRetinaScaling(),\n width = dims.x / this.scaleX / retinaScaling,\n height = dims.y / this.scaleY / retinaScaling,\n pCanvas = createCanvasElementFor({\n // in case width and height are less than 1px, we have to round up.\n // since the pattern is no-repeat, this is fine\n width: Math.ceil(width),\n height: Math.ceil(height),\n });\n\n const pCtx = pCanvas.getContext('2d');\n if (!pCtx) {\n return;\n }\n pCtx.beginPath();\n pCtx.moveTo(0, 0);\n pCtx.lineTo(width, 0);\n pCtx.lineTo(width, height);\n pCtx.lineTo(0, height);\n pCtx.closePath();\n pCtx.translate(width / 2, height / 2);\n pCtx.scale(\n dims.zoomX / this.scaleX / retinaScaling,\n dims.zoomY / this.scaleY / retinaScaling,\n );\n this._applyPatternGradientTransform(pCtx, filler);\n pCtx.fillStyle = filler.toLive(ctx)!;\n pCtx.fill();\n ctx.translate(\n -this.width / 2 - this.strokeWidth / 2,\n -this.height / 2 - this.strokeWidth / 2,\n );\n ctx.scale(\n (retinaScaling * this.scaleX) / dims.zoomX,\n (retinaScaling * this.scaleY) / dims.zoomY,\n );\n ctx.strokeStyle = pCtx.createPattern(pCanvas, 'no-repeat') ?? '';\n }\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates\n * It doesn't matter where the objects origin are, svg has left and top in the top left corner,\n * And this method is only run once on the object after the fromElement parser.\n * @private\n * @return {Point} center point from element coordinates\n */\n _findCenterFromElement() {\n return new Point(this.left + this.width / 2, this.top + this.height / 2);\n }\n\n /**\n * Clones an instance.\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @returns {Promise<FabricObject>}\n */\n clone(propertiesToInclude?: string[]): Promise<this> {\n const objectForm = this.toObject(propertiesToInclude);\n return (this.constructor as typeof FabricObject).fromObject(\n objectForm,\n ) as unknown as Promise<this>;\n }\n\n /**\n * Creates an instance of Image out of an object\n * makes use of toCanvasElement.\n * Once this method was based on toDataUrl and loadImage, so it also had a quality\n * and format option. toCanvasElement is faster and produce no loss of quality.\n * If you need to get a real Jpeg or Png from an object, using toDataURL is the right way to do it.\n * toCanvasElement and then toBlob from the obtained canvas is also a good option.\n * @todo fix the export type, it could not be Image but the type that getClass return for 'image'.\n * @param {ObjectToCanvasElementOptions} [options] for clone as image, passed to toDataURL\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @return {FabricImage} Object cloned as image.\n */\n cloneAsImage(options: ObjectToCanvasElementOptions): FabricImage {\n const canvasEl = this.toCanvasElement(options);\n // TODO: how to import Image w/o an import cycle?\n const ImageClass = classRegistry.getClass<typeof FabricImage>('image');\n return new ImageClass(canvasEl);\n }\n\n /**\n * Converts an object into a HTMLCanvas element\n * @param {ObjectToCanvasElementOptions} options Options object\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @param {Boolean} [options.viewportTransform] Account for canvas viewport transform\n * @param {(el?: HTMLCanvasElement) => StaticCanvas} [options.canvasProvider] Create the output canvas\n * @return {HTMLCanvasElement} Returns DOM element <canvas> with the FabricObject\n */\n toCanvasElement(options: ObjectToCanvasElementOptions = {}) {\n const origParams = saveObjectTransform(this),\n originalGroup = this.group,\n originalShadow = this.shadow,\n abs = Math.abs,\n retinaScaling = options.enableRetinaScaling ? getDevicePixelRatio() : 1,\n multiplier = (options.multiplier || 1) * retinaScaling,\n canvasProvider: (el: HTMLCanvasElement) => StaticCanvas =\n options.canvasProvider ||\n ((el: HTMLCanvasElement) =>\n new StaticCanvas(el, {\n enableRetinaScaling: false,\n renderOnAddRemove: false,\n skipOffscreen: false,\n }));\n delete this.group;\n if (options.withoutTransform) {\n resetObjectTransform(this);\n }\n if (options.withoutShadow) {\n this.shadow = null;\n }\n if (options.viewportTransform) {\n sendObjectToPlane(this, this.getViewportTransform());\n }\n\n this.setCoords();\n const el = createCanvasElement(),\n boundingRect = this.getBoundingRect(),\n shadow = this.shadow,\n shadowOffset = new Point();\n\n if (shadow) {\n const shadowBlur = shadow.blur;\n const scaling = shadow.nonScaling\n ? new Point(1, 1)\n : this.getObjectScaling();\n // consider non scaling shadow.\n shadowOffset.x =\n 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * abs(scaling.x);\n shadowOffset.y =\n 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * abs(scaling.y);\n }\n const width = boundingRect.width + shadowOffset.x,\n height = boundingRect.height + shadowOffset.y;\n // if the current width/height is not an integer\n // we need to make it so.\n el.width = Math.ceil(width);\n el.height = Math.ceil(height);\n const canvas = canvasProvider(el);\n if (options.format === 'jpeg') {\n canvas.backgroundColor = '#fff';\n }\n this.setPositionByOrigin(\n new Point(canvas.width / 2, canvas.height / 2),\n CENTER,\n CENTER,\n );\n const originalCanvas = this.canvas;\n // static canvas and canvas have both an array of InteractiveObjects\n // @ts-expect-error this needs to be fixed somehow, or ignored globally\n canvas._objects = [this];\n this.set('canvas', canvas);\n this.setCoords();\n const canvasEl = canvas.toCanvasElement(multiplier || 1, options);\n this.set('canvas', originalCanvas);\n this.shadow = originalShadow;\n if (originalGroup) {\n this.group = originalGroup;\n }\n this.set(origParams);\n this.setCoords();\n // canvas.dispose will call image.dispose that will nullify the elements\n // since this canvas is a simple element for the process, we remove references\n // to objects in this way in order to avoid object trashing.\n canvas._objects = [];\n // since render has settled it is safe to destroy canvas\n canvas.destroy();\n return canvasEl;\n }\n\n /**\n * Converts an object into a data-url-like string\n * @param {Object} options Options object\n * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n * @param {Number} [options.multiplier=1] Multiplier to scale by\n * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4\n * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4\n * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2\n * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n */\n toDataURL(options: toDataURLOptions = {}) {\n return toDataURL(\n this.toCanvasElement(options),\n options.format || 'png',\n options.quality || 1,\n );\n }\n toBlob(options: toDataURLOptions = {}) {\n return toBlob(\n this.toCanvasElement(options),\n options.format || 'png',\n options.quality || 1,\n );\n }\n\n /**\n * Checks if the instance is of any of the specified types.\n * We use this to filter a list of objects for the `getObjects` function.\n *\n * For detecting an instance type `instanceOf` is a better check,\n * but to avoid to make specific classes a dependency of generic code\n * internally we use this.\n *\n * This compares both the static class `type` and the instance's own `type` property\n * against the provided list of types.\n *\n * @param types - A list of type strings to check against.\n * @returns `true` if the object's type or class type matches any in the list, otherwise `false`.\n */\n isType(...types: string[]) {\n return (\n types.includes((this.constructor as typeof FabricObject).type) ||\n types.includes(this.type)\n );\n }\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance (is 1 unless subclassed)\n */\n complexity() {\n return 1;\n }\n\n /**\n * Returns a JSON representation of an instance\n * @return {Object} JSON\n */\n toJSON() {\n // delegate, not alias\n return this.toObject();\n }\n\n /**\n * Sets \"angle\" of an instance with centered rotation\n * @param {TDegree} angle Angle value (in degrees)\n */\n rotate(angle: TDegree) {\n const { centeredRotation, originX, originY } = this;\n\n if (centeredRotation) {\n const { x, y } = this.getRelativeCenterPoint();\n this.originX = CENTER;\n this.originY = CENTER;\n this.left = x;\n this.top = y;\n }\n\n this.set('angle', angle);\n\n if (centeredRotation) {\n const { x, y } = this.getPositionByOrigin(originX, originY);\n this.left = x;\n this.top = y;\n this.originX = originX;\n this.originY = originY;\n }\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() {\n // implemented by sub-classes, as needed.\n }\n\n /**\n * Sets canvas globalCompositeOperation for specific object\n * custom composition operation for the particular object can be specified using globalCompositeOperation property\n * @param {CanvasRenderingContext2D} ctx Rendering canvas context\n */\n _setupCompositeOperation(ctx: CanvasRenderingContext2D) {\n if (this.globalCompositeOperation) {\n ctx.globalCompositeOperation = this.globalCompositeOperation;\n }\n }\n\n /**\n * cancel instance's running animations\n * override if necessary to dispose artifacts such as `clipPath`\n */\n dispose() {\n runningAnimations.cancelByTarget(this);\n this.off();\n this._set('canvas', undefined);\n // clear caches\n this._cacheCanvas && getEnv().dispose(this._cacheCanvas);\n this._cacheCanvas = undefined;\n this._cacheContext = null;\n }\n\n // #region Animation methods\n /**\n * List of properties to consider for animating colors.\n * @type String[]\n */\n static colorProperties: string[] = [FILL, STROKE, 'backgroundColor'];\n\n /**\n * Animates object's properties\n * @param {Record<string, number | number[] | TColorArg>} animatable map of keys and end values\n * @param {Partial<AnimationOptions<T>>} options\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#animation}\n * @return {Record<string, TAnimation<T>>} map of animation contexts\n *\n * As object — multiple properties\n *\n * object.animate({ left: ..., top: ... });\n * object.animate({ left: ..., top: ... }, { duration: ... });\n */\n animate<T extends number | number[] | TColorArg>(\n animatable: Record<string, T>,\n options?: Partial<AnimationOptions<T>>,\n ): Record<string, TAnimation<T>> {\n return Object.entries(animatable).reduce(\n (acc, [key, endValue]) => {\n acc[key] = this._animate(key, endValue, options);\n return acc;\n },\n {} as Record<string, TAnimation<T>>,\n );\n }\n\n /**\n * @private\n * @param {String} key Property to animate\n * @param {String} to Value to animate to\n * @param {Object} [options] Options object\n */\n _animate<T extends number | number[] | TColorArg>(\n key: string,\n endValue: T,\n options: Partial<AnimationOptions<T>> = {},\n ): TAnimation<T> {\n const path = key.split('.');\n const propIsColor = (\n this.constructor as typeof FabricObject\n ).colorProperties.includes(path[path.length - 1]);\n const { abort, startValue, onChange, onComplete } = options;\n const animationOptions = {\n ...options,\n target: this,\n // path.reduce... is the current value in case start value isn't provided\n startValue:\n startValue ?? path.reduce((deep: any, key) => deep[key], this),\n endValue,\n abort: abort?.bind(this),\n onChange: (\n value: number | number[] | string,\n valueProgress: number,\n durationProgress: number,\n ) => {\n path.reduce((deep: Record<string, any>, key, index) => {\n if (index === path.length - 1) {\n deep[key] = value;\n }\n return deep[key];\n }, this);\n onChange &&\n // @ts-expect-error generic callback arg0 is wrong\n onChange(value, valueProgress, durationProgress);\n },\n onComplete: (\n value: number | number[] | string,\n valueProgress: number,\n durationProgress: number,\n ) => {\n this.setCoords();\n onComplete &&\n // @ts-expect-error generic callback arg0 is wrong\n onComplete(value, valueProgress, durationProgress);\n },\n } as AnimationOptions<T>;\n\n return (\n propIsColor\n ? animateColor(animationOptions as ColorAnimationOptions)\n : animate(\n animationOptions as ValueAnimationOptions | ArrayAnimationOptions,\n )\n ) as TAnimation<T>;\n }\n\n // #region Object stacking methods\n\n /**\n * A reference to the parent of the object\n * Used to keep the original parent ref when the object has been added to an ActiveSelection, hence loosing the `group` ref\n */\n declare parent?: Group;\n\n /**\n * Checks if object is descendant of target\n * Should be used instead of {@link Group.contains} or {@link StaticCanvas.contains} for performance reasons\n * @param {TAncestor} target\n * @returns {boolean}\n */\n isDescendantOf(target: TAncestor): boolean {\n const { parent, group } = this;\n return (\n parent === target ||\n group === target ||\n // walk up\n (!!parent && parent.isDescendantOf(target)) ||\n (!!group && group !== parent && group.isDescendantOf(target))\n );\n }\n\n /**\n * @returns {Ancestors} ancestors (excluding `ActiveSelection`) from bottom to top\n */\n getAncestors(): Ancestors {\n const ancestors: TAncestor[] = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let parent: TAncestor | undefined = this;\n do {\n parent = parent.parent;\n parent && ancestors.push(parent);\n } while (parent);\n return ancestors as Ancestors;\n }\n\n /**\n * Compare ancestors\n *\n * @param {StackedObject} other\n * @returns {AncestryComparison} an object that represent the ancestry situation.\n */\n findCommonAncestors<T extends this>(other: T): AncestryComparison {\n if (this === other) {\n return {\n fork: [],\n otherFork: [],\n common: [this, ...this.getAncestors()],\n } as AncestryComparison;\n }\n const ancestors = this.getAncestors();\n const otherAncestors = other.getAncestors();\n // if `this` has no ancestors and `this` is top ancestor of `other` we must handle the following case\n if (\n ancestors.length === 0 &&\n otherAncestors.length > 0 &&\n this === otherAncestors[otherAncestors.length - 1]\n ) {\n return {\n fork: [],\n otherFork: [\n other,\n ...otherAncestors.slice(0, otherAncestors.length - 1),\n ],\n common: [this],\n } as AncestryComparison;\n }\n // compare ancestors\n for (let i = 0, ancestor; i < ancestors.length; i++) {\n ancestor = ancestors[i];\n if (ancestor === other) {\n return {\n fork: [this, ...ancestors.slice(0, i)],\n otherFork: [],\n common: ancestors.slice(i),\n } as AncestryComparison;\n }\n for (let j = 0; j < otherAncestors.length; j++) {\n if (this === otherAncestors[j]) {\n return {\n fork: [],\n otherFork: [other, ...otherAncestors.slice(0, j)],\n common: [this, ...ancestors],\n } as AncestryComparison;\n }\n if (ancestor === otherAncestors[j]) {\n return {\n fork: [this, ...ancestors.slice(0, i)],\n otherFork: [other, ...otherAncestors.slice(0, j)],\n common: ancestors.slice(i),\n } as AncestryComparison;\n }\n }\n }\n // nothing shared\n return {\n fork: [this, ...ancestors],\n otherFork: [other, ...otherAncestors],\n common: [],\n } as AncestryComparison;\n }\n\n /**\n *\n * @param {StackedObject} other\n * @returns {boolean}\n */\n hasCommonAncestors<T extends this>(other: T): boolean {\n const commonAncestors = this.findCommonAncestors(other);\n return commonAncestors && !!commonAncestors.common.length;\n }\n\n /**\n *\n * @param {FabricObject} other object to compare against\n * @returns {boolean | undefined} if objects do not share a common ancestor or they are strictly equal it is impossible to determine which is in front of the other; in such cases the function returns `undefined`\n */\n isInFrontOf<T extends this>(other: T): boolean | undefined {\n if (this === other) {\n return undefined;\n }\n const ancestorData = this.findCommonAncestors(other);\n\n if (ancestorData.fork.includes(other as any)) {\n return true;\n }\n if (ancestorData.otherFork.includes(this as any)) {\n return false;\n }\n // if there isn't a common ancestor, we take the canvas.\n // if there is no canvas, there is nothing to compare\n const firstCommonAncestor = ancestorData.common[0] || this.canvas;\n if (!firstCommonAncestor) {\n return undefined;\n }\n const headOfFork = ancestorData.fork.pop(),\n headOfOtherFork = ancestorData.otherFork.pop(),\n thisIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n headOfFork as any,\n ),\n otherIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n headOfOtherFork as any,\n );\n return thisIndex > -1 && thisIndex > otherIndex;\n }\n\n // #region Serialization\n /**\n * Define a list of custom properties that will be serialized when\n * instance.toObject() gets called\n */\n static customProperties: string[] = [];\n\n /**\n * Returns an object representation of an instance\n * @param {string[]} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject(propertiesToInclude: any[] = []): any {\n const propertiesToSerialize = propertiesToInclude.concat(\n FabricObject.customProperties,\n (this.constructor as typeof FabricObject).customProperties || [],\n );\n let clipPathData: Partial<SerializedObjectProps> | undefined;\n const NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;\n const {\n clipPath,\n fill,\n stroke,\n shadow,\n strokeDashArray,\n left,\n top,\n originX,\n originY,\n width,\n height,\n strokeWidth,\n strokeLineCap,\n strokeDashOffset,\n strokeLineJoin,\n strokeUniform,\n strokeMiterLimit,\n scaleX,\n scaleY,\n angle,\n flipX,\n flipY,\n opacity,\n visible,\n backgroundColor,\n fillRule,\n paintFirst,\n globalCompositeOperation,\n skewX,\n skewY,\n } = this;\n if (clipPath && !clipPath.excludeFromExport) {\n clipPathData = clipPath.toObject(\n propertiesToSerialize.concat('inverted', 'absolutePositioned'),\n );\n }\n const toFixedBound = (val: number) => toFixed(val, NUM_FRACTION_DIGITS);\n const object = {\n ...pick(this, propertiesToSerialize as (keyof this)[]),\n type: (this.constructor as typeof FabricObject).type,\n version: VERSION,\n originX,\n originY,\n left: toFixedBound(left),\n top: toFixedBound(top),\n width: toFixedBound(width),\n height: toFixedBound(height),\n fill: isSerializableFiller(fill) ? fill.toObject() : fill,\n stroke: isSerializableFiller(stroke) ? stroke.toObject() : stroke,\n strokeWidth: toFixedBound(strokeWidth),\n strokeDashArray: strokeDashArray\n ? strokeDashArray.concat()\n : strokeDashArray,\n strokeLineCap,\n strokeDashOffset,\n strokeLineJoin,\n strokeUniform,\n strokeMiterLimit: toFixedBound(strokeMiterLimit),\n scaleX: toFixedBound(scaleX),\n scaleY: toFixedBound(scaleY),\n angle: toFixedBound(angle),\n flipX,\n flipY,\n opacity: toFixedBound(opacity),\n shadow: shadow ? shadow.toObject() : shadow,\n visible,\n backgroundColor,\n fillRule,\n paintFirst,\n globalCompositeOperation,\n skewX: toFixedBound(skewX),\n skewY: toFixedBound(skewY),\n ...(clipPathData ? { clipPath: clipPathData } : null),\n };\n\n return !this.includeDefaultValues\n ? this._removeDefaultValues(object)\n : 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(propertiesToInclude?: any[]): any {\n // will be overwritten by subclasses\n return this.toObject(propertiesToInclude);\n }\n\n /**\n * @private\n * @param {Object} object\n */\n _removeDefaultValues<T extends object>(object: T): Partial<T> {\n // getDefaults() ( get from static ownDefaults ) should win over prototype since anyway they get assigned to instance\n // ownDefault vs prototype is swappable only if you change all the fabric objects consistently.\n const defaults = (this.constructor as typeof FabricObject).getDefaults();\n const hasStaticDefaultValues = Object.keys(defaults).length > 0;\n const baseValues = hasStaticDefaultValues\n ? defaults\n : Object.getPrototypeOf(this);\n\n return pickBy(object, (value, key) => {\n if (key === LEFT || key === TOP || key === 'type') {\n return true;\n }\n const baseValue = baseValues[key];\n return (\n value !== baseValue &&\n // basically a check for [] === []\n !(\n Array.isArray(value) &&\n Array.isArray(baseValue) &&\n value.length === 0 &&\n baseValue.length === 0\n )\n );\n });\n }\n\n /**\n * Returns a string representation of an instance\n * @return {String}\n */\n toString() {\n return `#<${(this.constructor as typeof FabricObject).type}>`;\n }\n\n /**\n *\n * @param {Function} klass\n * @param {object} object\n * @param {object} [options]\n * @param {string} [options.extraParam] property to pass as first argument to the constructor\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject>}\n */\n static _fromObject<S extends FabricObject>(\n { type, ...serializedObjectOptions }: Record<string, unknown>,\n { extraParam, ...options }: Abortable & { extraParam?: string } = {},\n ): Promise<S> {\n return enlivenObjectEnlivables<any>(serializedObjectOptions, options).then(\n (enlivedObjectOptions) => {\n // from the resulting enlived options, extract options.extraParam to arg0\n // to avoid accidental overrides later\n if (extraParam) {\n delete enlivedObjectOptions[extraParam];\n return new this(\n serializedObjectOptions[extraParam],\n // @ts-expect-error different signature\n enlivedObjectOptions,\n );\n } else {\n return new this(enlivedObjectOptions);\n }\n },\n ) as Promise<S>;\n }\n\n /**\n *\n * @param {object} object\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject>}\n */\n static fromObject<T extends TOptions<SerializedObjectProps>>(\n object: T,\n options?: Abortable,\n ) {\n return this._fromObject(object, options);\n }\n}\n\nclassRegistry.setClass(FabricObject);\nclassRegistry.setClass(FabricObject, 'object');\n","import type {\n ObjectModificationEvents,\n TModificationEvents,\n} from '../EventTypeDefs';\n\nexport const fireEvent = (\n eventName: TModificationEvents,\n options: ObjectModificationEvents[typeof eventName],\n) => {\n const {\n transform: { target },\n } = options;\n target.canvas?.fire(`object:${eventName}`, {\n ...options,\n target,\n });\n target.fire(eventName, options);\n};\n","import type {\n TModificationEvents,\n Transform,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { fireEvent } from './fireEvent';\nimport { commonEventInfo } from './util';\n\n/**\n * Wrap an action handler with firing an event if the action is performed\n * @param {TModificationEvents} eventName the event we want to fire\n * @param {TransformActionHandler<T>} actionHandler the function to wrap\n * @param {object} extraEventInfo extra information to pas to the event handler\n * @return {TransformActionHandler<T>} a function with an action handler signature\n */\nexport const wrapWithFireEvent = <\n T extends Transform,\n P extends object = Record<string, never>,\n>(\n eventName: TModificationEvents,\n actionHandler: TransformActionHandler<T>,\n extraEventInfo?: P,\n) => {\n return ((eventData, transform, x, y) => {\n const actionPerformed = actionHandler(eventData, transform, x, y);\n if (actionPerformed) {\n fireEvent(eventName, {\n ...commonEventInfo(eventData, transform, x, y),\n ...extraEventInfo,\n });\n }\n return actionPerformed;\n }) as TransformActionHandler<T>;\n};\n","import type { Transform, TransformActionHandler } from '../EventTypeDefs';\n\n/**\n * Wrap an action handler with saving/restoring object position on the transform.\n * this is the code that permits to objects to keep their position while transforming.\n * @param {Function} actionHandler the function to wrap\n * @return {Function} a function with an action handler signature\n */\nexport function wrapWithFixedAnchor<T extends Transform>(\n actionHandler: TransformActionHandler<T>,\n) {\n return ((eventData, transform, x, y) => {\n const { target, originX, originY } = transform,\n constraint = target.getPositionByOrigin(originX, originY),\n actionPerformed = actionHandler(eventData, transform, x, y);\n // flipping requires to change the transform origin, so we read from the mutated transform\n // instead of leveraging the one destructured before\n target.setPositionByOrigin(\n constraint,\n transform.originX,\n transform.originY,\n );\n return actionPerformed;\n }) as TransformActionHandler<T>;\n}\n","import type { TransformActionHandler } from '../EventTypeDefs';\nimport { RESIZING } from '../constants';\nimport { resolveOrigin } from '../util/misc/resolveOrigin';\nimport { getLocalPoint, isTransformCentered } from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\n\nexport const changeObjectDimensionGen =\n (\n dimension: 'width' | 'height',\n origin: 'originX' | 'originY',\n xorY: 'x' | 'y',\n scale: 'scaleX' | 'scaleY',\n ): TransformActionHandler =>\n (eventData, transform, x, y) => {\n const localPoint = getLocalPoint(\n transform,\n transform.originX,\n transform.originY,\n x,\n y,\n );\n const localPointValue = localPoint[xorY];\n // make sure the control changes width ONLY from it's side of target\n const originValue = resolveOrigin(transform[origin]);\n if (\n originValue === 0 ||\n (originValue > 0 && localPointValue < 0) ||\n (originValue < 0 && localPointValue > 0)\n ) {\n const { target } = transform,\n strokePadding =\n target.strokeWidth / (target.strokeUniform ? target[scale] : 1),\n multiplier = isTransformCentered(transform) ? 2 : 1,\n oldWidth = target[dimension],\n newWidth =\n Math.abs((localPointValue * multiplier) / target[scale]) -\n strokePadding;\n target.set(dimension, Math.max(newWidth, 1));\n // check against actual target width in case `newWidth` was rejected\n return oldWidth !== target[dimension];\n }\n return false;\n };\n\n/**\n * Action handler to change object's width\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * You want to use this only if you are building a new control handler and you want\n * to reuse some logic. use \"changeWidth\" if you are looking to just use a control for width\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const changeObjectWidth: TransformActionHandler =\n changeObjectDimensionGen('width', 'originX', 'x', 'scaleX');\n\n/**\n * Action handler to change object's height\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * You want to use this only if you are building a new control handler and you want\n * to reuse some logic. use \"changeHeight\" if you are looking to just use a control for height\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const changeObjectHeight: TransformActionHandler =\n changeObjectDimensionGen('height', 'originY', 'y', 'scaleY');\n\n/**\n * Control handler for changing width\n */\nexport const changeWidth = wrapWithFireEvent(\n RESIZING,\n wrapWithFixedAnchor(changeObjectWidth),\n);\n\n/**\n * Control handler for changing height\n */\nexport const changeHeight = wrapWithFireEvent(\n RESIZING,\n wrapWithFixedAnchor(changeObjectHeight),\n);\n","import { twoMathPi } from '../constants';\nimport type { InteractiveFabricObject } from '../shapes/Object/InteractiveObject';\nimport type { Control } from './Control';\n\nexport type ControlRenderingStyleOverride = Partial<\n Pick<\n InteractiveFabricObject,\n | 'cornerStyle'\n | 'cornerSize'\n | 'cornerColor'\n | 'cornerStrokeColor'\n | 'cornerDashArray'\n | 'transparentCorners'\n >\n>;\n\nexport type ControlRenderer<\n O extends InteractiveFabricObject = InteractiveFabricObject,\n> = (\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride,\n fabricObject: O,\n) => void;\n\n/**\n * Render a round control, as per fabric features.\n * This function is written to respect object properties like transparentCorners, cornerSize\n * cornerColor, cornerStrokeColor\n * plus the addition of offsetY and offsetX.\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Number} left x coordinate where the control center should be\n * @param {Number} top y coordinate where the control center should be\n * @param {Object} styleOverride override for FabricObject controls style\n * @param {FabricObject} fabricObject the fabric object for which we are rendering controls\n */\nexport function renderCircleControl(\n this: Control,\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride,\n fabricObject: InteractiveFabricObject,\n) {\n ctx.save();\n const { stroke, xSize, ySize, opName } = this.commonRenderProps(\n ctx,\n left,\n top,\n fabricObject,\n styleOverride,\n );\n let size = xSize;\n // TODO: use proper ellipse code.\n if (xSize > ySize) {\n ctx.scale(1.0, ySize / xSize);\n } else if (ySize > xSize) {\n size = ySize;\n ctx.scale(xSize / ySize, 1.0);\n }\n ctx.beginPath();\n ctx.arc(0, 0, size / 2, 0, twoMathPi, false);\n ctx[opName]();\n if (stroke) {\n ctx.stroke();\n }\n ctx.restore();\n}\n\n/**\n * Render a square control, as per fabric features.\n * This function is written to respect object properties like transparentCorners, cornerSize\n * cornerColor, cornerStrokeColor\n * plus the addition of offsetY and offsetX.\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @param {Number} left x coordinate where the control center should be\n * @param {Number} top y coordinate where the control center should be\n * @param {Object} styleOverride override for FabricObject controls style\n * @param {FabricObject} fabricObject the fabric object for which we are rendering controls\n */\nexport function renderSquareControl(\n this: Control,\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride,\n fabricObject: InteractiveFabricObject,\n) {\n ctx.save();\n const { stroke, xSize, ySize, opName } = this.commonRenderProps(\n ctx,\n left,\n top,\n fabricObject,\n styleOverride,\n ),\n xSizeBy2 = xSize / 2,\n ySizeBy2 = ySize / 2;\n // this does not work, and fixed with ( && ) does not make sense.\n // to have real transparent corners we need the controls on upperCanvas\n // transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\n ctx[`${opName}Rect`](-xSizeBy2, -ySizeBy2, xSize, ySize);\n if (stroke) {\n ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);\n }\n ctx.restore();\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type {\n ControlActionHandler,\n TPointerEvent,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { Intersection } from '../Intersection';\nimport { Point } from '../Point';\nimport { FILL, SCALE, STROKE } from '../constants';\nimport type {\n InteractiveFabricObject,\n TOCoord,\n} from '../shapes/Object/InteractiveObject';\nimport type { TCornerPoint, TDegree, TMat2D } from '../typedefs';\nimport {\n createRotateMatrix,\n createScaleMatrix,\n createTranslateMatrix,\n multiplyTransformMatrixArray,\n} from '../util/misc/matrix';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\nimport type { ControlRenderingStyleOverride } from './controlRendering';\nimport { renderCircleControl, renderSquareControl } from './controlRendering';\n\nexport class Control {\n /**\n * keep track of control visibility.\n * mainly for backward compatibility.\n * if you do not want to see a control, you can remove it\n * from the control set.\n * @type {Boolean}\n * @default true\n */\n visible = true;\n\n /**\n * Name of the action that the control will likely execute.\n * This is optional. FabricJS uses to identify what the user is doing for some\n * extra optimizations. If you are writing a custom control and you want to know\n * somewhere else in the code what is going on, you can use this string here.\n * you can also provide a custom getActionName if your control run multiple actions\n * depending on some external state.\n * default to scale since is the most common, used on 4 corners by default\n * @type {String}\n * @default 'scale'\n */\n actionName = SCALE;\n\n /**\n * Drawing angle of the control.\n * NOT used for now, but name marked as needed for internal logic\n * example: to reuse the same drawing function for different rotated controls\n * @type {Number}\n * @default 0\n */\n angle = 0;\n\n /**\n * Relative position of the control. X\n * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n x = 0;\n\n /**\n * Relative position of the control. Y\n * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n y = 0;\n\n /**\n * Horizontal offset of the control from the defined position. In pixels\n * Positive offset moves the control to the right, negative to the left.\n * It used when you want to have position of control that does not scale with\n * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\n * the boundind box, with an offset of 30 pixels vertically. Those 30 pixels will\n * stay 30 pixels no matter how the object is big. Another example is having 2\n * controls in the corner, that stay in the same position when the object scale.\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n offsetX = 0;\n\n /**\n * Vertical offset of the control from the defined position. In pixels\n * Positive offset moves the control to the bottom, negative to the top.\n * @type {Number}\n * @default 0\n */\n offsetY = 0;\n\n /**\n * Sets the length of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeX = 0;\n\n /**\n * Sets the height of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeY = 0;\n\n /**\n * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeX = 0;\n\n /**\n * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeY = 0;\n\n /**\n * Css cursor style to display when the control is hovered.\n * if the method `cursorStyleHandler` is provided, this property is ignored.\n * @type {String}\n * @default 'crosshair'\n */\n cursorStyle = 'crosshair';\n\n /**\n * If controls has an offsetY or offsetX, draw a line that connects\n * the control to the bounding box\n * @type {Boolean}\n * @default false\n */\n withConnection = false;\n\n constructor(options?: Partial<Control>) {\n Object.assign(this, options);\n }\n\n /**\n * The control actionHandler, provide one to handle action ( control being moved )\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare actionHandler: TransformActionHandler;\n\n /**\n * The control handler for mouse down, provide one to handle mouse down on control\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare mouseDownHandler?: ControlActionHandler;\n\n /**\n * The control mouseUpHandler, provide one to handle an effect on mouse up.\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare mouseUpHandler?: ControlActionHandler;\n\n shouldActivate(\n controlKey: string,\n fabricObject: InteractiveFabricObject,\n pointer: Point,\n { tl, tr, br, bl }: TCornerPoint,\n ) {\n // TODO: locking logic can be handled here instead of in the control handler logic\n return (\n fabricObject.canvas?.getActiveObject() === fabricObject &&\n fabricObject.isControlVisible(controlKey) &&\n Intersection.isPointInPolygon(pointer, [tl, tr, br, bl])\n );\n }\n\n /**\n * Returns control actionHandler\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getActionHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): TransformActionHandler | undefined {\n return this.actionHandler;\n }\n\n /**\n * Returns control mouseDown handler\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseDownHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): ControlActionHandler | undefined {\n return this.mouseDownHandler;\n }\n\n /**\n * Returns control mouseUp handler.\n * During actions the fabricObject or the control can be of different obj\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseUpHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): ControlActionHandler | undefined {\n return this.mouseUpHandler;\n }\n\n /**\n * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\n * function you can pass one in the constructor\n * the cursorStyle property\n * @param {Event} eventData the native mouse event\n * @param {Control} control the current control ( likely this)\n * @param {FabricObject} object on which the control is displayed\n * @return {String}\n */\n cursorStyleHandler(\n eventData: TPointerEvent,\n control: Control,\n fabricObject: InteractiveFabricObject,\n coord: TOCoord,\n ) {\n return control.cursorStyle;\n }\n\n /**\n * Returns the action name. The basic implementation just return the actionName property.\n * @param {Event} eventData the native mouse event\n * @param {Control} control the current control ( likely this)\n * @param {FabricObject} object on which the control is displayed\n * @return {String}\n */\n getActionName(\n eventData: TPointerEvent,\n control: Control,\n fabricObject: InteractiveFabricObject,\n ) {\n return control.actionName;\n }\n\n /**\n * Returns controls visibility\n * @param {FabricObject} object on which the control is displayed\n * @param {String} controlKey key where the control is memorized on the\n * @return {Boolean}\n */\n getVisibility(fabricObject: InteractiveFabricObject, controlKey: string) {\n return fabricObject._controlsVisibility?.[controlKey] ?? this.visible;\n }\n\n /**\n * Sets controls visibility\n * @param {Boolean} visibility for the object\n * @return {Void}\n */\n setVisibility(\n visibility: boolean,\n name?: string,\n fabricObject?: InteractiveFabricObject,\n ) {\n this.visible = visibility;\n }\n\n positionHandler(\n dim: Point,\n finalMatrix: TMat2D,\n fabricObject: InteractiveFabricObject,\n currentControl: Control,\n ) {\n return new Point(\n this.x * dim.x + this.offsetX,\n this.y * dim.y + this.offsetY,\n ).transform(finalMatrix);\n }\n\n /**\n * Returns the coords for this control based on object values.\n * @param {Number} objectAngle angle from the fabric object holding the control\n * @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if\n * isTouch is true)\n * @param {Number} centerX x coordinate where the control center should be\n * @param {Number} centerY y coordinate where the control center should be\n * @param {boolean} isTouch true if touch corner, false if normal corner\n */\n calcCornerCoords(\n angle: TDegree,\n objectCornerSize: number,\n centerX: number,\n centerY: number,\n isTouch: boolean,\n fabricObject: InteractiveFabricObject,\n ) {\n const t = multiplyTransformMatrixArray([\n createTranslateMatrix(centerX, centerY),\n createRotateMatrix({ angle }),\n createScaleMatrix(\n (isTouch ? this.touchSizeX : this.sizeX) || objectCornerSize,\n (isTouch ? this.touchSizeY : this.sizeY) || objectCornerSize,\n ),\n ]);\n return {\n tl: new Point(-0.5, -0.5).transform(t),\n tr: new Point(0.5, -0.5).transform(t),\n br: new Point(0.5, 0.5).transform(t),\n bl: new Point(-0.5, 0.5).transform(t),\n };\n }\n\n /**\n * This is an helper method to prepare the canvas to render a control\n * It detectes common control properties and sets the correct fill and\n * stroke styles on the context. It does not execute translations or\n * rotations since different controls need differnt combination of these.\n */\n commonRenderProps(\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n fabricObject: InteractiveFabricObject,\n styleOverride: ControlRenderingStyleOverride = {},\n ): {\n stroke: boolean;\n xSize: number;\n ySize: number;\n transparentCorners: boolean;\n opName: 'stroke' | 'fill';\n } {\n const { cornerSize, cornerColor, transparentCorners, cornerStrokeColor } =\n styleOverride,\n sizeFromProps = cornerSize || fabricObject.cornerSize,\n xSize = this.sizeX || sizeFromProps,\n ySize = this.sizeY || sizeFromProps,\n transparent =\n typeof transparentCorners !== 'undefined'\n ? transparentCorners\n : fabricObject.transparentCorners,\n opName = transparent ? STROKE : FILL,\n strokeColor = cornerStrokeColor || fabricObject.cornerStrokeColor,\n stroke = !transparent && !!strokeColor;\n ctx.fillStyle = cornerColor || fabricObject.cornerColor || '';\n ctx.strokeStyle = strokeColor || '';\n ctx.translate(left, top);\n // angle is relative to canvas plane\n ctx.rotate(degreesToRadians(fabricObject.getTotalAngle()));\n return {\n stroke,\n xSize,\n ySize,\n transparentCorners: transparent,\n opName,\n };\n }\n\n /**\n * Render function for the control.\n * When this function runs the context is unscaled. unrotate. Just retina scaled.\n * all the functions will have to translate to the point left,top before starting Drawing\n * if they want to draw a control where the position is detected.\n * left and top are the result of the positionHandler function\n * @param {RenderingContext2D} ctx the context where the control will be drawn\n * @param {Number} left position of the canvas where we are about to render the control.\n * @param {Number} top position of the canvas where we are about to render the control.\n * @param {Object} styleOverride\n * @param {FabricObject} fabricObject the object where the control is about to be rendered\n */\n render(\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride | undefined,\n fabricObject: InteractiveFabricObject,\n ) {\n styleOverride = styleOverride || {};\n switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\n case 'circle':\n renderCircleControl.call(\n this,\n ctx,\n left,\n top,\n styleOverride,\n fabricObject,\n );\n break;\n default:\n renderSquareControl.call(\n this,\n ctx,\n left,\n top,\n styleOverride,\n fabricObject,\n );\n }\n }\n}\n","import type {\n ControlCursorCallback,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { ROTATING } from '../constants';\nimport { radiansToDegrees } from '../util/misc/radiansDegreesConversion';\nimport { isLocked, NOT_ALLOWED_CURSOR } from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\n\n/**\n * Find the correct style for the control that is used for rotation.\n * this function is very simple and it just take care of not-allowed or standard cursor\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\nexport const rotationStyleHandler: ControlCursorCallback = (\n eventData,\n control,\n fabricObject,\n) => {\n if (fabricObject.lockRotation) {\n return NOT_ALLOWED_CURSOR;\n }\n return control.cursorStyle;\n};\n\n/**\n * Action handler for rotation and snapping, without anchor point.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n * @private\n */\nconst rotateObjectWithSnapping: TransformActionHandler = (\n eventData,\n { target, ex, ey, theta, originX, originY },\n x,\n y,\n) => {\n const pivotPoint = target.getPositionByOrigin(originX, originY);\n\n if (isLocked(target, 'lockRotation')) {\n return false;\n }\n\n const lastAngle = Math.atan2(ey - pivotPoint.y, ex - pivotPoint.x),\n curAngle = Math.atan2(y - pivotPoint.y, x - pivotPoint.x);\n let angle = radiansToDegrees(curAngle - lastAngle + theta);\n\n if (target.snapAngle && target.snapAngle > 0) {\n const snapAngle = target.snapAngle,\n snapThreshold = target.snapThreshold || snapAngle,\n rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle,\n leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;\n\n if (Math.abs(angle - leftAngleLocked) < snapThreshold) {\n angle = leftAngleLocked;\n } 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 const hasRotated = target.angle !== angle;\n // TODO: why aren't we using set?\n target.angle = angle;\n return hasRotated;\n};\n\nexport const rotationWithSnapping = wrapWithFireEvent(\n ROTATING,\n wrapWithFixedAnchor(rotateObjectWithSnapping),\n);\n","import type {\n ControlCursorCallback,\n TPointerEvent,\n Transform,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TAxis } from '../typedefs';\nimport type { Canvas } from '../canvas/Canvas';\nimport {\n findCornerQuadrant,\n getLocalPoint,\n invertOrigin,\n isLocked,\n isTransformCentered,\n NOT_ALLOWED_CURSOR,\n} from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\nimport { SCALE_X, SCALE_Y, SCALING } from '../constants';\n\ntype ScaleTransform = Transform & {\n gestureScale?: number;\n signX?: number;\n signY?: number;\n};\n\ntype ScaleBy = TAxis | 'equally' | '' | undefined;\n\n/**\n * Inspect event and fabricObject properties to understand if the scaling action\n * @param {Event} eventData from the user action\n * @param {FabricObject} fabricObject the fabric object about to scale\n * @return {Boolean} true if scale is proportional\n */\nexport function scaleIsProportional(\n eventData: TPointerEvent,\n fabricObject: FabricObject,\n): boolean {\n const canvas = fabricObject.canvas as Canvas,\n uniformIsToggled = eventData[canvas.uniScaleKey!];\n return (\n (canvas.uniformScaling && !uniformIsToggled) ||\n (!canvas.uniformScaling && uniformIsToggled)\n );\n}\n\n/**\n * Inspect fabricObject to understand if the current scaling action is allowed\n * @param {FabricObject} fabricObject the fabric object about to scale\n * @param {String} by 'x' or 'y' or ''\n * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\n * @return {Boolean} true if scaling is not allowed at current conditions\n */\nexport function scalingIsForbidden(\n fabricObject: FabricObject,\n by: ScaleBy,\n scaleProportionally: boolean,\n) {\n const lockX = isLocked(fabricObject, 'lockScalingX'),\n lockY = isLocked(fabricObject, 'lockScalingY');\n if (lockX && lockY) {\n return true;\n }\n if (!by && (lockX || lockY) && scaleProportionally) {\n return true;\n }\n if (lockX && by === 'x') {\n return true;\n }\n if (lockY && by === 'y') {\n return true;\n }\n // code crashes because of a division by 0 if a 0 sized object is scaled\n // forbid to prevent scaling to happen. ISSUE-9475\n const { width, height, strokeWidth } = fabricObject;\n if (width === 0 && strokeWidth === 0 && by !== 'y') {\n return true;\n }\n if (height === 0 && strokeWidth === 0 && by !== 'x') {\n return true;\n }\n return false;\n}\n\nconst scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'];\n\n/**\n * return the correct cursor style for the scale action\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\nexport const scaleCursorStyleHandler: ControlCursorCallback = (\n eventData,\n control,\n fabricObject,\n coord,\n) => {\n const scaleProportionally = scaleIsProportional(eventData, fabricObject),\n by =\n control.x !== 0 && control.y === 0\n ? 'x'\n : control.x === 0 && control.y !== 0\n ? 'y'\n : '';\n if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\n return NOT_ALLOWED_CURSOR;\n }\n const n = findCornerQuadrant(fabricObject, control, coord);\n return `${scaleMap[n]}-resize`;\n};\n\n/**\n * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @param {Object} options additional information for scaling\n * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\n * @return {Boolean} true if some change happened\n * @private\n */\nfunction scaleObject(\n eventData: TPointerEvent,\n transform: ScaleTransform,\n x: number,\n y: number,\n options: { by?: ScaleBy } = {},\n) {\n const target = transform.target,\n by = options.by,\n scaleProportionally = scaleIsProportional(eventData, target),\n forbidScaling = scalingIsForbidden(target, by, scaleProportionally);\n let newPoint, scaleX, scaleY, dim, signX, signY;\n\n if (forbidScaling) {\n return false;\n }\n if (transform.gestureScale) {\n scaleX = transform.scaleX * transform.gestureScale;\n scaleY = transform.scaleY * transform.gestureScale;\n } else {\n newPoint = getLocalPoint(\n transform,\n transform.originX,\n transform.originY,\n x,\n y,\n );\n // use of sign: We use sign to detect change of direction of an action. sign usually change when\n // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\n // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\n // cross many time the origin point and flip the object. so we need a way to filter out the noise.\n // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\n signX = by !== 'y' ? Math.sign(newPoint.x || transform.signX || 1) : 1;\n signY = by !== 'x' ? Math.sign(newPoint.y || transform.signY || 1) : 1;\n if (!transform.signX) {\n transform.signX = signX;\n }\n if (!transform.signY) {\n transform.signY = signY;\n }\n\n if (\n isLocked(target, 'lockScalingFlip') &&\n (transform.signX !== signX || transform.signY !== signY)\n ) {\n return false;\n }\n\n dim = target._getTransformedDimensions();\n // missing detection of flip and logic to switch the origin\n if (scaleProportionally && !by) {\n // uniform scaling\n const distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\n { original } = transform,\n originalDistance =\n Math.abs((dim.x * original.scaleX) / target.scaleX) +\n Math.abs((dim.y * original.scaleY) / target.scaleY),\n scale = distance / originalDistance;\n scaleX = original.scaleX * scale;\n scaleY = original.scaleY * scale;\n } else {\n scaleX = Math.abs((newPoint.x * target.scaleX) / dim.x);\n scaleY = Math.abs((newPoint.y * target.scaleY) / dim.y);\n }\n // if we are scaling by center, we need to double the scale\n if (isTransformCentered(transform)) {\n scaleX *= 2;\n scaleY *= 2;\n }\n if (transform.signX !== signX && by !== 'y') {\n transform.originX = invertOrigin(transform.originX);\n scaleX *= -1;\n transform.signX = signX;\n }\n if (transform.signY !== signY && by !== 'x') {\n transform.originY = invertOrigin(transform.originY);\n scaleY *= -1;\n transform.signY = signY;\n }\n }\n // minScale is taken care of in the setter.\n const oldScaleX = target.scaleX,\n oldScaleY = target.scaleY;\n if (!by) {\n !isLocked(target, 'lockScalingX') && target.set(SCALE_X, scaleX);\n !isLocked(target, 'lockScalingY') && target.set(SCALE_Y, scaleY);\n } else {\n // forbidden cases already handled on top here.\n by === 'x' && target.set(SCALE_X, scaleX);\n by === 'y' && target.set(SCALE_Y, scaleY);\n }\n return oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\n}\n\n/**\n * Generic scaling logic, to scale from corners either equally or freely.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const scaleObjectFromCorner: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y);\n};\n\n/**\n * Scaling logic for the X axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nconst scaleObjectX: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y, { by: 'x' });\n};\n\n/**\n * Scaling logic for the Y axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nconst scaleObjectY: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y, { by: 'y' });\n};\n\nexport const scalingEqually = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectFromCorner),\n);\n\nexport const scalingX = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectX),\n);\n\nexport const scalingY = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectY),\n);\n","import type {\n ControlCursorCallback,\n TPointerEvent,\n Transform,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { resolveOrigin } from '../util/misc/resolveOrigin';\nimport { Point } from '../Point';\nimport type { TAxis, TAxisKey } from '../typedefs';\nimport {\n degreesToRadians,\n radiansToDegrees,\n} from '../util/misc/radiansDegreesConversion';\nimport {\n findCornerQuadrant,\n getLocalPoint,\n isLocked,\n NOT_ALLOWED_CURSOR,\n} from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\nimport {\n CENTER,\n SCALE_X,\n SCALE_Y,\n SKEWING,\n SKEW_X,\n SKEW_Y,\n} from '../constants';\n\nexport type SkewTransform = Transform & { skewingSide: -1 | 1 };\n\nconst AXIS_KEYS: Record<\n TAxis,\n {\n counterAxis: TAxis;\n scale: TAxisKey<'scale'>;\n skew: TAxisKey<'skew'>;\n lockSkewing: TAxisKey<'lockSkewing'>;\n origin: TAxisKey<'origin'>;\n flip: TAxisKey<'flip'>;\n }\n> = {\n x: {\n counterAxis: 'y',\n scale: SCALE_X,\n skew: SKEW_X,\n lockSkewing: 'lockSkewingX',\n origin: 'originX',\n flip: 'flipX',\n },\n y: {\n counterAxis: 'x',\n scale: SCALE_Y,\n skew: SKEW_Y,\n lockSkewing: 'lockSkewingY',\n origin: 'originY',\n flip: 'flipY',\n },\n};\n\nconst skewMap = ['ns', 'nesw', 'ew', 'nwse'];\n\n/**\n * return the correct cursor style for the skew action\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\nexport const skewCursorStyleHandler: ControlCursorCallback = (\n eventData,\n control,\n fabricObject,\n coord,\n) => {\n if (control.x !== 0 && isLocked(fabricObject, 'lockSkewingY')) {\n return NOT_ALLOWED_CURSOR;\n }\n if (control.y !== 0 && isLocked(fabricObject, 'lockSkewingX')) {\n return NOT_ALLOWED_CURSOR;\n }\n const n = findCornerQuadrant(fabricObject, control, coord) % 4;\n return `${skewMap[n]}-resize`;\n};\n\n/**\n * Since skewing is applied before scaling, calculations are done in a scaleless plane\n * @see https://github.com/fabricjs/fabric.js/pull/8380\n */\nfunction skewObject(\n axis: TAxis,\n { target, ex, ey, skewingSide, ...transform }: SkewTransform,\n pointer: Point,\n) {\n const { skew: skewKey } = AXIS_KEYS[axis],\n offset = pointer\n .subtract(new Point(ex, ey))\n .divide(new Point(target.scaleX, target.scaleY))[axis],\n skewingBefore = target[skewKey],\n skewingStart = transform[skewKey],\n shearingStart = Math.tan(degreesToRadians(skewingStart)),\n // let a, b be the size of target\n // let a' be the value of a after applying skewing\n // then:\n // a' = a + b * skewA => skewA = (a' - a) / b\n // the value b is tricky since skewY is applied before skewX\n b =\n axis === 'y'\n ? target._getTransformedDimensions({\n scaleX: 1,\n scaleY: 1,\n // since skewY is applied before skewX, b (=width) is not affected by skewX\n skewX: 0,\n }).x\n : target._getTransformedDimensions({\n scaleX: 1,\n scaleY: 1,\n }).y;\n\n const shearing =\n (2 * offset * skewingSide) /\n // we max out fractions to safeguard from asymptotic behavior\n Math.max(b, 1) +\n // add starting state\n shearingStart;\n\n const skewing = radiansToDegrees(Math.atan(shearing));\n\n target.set(skewKey, skewing);\n const changed = skewingBefore !== target[skewKey];\n\n if (changed && axis === 'y') {\n // we don't want skewing to affect scaleX\n // so we factor it by the inverse skewing diff to make it seem unchanged to the viewer\n const { skewX, scaleX } = target,\n dimBefore = target._getTransformedDimensions({ skewY: skewingBefore }),\n dimAfter = target._getTransformedDimensions(),\n compensationFactor = skewX !== 0 ? dimBefore.x / dimAfter.x : 1;\n compensationFactor !== 1 &&\n target.set(SCALE_X, compensationFactor * scaleX);\n }\n\n return changed;\n}\n\n/**\n * Wrapped Action handler for skewing on a given axis, takes care of the\n * skew direction and determines the correct transform origin for the anchor point\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nfunction skewHandler(\n axis: TAxis,\n eventData: TPointerEvent,\n transform: Transform,\n x: number,\n y: number,\n) {\n const { target } = transform,\n {\n counterAxis,\n origin: originKey,\n lockSkewing: lockSkewingKey,\n skew: skewKey,\n flip: flipKey,\n } = AXIS_KEYS[axis];\n if (isLocked(target, lockSkewingKey)) {\n return false;\n }\n\n const { origin: counterOriginKey, flip: counterFlipKey } =\n AXIS_KEYS[counterAxis],\n counterOriginFactor =\n resolveOrigin(transform[counterOriginKey]) *\n (target[counterFlipKey] ? -1 : 1),\n // if the counter origin is top/left (= -0.5) then we are skewing x/y values on the bottom/right side of target respectively.\n // if the counter origin is bottom/right (= 0.5) then we are skewing x/y values on the top/left side of target respectively.\n // skewing direction on the top/left side of target is OPPOSITE to the direction of the movement of the pointer,\n // so we factor skewing direction by this value.\n skewingSide = (-Math.sign(counterOriginFactor) *\n (target[flipKey] ? -1 : 1)) as 1 | -1,\n skewingDirection =\n ((target[skewKey] === 0 &&\n // in case skewing equals 0 we use the pointer offset from target center to determine the direction of skewing\n getLocalPoint(transform, CENTER, CENTER, x, y)[axis] > 0) ||\n // in case target has skewing we use that as the direction\n target[skewKey] > 0\n ? 1\n : -1) * skewingSide,\n // anchor to the opposite side of the skewing direction\n // normalize value from [-1, 1] to origin value [0, 1]\n origin = -skewingDirection * 0.5 + 0.5;\n\n const finalHandler = wrapWithFireEvent<SkewTransform>(\n SKEWING,\n wrapWithFixedAnchor((eventData, transform, x, y) =>\n skewObject(axis, transform, new Point(x, y)),\n ),\n );\n\n return finalHandler(\n eventData,\n {\n ...transform,\n [originKey]: origin,\n skewingSide,\n },\n x,\n y,\n );\n}\n\n/**\n * Wrapped Action handler for skewing on the X axis, takes care of the\n * skew direction and determines the correct transform origin for the anchor point\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const skewHandlerX: TransformActionHandler = (\n eventData,\n transform,\n x,\n y,\n) => {\n return skewHandler('x', eventData, transform, x, y);\n};\n\n/**\n * Wrapped Action handler for skewing on the Y axis, takes care of the\n * skew direction and determines the correct transform origin for the anchor point\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const skewHandlerY: TransformActionHandler = (\n eventData,\n transform,\n x,\n y,\n) => {\n return skewHandler('y', eventData, transform, x, y);\n};\n","import type {\n ControlCallback,\n ControlCursorCallback,\n TPointerEvent,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { SCALE_X, SCALE_Y, SKEW_X, SKEW_Y } from '../constants';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TAxisKey } from '../typedefs';\nimport { scaleCursorStyleHandler, scalingX, scalingY } from './scale';\nimport { skewCursorStyleHandler, skewHandlerX, skewHandlerY } from './skew';\n\nfunction isAltAction(eventData: TPointerEvent, target: FabricObject) {\n return eventData[target.canvas!.altActionKey!];\n}\n\n/**\n * Inspect event, control and fabricObject to return the correct action name\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} an action name\n */\nexport const scaleOrSkewActionName: ControlCallback<\n TAxisKey<'skew' | 'scale'> | ''\n> = (eventData, control, fabricObject) => {\n const isAlternative = isAltAction(eventData, fabricObject);\n if (control.x === 0) {\n // then is scaleY or skewX\n return isAlternative ? SKEW_X : SCALE_Y;\n }\n if (control.y === 0) {\n // then is scaleY or skewX\n return isAlternative ? SKEW_Y : SCALE_X;\n }\n return '';\n};\n\n/**\n * Combine skew and scale style handlers to cover fabric standard use case\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\nexport const scaleSkewCursorStyleHandler: ControlCursorCallback = (\n eventData,\n control,\n fabricObject,\n coord,\n) => {\n return isAltAction(eventData, fabricObject)\n ? skewCursorStyleHandler(eventData, control, fabricObject, coord)\n : scaleCursorStyleHandler(eventData, control, fabricObject, coord);\n};\n/**\n * Composed action handler to either scale X or skew Y\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const scalingXOrSkewingY: TransformActionHandler = (\n eventData,\n transform,\n x,\n y,\n) => {\n return isAltAction(eventData, transform.target)\n ? skewHandlerY(eventData, transform, x, y)\n : scalingX(eventData, transform, x, y);\n};\n\n/**\n * Composed action handler to either scale Y or skew X\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const scalingYOrSkewingX: TransformActionHandler = (\n eventData,\n transform,\n x,\n y,\n) => {\n return isAltAction(eventData, transform.target)\n ? skewHandlerX(eventData, transform, x, y)\n : scalingY(eventData, transform, x, y);\n};\n","import { RESIZING, ROTATE } from '../constants';\nimport { changeWidth } from './changeWidth';\nimport { Control } from './Control';\nimport { rotationStyleHandler, rotationWithSnapping } from './rotate';\nimport { scaleCursorStyleHandler, scalingEqually } from './scale';\nimport {\n scaleOrSkewActionName,\n scaleSkewCursorStyleHandler,\n scalingXOrSkewingY,\n scalingYOrSkewingX,\n} from './scaleSkew';\n\n// use this function if you want to generate new controls for every instance\nexport const createObjectDefaultControls = () => ({\n ml: new Control({\n x: -0.5,\n y: 0,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionHandler: scalingXOrSkewingY,\n getActionName: scaleOrSkewActionName,\n }),\n\n mr: new Control({\n x: 0.5,\n y: 0,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionHandler: scalingXOrSkewingY,\n getActionName: scaleOrSkewActionName,\n }),\n\n mb: new Control({\n x: 0,\n y: 0.5,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionHandler: scalingYOrSkewingX,\n getActionName: scaleOrSkewActionName,\n }),\n\n mt: new Control({\n x: 0,\n y: -0.5,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionHandler: scalingYOrSkewingX,\n getActionName: scaleOrSkewActionName,\n }),\n\n tl: new Control({\n x: -0.5,\n y: -0.5,\n cursorStyleHandler: scaleCursorStyleHandler,\n actionHandler: scalingEqually,\n }),\n\n tr: new Control({\n x: 0.5,\n y: -0.5,\n cursorStyleHandler: scaleCursorStyleHandler,\n actionHandler: scalingEqually,\n }),\n\n bl: new Control({\n x: -0.5,\n y: 0.5,\n cursorStyleHandler: scaleCursorStyleHandler,\n actionHandler: scalingEqually,\n }),\n\n br: new Control({\n x: 0.5,\n y: 0.5,\n cursorStyleHandler: scaleCursorStyleHandler,\n actionHandler: scalingEqually,\n }),\n\n mtr: new Control({\n x: 0,\n y: -0.5,\n actionHandler: rotationWithSnapping,\n cursorStyleHandler: rotationStyleHandler,\n offsetY: -40,\n withConnection: true,\n actionName: ROTATE,\n }),\n});\n\nexport const createResizeControls = () => ({\n mr: new Control({\n x: 0.5,\n y: 0,\n actionHandler: changeWidth,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionName: RESIZING,\n }),\n ml: new Control({\n x: -0.5,\n y: 0,\n actionHandler: changeWidth,\n cursorStyleHandler: scaleSkewCursorStyleHandler,\n actionName: RESIZING,\n }),\n});\n\nexport const createTextboxDefaultControls = () => ({\n ...createObjectDefaultControls(),\n ...createResizeControls(),\n});\n","import { Point, ZERO } from '../../Point';\nimport type { TCornerPoint, TDegree } from '../../typedefs';\nimport { FabricObject } from './Object';\nimport { degreesToRadians } from '../../util/misc/radiansDegreesConversion';\nimport type { TQrDecomposeOut } from '../../util/misc/matrix';\nimport {\n calcDimensionsMatrix,\n createRotateMatrix,\n createTranslateMatrix,\n multiplyTransformMatrices,\n qrDecompose,\n} from '../../util/misc/matrix';\nimport type { Control } from '../../controls/Control';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport type { ObjectEvents, TPointerEvent } from '../../EventTypeDefs';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { ControlRenderingStyleOverride } from '../../controls/controlRendering';\nimport type { FabricObjectProps } from './types/FabricObjectProps';\nimport type { TFabricObjectProps, SerializedObjectProps } from './types';\nimport { createObjectDefaultControls } from '../../controls/commonControls';\nimport { interactiveObjectDefaultValues } from './defaultValues';\nimport { SCALE } from '../../constants';\n\nexport type TOCoord = Point & {\n corner: TCornerPoint;\n touchCorner: TCornerPoint;\n};\n\nexport type TControlSet = Record<string, Control>;\n\nexport type TBorderRenderingStyleOverride = Partial<\n Pick<InteractiveFabricObject, 'borderColor' | 'borderDashArray'>\n>;\n\nexport type TStyleOverride = ControlRenderingStyleOverride &\n TBorderRenderingStyleOverride &\n Partial<\n Pick<InteractiveFabricObject, 'hasBorders' | 'hasControls'> & {\n forActiveSelection: boolean;\n }\n >;\n\nexport class InteractiveFabricObject<\n Props extends TFabricObjectProps = Partial<FabricObjectProps>,\n SProps extends SerializedObjectProps = SerializedObjectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements FabricObjectProps\n{\n declare noScaleCache: boolean;\n\n declare snapAngle?: TDegree;\n declare snapThreshold?: TDegree;\n\n declare lockMovementX: boolean;\n declare lockMovementY: boolean;\n declare lockRotation: boolean;\n declare lockScalingX: boolean;\n declare lockScalingY: boolean;\n declare lockSkewingX: boolean;\n declare lockSkewingY: boolean;\n declare lockScalingFlip: boolean;\n\n declare cornerSize: number;\n declare touchCornerSize: number;\n declare transparentCorners: boolean;\n declare cornerColor: string;\n declare cornerStrokeColor: string;\n declare cornerStyle: 'rect' | 'circle';\n declare cornerDashArray: number[] | null;\n declare hasControls: boolean;\n\n declare borderColor: string;\n declare borderDashArray: number[] | null;\n declare borderOpacityWhenMoving: number;\n declare borderScaleFactor: number;\n declare hasBorders: boolean;\n declare selectionBackgroundColor: string;\n\n declare selectable: boolean;\n declare evented: boolean;\n declare perPixelTargetFind: boolean;\n declare activeOn: 'down' | 'up';\n\n declare hoverCursor: CSSStyleDeclaration['cursor'] | null;\n declare moveCursor: CSSStyleDeclaration['cursor'] | null;\n\n /**\n * The object's controls' position in viewport coordinates\n * Calculated by {@link Control#positionHandler} and {@link Control#calcCornerCoords}, depending on {@link padding}.\n * `corner/touchCorner` describe the 4 points forming the interactive area of the corner.\n * Used to draw and locate controls.\n */\n declare oCoords: Record<string, TOCoord>;\n\n /**\n * keeps the value of the last hovered corner during mouse move.\n * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\n * It should be private, but there is no harm in using it as\n * a read-only property.\n * this isn't cleaned automatically. Non selected objects may have wrong values\n * @type [string]\n */\n declare __corner?: string;\n\n /**\n * a map of control visibility for this object.\n * this was left when controls were introduced to not break the api too much\n * this takes priority over the generic control visibility\n */\n declare _controlsVisibility: Record<string, boolean>;\n\n /**\n * holds the controls for the object.\n * controls are added by default_controls.js\n */\n declare controls: TControlSet;\n\n /**\n * internal boolean to signal the code that the object is\n * part of the move action.\n */\n declare isMoving?: boolean;\n\n /**\n * A boolean used from the gesture module to keep tracking of a scaling\n * action when there is no scaling transform in place.\n * This is an edge case and is used twice in all codebase.\n * Probably added to keep track of some performance issues\n * @TODO use git blame to investigate why it was added\n * DON'T USE IT. WE WILL TRY TO REMOVE IT\n */\n declare _scaling?: boolean;\n\n declare canvas?: Canvas;\n\n static ownDefaults = interactiveObjectDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...InteractiveFabricObject.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(\n this,\n (this.constructor as typeof InteractiveFabricObject).createControls(),\n InteractiveFabricObject.ownDefaults,\n );\n this.setOptions(options);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults\n * @param {Object} [options] Options object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createObjectDefaultControls() };\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() {\n const targetCanvas = this.canvas;\n if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\n const transform = targetCanvas._currentTransform,\n target = transform.target,\n action = transform.action;\n if (\n this === (target as unknown as this) &&\n action &&\n action.startsWith(SCALE)\n ) {\n return false;\n }\n }\n return super._updateCacheCanvas();\n }\n\n getActiveControl() {\n const key = this.__corner;\n return key\n ? {\n key,\n control: this.controls[key],\n coord: this.oCoords[key],\n }\n : undefined;\n }\n\n /**\n * Determines which corner is under the mouse cursor, represented by `pointer`.\n * This function returns a corner only if the object is the active one.\n * This is done to avoid selecting corner of non active object and activating transformations\n * rather than drag action. The default behavior of fabricJS is that if you want to transform\n * an object, first you select it to show the control set\n * @private\n * @param {Object} pointer The pointer indicating the mouse position\n * @param {boolean} forTouch indicates if we are looking for interaction area with a touch action\n * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or 0 if nothing is found.\n */\n findControl(\n pointer: Point,\n forTouch = false,\n ): { key: string; control: Control; coord: TOCoord } | undefined {\n if (!this.hasControls || !this.canvas) {\n return undefined;\n }\n\n this.__corner = undefined;\n const cornerEntries = Object.entries(this.oCoords);\n for (let i = cornerEntries.length - 1; i >= 0; i--) {\n const [key, corner] = cornerEntries[i];\n const control = this.controls[key];\n\n if (\n control.shouldActivate(\n key,\n this,\n pointer,\n forTouch ? corner.touchCorner : corner.corner,\n )\n ) {\n // this.canvas.contextTop.fillRect(pointer.x - 1, pointer.y - 1, 2, 2);\n this.__corner = key;\n\n return { key, control, coord: this.oCoords[key] };\n }\n }\n\n return undefined;\n }\n\n /**\n * Calculates the coordinates of the center of each control plus the corners of the control itself\n * This basically just delegates to each control positionHandler\n * WARNING: changing what is passed to positionHandler is a breaking change, since position handler\n * is a public api and should be done just if extremely necessary\n * @return {Record<string, TOCoord>}\n */\n calcOCoords(): Record<string, TOCoord> {\n const vpt = this.getViewportTransform(),\n center = this.getCenterPoint(),\n tMatrix = createTranslateMatrix(center.x, center.y),\n rMatrix = createRotateMatrix({\n angle: this.getTotalAngle() - (!!this.group && this.flipX ? 180 : 0),\n }),\n positionMatrix = multiplyTransformMatrices(tMatrix, rMatrix),\n startMatrix = multiplyTransformMatrices(vpt, positionMatrix),\n finalMatrix = multiplyTransformMatrices(startMatrix, [\n 1 / vpt[0],\n 0,\n 0,\n 1 / vpt[3],\n 0,\n 0,\n ]),\n transformOptions = this.group\n ? qrDecompose(this.calcTransformMatrix())\n : undefined;\n // decomposing could bring negative scaling and `_calculateCurrentDimensions` can't take it\n if (transformOptions) {\n transformOptions.scaleX = Math.abs(transformOptions.scaleX);\n transformOptions.scaleY = Math.abs(transformOptions.scaleY);\n }\n const dim = this._calculateCurrentDimensions(transformOptions),\n coords: Record<string, TOCoord> = {};\n\n this.forEachControl((control, key) => {\n const position = control.positionHandler(dim, finalMatrix, this, control);\n // coords[key] are sometimes used as points. Those are points to which we add\n // the property corner and touchCorner from `_calcCornerCoords`.\n // don't remove this assign for an object spread.\n coords[key] = Object.assign(\n position,\n this._calcCornerCoords(control, position),\n );\n });\n\n // debug code\n /*\n const canvas = this.canvas;\n setTimeout(function () {\n if (!canvas) return;\n canvas.contextTop.clearRect(0, 0, 700, 700);\n canvas.contextTop.fillStyle = 'green';\n Object.keys(coords).forEach(function(key) {\n const control = coords[key];\n canvas.contextTop.fillRect(control.x, control.y, 3, 3);\n });\n } 50);\n */\n return coords;\n }\n\n /**\n * Sets the coordinates that determine the interaction area of each control\n * note: if we would switch to ROUND corner area, all of this would disappear.\n * everything would resolve to a single point and a pythagorean theorem for the distance\n * @todo evaluate simplification of code switching to circle interaction area at runtime\n * @private\n */\n private _calcCornerCoords(control: Control, position: Point) {\n const angle = this.getTotalAngle();\n const corner = control.calcCornerCoords(\n angle,\n this.cornerSize,\n position.x,\n position.y,\n false,\n this,\n );\n const touchCorner = control.calcCornerCoords(\n angle,\n this.touchCornerSize,\n position.x,\n position.y,\n true,\n this,\n );\n return { corner, touchCorner };\n }\n\n /**\n * @override set controls' coordinates as well\n * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link https://fabric5.fabricjs.com/fabric-gotchas}\n * @return {void}\n */\n setCoords(): void {\n super.setCoords();\n this.canvas && (this.oCoords = this.calcOCoords());\n }\n\n /**\n * Calls a function for each control. The function gets called,\n * with the control, the control's key and the object that is calling the iterator\n * @param {Function} fn function to iterate over the controls over\n */\n forEachControl(\n fn: (\n control: Control,\n key: string,\n fabricObject: InteractiveFabricObject,\n ) => any,\n ) {\n for (const i in this.controls) {\n fn(this.controls[i], i, this);\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 * @todo evaluate if make this disappear in favor of a pre-render hook for objects\n * this was added by Andrea Bogazzi to make possible some feature for work reasons\n * it seemed a good option, now is an edge case\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n */\n drawSelectionBackground(ctx: CanvasRenderingContext2D): void {\n if (\n !this.selectionBackgroundColor ||\n (this.canvas && (this.canvas._activeObject as unknown as this) !== this)\n ) {\n return;\n }\n ctx.save();\n const center = this.getRelativeCenterPoint(),\n wh = this._calculateCurrentDimensions(),\n vpt = this.getViewportTransform();\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 }\n\n /**\n * @public override this function in order to customize the drawing of the control box, e.g. rounded corners, different border style.\n * @param {CanvasRenderingContext2D} ctx ctx is rotated and translated so that (0,0) is at object's center\n * @param {Point} size the control box size used\n */\n strokeBorders(ctx: CanvasRenderingContext2D, size: Point): void {\n ctx.strokeRect(-size.x / 2, -size.y / 2, size.x, size.y);\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {Point} size\n * @param {TStyleOverride} styleOverride object to override the object style\n */\n _drawBorders(\n ctx: CanvasRenderingContext2D,\n size: Point,\n styleOverride: TStyleOverride = {},\n ): void {\n const options = {\n hasControls: this.hasControls,\n borderColor: this.borderColor,\n borderDashArray: this.borderDashArray,\n ...styleOverride,\n };\n ctx.save();\n ctx.strokeStyle = options.borderColor;\n this._setLineDash(ctx, options.borderDashArray);\n this.strokeBorders(ctx, size);\n options.hasControls && this.drawControlsConnectingLines(ctx, size);\n ctx.restore();\n }\n\n /**\n * Renders controls and borders for the object\n * the context here is not transformed\n * @todo move to interactivity\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {TStyleOverride} [styleOverride] properties to override the object style\n */\n _renderControls(\n ctx: CanvasRenderingContext2D,\n styleOverride: TStyleOverride = {},\n ) {\n const { hasBorders, hasControls } = this;\n const styleOptions = {\n hasBorders,\n hasControls,\n ...styleOverride,\n };\n const vpt = this.getViewportTransform(),\n shouldDrawBorders = styleOptions.hasBorders,\n shouldDrawControls = styleOptions.hasControls;\n const matrix = multiplyTransformMatrices(vpt, this.calcTransformMatrix());\n const options = qrDecompose(matrix);\n ctx.save();\n ctx.translate(options.translateX, options.translateY);\n ctx.lineWidth = this.borderScaleFactor; // 1 * this.borderScaleFactor;\n // since interactive groups have been introduced, an object could be inside a group and needing controls\n // the following equality check `this.group === this.parent` covers:\n // object without a group ( undefined === undefined )\n // object inside a group\n // excludes object inside a group but multi selected since group and parent will differ in value\n if (this.group === this.parent) {\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n }\n if (this.flipX) {\n options.angle -= 180;\n }\n ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));\n shouldDrawBorders && this.drawBorders(ctx, options, styleOverride);\n shouldDrawControls && this.drawControls(ctx, styleOverride);\n ctx.restore();\n }\n\n /**\n * Draws borders of an object's bounding box.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {object} options object representing current object parameters\n * @param {TStyleOverride} [styleOverride] object to override the object style\n */\n drawBorders(\n ctx: CanvasRenderingContext2D,\n options: TQrDecomposeOut,\n styleOverride: TStyleOverride,\n ): void {\n let size;\n if ((styleOverride && styleOverride.forActiveSelection) || this.group) {\n const bbox = sizeAfterTransform(\n this.width,\n this.height,\n calcDimensionsMatrix(options),\n ),\n stroke = !this.isStrokeAccountedForInDimensions()\n ? (this.strokeUniform\n ? new Point().scalarAdd(this.canvas ? this.canvas.getZoom() : 1)\n : // this is extremely confusing. options comes from the upper function\n // and is the qrDecompose of a matrix that takes in account zoom too\n new Point(options.scaleX, options.scaleY)\n ).scalarMultiply(this.strokeWidth)\n : ZERO;\n size = bbox\n .add(stroke)\n .scalarAdd(this.borderScaleFactor)\n .scalarAdd(this.padding * 2);\n } else {\n size = this._calculateCurrentDimensions().scalarAdd(\n this.borderScaleFactor,\n );\n }\n this._drawBorders(ctx, size, styleOverride);\n }\n\n /**\n * Draws lines from a borders of an object's bounding box to controls that have `withConnection` property set.\n * Requires public properties: width, height\n * Requires public options: padding, borderColor\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {Point} size object size x = width, y = height\n */\n drawControlsConnectingLines(\n ctx: CanvasRenderingContext2D,\n size: Point,\n ): void {\n let shouldStroke = false;\n\n ctx.beginPath();\n this.forEachControl((control, key) => {\n // in this moment, the ctx is centered on the object.\n // width and height of the above function are the size of the bbox.\n if (control.withConnection && control.getVisibility(this, key)) {\n // reset movement for each control\n shouldStroke = true;\n ctx.moveTo(control.x * size.x, control.y * size.y);\n ctx.lineTo(\n control.x * size.x + control.offsetX,\n control.y * size.y + control.offsetY,\n );\n }\n });\n shouldStroke && ctx.stroke();\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 * Be aware that since fabric 6.0 this function does not call setCoords anymore.\n * setCoords needs to be called manually if the object of which we are rendering controls\n * is outside the standard selection and transform process.\n * @param {CanvasRenderingContext2D} ctx Context to draw on\n * @param {ControlRenderingStyleOverride} styleOverride object to override the object style\n */\n drawControls(\n ctx: CanvasRenderingContext2D,\n styleOverride: ControlRenderingStyleOverride = {},\n ) {\n ctx.save();\n const retinaScaling = this.getCanvasRetinaScaling();\n const { cornerStrokeColor, cornerDashArray, cornerColor } = this;\n const options = {\n cornerStrokeColor,\n cornerDashArray,\n cornerColor,\n ...styleOverride,\n };\n ctx.setTransform(retinaScaling, 0, 0, retinaScaling, 0, 0);\n ctx.strokeStyle = ctx.fillStyle = options.cornerColor;\n if (!this.transparentCorners) {\n ctx.strokeStyle = options.cornerStrokeColor;\n }\n this._setLineDash(ctx, options.cornerDashArray);\n this.forEachControl((control, key) => {\n if (control.getVisibility(this, key)) {\n const p = this.oCoords[key];\n control.render(ctx, p.x, p.y, options, this);\n }\n });\n ctx.restore();\n }\n\n /**\n * Returns true if the specified control is visible, false otherwise.\n * @param {string} controlKey The key of the control. Possible values are usually 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr',\n * but since the control api allow for any control name, can be any string.\n * @returns {boolean} true if the specified control is visible, false otherwise\n */\n isControlVisible(controlKey: string): boolean {\n return (\n this.controls[controlKey] &&\n this.controls[controlKey].getVisibility(this, controlKey)\n );\n }\n\n /**\n * Sets the visibility of the specified control.\n * please do not use.\n * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n * but since the control api allow for any control name, can be any string.\n * @param {Boolean} visible true to set the specified control visible, false otherwise\n * @todo discuss this overlap of priority here with the team. Andrea Bogazzi for details\n */\n setControlVisible(controlKey: string, visible: boolean) {\n if (!this._controlsVisibility) {\n this._controlsVisibility = {};\n }\n this._controlsVisibility[controlKey] = visible;\n }\n\n /**\n * Sets the visibility state of object controls, this is just a bulk option for setControlVisible;\n * @param {Record<string, boolean>} [options] with an optional key per control\n * example: {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n */\n setControlsVisibility(options: Record<string, boolean> = {}) {\n Object.entries(options).forEach(([controlKey, visibility]) =>\n this.setControlVisible(controlKey, visibility),\n );\n }\n\n /**\n * Clears the canvas.contextTop in a specific area that corresponds to the object's bounding box\n * that is in the canvas.contextContainer.\n * This function is used to clear pieces of contextTop where we render ephemeral effects on top of the object.\n * Example: blinking cursor text selection, drag effects.\n * @todo discuss swapping restoreManually with a renderCallback, but think of async issues\n * @param {Boolean} [restoreManually] When true won't restore the context after clear, in order to draw something else.\n * @return {CanvasRenderingContext2D|undefined} canvas.contextTop that is either still transformed\n * with the object transformMatrix, or restored to neutral transform\n */\n clearContextTop(\n restoreManually?: boolean,\n ): CanvasRenderingContext2D | undefined {\n if (!this.canvas) {\n return;\n }\n const ctx = this.canvas.contextTop;\n if (!ctx) {\n return;\n }\n const v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n this.transform(ctx);\n // we add 4 pixel, to be sure to do not leave any pixel out\n const width = this.width + 4,\n height = this.height + 4;\n ctx.clearRect(-width / 2, -height / 2, width, height);\n\n restoreManually || ctx.restore();\n return ctx;\n }\n\n /**\n * This callback function is called every time _discardActiveObject or _setActiveObject\n * try to to deselect this object. If the function returns true, the process is cancelled\n * @param {Object} [_options] options sent from the upper functions\n * @param {TPointerEvent} [options.e] event if the process is generated by an event\n * @param {FabricObject} [options.object] next object we are setting as active, and reason why\n * this is being deselected\n */\n onDeselect(_options?: {\n e?: TPointerEvent;\n object?: InteractiveFabricObject;\n }): boolean {\n // implemented by sub-classes, as needed.\n return false;\n }\n\n /**\n * This callback function is called every time _discardActiveObject or _setActiveObject\n * try to to select this object. If the function returns true, the process is cancelled\n * @param {Object} [_options] options sent from the upper functions\n * @param {Event} [_options.e] event if the process is generated by an event\n */\n onSelect(_options?: { e?: TPointerEvent }): boolean {\n // implemented by sub-classes, as needed.\n return false;\n }\n\n /**\n * Override to customize Drag behavior\n * Fired from {@link Canvas#_onMouseMove}\n * @returns true in order for the window to start a drag session\n */\n shouldStartDragging(_e: TPointerEvent) {\n return false;\n }\n\n /**\n * Override to customize Drag behavior\\\n * Fired once a drag session has started\n * @returns true to handle the drag event\n */\n onDragStart(_e: DragEvent) {\n return false;\n }\n\n /**\n * Override to customize drag and drop behavior\n * @public\n * @param {DragEvent} _e\n * @returns {boolean} true if the object currently dragged can be dropped on the target\n */\n canDrop(_e: DragEvent): boolean {\n return false;\n }\n\n /**\n * Override to customize drag and drop behavior\n * render a specific effect when an object is the source of a drag event\n * example: render the selection status for the part of text that is being dragged from a text object\n * @public\n * @param {DragEvent} _e\n */\n renderDragSourceEffect(_e: DragEvent) {\n // for subclasses\n }\n\n /**\n * Override to customize drag and drop behavior\n * render a specific effect when an object is the target of a drag event\n * used to show that the underly object can receive a drop, or to show how the\n * object will change when dropping. example: show the cursor where the text is about to be dropped\n * @public\n * @param {DragEvent} _e\n */\n renderDropTargetEffect(_e: DragEvent) {\n // for subclasses\n }\n}\n","import type { Constructor } from '../typedefs';\n\n/***\n * https://www.typescriptlang.org/docs/handbook/mixins.html#alternative-pattern\n */\nexport function applyMixins<T extends Constructor, S extends Constructor>(\n derivedCtor: T,\n constructors: S[],\n) {\n constructors.forEach((baseCtor) => {\n Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {\n name !== 'constructor' &&\n Object.defineProperty(\n derivedCtor.prototype,\n name,\n Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||\n Object.create(null),\n );\n });\n });\n return derivedCtor as T & { prototype: InstanceType<T & S> };\n}\n","import type { ObjectEvents } from '../../EventTypeDefs';\nimport { FabricObjectSVGExportMixin } from './FabricObjectSVGExportMixin';\nimport { InteractiveFabricObject } from './InteractiveObject';\nimport { applyMixins } from '../../util/applyMixins';\nimport type { FabricObjectProps } from './types/FabricObjectProps';\nimport type { TFabricObjectProps, SerializedObjectProps } from './types';\nimport { classRegistry } from '../../ClassRegistry';\n\n// TODO somehow we have to make a tree-shakeable import\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface FabricObject<\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Props extends TFabricObjectProps = Partial<FabricObjectProps>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n SProps extends SerializedObjectProps = SerializedObjectProps,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n EventSpec extends ObjectEvents = ObjectEvents,\n> extends FabricObjectSVGExportMixin {}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nexport class FabricObject<\n Props extends TFabricObjectProps = Partial<FabricObjectProps>,\n SProps extends SerializedObjectProps = SerializedObjectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n> extends InteractiveFabricObject<Props, SProps, EventSpec> {}\n\napplyMixins(FabricObject, [FabricObjectSVGExportMixin]);\n\nclassRegistry.setClass(FabricObject);\nclassRegistry.setClass(FabricObject, 'object');\n\nexport { cacheProperties } from './defaultValues';\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 in canvasElementCoordinate, not fabric space. integer\n * @param {Number} y y coordinate in canvasElementCoordinate, not fabric space. integer\n * @param {Number} tolerance Tolerance pixels around the point, not alpha tolerance, integer\n * @return {boolean} true if transparent\n */\nexport const isTransparent = (\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n tolerance: number,\n): boolean => {\n tolerance = Math.round(tolerance);\n const size = tolerance * 2 + 1;\n const { data } = ctx.getImageData(x - tolerance, y - tolerance, size, size);\n\n // Split image data - for tolerance > 1, pixelDataSize = 4;\n for (let i = 3; i < data.length; i += 4) {\n const alphaChannel = data[i];\n if (alphaChannel > 0) {\n return false;\n }\n }\n return true;\n};\n","import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { degreesToRadians } from '../radiansDegreesConversion';\nimport { createVector } from '../vectors';\nimport type { TProjectStrokeOnPointsOptions, TProjection } from './types';\n\n/**\n * @see https://github.com/fabricjs/fabric.js/pull/8344\n * @todo consider removing skewing from points before calculating stroke projection,\n * see https://github.com/fabricjs/fabric.js/commit/494a10ee2f8c2278ae9a55b20bf50cf6ee25b064#commitcomment-94751537\n */\nexport abstract class StrokeProjectionsBase {\n declare options: TProjectStrokeOnPointsOptions;\n declare scale: Point;\n declare strokeUniformScalar: Point;\n declare strokeProjectionMagnitude: number;\n\n constructor(options: TProjectStrokeOnPointsOptions) {\n this.options = options;\n this.strokeProjectionMagnitude = this.options.strokeWidth / 2;\n this.scale = new Point(this.options.scaleX, this.options.scaleY);\n this.strokeUniformScalar = this.options.strokeUniform\n ? new Point(1 / this.options.scaleX, 1 / this.options.scaleY)\n : new Point(1, 1);\n }\n\n /**\n * When the stroke is uniform, scaling affects the arrangement of points. So we must take it into account.\n */\n protected createSideVector(from: XY, to: XY) {\n const v = createVector(from, to);\n return this.options.strokeUniform ? v.multiply(this.scale) : v;\n }\n\n protected abstract calcOrthogonalProjection(\n from: Point,\n to: Point,\n magnitude?: number,\n ): Point;\n\n protected projectOrthogonally(from: Point, to: Point, magnitude?: number) {\n return this.applySkew(\n from.add(this.calcOrthogonalProjection(from, to, magnitude)),\n );\n }\n\n protected isSkewed() {\n return this.options.skewX !== 0 || this.options.skewY !== 0;\n }\n\n protected applySkew(point: Point) {\n const p = new Point(point);\n // skewY must be applied before skewX as this distortion affects skewX calculation\n p.y += p.x * Math.tan(degreesToRadians(this.options.skewY));\n p.x += p.y * Math.tan(degreesToRadians(this.options.skewX));\n return p;\n }\n\n protected scaleUnitVector(unitVector: Point, scalar: number) {\n return unitVector.multiply(this.strokeUniformScalar).scalarMultiply(scalar);\n }\n\n protected abstract projectPoints(): Point[];\n\n public abstract project(): TProjection[];\n}\n","import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { halfPI, twoMathPi } from '../../../constants';\nimport type { TRadian } from '../../../typedefs';\nimport { degreesToRadians } from '../radiansDegreesConversion';\nimport {\n calcAngleBetweenVectors,\n calcVectorRotation,\n crossProduct,\n getOrthonormalVector,\n getUnitVector,\n isBetweenVectors,\n magnitude,\n rotateVector,\n} from '../vectors';\nimport { StrokeProjectionsBase } from './StrokeProjectionsBase';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\nconst zeroVector = new Point();\n\n/**\n * class in charge of finding projections for each type of line join\n * @see {@link [Closed path projections at #8344](https://github.com/fabricjs/fabric.js/pull/8344#2-closed-path)}\n *\n * - MDN:\n * - https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin\n * - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin\n * - Spec: https://svgwg.org/svg2-draft/painting.html#StrokeLinejoinProperty\n * - Playground to understand how the line joins works: https://hypertolosana.github.io/efficient-webgl-stroking/index.html\n * - View the calculated projections for each of the control points: https://codesandbox.io/s/project-stroke-points-with-context-to-trace-b8jc4j?file=/src/index.js\n *\n */\nexport class StrokeLineJoinProjections extends StrokeProjectionsBase {\n /**\n * The point being projected (the angle ∠BAC)\n */\n declare A: Point;\n /**\n * The point before A\n */\n declare B: Point;\n /**\n * The point after A\n */\n declare C: Point;\n /**\n * The AB vector\n */\n AB: Point;\n /**\n * The AC vector\n */\n AC: Point;\n /**\n * The angle of A (∠BAC)\n */\n alpha: TRadian;\n /**\n * The bisector of A (∠BAC)\n */\n bisector: Point;\n\n static getOrthogonalRotationFactor(vector1: Point, vector2?: Point) {\n const angle = vector2\n ? calcAngleBetweenVectors(vector1, vector2)\n : calcVectorRotation(vector1);\n return Math.abs(angle) < halfPI ? -1 : 1;\n }\n\n constructor(A: XY, B: XY, C: XY, options: TProjectStrokeOnPointsOptions) {\n super(options);\n this.A = new Point(A);\n this.B = new Point(B);\n this.C = new Point(C);\n this.AB = this.createSideVector(this.A, this.B);\n this.AC = this.createSideVector(this.A, this.C);\n this.alpha = calcAngleBetweenVectors(this.AB, this.AC);\n this.bisector = getUnitVector(\n // if AC is also the zero vector nothing will be projected\n // in that case the next point will handle the projection\n rotateVector(this.AB.eq(zeroVector) ? this.AC : this.AB, this.alpha / 2),\n );\n }\n\n calcOrthogonalProjection(\n from: Point,\n to: Point,\n magnitude: number = this.strokeProjectionMagnitude,\n ) {\n const vector = this.createSideVector(from, to);\n const orthogonalProjection = getOrthonormalVector(vector);\n const correctSide = StrokeLineJoinProjections.getOrthogonalRotationFactor(\n orthogonalProjection,\n this.bisector,\n );\n return this.scaleUnitVector(orthogonalProjection, magnitude * correctSide);\n }\n\n /**\n * BEVEL\n * Calculation: the projection points are formed by the vector orthogonal to the vertex.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-2-bevel\n */\n projectBevel() {\n const projections: Point[] = [];\n // if `alpha` equals 0 or 2*PI, the projections are the same for `B` and `C`\n (this.alpha % twoMathPi === 0 ? [this.B] : [this.B, this.C]).forEach(\n (to) => {\n projections.push(this.projectOrthogonally(this.A, to));\n projections.push(\n this.projectOrthogonally(this.A, to, -this.strokeProjectionMagnitude),\n );\n },\n );\n return projections;\n }\n\n /**\n * MITER\n * Calculation: the corner is formed by extending the outer edges of the stroke\n * at the tangents of the path segments until they intersect.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-1-miter\n */\n projectMiter() {\n const projections: Point[] = [],\n alpha = Math.abs(this.alpha),\n hypotUnitScalar = 1 / Math.sin(alpha / 2),\n miterVector = this.scaleUnitVector(\n this.bisector,\n -this.strokeProjectionMagnitude * hypotUnitScalar,\n );\n\n // When two line segments meet at a sharp angle, it is possible for the join to extend,\n // far beyond the thickness of the line stroking the path. The stroke-miterlimit imposes\n // a limit on the extent of the line join.\n // MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\n // When the stroke is uniform, scaling changes the arrangement of points, this changes the miter-limit\n const strokeMiterLimit = this.options.strokeUniform\n ? magnitude(\n this.scaleUnitVector(this.bisector, this.options.strokeMiterLimit),\n )\n : this.options.strokeMiterLimit;\n\n if (\n magnitude(miterVector) / this.strokeProjectionMagnitude <=\n strokeMiterLimit\n ) {\n projections.push(this.applySkew(this.A.add(miterVector)));\n }\n /* when the miter-limit is reached, the stroke line join becomes of type bevel.\n We always need two orthogonal projections which are basically bevel-type projections,\n so regardless of whether the miter-limit was reached or not, we include these projections.\n */\n projections.push(...this.projectBevel());\n\n return projections;\n }\n\n /**\n * ROUND (without skew)\n * Calculation: the projections are the two vectors parallel to X and Y axes\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-1-round-without-skew\n */\n private projectRoundNoSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [],\n // correctSide is used to only consider projecting for the outer side\n correctSide = new Point(\n StrokeLineJoinProjections.getOrthogonalRotationFactor(this.bisector),\n StrokeLineJoinProjections.getOrthogonalRotationFactor(\n new Point(this.bisector.y, this.bisector.x),\n ),\n ),\n radiusOnAxisX = new Point(1, 0)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide),\n radiusOnAxisY = new Point(0, 1)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide);\n\n [radiusOnAxisX, radiusOnAxisY].forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.A.add(vector));\n }\n });\n return projections;\n }\n\n /**\n * ROUND (with skew)\n * Calculation: the projections are the points furthest from the vertex in\n * the direction of the X and Y axes after distortion.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-2-round-skew\n */\n private projectRoundWithSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [];\n\n const { skewX, skewY, scaleX, scaleY, strokeUniform } = this.options,\n shearing = new Point(\n Math.tan(degreesToRadians(skewX)),\n Math.tan(degreesToRadians(skewY)),\n );\n // The points furthest from the vertex in the direction of the X and Y axes after distortion\n const circleRadius = this.strokeProjectionMagnitude,\n newY = strokeUniform\n ? circleRadius /\n scaleY /\n Math.sqrt(1 / scaleY ** 2 + (1 / scaleX ** 2) * shearing.y ** 2)\n : circleRadius / Math.sqrt(1 + shearing.y ** 2),\n furthestY = new Point(\n // Safe guard due to floating point precision. In some situations the square root\n // was returning NaN because of a negative number close to zero.\n Math.sqrt(Math.max(circleRadius ** 2 - newY ** 2, 0)),\n newY,\n ),\n newX = strokeUniform\n ? circleRadius /\n Math.sqrt(\n 1 +\n (shearing.x ** 2 * (1 / scaleY) ** 2) /\n (1 / scaleX + (1 / scaleX) * shearing.x * shearing.y) ** 2,\n )\n : circleRadius /\n Math.sqrt(1 + shearing.x ** 2 / (1 + shearing.x * shearing.y) ** 2),\n furthestX = new Point(\n newX,\n Math.sqrt(Math.max(circleRadius ** 2 - newX ** 2, 0)),\n );\n\n [\n furthestX,\n furthestX.scalarMultiply(-1),\n furthestY,\n furthestY.scalarMultiply(-1),\n ]\n // We need to skew the vector here as this information is used to check if\n // it is between the start and end of the circle segment\n .map((vector) =>\n this.applySkew(\n strokeUniform ? vector.multiply(this.strokeUniformScalar) : vector,\n ),\n )\n .forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.applySkew(this.A).add(vector));\n }\n });\n\n return projections;\n }\n\n projectRound() {\n const projections: Point[] = [];\n /* Include the start and end points of the circle segment, so that only\n the projections contained within it are included */\n // add the orthogonal projections (start and end points of circle segment)\n projections.push(...this.projectBevel());\n // let's determines which one of the orthogonal projection is the beginning and end of the circle segment.\n // when `alpha` equals 0 or 2*PI, we have a straight line, so the way to find the start/end is different.\n const isStraightLine = this.alpha % twoMathPi === 0,\n // change the origin of the projections to point A\n // so that the cross product calculation is correct\n newOrigin = this.applySkew(this.A),\n proj0 = projections[isStraightLine ? 0 : 2].subtract(newOrigin),\n proj1 = projections[isStraightLine ? 1 : 0].subtract(newOrigin),\n // when `isStraightLine` === true, we compare with the vector opposite AB, otherwise we compare with the bisector.\n comparisonVector = isStraightLine\n ? this.applySkew(this.AB.scalarMultiply(-1))\n : this.applySkew(\n this.bisector.multiply(this.strokeUniformScalar).scalarMultiply(-1),\n ),\n // the beginning of the circle segment is always to the right of the comparison vector (cross product > 0)\n isProj0Start = crossProduct(proj0, comparisonVector) > 0,\n startCircle = isProj0Start ? proj0 : proj1,\n endCircle = isProj0Start ? proj1 : proj0;\n if (!this.isSkewed()) {\n projections.push(...this.projectRoundNoSkew(startCircle, endCircle));\n } else {\n projections.push(...this.projectRoundWithSkew(startCircle, endCircle));\n }\n return projections;\n }\n\n /**\n * Project stroke width on points returning projections for each point as follows:\n * - `miter`: 1 point corresponding to the outer boundary. If the miter limit is exceeded, it will be 2 points (becomes bevel)\n * - `bevel`: 2 points corresponding to the bevel possible boundaries, orthogonal to the stroke.\n * - `round`: same as `bevel` when it has no skew, with skew are 4 points.\n */\n protected projectPoints() {\n switch (this.options.strokeLineJoin) {\n case 'miter':\n return this.projectMiter();\n case 'round':\n return this.projectRound();\n default:\n return this.projectBevel();\n }\n }\n\n public project(): TProjection[] {\n return this.projectPoints().map((point) => ({\n originPoint: this.A,\n projectedPoint: point,\n angle: this.alpha,\n bisector: this.bisector,\n }));\n }\n}\n","import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { getOrthonormalVector, getUnitVector } from '../vectors';\nimport { StrokeLineJoinProjections } from './StrokeLineJoinProjections';\nimport { StrokeProjectionsBase } from './StrokeProjectionsBase';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\n/**\n * class in charge of finding projections for each type of line cap for start/end of an open path\n * @see {@link [Open path projections at #8344](https://github.com/fabricjs/fabric.js/pull/8344#1-open-path)}\n *\n * Reference:\n * - MDN:\n * - https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap\n * - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap\n * - Spec: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-linecap-dev\n * - Playground to understand how the line joins works: https://hypertolosana.github.io/efficient-webgl-stroking/index.html\n * - View the calculated projections for each of the control points: https://codesandbox.io/s/project-stroke-points-with-context-to-trace-b8jc4j?file=/src/index.js\n */\nexport class StrokeLineCapProjections extends StrokeProjectionsBase {\n /**\n * edge point\n */\n declare A: Point;\n /**\n * point next to edge point\n */\n declare T: Point;\n\n constructor(A: XY, T: XY, options: TProjectStrokeOnPointsOptions) {\n super(options);\n this.A = new Point(A);\n this.T = new Point(T);\n }\n\n calcOrthogonalProjection(\n from: Point,\n to: Point,\n magnitude: number = this.strokeProjectionMagnitude,\n ) {\n const vector = this.createSideVector(from, to);\n return this.scaleUnitVector(getOrthonormalVector(vector), magnitude);\n }\n\n /**\n * OPEN PATH START/END - Line cap: Butt\n * Calculation: to find the projections, just find the points orthogonal to the stroke\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#1-1-butt\n */\n projectButt() {\n return [\n this.projectOrthogonally(this.A, this.T, this.strokeProjectionMagnitude),\n this.projectOrthogonally(this.A, this.T, -this.strokeProjectionMagnitude),\n ];\n }\n\n /**\n * OPEN PATH START/END - Line cap: Round\n * Calculation: same as stroke line join `round`\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#1-2-round\n */\n projectRound() {\n const projections: Point[] = [];\n\n if (!this.isSkewed() && this.A.eq(this.T)) {\n /* 1 point case without `skew`\n When `strokeUniform` is true, scaling has no effect.\n So we divide by scale, to remove its effect.\n */\n const projection = new Point(1, 1)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar);\n projections.push(\n this.applySkew(this.A.add(projection)),\n this.applySkew(this.A.subtract(projection)),\n );\n } else {\n projections.push(\n ...new StrokeLineJoinProjections(\n this.A,\n this.T,\n this.T,\n this.options,\n ).projectRound(),\n );\n }\n\n return projections;\n }\n\n /**\n * OPEN PATH START/END - Line cap: Square\n * Calculation: project a rectangle of points on the stroke in the opposite direction of the vector `AT`\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#1-3-square\n */\n projectSquare() {\n const projections: Point[] = [];\n\n if (this.A.eq(this.T)) {\n /* 1 point case without `skew`\n When `strokeUniform` is true, scaling has no effect.\n So we divide by scale, to remove its effect.\n */\n const projection = new Point(1, 1)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar);\n projections.push(this.A.add(projection), this.A.subtract(projection));\n } else {\n const orthogonalProjection = this.calcOrthogonalProjection(\n this.A,\n this.T,\n this.strokeProjectionMagnitude,\n );\n const strokePointingOut = this.scaleUnitVector(\n getUnitVector(this.createSideVector(this.A, this.T)),\n -this.strokeProjectionMagnitude,\n );\n const projectedA = this.A.add(strokePointingOut);\n projections.push(\n projectedA.add(orthogonalProjection),\n projectedA.subtract(orthogonalProjection),\n );\n }\n\n return projections.map((p) => this.applySkew(p));\n }\n\n protected projectPoints() {\n switch (this.options.strokeLineCap) {\n case 'round':\n return this.projectRound();\n case 'square':\n return this.projectSquare();\n default:\n return this.projectButt();\n }\n }\n\n public project(): TProjection[] {\n return this.projectPoints().map((point) => ({\n originPoint: this.A,\n projectedPoint: point,\n }));\n }\n}\n","import { Point, type XY } from '../../../Point';\nimport { findIndexRight } from '../../internals/findRight';\nimport { StrokeLineCapProjections } from './StrokeLineCapProjections';\nimport { StrokeLineJoinProjections } from './StrokeLineJoinProjections';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\nexport type * from './types';\n\n/**\n *\n * Used to calculate object's bounding box\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344\n *\n */\nexport const projectStrokeOnPoints = (\n points: XY[],\n options: TProjectStrokeOnPointsOptions,\n openPath = false,\n): TProjection[] => {\n const projections: TProjection[] = [];\n\n if (points.length === 0) {\n return projections;\n }\n\n // first we remove duplicate neighboring points\n const reduced = points.reduce(\n (reduced, point) => {\n if (!reduced[reduced.length - 1].eq(point)) {\n reduced.push(new Point(point));\n }\n return reduced;\n },\n [new Point(points[0])],\n );\n\n if (reduced.length === 1) {\n openPath = true;\n } else if (!openPath) {\n // remove points from end in case they equal the first point\n // in order to correctly project the first point\n const start = reduced[0];\n const index = findIndexRight(reduced, (point) => !point.eq(start));\n reduced.splice(index + 1);\n }\n\n reduced.forEach((A, index, points) => {\n let B: XY, C: XY;\n if (index === 0) {\n C = points[1];\n B = openPath ? A : points[points.length - 1];\n } else if (index === points.length - 1) {\n B = points[index - 1];\n C = openPath ? A : points[0];\n } else {\n B = points[index - 1];\n C = points[index + 1];\n }\n\n if (openPath && points.length === 1) {\n projections.push(\n ...new StrokeLineCapProjections(A, A, options).project(),\n );\n } else if (openPath && (index === 0 || index === points.length - 1)) {\n projections.push(\n ...new StrokeLineCapProjections(\n A,\n index === 0 ? C : B,\n options,\n ).project(),\n );\n } else {\n projections.push(\n ...new StrokeLineJoinProjections(A, B, C, options).project(),\n );\n }\n });\n\n return projections;\n};\n","export const findIndexRight = <T>(\n array: T[],\n predicate: (value: T, index: number, array: T[]) => boolean,\n) => {\n for (let index = array.length - 1; index >= 0; index--) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n};\n","import type { TextStyle } from '../../shapes/Text/StyledText';\n\nexport const cloneStyles = (style: TextStyle): TextStyle => {\n const newObj: TextStyle = {};\n Object.keys(style).forEach((key) => {\n newObj[key] = {};\n Object.keys(style[key]).forEach((keyInner) => {\n newObj[key][keyInner] = { ...style[key][keyInner] };\n });\n });\n return newObj;\n};\n","import { getFabricWindow } from '../env';\n\n/**\n * Capitalizes a 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 */\nexport const capitalize = (string: string, firstLetterOnly = false): string =>\n `${string.charAt(0).toUpperCase()}${\n firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()\n }`;\n\n/**\n * Escapes XML in a string\n * @param {String} string String to escape\n * @return {String} Escaped version of a string\n */\nexport const escapeXml = (string: string): string =>\n string\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n\nlet segmenter: Intl.Segmenter | false;\n\nconst getSegmenter = () => {\n if (!segmenter) {\n segmenter =\n 'Intl' in getFabricWindow() &&\n 'Segmenter' in Intl &&\n new Intl.Segmenter(undefined, {\n granularity: 'grapheme',\n });\n }\n return segmenter;\n};\n\n/**\n * Divide a string in the user perceived single units\n * @param {String} textstring String to escape\n * @return {Array} array containing the graphemes\n */\nexport const graphemeSplit = (textstring: string): string[] => {\n segmenter || getSegmenter();\n if (segmenter) {\n const segments = segmenter.segment(textstring);\n return Array.from(segments).map(({ segment }) => segment);\n }\n\n //Fallback\n return graphemeSplitImpl(textstring);\n};\n\nconst graphemeSplitImpl = (textstring: string): string[] => {\n const graphemes: string[] = [];\n for (let i = 0, chr; i < textstring.length; i++) {\n if ((chr = getWholeChar(textstring, i)) === false) {\n continue;\n }\n graphemes.push(chr);\n }\n return graphemes;\n};\n\n// taken from mdn in the charAt doc page.\nconst getWholeChar = (str: string, i: number): string | false => {\n const code = str.charCodeAt(i);\n if (isNaN(code)) {\n return ''; // Position not found\n }\n if (code < 0xd800 || code > 0xdfff) {\n return str.charAt(i);\n }\n\n // High surrogate (could change last hex to 0xDB7F to treat high private\n // surrogates as single characters)\n if (0xd800 <= code && code <= 0xdbff) {\n if (str.length <= i + 1) {\n throw 'High surrogate without following low surrogate';\n }\n const next = str.charCodeAt(i + 1);\n if (0xdc00 > next || next > 0xdfff) {\n throw 'High surrogate without following low surrogate';\n }\n return str.charAt(i) + str.charAt(i + 1);\n }\n // Low surrogate (0xDC00 <= code && code <= 0xDFFF)\n if (i === 0) {\n throw 'Low surrogate without preceding high surrogate';\n }\n const prev = str.charCodeAt(i - 1);\n\n // (could change last hex to 0xDB7F to treat high private\n // surrogates as single characters)\n if (0xd800 > prev || prev > 0xdbff) {\n throw 'Low surrogate without preceding high surrogate';\n }\n // We can pass over low surrogates now as the second component\n // in a pair which we have already processed\n return false;\n};\n","import { reNewline } from '../../constants';\nimport type {\n TextStyle,\n TextStyleDeclaration,\n} from '../../shapes/Text/StyledText';\nimport { cloneStyles } from '../internals/cloneStyles';\nimport { graphemeSplit } from '../lang_string';\n\nexport type TextStyleArray = {\n start: number;\n end: number;\n style: TextStyleDeclaration;\n}[];\n\n/**\n * @param {Object} prevStyle first style to compare\n * @param {Object} thisStyle second style to compare\n * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties\n * @return {boolean} true if the style changed\n */\nexport const hasStyleChanged = (\n prevStyle: TextStyleDeclaration,\n thisStyle: TextStyleDeclaration,\n forTextSpans = false,\n) =>\n prevStyle.fill !== thisStyle.fill ||\n prevStyle.stroke !== thisStyle.stroke ||\n prevStyle.strokeWidth !== thisStyle.strokeWidth ||\n prevStyle.fontSize !== thisStyle.fontSize ||\n prevStyle.fontFamily !== thisStyle.fontFamily ||\n prevStyle.fontWeight !== thisStyle.fontWeight ||\n prevStyle.fontStyle !== thisStyle.fontStyle ||\n prevStyle.textDecorationThickness !== thisStyle.textDecorationThickness ||\n prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor ||\n prevStyle.deltaY !== thisStyle.deltaY ||\n (forTextSpans &&\n (prevStyle.overline !== thisStyle.overline ||\n prevStyle.underline !== thisStyle.underline ||\n prevStyle.linethrough !== thisStyle.linethrough));\n\n/**\n * Returns the array form of a text object's inline styles property with styles grouped in ranges\n * rather than per character. This format is less verbose, and is better suited for storage\n * so it is used in serialization (not during runtime).\n * @param {object} styles per character styles for a text object\n * @param {String} text the text string that the styles are applied to\n * @return {{start: number, end: number, style: object}[]}\n */\nexport const stylesToArray = (\n styles: TextStyle,\n text: string,\n): TextStyleArray => {\n const textLines = text.split('\\n'),\n stylesArray = [];\n let charIndex = -1,\n prevStyle = {};\n // clone style structure to prevent mutation\n styles = cloneStyles(styles);\n\n //loop through each textLine\n for (let i = 0; i < textLines.length; i++) {\n const chars = graphemeSplit(textLines[i]);\n if (!styles[i]) {\n //no styles exist for this line, so add the line's length to the charIndex total and reset prevStyle\n charIndex += chars.length;\n prevStyle = {};\n continue;\n }\n //loop through each character of the current line\n for (let c = 0; c < chars.length; c++) {\n charIndex++;\n const thisStyle = styles[i][c];\n //check if style exists for this character\n if (thisStyle && Object.keys(thisStyle).length > 0) {\n if (hasStyleChanged(prevStyle, thisStyle, true)) {\n stylesArray.push({\n start: charIndex,\n end: charIndex + 1,\n style: thisStyle,\n });\n } else {\n //if style is the same as previous character, increase end index\n stylesArray[stylesArray.length - 1].end++;\n }\n }\n prevStyle = thisStyle || {};\n }\n }\n return stylesArray;\n};\n\n/**\n * Returns the object form of the styles property with styles that are assigned per\n * character rather than grouped by range. This format is more verbose, and is\n * only used during runtime (not for serialization/storage)\n * @param {Array} styles the serialized form of a text object's styles\n * @param {String} text the text string that the styles are applied to\n * @return {Object}\n */\nexport const stylesFromArray = (\n styles: TextStyleArray | TextStyle,\n text: string,\n): TextStyle => {\n if (!Array.isArray(styles)) {\n // clone to prevent mutation\n return cloneStyles(styles);\n }\n const textLines = text.split(reNewline),\n stylesObject: TextStyle = {};\n let charIndex = -1,\n styleIndex = 0;\n //loop through each textLine\n for (let i = 0; i < textLines.length; i++) {\n const chars = graphemeSplit(textLines[i]);\n\n //loop through each character of the current line\n for (let c = 0; c < chars.length; c++) {\n charIndex++;\n //check if there's a style collection that includes the current character\n if (\n styles[styleIndex] &&\n styles[styleIndex].start <= charIndex &&\n charIndex < styles[styleIndex].end\n ) {\n //create object for line index if it doesn't exist\n stylesObject[i] = stylesObject[i] || {};\n //assign a style at this character's index\n stylesObject[i][c] = { ...styles[styleIndex].style };\n //if character is at the end of the current style collection, move to the next\n if (charIndex === styles[styleIndex].end - 1) {\n styleIndex++;\n }\n }\n }\n }\n return stylesObject;\n};\n","import { FILL, STROKE } from '../constants';\n\n/**\n * Attributes parsed from all SVG elements\n * @type array\n */\nexport const SHARED_ATTRIBUTES = [\n 'display',\n 'transform',\n FILL,\n 'fill-opacity',\n 'fill-rule',\n 'opacity',\n STROKE,\n 'stroke-dasharray',\n 'stroke-linecap',\n 'stroke-dashoffset',\n 'stroke-linejoin',\n 'stroke-miterlimit',\n 'stroke-opacity',\n 'stroke-width',\n 'id',\n 'paint-order',\n 'vector-effect',\n 'instantiated_by_use',\n 'clip-path',\n];\n","export function selectorMatches(\n element: HTMLElement | SVGElement,\n selector: string,\n) {\n const nodeName = element.nodeName;\n const classNames = element.getAttribute('class');\n const id = element.getAttribute('id');\n const azAz = '(?![a-zA-Z\\\\-]+)';\n let 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 + azAz, 'i');\n selector = selector.replace(matcher, '');\n }\n if (classNames && selector.length) {\n const splitClassNames = classNames.split(' ');\n for (let i = splitClassNames.length; i--; ) {\n matcher = new RegExp('\\\\.' + splitClassNames[i] + azAz, 'i');\n selector = selector.replace(matcher, '');\n }\n }\n return selector.length === 0;\n}\n","import { selectorMatches } from './selectorMatches';\nimport { doesSomeParentMatch } from './doesSomeParentMatch';\n\n/**\n * @private\n */\n\nexport function elementMatchesRule(\n element: HTMLElement | SVGElement,\n selectors: string[],\n) {\n let parentMatching = true;\n // start from rightmost selector.\n const 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","import { selectorMatches } from './selectorMatches';\n\nexport function doesSomeParentMatch(\n element: HTMLElement | SVGElement,\n selectors: string[],\n) {\n let selector: string,\n parentMatching = true;\n while (\n element.parentElement &&\n element.parentElement.nodeType === 1 &&\n selectors.length\n ) {\n if (parentMatching) {\n selector = selectors.pop()!;\n }\n element = element.parentElement;\n parentMatching = selectorMatches(element, selector!);\n }\n return selectors.length === 0;\n}\n","import { elementMatchesRule } from './elementMatchesRule';\nimport type { CSSRules } from './typedefs';\n\n/**\n * @private\n */\n\nexport function getGlobalStylesForElement(\n element: HTMLElement | SVGElement,\n cssRules: CSSRules = {},\n) {\n let styles: Record<string, string> = {};\n for (const rule in cssRules) {\n if (elementMatchesRule(element, rule.split(' '))) {\n styles = {\n ...styles,\n ...cssRules[rule],\n };\n }\n }\n return styles;\n}\n","import { attributesMap } from './constants';\n\nexport const normalizeAttr = (\n attr: keyof typeof attributesMap | string,\n): string => attributesMap[attr as keyof typeof attributesMap] ?? attr;\n","import { reNum } from '../../parser/constants';\nimport { normalizeWs } from './normalizeWhiteSpace';\n\nconst regex = new RegExp(`(${reNum})`, 'gi');\n\nexport const cleanupSvgAttribute = (attributeValue: string) =>\n normalizeWs(\n attributeValue\n .replace(regex, ' $1 ')\n // replace annoying commas and arbitrary whitespace with single spaces\n .replace(/,/gi, ' '),\n );\n","import { ROTATE, SCALE, SKEW_X, SKEW_Y, iMatrix } from '../constants';\nimport { reNum } from './constants';\nimport type { TMat2D } from '../typedefs';\nimport { cleanupSvgAttribute } from '../util/internals/cleanupSvgAttribute';\nimport {\n createRotateMatrix,\n createScaleMatrix,\n createSkewXMatrix,\n createSkewYMatrix,\n createTranslateMatrix,\n multiplyTransformMatrixArray,\n} from '../util/misc/matrix';\n\n// == begin transform regexp\nconst p = `(${reNum})`;\nconst skewX = String.raw`(skewX)\\(${p}\\)`;\nconst skewY = String.raw`(skewY)\\(${p}\\)`;\nconst rotate = String.raw`(rotate)\\(${p}(?: ${p} ${p})?\\)`;\nconst scale = String.raw`(scale)\\(${p}(?: ${p})?\\)`;\nconst translate = String.raw`(translate)\\(${p}(?: ${p})?\\)`;\nconst matrix = String.raw`(matrix)\\(${p} ${p} ${p} ${p} ${p} ${p}\\)`;\nconst transform = `(?:${matrix}|${translate}|${rotate}|${scale}|${skewX}|${skewY})`;\nconst transforms = `(?:${transform}*)`;\nconst transformList = String.raw`^\\s*(?:${transforms}?)\\s*$`;\n// http://www.w3.org/TR/SVG/coords.html#TransformAttribute\nconst reTransformList = new RegExp(transformList);\nconst reTransform = new RegExp(transform);\nconst reTransformAll = new RegExp(transform, 'g');\n// == end transform regexp\n\n/**\n * Parses \"transform\" attribute, returning an array of values\n * @param {String} attributeValue String containing attribute value\n * @return {TTransformMatrix} Array of 6 elements representing transformation matrix\n */\nexport function parseTransformAttribute(attributeValue: string): TMat2D {\n // first we clean the string\n attributeValue = cleanupSvgAttribute(attributeValue)\n // remove spaces around front parentheses\n .replace(/\\s*([()])\\s*/gi, '$1');\n\n // start with identity matrix\n const matrices: TMat2D[] = [];\n\n // return if no argument was given or\n // an argument does not match transform attribute regexp\n if (\n !attributeValue ||\n (attributeValue && !reTransformList.test(attributeValue))\n ) {\n return [...iMatrix];\n }\n\n for (const match of attributeValue.matchAll(reTransformAll)) {\n const transformMatch = reTransform.exec(match[0]);\n if (!transformMatch) {\n continue;\n }\n let matrix: TMat2D = iMatrix;\n const matchedParams = transformMatch.filter((m) => !!m);\n const [, operation, ...rawArgs] = matchedParams;\n const [arg0, arg1, arg2, arg3, arg4, arg5] = rawArgs.map((arg) =>\n parseFloat(arg),\n );\n\n switch (operation) {\n case 'translate':\n matrix = createTranslateMatrix(arg0, arg1);\n break;\n case ROTATE:\n matrix = createRotateMatrix({ angle: arg0 }, { x: arg1, y: arg2 });\n break;\n case SCALE:\n matrix = createScaleMatrix(arg0, arg1);\n break;\n case SKEW_X:\n matrix = createSkewXMatrix(arg0);\n break;\n case SKEW_Y:\n matrix = createSkewYMatrix(arg0);\n break;\n case 'matrix':\n matrix = [arg0, arg1, arg2, arg3, arg4, arg5];\n break;\n }\n\n // snapshot current matrix into matrices array\n matrices.push(matrix);\n }\n\n return multiplyTransformMatrixArray(matrices);\n}\n","import { multiplyTransformMatrices } from '../util/misc/matrix';\nimport { parseUnit } from '../util/misc/svgParsing';\nimport { parseTransformAttribute } from './parseTransformAttribute';\nimport { CENTER, LEFT, RIGHT, NONE, FILL, STROKE } from '../constants';\nimport { TEXT_DECORATION_THICKNESS } from '../shapes/Text/constants';\n\nexport function normalizeValue(\n attr: string,\n value: any,\n parentAttributes: Record<string, any>,\n fontSize: number,\n): string | null | boolean | number[] | number {\n const isArray = Array.isArray(value);\n let parsed: number | number[];\n let ouputValue: string | null | boolean | number[] | number = value;\n if ((attr === FILL || attr === STROKE) && value === NONE) {\n ouputValue = '';\n } else if (attr === 'strokeUniform') {\n return value === 'non-scaling-stroke';\n } else if (attr === 'strokeDashArray') {\n if (value === NONE) {\n ouputValue = null;\n } else {\n ouputValue = value.replace(/,/g, ' ').split(/\\s+/).map(parseFloat);\n }\n } else if (attr === 'transformMatrix') {\n if (parentAttributes && parentAttributes.transformMatrix) {\n ouputValue = multiplyTransformMatrices(\n parentAttributes.transformMatrix,\n parseTransformAttribute(value),\n );\n } else {\n ouputValue = parseTransformAttribute(value);\n }\n } else if (attr === 'visible') {\n ouputValue = value !== NONE && value !== 'hidden';\n // display=none on parent element always takes precedence over child element\n if (parentAttributes && parentAttributes.visible === false) {\n ouputValue = false;\n }\n } else if (attr === 'opacity') {\n ouputValue = parseFloat(value);\n if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {\n ouputValue *= parentAttributes.opacity as number;\n }\n } else if (attr === 'textAnchor' /* text-anchor */) {\n ouputValue = value === 'start' ? LEFT : value === 'end' ? RIGHT : CENTER;\n } else if (attr === 'charSpacing' || attr === TEXT_DECORATION_THICKNESS) {\n // parseUnit returns px and we convert it to em\n parsed = (parseUnit(value, fontSize) / fontSize) * 1000;\n } else if (attr === 'paintFirst') {\n const fillIndex = value.indexOf(FILL);\n const strokeIndex = value.indexOf(STROKE);\n ouputValue = FILL;\n if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {\n ouputValue = STROKE;\n } else if (fillIndex === -1 && strokeIndex > -1) {\n ouputValue = STROKE;\n }\n } else if (\n attr === 'href' ||\n attr === 'xlink:href' ||\n attr === 'font' ||\n attr === 'id'\n ) {\n return value;\n } else if (attr === 'imageSmoothing') {\n return value === 'optimizeQuality';\n } else {\n parsed = isArray\n ? (value as string[]).map(parseUnit)\n : parseUnit(value, fontSize);\n }\n\n return !isArray && isNaN(parsed! as number) ? ouputValue : parsed!;\n}\n","/**\n * Takes a style string and parses it in one that has only defined values\n * and lowercases properties\n * @param style\n * @param oStyle\n */\nexport function parseStyleString(\n style: string,\n oStyle: Record<string, any>,\n): void {\n style\n .replace(/;\\s*$/, '')\n .split(';')\n .forEach((chunk) => {\n if (!chunk) return;\n const [attr, value] = chunk.split(':');\n oStyle[attr.trim().toLowerCase()] = value.trim();\n });\n}\n","import { parseStyleObject } from './parseStyleObject';\nimport { parseStyleString } from './parseStyleString';\n\n/**\n * Parses \"style\" attribute, retuning an object with values\n * @param {SVGElement} element Element to parse\n * @return {Object} Objects with values parsed from style attribute of an element\n */\nexport function parseStyleAttribute(\n element: HTMLElement | SVGElement,\n): Record<string, any> {\n const oStyle: Record<string, any> = {},\n style = element.getAttribute('style');\n\n if (!style) {\n return oStyle;\n }\n\n if (typeof style === 'string') {\n parseStyleString(style, oStyle);\n } else {\n parseStyleObject(style, oStyle);\n }\n\n return oStyle;\n}\n","/**\n * Takes a style object and parses it in one that has only defined values\n * and lowercases properties\n * @param style\n * @param oStyle\n */\nexport function parseStyleObject(\n style: Record<string, any>,\n oStyle: Record<string, any>,\n): void {\n Object.entries(style).forEach(([prop, value]) => {\n if (value === undefined) {\n return;\n }\n oStyle[prop.toLowerCase()] = value;\n });\n}\n","import { Color } from '../color/Color';\nimport { toFixed } from '../util/misc/toFixed';\nimport { FabricObject } from '../shapes/Object/FabricObject';\n\nconst colorAttributesMap = {\n stroke: 'strokeOpacity',\n fill: 'fillOpacity',\n};\n\n/**\n * @private\n * @param {Object} attributes Array of attributes to parse\n */\n\nexport function setStrokeFillOpacity(\n attributes: Record<string, any>,\n): Record<string, any> {\n const defaults = FabricObject.getDefaults();\n Object.entries(colorAttributesMap).forEach(([attr, colorAttr]) => {\n if (\n typeof attributes[colorAttr] === 'undefined' ||\n attributes[attr] === ''\n ) {\n return;\n }\n if (typeof attributes[attr] === 'undefined') {\n if (!defaults[attr]) {\n return;\n }\n attributes[attr] = defaults[attr];\n }\n if (attributes[attr].indexOf('url(') === 0) {\n return;\n }\n const color = new Color(attributes[attr]);\n attributes[attr] = color\n .setAlpha(toFixed(color.getAlpha() * attributes[colorAttr], 2))\n .toRgba();\n });\n return attributes;\n}\n","import { DEFAULT_SVG_FONT_SIZE } from '../constants';\nimport { parseUnit } from '../util/misc/svgParsing';\nimport { cPath, fSize, svgValidParentsRegEx } from './constants';\nimport { getGlobalStylesForElement } from './getGlobalStylesForElement';\nimport { normalizeAttr } from './normalizeAttr';\nimport { normalizeValue } from './normalizeValue';\nimport { parseFontDeclaration } from './parseFontDeclaration';\nimport { parseStyleAttribute } from './parseStyleAttribute';\nimport { setStrokeFillOpacity } from './setStrokeFillOpacity';\nimport type { CSSRules } from './typedefs';\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 * @param {SVGElement | HTMLElement} element Element to parse\n * @param {Array} attributes Array of attributes to parse\n * @return {Object} object containing parsed attributes' names/values\n */\nexport function parseAttributes(\n element: HTMLElement | SVGElement | null,\n attributes: string[],\n cssRules?: CSSRules,\n): Record<string, any> {\n if (!element) {\n return {};\n }\n\n let parentAttributes: Record<string, string> = {},\n fontSize: number,\n parentFontSize = DEFAULT_SVG_FONT_SIZE;\n\n // if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards\n if (\n element.parentNode &&\n svgValidParentsRegEx.test(element.parentNode.nodeName)\n ) {\n parentAttributes = parseAttributes(\n element.parentElement,\n attributes,\n cssRules,\n );\n if (parentAttributes.fontSize) {\n fontSize = parentFontSize = parseUnit(parentAttributes.fontSize);\n }\n }\n\n const ownAttributes: Record<string, string> = {\n ...attributes.reduce<Record<string, string>>((memo, attr) => {\n const value = element.getAttribute(attr);\n if (value) {\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 ...getGlobalStylesForElement(element, cssRules),\n ...parseStyleAttribute(element),\n };\n\n if (ownAttributes[cPath]) {\n element.setAttribute(cPath, ownAttributes[cPath]);\n }\n if (ownAttributes[fSize]) {\n // looks like the minimum should be 9px when dealing with ems. this is what looks like in browsers.\n fontSize = parseUnit(ownAttributes[fSize], parentFontSize);\n ownAttributes[fSize] = `${fontSize}`;\n }\n\n // this should have its own complex type\n const normalizedStyle: Record<\n string,\n string | boolean | number | number[] | null\n > = {};\n for (const attr in ownAttributes) {\n const normalizedAttr = normalizeAttr(attr);\n const normalizedValue = normalizeValue(\n normalizedAttr,\n ownAttributes[attr],\n parentAttributes,\n fontSize!,\n );\n normalizedStyle[normalizedAttr] = normalizedValue;\n }\n if (normalizedStyle && normalizedStyle.font) {\n parseFontDeclaration(normalizedStyle.font as string, normalizedStyle);\n }\n const mergedAttrs = { ...parentAttributes, ...normalizedStyle };\n return svgValidParentsRegEx.test(element.nodeName)\n ? mergedAttrs\n : setStrokeFillOpacity(mergedAttrs);\n}\n","import { NORMAL } from '../constants';\nimport { parseUnit } from '../util/misc/svgParsing';\nimport { reFontDeclaration } from './constants';\n\n/**\n * Parses a short font declaration, building adding its properties to a style object\n * @param {String} value font declaration\n * @param {Object} oStyle definition\n */\nexport function parseFontDeclaration(\n value: string,\n oStyle: Record<string, any>,\n): void {\n const match = value.match(reFontDeclaration);\n\n if (!match) {\n return;\n }\n const 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))\n ? fontWeight\n : 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","import { kRect } from '../constants';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport type { CSSRules } from '../parser/typedefs';\n\nexport const rectDefaultValues: Partial<TClassProperties<Rect>> = {\n rx: 0,\n ry: 0,\n};\n\ninterface UniqueRectProps {\n rx: number;\n ry: number;\n}\n\nexport interface SerializedRectProps\n extends SerializedObjectProps,\n UniqueRectProps {}\n\nexport interface RectProps extends FabricObjectProps, UniqueRectProps {}\n\nconst RECT_PROPS = ['rx', 'ry'] as const;\n\nexport class Rect<\n Props extends TOptions<RectProps> = Partial<RectProps>,\n SProps extends SerializedRectProps = SerializedRectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements RectProps\n{\n /**\n * Horizontal border radius\n * @type Number\n */\n declare rx: number;\n\n /**\n * Vertical border radius\n * @type Number\n */\n declare ry: number;\n\n static type = 'Rect';\n\n static cacheProperties = [...cacheProperties, ...RECT_PROPS];\n\n static ownDefaults = rectDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Rect.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(this, Rect.ownDefaults);\n this.setOptions(options);\n this._initRxRy();\n }\n /**\n * Initializes rx/ry attributes\n * @private\n */\n _initRxRy() {\n const { rx, ry } = this;\n if (rx && !ry) {\n this.ry = rx;\n } else if (ry && !rx) {\n this.rx = ry;\n }\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n const { width: w, height: h } = this;\n const x = -w / 2;\n const y = -h / 2;\n const rx = this.rx ? Math.min(this.rx, w / 2) : 0;\n const ry = this.ry ? Math.min(this.ry, h / 2) : 0;\n const isRounded = rx !== 0 || ry !== 0;\n\n ctx.beginPath();\n\n ctx.moveTo(x + rx, y);\n\n ctx.lineTo(x + w - rx, y);\n isRounded &&\n ctx.bezierCurveTo(\n x + w - kRect * rx,\n y,\n x + w,\n y + kRect * ry,\n x + w,\n y + ry,\n );\n\n ctx.lineTo(x + w, y + h - ry);\n isRounded &&\n ctx.bezierCurveTo(\n x + w,\n y + h - kRect * ry,\n x + w - kRect * rx,\n y + h,\n x + w - rx,\n y + h,\n );\n\n ctx.lineTo(x + rx, y + h);\n isRounded &&\n ctx.bezierCurveTo(\n x + kRect * rx,\n y + h,\n x,\n y + h - kRect * ry,\n x,\n y + h - ry,\n );\n\n ctx.lineTo(x, y + ry);\n isRounded &&\n ctx.bezierCurveTo(x, y + kRect * ry, x + kRect * rx, y, x + rx, y);\n\n ctx.closePath();\n\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject([...RECT_PROPS, ...propertiesToInclude]);\n }\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const { width, height, rx, ry } = this;\n return [\n '<rect ',\n 'COMMON_PARTS',\n `x=\"${-width / 2}\" y=\"${\n -height / 2\n }\" rx=\"${rx}\" ry=\"${ry}\" width=\"${width}\" height=\"${height}\" />\\n`,\n ];\n }\n\n /**\n * List of attribute names to account for when parsing SVG element (used by `Rect.fromElement`)\n * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement\n */\n static ATTRIBUTE_NAMES = [\n ...SHARED_ATTRIBUTES,\n 'x',\n 'y',\n 'rx',\n 'ry',\n 'width',\n 'height',\n ];\n\n /* _FROM_SVG_START_ */\n\n /**\n * Returns {@link Rect} instance from an SVG element\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement | SVGElement,\n options?: Abortable,\n cssRules?: CSSRules,\n ) {\n const {\n left = 0,\n top = 0,\n width = 0,\n height = 0,\n visible = true,\n ...restOfparsedAttributes\n } = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);\n\n return new this({\n ...options,\n ...restOfparsedAttributes,\n left,\n top,\n width,\n height,\n visible: Boolean(visible && width && height),\n });\n }\n\n /* _FROM_SVG_END_ */\n}\n\nclassRegistry.setClass(Rect);\nclassRegistry.setSVGClass(Rect);\n","export const LAYOUT_TYPE_INITIALIZATION = 'initialization';\nexport const LAYOUT_TYPE_ADDED = 'added';\nexport const LAYOUT_TYPE_REMOVED = 'removed';\nexport const LAYOUT_TYPE_IMPERATIVE = 'imperative';\nexport const LAYOUT_TYPE_OBJECT_MODIFIED = 'object_modified';\nexport const LAYOUT_TYPE_OBJECT_MODIFYING = 'object_modifying';\n","import { Point, ZERO } from '../../Point';\nimport type { Group } from '../../shapes/Group';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { multiplyTransformMatrixArray } from '../../util/misc/matrix';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport {\n calcPlaneChangeMatrix,\n sendVectorToPlane,\n} from '../../util/misc/planeChange';\n\n/**\n * @returns 2 points, the tl and br corners of the non rotated bounding box of an object\n * in the {@link group} plane, taking into account objects that {@link group} is their parent\n * but also belong to the active selection.\n */\nexport const getObjectBounds = (\n destinationGroup: Group,\n object: FabricObject,\n): Point[] => {\n const {\n strokeUniform,\n strokeWidth,\n width,\n height,\n group: currentGroup,\n } = object;\n const t =\n currentGroup && currentGroup !== destinationGroup\n ? calcPlaneChangeMatrix(\n currentGroup.calcTransformMatrix(),\n destinationGroup.calcTransformMatrix(),\n )\n : null;\n const objectCenter = t\n ? object.getRelativeCenterPoint().transform(t)\n : object.getRelativeCenterPoint();\n const accountForStroke = !object['isStrokeAccountedForInDimensions']();\n const strokeUniformVector =\n strokeUniform && accountForStroke\n ? sendVectorToPlane(\n new Point(strokeWidth, strokeWidth),\n undefined,\n destinationGroup.calcTransformMatrix(),\n )\n : ZERO;\n const scalingStrokeWidth =\n !strokeUniform && accountForStroke ? strokeWidth : 0;\n const sizeVector = sizeAfterTransform(\n width + scalingStrokeWidth,\n height + scalingStrokeWidth,\n multiplyTransformMatrixArray([t, object.calcOwnMatrix()], true),\n )\n .add(strokeUniformVector)\n .scalarDivide(2);\n return [objectCenter.subtract(sizeVector), objectCenter.add(sizeVector)];\n};\n","import { Point } from '../../Point';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { makeBoundingBoxFromPoints } from '../../util/misc/boundingBoxFromPoints';\nimport {\n LAYOUT_TYPE_INITIALIZATION,\n LAYOUT_TYPE_IMPERATIVE,\n} from '../constants';\nimport type {\n InitializationLayoutContext,\n LayoutStrategyResult,\n StrictLayoutContext,\n} from '../types';\nimport { getObjectBounds } from './utils';\n\n/**\n * Exposes a main public method {@link calcLayoutResult} that is used by the `LayoutManager` to perform layout.\n * Returning `undefined` signals the `LayoutManager` to skip the layout.\n *\n * In charge of calculating the bounding box of the passed objects.\n */\nexport abstract class LayoutStrategy {\n /**\n * override by subclass for persistence (TS does not support `static abstract`)\n */\n static type = 'strategy';\n\n /**\n * Used by the `LayoutManager` to perform layout\n * @TODO/fix: if this method is calcResult, should calc unconditionally.\n * the condition to not calc should be evaluated by the layoutManager.\n * @returns layout result **OR** `undefined` to skip layout\n */\n public calcLayoutResult(\n context: StrictLayoutContext,\n objects: FabricObject[],\n ): LayoutStrategyResult | undefined {\n if (this.shouldPerformLayout(context)) {\n return this.calcBoundingBox(objects, context);\n }\n }\n\n shouldPerformLayout({ type, prevStrategy, strategy }: StrictLayoutContext) {\n return (\n type === LAYOUT_TYPE_INITIALIZATION ||\n type === LAYOUT_TYPE_IMPERATIVE ||\n (!!prevStrategy && strategy !== prevStrategy)\n );\n }\n\n shouldLayoutClipPath({ type, target: { clipPath } }: StrictLayoutContext) {\n return (\n type !== LAYOUT_TYPE_INITIALIZATION &&\n clipPath &&\n !clipPath.absolutePositioned\n );\n }\n\n getInitialSize(\n context: StrictLayoutContext & InitializationLayoutContext,\n result: Pick<LayoutStrategyResult, 'center' | 'size'>,\n ) {\n return result.size;\n }\n\n /**\n * Override this method to customize layout.\n */\n calcBoundingBox(\n objects: FabricObject[],\n context: StrictLayoutContext,\n ): LayoutStrategyResult | undefined {\n const { type, target } = context;\n if (type === LAYOUT_TYPE_IMPERATIVE && context.overrides) {\n return context.overrides;\n }\n if (objects.length === 0) {\n return;\n }\n const { left, top, width, height } = makeBoundingBoxFromPoints(\n objects\n .map((object) => getObjectBounds(target, object))\n .reduce<Point[]>((coords, curr) => coords.concat(curr), []),\n );\n const bboxSize = new Point(width, height);\n const bboxLeftTop = new Point(left, top);\n const bboxCenter = bboxLeftTop.add(bboxSize.scalarDivide(2));\n\n if (type === LAYOUT_TYPE_INITIALIZATION) {\n const actualSize = this.getInitialSize(context, {\n size: bboxSize,\n center: bboxCenter,\n });\n return {\n // in `initialization` we do not account for target's transformation matrix\n center: bboxCenter,\n // TODO: investigate if this is still necessary\n relativeCorrection: new Point(0, 0),\n size: actualSize,\n };\n } else {\n // we send `relativeCenter` up to group's containing plane\n const center = bboxCenter.transform(target.calcOwnMatrix());\n return {\n center,\n size: bboxSize,\n };\n }\n }\n}\n","import type { StrictLayoutContext } from '../types';\nimport { LayoutStrategy } from './LayoutStrategy';\nimport { classRegistry } from '../../ClassRegistry';\n\n/**\n * Layout will adjust the bounding box to fit target's objects.\n */\nexport class FitContentLayout extends LayoutStrategy {\n static readonly type = 'fit-content';\n\n /**\n * @override layout on all triggers\n * Override at will\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n shouldPerformLayout(context: StrictLayoutContext) {\n return true;\n }\n}\n\nclassRegistry.setClass(FitContentLayout);\n","import { Point } from '../Point';\nimport {\n CENTER,\n CHANGED,\n MODIFIED,\n MODIFY_PATH,\n MODIFY_POLY,\n MOVING,\n RESIZING,\n ROTATING,\n SCALING,\n SKEWING,\n iMatrix,\n} from '../constants';\nimport type { Group } from '../shapes/Group';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport { invertTransform } from '../util/misc/matrix';\nimport { resolveOrigin } from '../util/misc/resolveOrigin';\nimport { FitContentLayout } from './LayoutStrategies/FitContentLayout';\nimport type { LayoutStrategy } from './LayoutStrategies/LayoutStrategy';\nimport {\n LAYOUT_TYPE_INITIALIZATION,\n LAYOUT_TYPE_ADDED,\n LAYOUT_TYPE_REMOVED,\n LAYOUT_TYPE_IMPERATIVE,\n LAYOUT_TYPE_OBJECT_MODIFIED,\n LAYOUT_TYPE_OBJECT_MODIFYING,\n} from './constants';\nimport type {\n LayoutContext,\n LayoutResult,\n RegistrationContext,\n StrictLayoutContext,\n} from './types';\nimport { classRegistry } from '../ClassRegistry';\nimport type { TModificationEvents } from '../EventTypeDefs';\n\nconst LAYOUT_MANAGER = 'layoutManager';\n\nexport type SerializedLayoutManager = {\n type: string;\n strategy: string;\n};\n\nexport class LayoutManager {\n declare private _prevLayoutStrategy?: LayoutStrategy;\n declare protected _subscriptions: Map<FabricObject, VoidFunction[]>;\n\n strategy: LayoutStrategy;\n\n constructor(strategy: LayoutStrategy = new FitContentLayout()) {\n this.strategy = strategy;\n this._subscriptions = new Map();\n }\n\n public performLayout(context: LayoutContext) {\n const strictContext: StrictLayoutContext = {\n bubbles: true,\n strategy: this.strategy,\n ...context,\n prevStrategy: this._prevLayoutStrategy,\n stopPropagation() {\n this.bubbles = false;\n },\n };\n\n this.onBeforeLayout(strictContext);\n\n const layoutResult = this.getLayoutResult(strictContext);\n if (layoutResult) {\n this.commitLayout(strictContext, layoutResult);\n }\n\n this.onAfterLayout(strictContext, layoutResult);\n this._prevLayoutStrategy = strictContext.strategy;\n }\n\n /**\n * Attach handlers for events that we know will invalidate the layout when\n * performed on child objects ( general transforms ).\n * Returns the disposers for later unsubscribing and cleanup\n * @param {FabricObject} object\n * @param {RegistrationContext & Partial<StrictLayoutContext>} context\n * @returns {VoidFunction[]} disposers remove the handlers\n */\n protected attachHandlers(\n object: FabricObject,\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ): VoidFunction[] {\n const { target } = context;\n return (\n [\n MODIFIED,\n MOVING,\n RESIZING,\n ROTATING,\n SCALING,\n SKEWING,\n CHANGED,\n MODIFY_POLY,\n MODIFY_PATH,\n ] as (TModificationEvents & 'modified')[]\n ).map((key) =>\n object.on(key, (e) =>\n this.performLayout(\n key === MODIFIED\n ? {\n type: LAYOUT_TYPE_OBJECT_MODIFIED,\n trigger: key,\n e,\n target,\n }\n : {\n type: LAYOUT_TYPE_OBJECT_MODIFYING,\n trigger: key,\n e,\n target,\n },\n ),\n ),\n );\n }\n\n /**\n * Subscribe an object to transform events that will trigger a layout change on the parent\n * This is important only for interactive groups.\n * @param object\n * @param context\n */\n protected subscribe(\n object: FabricObject,\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ) {\n this.unsubscribe(object, context);\n const disposers = this.attachHandlers(object, context);\n this._subscriptions.set(object, disposers);\n }\n\n /**\n * unsubscribe object layout triggers\n */\n protected unsubscribe(\n object: FabricObject,\n _context?: RegistrationContext & Partial<StrictLayoutContext>,\n ) {\n (this._subscriptions.get(object) || []).forEach((d) => d());\n this._subscriptions.delete(object);\n }\n\n unsubscribeTargets(\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ) {\n context.targets.forEach((object) => this.unsubscribe(object, context));\n }\n\n subscribeTargets(\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ) {\n context.targets.forEach((object) => this.subscribe(object, context));\n }\n\n protected onBeforeLayout(context: StrictLayoutContext) {\n const { target, type } = context;\n const { canvas } = target;\n // handle layout triggers subscription\n // @TODO: gate the registration when the group is interactive\n if (type === LAYOUT_TYPE_INITIALIZATION || type === LAYOUT_TYPE_ADDED) {\n this.subscribeTargets(context);\n } else if (type === LAYOUT_TYPE_REMOVED) {\n this.unsubscribeTargets(context);\n }\n // fire layout event (event will fire only for layouts after initialization layout)\n target.fire('layout:before', {\n context,\n });\n canvas &&\n canvas.fire('object:layout:before', {\n target,\n context,\n });\n\n if (type === LAYOUT_TYPE_IMPERATIVE && context.deep) {\n const { strategy: _, ...tricklingContext } = context;\n // traverse the tree\n target.forEachObject(\n (object) =>\n (object as Group).layoutManager &&\n (object as Group).layoutManager.performLayout({\n ...tricklingContext,\n bubbles: false,\n target: object as Group,\n }),\n );\n }\n }\n\n protected getLayoutResult(\n context: StrictLayoutContext,\n ): Required<LayoutResult> | undefined {\n const { target, strategy, type } = context;\n\n const result = strategy.calcLayoutResult(context, target.getObjects());\n\n if (!result) {\n return;\n }\n\n const prevCenter =\n type === LAYOUT_TYPE_INITIALIZATION\n ? new Point()\n : target.getRelativeCenterPoint();\n\n const {\n center: nextCenter,\n correction = new Point(),\n relativeCorrection = new Point(),\n } = result;\n const offset = prevCenter\n .subtract(nextCenter)\n .add(correction)\n .transform(\n // in `initialization` we do not account for target's transformation matrix\n type === LAYOUT_TYPE_INITIALIZATION\n ? iMatrix\n : invertTransform(target.calcOwnMatrix()),\n true,\n )\n .add(relativeCorrection);\n\n return {\n result,\n prevCenter,\n nextCenter,\n offset,\n };\n }\n\n protected commitLayout(\n context: StrictLayoutContext,\n layoutResult: Required<LayoutResult>,\n ) {\n const { target } = context;\n const {\n result: { size },\n nextCenter,\n } = layoutResult;\n // set dimensions\n target.set({ width: size.x, height: size.y });\n // layout descendants\n this.layoutObjects(context, layoutResult);\n // set position\n // in `initialization` we do not account for target's transformation matrix\n if (context.type === LAYOUT_TYPE_INITIALIZATION) {\n // TODO: what about strokeWidth?\n target.set({\n left:\n context.x ?? nextCenter.x + size.x * resolveOrigin(target.originX),\n top: context.y ?? nextCenter.y + size.y * resolveOrigin(target.originY),\n });\n } else {\n target.setPositionByOrigin(nextCenter, CENTER, CENTER);\n // invalidate\n target.setCoords();\n target.set('dirty', true);\n }\n }\n\n protected layoutObjects(\n context: StrictLayoutContext,\n layoutResult: Required<LayoutResult>,\n ) {\n const { target } = context;\n // adjust objects to account for new center\n target.forEachObject((object) => {\n object.group === target &&\n this.layoutObject(context, layoutResult, object);\n });\n // adjust clip path to account for new center\n context.strategy.shouldLayoutClipPath(context) &&\n this.layoutObject(context, layoutResult, target.clipPath as FabricObject);\n }\n\n /**\n * @param {FabricObject} object\n * @param {Point} offset\n */\n protected layoutObject(\n context: StrictLayoutContext,\n { offset }: Required<LayoutResult>,\n object: FabricObject,\n ) {\n // TODO: this is here for cache invalidation.\n // verify if this is necessary since we have explicit\n // cache invalidation at the end of commitLayout\n object.set({\n left: object.left + offset.x,\n top: object.top + offset.y,\n });\n }\n\n protected onAfterLayout(\n context: StrictLayoutContext,\n layoutResult?: LayoutResult,\n ) {\n const {\n target,\n strategy,\n bubbles,\n prevStrategy: _,\n ...bubblingContext\n } = context;\n const { canvas } = target;\n\n // fire layout event (event will fire only for layouts after initialization layout)\n target.fire('layout:after', {\n context,\n result: layoutResult,\n });\n canvas &&\n canvas.fire('object:layout:after', {\n context,\n result: layoutResult,\n target,\n });\n\n // bubble\n const parent = target.parent;\n if (bubbles && parent?.layoutManager) {\n // add target to context#path\n (bubblingContext.path || (bubblingContext.path = [])).push(target);\n // all parents should invalidate their layout\n parent.layoutManager.performLayout({\n ...bubblingContext,\n target: parent,\n });\n }\n target.set('dirty', true);\n }\n\n dispose() {\n const { _subscriptions } = this;\n _subscriptions.forEach((disposers) => disposers.forEach((d) => d()));\n _subscriptions.clear();\n }\n\n toObject() {\n return {\n type: LAYOUT_MANAGER,\n strategy: (this.strategy.constructor as typeof LayoutStrategy).type,\n };\n }\n\n toJSON() {\n return this.toObject();\n }\n}\n\nclassRegistry.setClass(LayoutManager, LAYOUT_MANAGER);\n","import type { CollectionEvents, ObjectEvents } from '../EventTypeDefs';\nimport { createCollectionMixin } from '../Collection';\nimport type {\n TClassProperties,\n TSVGReviver,\n TOptions,\n Abortable,\n} from '../typedefs';\nimport {\n invertTransform,\n multiplyTransformMatrices,\n} from '../util/misc/matrix';\nimport {\n enlivenObjectEnlivables,\n enlivenObjects,\n} from '../util/misc/objectEnlive';\nimport { applyTransformToObject } from '../util/misc/objectTransforms';\nimport { FabricObject } from './Object/FabricObject';\nimport { Rect } from './Rect';\nimport { classRegistry } from '../ClassRegistry';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport { log } from '../util/internals/console';\nimport type {\n ImperativeLayoutOptions,\n LayoutBeforeEvent,\n LayoutAfterEvent,\n} from '../LayoutManager/types';\nimport { LayoutManager } from '../LayoutManager/LayoutManager';\nimport {\n LAYOUT_TYPE_ADDED,\n LAYOUT_TYPE_IMPERATIVE,\n LAYOUT_TYPE_INITIALIZATION,\n LAYOUT_TYPE_REMOVED,\n} from '../LayoutManager/constants';\nimport type { SerializedLayoutManager } from '../LayoutManager/LayoutManager';\nimport type { FitContentLayout } from '../LayoutManager';\nimport type { DrawContext } from './Object/Object';\n\n/**\n * This class handles the specific case of creating a group using {@link Group#fromObject} and is not meant to be used in any other case.\n * We could have used a boolean in the constructor, as we did previously, but we think the boolean\n * would stay in the group's constructor interface and create confusion, therefore it was removed.\n * This layout manager doesn't do anything and therefore keeps the exact layout the group had when {@link Group#toObject} was called.\n */\nclass NoopLayoutManager extends LayoutManager {\n performLayout() {}\n}\n\nexport interface GroupEvents extends ObjectEvents, CollectionEvents {\n 'layout:before': LayoutBeforeEvent;\n 'layout:after': LayoutAfterEvent;\n}\n\nexport interface GroupOwnProps {\n subTargetCheck: boolean;\n interactive: boolean;\n}\n\nexport interface SerializedGroupProps\n extends SerializedObjectProps,\n GroupOwnProps {\n objects: SerializedObjectProps[];\n layoutManager: SerializedLayoutManager;\n}\n\nexport interface GroupProps extends FabricObjectProps, GroupOwnProps {\n layoutManager: LayoutManager;\n}\n\nexport const groupDefaultValues: Partial<TClassProperties<Group>> = {\n strokeWidth: 0,\n subTargetCheck: false,\n interactive: false,\n};\n\n/**\n * @fires object:added\n * @fires object:removed\n * @fires layout:before\n * @fires layout:after\n */\nexport class Group\n extends createCollectionMixin(\n FabricObject<GroupProps, SerializedGroupProps, GroupEvents>,\n )\n implements GroupProps\n{\n /**\n * Used to optimize performance\n * set to `false` if you don't need contained objects to be targets of events\n * @type boolean\n */\n declare subTargetCheck: boolean;\n\n /**\n * Used to allow targeting of object inside groups.\n * set to true if you want to select an object inside a group.\\\n * **REQUIRES** `subTargetCheck` set to true\n * This will be not removed but slowly replaced with a method setInteractive\n * that will take care of enabling subTargetCheck and necessary object events.\n * There is too much attached to group interactivity to just be evaluated by a\n * boolean in the code\n * @deprecated\n * @type boolean\n */\n declare interactive: boolean;\n\n declare layoutManager: LayoutManager;\n\n /**\n * Used internally to optimize performance\n * Once an object is selected, instance is rendered without the selected object.\n * This way instance is cached only once for the entire interaction with the selected object.\n * @private\n */\n protected _activeObjects: FabricObject[] = [];\n\n static type = 'Group';\n\n static ownDefaults: Record<string, any> = groupDefaultValues;\n private __objectSelectionTracker: (ev: ObjectEvents['selected']) => void;\n private __objectSelectionDisposer: (ev: ObjectEvents['deselected']) => void;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Group.ownDefaults,\n };\n }\n\n /**\n * Constructor\n *\n * @param {FabricObject[]} [objects] instance objects\n * @param {Object} [options] Options object\n */\n constructor(objects: FabricObject[] = [], options: Partial<GroupProps> = {}) {\n super();\n Object.assign(this, Group.ownDefaults);\n this.setOptions(options);\n this.groupInit(objects, options);\n }\n\n /**\n * Shared code between group and active selection\n * Meant to be used by the constructor.\n */\n protected groupInit(\n objects: FabricObject[],\n options: {\n layoutManager?: LayoutManager;\n top?: number;\n left?: number;\n },\n ) {\n this._objects = [...objects]; // Avoid unwanted mutations of Collection to affect the caller\n\n this.__objectSelectionTracker = this.__objectSelectionMonitor.bind(\n this,\n true,\n );\n this.__objectSelectionDisposer = this.__objectSelectionMonitor.bind(\n this,\n false,\n );\n\n this.forEachObject((object) => {\n this.enterGroup(object, false);\n });\n\n // perform initial layout\n this.layoutManager = options.layoutManager ?? new LayoutManager();\n this.layoutManager.performLayout({\n type: LAYOUT_TYPE_INITIALIZATION,\n target: this,\n targets: [...objects],\n // @TODO remove this concept from the layout manager.\n // Layout manager will calculate the correct position,\n // group options can override it later.\n x: options.left,\n y: options.top,\n });\n }\n\n /**\n * Checks if object can enter group and logs relevant warnings\n * @private\n * @param {FabricObject} object\n * @returns\n */\n canEnterGroup(object: FabricObject) {\n if (object === this || this.isDescendantOf(object)) {\n // prevent circular object tree\n log(\n 'error',\n 'Group: circular object trees are not supported, this call has no effect',\n );\n return false;\n } else if (this._objects.indexOf(object) !== -1) {\n // is already in the objects array\n log(\n 'error',\n 'Group: duplicate objects are not supported inside group, this call has no effect',\n );\n return false;\n }\n return true;\n }\n\n /**\n * Override this method to enhance performance (for groups with a lot of objects).\n * If Overriding, be sure not pass illegal objects to group - it will break your app.\n * @private\n */\n protected _filterObjectsBeforeEnteringGroup(objects: FabricObject[]) {\n return objects.filter((object, index, array) => {\n // can enter AND is the first occurrence of the object in the passed args (to prevent adding duplicates)\n return this.canEnterGroup(object) && array.indexOf(object) === index;\n });\n }\n\n /**\n * Add objects\n * @param {...FabricObject[]} objects\n */\n add(...objects: FabricObject[]) {\n const allowedObjects = this._filterObjectsBeforeEnteringGroup(objects);\n const size = super.add(...allowedObjects);\n this._onAfterObjectsChange(LAYOUT_TYPE_ADDED, allowedObjects);\n return size;\n }\n\n /**\n * Inserts an object into collection at specified index\n * @param {FabricObject[]} objects Object to insert\n * @param {Number} index Index to insert object at\n */\n insertAt(index: number, ...objects: FabricObject[]) {\n const allowedObjects = this._filterObjectsBeforeEnteringGroup(objects);\n const size = super.insertAt(index, ...allowedObjects);\n this._onAfterObjectsChange(LAYOUT_TYPE_ADDED, allowedObjects);\n return size;\n }\n\n /**\n * Remove objects\n * @param {...FabricObject[]} objects\n * @returns {FabricObject[]} removed objects\n */\n remove(...objects: FabricObject[]) {\n const removed = super.remove(...objects);\n this._onAfterObjectsChange(LAYOUT_TYPE_REMOVED, removed);\n return removed;\n }\n\n _onObjectAdded(object: FabricObject) {\n this.enterGroup(object, true);\n this.fire('object:added', { target: object });\n object.fire('added', { target: this });\n }\n\n /**\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object should exit group without applying group's transform to it\n */\n _onObjectRemoved(object: FabricObject, removeParentTransform?: boolean) {\n this.exitGroup(object, removeParentTransform);\n this.fire('object:removed', { target: object });\n object.fire('removed', { target: this });\n }\n\n /**\n * @private\n * @param {'added'|'removed'} type\n * @param {FabricObject[]} targets\n */\n _onAfterObjectsChange(type: 'added' | 'removed', targets: FabricObject[]) {\n this.layoutManager.performLayout({\n type,\n targets,\n target: this,\n });\n }\n\n _onStackOrderChanged() {\n this._set('dirty', true);\n }\n\n /**\n * @private\n * @param {string} key\n * @param {*} value\n */\n _set(key: string, value: any) {\n const prev = this[key as keyof this];\n super._set(key, value);\n if (key === 'canvas' && prev !== value) {\n (this._objects || []).forEach((object) => {\n object._set(key, value);\n });\n }\n return this;\n }\n\n /**\n * @private\n */\n _shouldSetNestedCoords() {\n return this.subTargetCheck;\n }\n\n /**\n * Remove all objects\n * @returns {FabricObject[]} removed objects\n */\n removeAll() {\n this._activeObjects = [];\n return this.remove(...this._objects);\n }\n\n /**\n * keeps track of the selected objects\n * @private\n */\n __objectSelectionMonitor<T extends boolean>(\n selected: T,\n {\n target: object,\n }: ObjectEvents[T extends true ? 'selected' : 'deselected'],\n ) {\n const activeObjects = this._activeObjects;\n if (selected) {\n activeObjects.push(object);\n this._set('dirty', true);\n } else if (activeObjects.length > 0) {\n const index = activeObjects.indexOf(object);\n if (index > -1) {\n activeObjects.splice(index, 1);\n this._set('dirty', true);\n }\n }\n }\n\n /**\n * @private\n * @param {boolean} watch\n * @param {FabricObject} object\n */\n _watchObject(watch: boolean, object: FabricObject) {\n // make sure we listen only once\n watch && this._watchObject(false, object);\n if (watch) {\n object.on('selected', this.__objectSelectionTracker);\n object.on('deselected', this.__objectSelectionDisposer);\n } else {\n object.off('selected', this.__objectSelectionTracker);\n object.off('deselected', this.__objectSelectionDisposer);\n }\n }\n\n /**\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object is in canvas coordinate plane\n */\n enterGroup(object: FabricObject, removeParentTransform?: boolean) {\n object.group && object.group.remove(object);\n object._set('parent', this);\n this._enterGroup(object, removeParentTransform);\n }\n\n /**\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object is in canvas coordinate plane\n */\n _enterGroup(object: FabricObject, removeParentTransform?: boolean) {\n if (removeParentTransform) {\n // can this be converted to utils (sendObjectToPlane)?\n applyTransformToObject(\n object,\n multiplyTransformMatrices(\n invertTransform(this.calcTransformMatrix()),\n object.calcTransformMatrix(),\n ),\n );\n }\n this._shouldSetNestedCoords() && object.setCoords();\n object._set('group', this);\n object._set('canvas', this.canvas);\n this._watchObject(true, object);\n const activeObject =\n this.canvas &&\n this.canvas.getActiveObject &&\n this.canvas.getActiveObject();\n // if we are adding the activeObject in a group\n if (\n activeObject &&\n (activeObject === object || object.isDescendantOf(activeObject))\n ) {\n this._activeObjects.push(object);\n }\n }\n\n /**\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object should exit group without applying group's transform to it\n */\n exitGroup(object: FabricObject, removeParentTransform?: boolean) {\n this._exitGroup(object, removeParentTransform);\n object._set('parent', undefined);\n object._set('canvas', undefined);\n }\n\n /**\n * Executes the inner fabric logic of exiting a group.\n * - Stop watching the object\n * - Remove the object from the optimization map this._activeObjects\n * - unset the group property of the object\n * @protected\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object should exit group without applying group's transform to it\n */\n _exitGroup(object: FabricObject, removeParentTransform?: boolean) {\n object._set('group', undefined);\n if (!removeParentTransform) {\n applyTransformToObject(\n object,\n multiplyTransformMatrices(\n this.calcTransformMatrix(),\n object.calcTransformMatrix(),\n ),\n );\n object.setCoords();\n }\n this._watchObject(false, object);\n const index =\n this._activeObjects.length > 0 ? this._activeObjects.indexOf(object) : -1;\n if (index > -1) {\n this._activeObjects.splice(index, 1);\n }\n }\n\n /**\n * Decide if the group should cache or not. Create its own cache level\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step.\n * Generally you do not cache objects in groups because the group is already cached.\n * @return {Boolean}\n */\n shouldCache() {\n const ownCache = FabricObject.prototype.shouldCache.call(this);\n if (ownCache) {\n for (let i = 0; i < this._objects.length; i++) {\n if (this._objects[i].willDrawShadow()) {\n this.ownCaching = false;\n return false;\n }\n }\n }\n return ownCache;\n }\n\n /**\n * Check if this object or a child object will cast a shadow\n * @return {Boolean}\n */\n willDrawShadow() {\n if (super.willDrawShadow()) {\n return true;\n }\n for (let i = 0; i < this._objects.length; i++) {\n if (this._objects[i].willDrawShadow()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Check if instance or its group are caching, recursively up\n * @return {Boolean}\n */\n isOnACache(): boolean {\n return this.ownCaching || (!!this.parent && this.parent.isOnACache());\n }\n\n /**\n * Execute the drawing operation for an object on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawObject(\n ctx: CanvasRenderingContext2D,\n forClipping: boolean | undefined,\n context: DrawContext,\n ) {\n this._renderBackground(ctx);\n for (let i = 0; i < this._objects.length; i++) {\n const obj = this._objects[i];\n // TODO: handle rendering edge case somehow\n if (this.canvas?.preserveObjectStacking && obj.group !== this) {\n ctx.save();\n ctx.transform(...invertTransform(this.calcTransformMatrix()));\n obj.render(ctx);\n ctx.restore();\n } else if (obj.group === this) {\n obj.render(ctx);\n }\n }\n this._drawClipPath(ctx, this.clipPath, context);\n }\n\n /**\n * @override\n * @return {Boolean}\n */\n setCoords() {\n super.setCoords();\n this._shouldSetNestedCoords() &&\n this.forEachObject((object) => object.setCoords());\n }\n\n triggerLayout(options: ImperativeLayoutOptions = {}) {\n this.layoutManager.performLayout({\n target: this,\n type: LAYOUT_TYPE_IMPERATIVE,\n ...options,\n });\n }\n\n /**\n * Renders instance on a given context\n * @param {CanvasRenderingContext2D} ctx context to render instance on\n */\n render(ctx: CanvasRenderingContext2D) {\n this._transformDone = true;\n super.render(ctx);\n this._transformDone = false;\n }\n\n /**\n *\n * @private\n * @param {'toObject'|'toDatalessObject'} [method]\n * @param {string[]} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @returns {FabricObject[]} serialized objects\n */\n __serializeObjects(\n method: 'toObject' | 'toDatalessObject',\n propertiesToInclude?: string[],\n ) {\n const _includeDefaultValues = this.includeDefaultValues;\n return this._objects\n .filter(function (obj) {\n return !obj.excludeFromExport;\n })\n .map(function (obj) {\n const originalDefaults = obj.includeDefaultValues;\n obj.includeDefaultValues = _includeDefaultValues;\n const data = obj[method || 'toObject'](propertiesToInclude);\n obj.includeDefaultValues = originalDefaults;\n // delete data.version;\n return data;\n });\n }\n\n /**\n * Returns object representation of an instance\n * @param {string[]} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<\n GroupProps & TClassProperties<this>,\n keyof SerializedGroupProps\n >,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SerializedGroupProps {\n const layoutManager = this.layoutManager.toObject();\n\n return {\n ...super.toObject([\n 'subTargetCheck',\n 'interactive',\n ...propertiesToInclude,\n ]),\n ...(layoutManager.strategy !== 'fit-content' || this.includeDefaultValues\n ? { layoutManager }\n : {}),\n objects: this.__serializeObjects(\n 'toObject',\n propertiesToInclude as string[],\n ),\n };\n }\n\n toString() {\n return `#<Group: (${this.complexity()})>`;\n }\n\n dispose() {\n this.layoutManager.unsubscribeTargets({\n targets: this.getObjects(),\n target: this,\n });\n this._activeObjects = [];\n this.forEachObject((object) => {\n this._watchObject(false, object);\n object.dispose();\n });\n super.dispose();\n }\n\n /**\n * @private\n */\n _createSVGBgRect(reviver?: TSVGReviver) {\n if (!this.backgroundColor) {\n return '';\n }\n const fillStroke = Rect.prototype._toSVG.call(this);\n const commons = fillStroke.indexOf('COMMON_PARTS');\n fillStroke[commons] = 'for=\"group\" ';\n const markup = fillStroke.join('');\n return reviver ? reviver(markup) : markup;\n }\n\n /**\n * Returns svg representation of an instance\n * @param {TSVGReviver} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n _toSVG(reviver?: TSVGReviver) {\n const svgString = ['<g ', 'COMMON_PARTS', ' >\\n'];\n const bg = this._createSVGBgRect(reviver);\n bg && svgString.push('\\t\\t', bg);\n for (let i = 0; i < this._objects.length; i++) {\n svgString.push('\\t\\t', this._objects[i].toSVG(reviver));\n }\n svgString.push('</g>\\n');\n return svgString;\n }\n\n /**\n * Returns styles-string for svg-export, specific version for group\n * @return {String}\n */\n getSvgStyles(): string {\n const opacity =\n typeof this.opacity !== 'undefined' && this.opacity !== 1\n ? `opacity: ${this.opacity};`\n : '',\n visibility = this.visible ? '' : ' visibility: hidden;';\n return [opacity, this.getSvgFilter(), visibility].join('');\n }\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {String} svg representation of an instance\n */\n toClipPathSVG(reviver?: TSVGReviver): string {\n const svgString = [];\n const bg = this._createSVGBgRect(reviver);\n bg && svgString.push('\\t', bg);\n for (let i = 0; i < this._objects.length; i++) {\n svgString.push('\\t', this._objects[i].toClipPathSVG(reviver));\n }\n return this._createBaseClipPathSVGMarkup(svgString, {\n reviver,\n });\n }\n\n /**\n * @todo support loading from svg\n * @private\n * @param {Object} object Object to create a group from\n * @returns {Promise<Group>}\n */\n static fromObject<T extends TOptions<SerializedGroupProps>>(\n { type, objects = [], layoutManager, ...options }: T,\n abortable?: Abortable,\n ) {\n return Promise.all([\n enlivenObjects<FabricObject>(objects, abortable),\n enlivenObjectEnlivables(options, abortable),\n ]).then(([objects, hydratedOptions]) => {\n const group = new this(objects, {\n ...options,\n ...hydratedOptions,\n layoutManager: new NoopLayoutManager(),\n });\n if (layoutManager) {\n const layoutClass = classRegistry.getClass<typeof LayoutManager>(\n layoutManager.type,\n );\n const strategyClass = classRegistry.getClass<typeof FitContentLayout>(\n layoutManager.strategy,\n );\n group.layoutManager = new layoutClass(new strategyClass());\n } else {\n group.layoutManager = new LayoutManager();\n }\n group.layoutManager.subscribeTargets({\n type: LAYOUT_TYPE_INITIALIZATION,\n target: group,\n targets: group.getObjects(),\n });\n group.setCoords();\n return group;\n });\n }\n}\n\nclassRegistry.setClass(Group);\n","import type { GroupProps } from '../../shapes/Group';\nimport { Group } from '../../shapes/Group';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\n\n/**\n * TODO experiment with different layout manager and svg results ( fixed fit content )\n * Groups SVG elements (usually those retrieved from SVG document)\n * @param {FabricObject[]} elements FabricObject(s) parsed from svg, to group\n * @return {FabricObject | Group}\n */\nexport const groupSVGElements = (\n elements: FabricObject[],\n options?: Partial<GroupProps>,\n) => {\n if (elements && elements.length === 1) {\n return elements[0];\n }\n return new Group(elements, options);\n};\n","import type { TSize } from '../../typedefs';\n\n/**\n * Finds the scale for the object source to fit inside the object destination,\n * keeping aspect ratio intact.\n * respect the total allowed area for the cache.\n * @param {TSize} source natural unscaled size of the object\n * @param {TSize} destination natural unscaled size of the object\n * @return {Number} scale factor to apply to source to fit into destination\n */\nexport const findScaleToFit = (source: TSize, destination: TSize) =>\n Math.min(\n destination.width / source.width,\n destination.height / source.height,\n );\n\n/**\n * Finds the scale for the object source to cover entirely the object destination,\n * keeping aspect ratio intact.\n * respect the total allowed area for the cache.\n * @param {TSize} source natural unscaled size of the object\n * @param {TSize} destination natural unscaled size of the object\n * @return {Number} scale factor to apply to source to cover destination\n */\nexport const findScaleToCover = (source: TSize, destination: TSize) =>\n Math.max(\n destination.width / source.width,\n destination.height / source.height,\n );\n","import { reNum } from '../../parser/constants';\n\nconst commaWsp = `\\\\s*,?\\\\s*`;\n\n/**\n * p for param\n * using \"bad naming\" here because it makes the regex much easier to read\n * p is a number that is preceded by an arbitary number of spaces, maybe 0,\n * a comma or not, and then possibly more spaces or not.\n */\nconst p = `${commaWsp}(${reNum})`;\n\n// const reMoveToCommand = `(M) ?(?:${p}${p} ?)+`;\n\n// const reLineCommand = `(L) ?(?:${p}${p} ?)+`;\n\n// const reHorizontalLineCommand = `(H) ?(?:${p} ?)+`;\n\n// const reVerticalLineCommand = `(V) ?(?:${p} ?)+`;\n\n// const reClosePathCommand = String.raw`(Z)\\s*`;\n\n// const reCubicCurveCommand = `(C) ?(?:${p}${p}${p}${p}${p}${p} ?)+`;\n\n// const reCubicCurveShortcutCommand = `(S) ?(?:${p}${p}${p}${p} ?)+`;\n\n// const reQuadraticCurveCommand = `(Q) ?(?:${p}${p}${p}${p} ?)+`;\n\n// const reQuadraticCurveShortcutCommand = `(T) ?(?:${p}${p} ?)+`;\n\nexport const reArcCommandPoints = `${p}${p}${p}${commaWsp}([01])${commaWsp}([01])${p}${p}`;\n// const reArcCommand = `(A) ?(?:${reArcCommandPoints} ?)+`;\n\n// export const rePathCommandGroups =\n// `(?:(?:${reMoveToCommand})` +\n// `|(?:${reLineCommand})` +\n// `|(?:${reHorizontalLineCommand})` +\n// `|(?:${reVerticalLineCommand})` +\n// `|(?:${reClosePathCommand})` +\n// `|(?:${reCubicCurveCommand})` +\n// `|(?:${reCubicCurveShortcutCommand})` +\n// `|(?:${reQuadraticCurveCommand})` +\n// `|(?:${reQuadraticCurveShortcutCommand})` +\n// `|(?:${reArcCommand}))`;\n\nexport const rePathCommand = '[mzlhvcsqta][^mzlhvcsqta]*';\n","import { cache } from '../../cache';\nimport { config } from '../../config';\nimport { halfPI, PiBy180 } from '../../constants';\nimport type { TMat2D, TRadian, TRectBounds } from '../../typedefs';\nimport { cos } from '../misc/cos';\nimport { multiplyTransformMatrices, transformPoint } from '../misc/matrix';\nimport { sin } from '../misc/sin';\nimport { toFixed } from '../misc/toFixed';\nimport type {\n TCurveInfo,\n TComplexPathData,\n TParsedAbsoluteCubicCurveCommand,\n TPathSegmentInfo,\n TPointAngle,\n TSimpleParsedCommand,\n TSimplePathData,\n TPathSegmentCommandInfo,\n TComplexParsedCommand,\n TPathSegmentInfoCommon,\n TEndPathInfo,\n TParsedArcCommand,\n TComplexParsedCommandType,\n} from './typedefs';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport { reArcCommandPoints, rePathCommand } from './regex';\nimport { reNum } from '../../parser/constants';\n\n/**\n * Commands that may be repeated\n */\nconst repeatedCommands: Record<string, 'l' | 'L'> = {\n m: 'l',\n M: 'L',\n};\n\n/**\n * Convert an arc of a rotated ellipse to a Bezier Curve\n * @param {TRadian} theta1 start of the arc\n * @param {TRadian} theta2 end of the arc\n * @param cosTh cosine of the angle of rotation\n * @param sinTh sine of the angle of rotation\n * @param rx x-axis radius (before rotation)\n * @param ry y-axis radius (before rotation)\n * @param cx1 center x of the ellipse\n * @param cy1 center y of the ellipse\n * @param mT\n * @param fromX starting point of arc x\n * @param fromY starting point of arc y\n */\nconst segmentToBezier = (\n theta1: TRadian,\n theta2: TRadian,\n cosTh: number,\n sinTh: number,\n rx: number,\n ry: number,\n cx1: number,\n cy1: number,\n mT: number,\n fromX: number,\n fromY: number,\n): TParsedAbsoluteCubicCurveCommand => {\n const costh1 = cos(theta1),\n sinth1 = sin(theta1),\n costh2 = cos(theta2),\n sinth2 = sin(theta2),\n toX = cosTh * rx * costh2 - sinTh * ry * sinth2 + cx1,\n toY = sinTh * rx * costh2 + cosTh * ry * sinth2 + cy1,\n cp1X = fromX + mT * (-cosTh * rx * sinth1 - sinTh * ry * costh1),\n cp1Y = fromY + mT * (-sinTh * rx * sinth1 + cosTh * ry * costh1),\n cp2X = toX + mT * (cosTh * rx * sinth2 + sinTh * ry * costh2),\n cp2Y = toY + mT * (sinTh * rx * sinth2 - cosTh * ry * costh2);\n\n return ['C', cp1X, cp1Y, cp2X, cp2Y, toX, toY];\n};\n\n/**\n * Adapted from {@link http://dxr.mozilla.org/mozilla-central/source/dom/svg/SVGPathDataParser.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 * @param toX\n * @param toY\n * @param rx\n * @param ry\n * @param {number} large 0 or 1 flag\n * @param {number} sweep 0 or 1 flag\n * @param rotateX\n */\nconst arcToSegments = (\n toX: number,\n toY: number,\n rx: number,\n ry: number,\n large: number,\n sweep: number,\n rotateX: TRadian,\n): TParsedAbsoluteCubicCurveCommand[] => {\n if (rx === 0 || ry === 0) {\n return [];\n }\n let fromX = 0,\n fromY = 0,\n root = 0;\n const PI = Math.PI,\n theta = rotateX * PiBy180,\n sinTheta = sin(theta),\n cosTh = cos(theta),\n px = 0.5 * (-cosTh * toX - sinTheta * toY),\n py = 0.5 * (-cosTh * toY + sinTheta * toX),\n rx2 = rx ** 2,\n ry2 = ry ** 2,\n py2 = py ** 2,\n px2 = px ** 2,\n pl = rx2 * ry2 - rx2 * py2 - ry2 * px2;\n let _rx = Math.abs(rx);\n let _ry = Math.abs(ry);\n\n if (pl < 0) {\n const s = Math.sqrt(1 - pl / (rx2 * ry2));\n _rx *= s;\n _ry *= s;\n } else {\n root =\n (large === sweep ? -1.0 : 1.0) * Math.sqrt(pl / (rx2 * py2 + ry2 * px2));\n }\n\n const cx = (root * _rx * py) / _ry,\n cy = (-root * _ry * px) / _rx,\n cx1 = cosTh * cx - sinTheta * cy + toX * 0.5,\n cy1 = sinTheta * cx + cosTh * cy + toY * 0.5;\n let mTheta = calcVectorAngle(1, 0, (px - cx) / _rx, (py - cy) / _ry);\n let dtheta = calcVectorAngle(\n (px - cx) / _rx,\n (py - cy) / _ry,\n (-px - cx) / _rx,\n (-py - cy) / _ry,\n );\n\n if (sweep === 0 && dtheta > 0) {\n dtheta -= 2 * PI;\n } else if (sweep === 1 && dtheta < 0) {\n dtheta += 2 * PI;\n }\n\n // Convert into cubic bezier segments <= 90deg\n const segments = Math.ceil(Math.abs((dtheta / PI) * 2)),\n result = [],\n mDelta = dtheta / segments,\n mT =\n ((8 / 3) * Math.sin(mDelta / 4) * Math.sin(mDelta / 4)) /\n Math.sin(mDelta / 2);\n let th3 = mTheta + mDelta;\n\n for (let i = 0; i < segments; i++) {\n result[i] = segmentToBezier(\n mTheta,\n th3,\n cosTh,\n sinTheta,\n _rx,\n _ry,\n cx1,\n cy1,\n mT,\n fromX,\n fromY,\n );\n fromX = result[i][5];\n fromY = result[i][6];\n mTheta = th3;\n th3 += mDelta;\n }\n return result;\n};\n\n/**\n * @private\n * Calculate the angle between two vectors\n * @param ux u endpoint x\n * @param uy u endpoint y\n * @param vx v endpoint x\n * @param vy v endpoint y\n */\nconst calcVectorAngle = (\n ux: number,\n uy: number,\n vx: number,\n vy: number,\n): TRadian => {\n const ta = Math.atan2(uy, ux),\n tb = Math.atan2(vy, vx);\n if (tb >= ta) {\n return tb - ta;\n } else {\n return 2 * Math.PI - (ta - tb);\n }\n};\n\n// functions for the Cubic beizer\n// taken from: https://github.com/konvajs/konva/blob/7.0.5/src/shapes/Path.ts#L350\nconst CB1 = (t: number) => t ** 3;\nconst CB2 = (t: number) => 3 * t ** 2 * (1 - t);\nconst CB3 = (t: number) => 3 * t * (1 - t) ** 2;\nconst CB4 = (t: number) => (1 - t) ** 3;\n\n/**\n * Calculate bounding box of a cubic Bezier curve\n * Taken from http://jsbin.com/ivomiq/56/edit (no credits available)\n * TODO: can we normalize this with the starting points set at 0 and then translated the bbox?\n * @param {number} begx starting point\n * @param {number} begy\n * @param {number} cp1x first control point\n * @param {number} cp1y\n * @param {number} cp2x second control point\n * @param {number} cp2y\n * @param {number} endx end of bezier\n * @param {number} endy\n * @return {TRectBounds} the rectangular bounds\n */\nexport function getBoundsOfCurve(\n begx: number,\n begy: number,\n cp1x: number,\n cp1y: number,\n cp2x: number,\n cp2y: number,\n endx: number,\n endy: number,\n): TRectBounds {\n let argsString: string;\n if (config.cachesBoundsOfCurve) {\n // eslint-disable-next-line\n argsString = [...arguments].join();\n if (cache.boundsOfCurveCache[argsString]) {\n return cache.boundsOfCurveCache[argsString];\n }\n }\n\n const sqrt = Math.sqrt,\n abs = Math.abs,\n tvalues = [],\n bounds: [[x: number, y: number], [x: number, y: number]] = [\n [0, 0],\n [0, 0],\n ];\n\n let b = 6 * begx - 12 * cp1x + 6 * cp2x;\n let a = -3 * begx + 9 * cp1x - 9 * cp2x + 3 * endx;\n let c = 3 * cp1x - 3 * begx;\n\n for (let i = 0; i < 2; ++i) {\n if (i > 0) {\n b = 6 * begy - 12 * cp1y + 6 * cp2y;\n a = -3 * begy + 9 * cp1y - 9 * cp2y + 3 * endy;\n c = 3 * cp1y - 3 * begy;\n }\n\n if (abs(a) < 1e-12) {\n if (abs(b) < 1e-12) {\n continue;\n }\n const t = -c / b;\n if (0 < t && t < 1) {\n tvalues.push(t);\n }\n continue;\n }\n const b2ac = b * b - 4 * c * a;\n if (b2ac < 0) {\n continue;\n }\n const sqrtb2ac = sqrt(b2ac);\n const t1 = (-b + sqrtb2ac) / (2 * a);\n if (0 < t1 && t1 < 1) {\n tvalues.push(t1);\n }\n const t2 = (-b - sqrtb2ac) / (2 * a);\n if (0 < t2 && t2 < 1) {\n tvalues.push(t2);\n }\n }\n\n let j = tvalues.length;\n const jlen = j;\n const iterator = getPointOnCubicBezierIterator(\n begx,\n begy,\n cp1x,\n cp1y,\n cp2x,\n cp2y,\n endx,\n endy,\n );\n while (j--) {\n const { x, y } = iterator(tvalues[j]);\n bounds[0][j] = x;\n bounds[1][j] = y;\n }\n\n bounds[0][jlen] = begx;\n bounds[1][jlen] = begy;\n bounds[0][jlen + 1] = endx;\n bounds[1][jlen + 1] = endy;\n const result: TRectBounds = [\n new Point(Math.min(...bounds[0]), Math.min(...bounds[1])),\n new Point(Math.max(...bounds[0]), Math.max(...bounds[1])),\n ];\n if (config.cachesBoundsOfCurve) {\n cache.boundsOfCurveCache[argsString!] = result;\n }\n return result;\n}\n\n/**\n * Converts arc to a bunch of cubic Bezier curves\n * @param {number} fx starting point x\n * @param {number} fy starting point y\n * @param {TParsedArcCommand} coords Arc command\n */\nexport const fromArcToBeziers = (\n fx: number,\n fy: number,\n [_, rx, ry, rot, large, sweep, tx, ty]: TParsedArcCommand,\n): TParsedAbsoluteCubicCurveCommand[] => {\n const segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);\n\n for (let i = 0, len = segsNorm.length; i < len; i++) {\n segsNorm[i][1] += fx;\n segsNorm[i][2] += fy;\n segsNorm[i][3] += fx;\n segsNorm[i][4] += fy;\n segsNorm[i][5] += fx;\n segsNorm[i][6] += fy;\n }\n return segsNorm;\n};\n\n/**\n * This function takes a parsed SVG path and makes it simpler for fabricJS logic.\n * Simplification consist of:\n * - All commands converted to absolute (lowercase to uppercase)\n * - S converted to C\n * - T converted to Q\n * - A converted to C\n * @param {TComplexPathData} path the array of commands of a parsed SVG path for `Path`\n * @return {TSimplePathData} the simplified array of commands of a parsed SVG path for `Path`\n * TODO: figure out how to remove the type assertions in a nice way\n */\nexport const makePathSimpler = (path: TComplexPathData): TSimplePathData => {\n // x and y represent the last point of the path, AKA the previous command point.\n // we add them to each relative command to make it an absolute comment.\n // we also swap the v V h H with L, because are easier to transform.\n let x = 0,\n y = 0;\n // x1 and y1 represent the last point of the subpath. the subpath is started with\n // m or M command. When a z or Z command is drawn, x and y need to be resetted to\n // the last x1 and y1.\n let x1 = 0,\n y1 = 0;\n // previous will host the letter of the previous command, to handle S and T.\n // controlX and controlY will host the previous reflected control point\n const destinationPath: TSimplePathData = [];\n let previous,\n // placeholders\n controlX = 0,\n controlY = 0;\n for (const parsedCommand of path) {\n const current: TComplexParsedCommand = [...parsedCommand];\n let converted: TSimpleParsedCommand | undefined;\n switch (\n current[0] // first letter\n ) {\n case 'l': // lineto, relative\n current[1] += x;\n current[2] += y;\n // falls through\n case 'L':\n x = current[1];\n y = current[2];\n converted = ['L', x, y];\n break;\n case 'h': // horizontal lineto, relative\n current[1] += x;\n // falls through\n case 'H':\n x = current[1];\n converted = ['L', x, y];\n break;\n case 'v': // vertical lineto, relative\n current[1] += y;\n // falls through\n case 'V':\n y = current[1];\n converted = ['L', x, y];\n break;\n case 'm': // moveTo, relative\n current[1] += x;\n current[2] += y;\n // falls through\n case 'M':\n x = current[1];\n y = current[2];\n x1 = current[1];\n y1 = current[2];\n converted = ['M', x, y];\n break;\n case 'c': // bezierCurveTo, relative\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n current[5] += x;\n current[6] += y;\n // falls through\n case 'C':\n controlX = current[3];\n controlY = current[4];\n x = current[5];\n y = current[6];\n converted = ['C', current[1], current[2], controlX, controlY, x, y];\n break;\n case 's': // shorthand cubic bezierCurveTo, relative\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n // falls through\n case 'S':\n // would be sScC but since we are swapping sSc for C, we check just that.\n if (previous === 'C') {\n // calculate reflection of previous control points\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n } else {\n // If there is no previous command or if the previous command was not a C, c, S, or s,\n // the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n x = current[3];\n y = current[4];\n converted = ['C', controlX, controlY, current[1], current[2], x, y];\n // converted[3] and converted[4] are NOW the second control point.\n // we keep it for the next reflection.\n controlX = converted[3];\n controlY = converted[4];\n break;\n case 'q': // quadraticCurveTo, relative\n current[1] += x;\n current[2] += y;\n current[3] += x;\n current[4] += y;\n // falls through\n case 'Q':\n controlX = current[1];\n controlY = current[2];\n x = current[3];\n y = current[4];\n converted = ['Q', controlX, controlY, x, y];\n break;\n case 't': // shorthand quadraticCurveTo, relative\n current[1] += x;\n current[2] += y;\n // falls through\n case 'T':\n if (previous === 'Q') {\n // calculate reflection of previous control point\n controlX = 2 * x - controlX;\n controlY = 2 * y - controlY;\n } else {\n // If there is no previous command or if the previous command was not a Q, q, T or t,\n // assume the control point is coincident with the current point\n controlX = x;\n controlY = y;\n }\n x = current[1];\n y = current[2];\n converted = ['Q', controlX, controlY, x, y];\n break;\n case 'a':\n current[6] += x;\n current[7] += y;\n // falls through\n case 'A':\n fromArcToBeziers(x, y, current).forEach((b) => destinationPath.push(b));\n x = current[6];\n y = current[7];\n break;\n case 'z':\n case 'Z':\n x = x1;\n y = y1;\n converted = ['Z'];\n break;\n default:\n }\n if (converted) {\n destinationPath.push(converted);\n previous = converted[0];\n } else {\n previous = '';\n }\n }\n return destinationPath;\n};\n\n// todo verify if we can just use the point class here\n/**\n * Calc length from point x1,y1 to x2,y2\n * @param {number} x1 starting point x\n * @param {number} y1 starting point y\n * @param {number} x2 starting point x\n * @param {number} y2 starting point y\n * @return {number} length of segment\n */\nconst calcLineLength = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): number => Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n\n/**\n * Get an iterator that takes a percentage and returns a point\n * @param {number} begx\n * @param {number} begy\n * @param {number} cp1x\n * @param {number} cp1y\n * @param {number} cp2x\n * @param {number} cp2y\n * @param {number} endx\n * @param {number} endy\n */\nconst getPointOnCubicBezierIterator =\n (\n begx: number,\n begy: number,\n cp1x: number,\n cp1y: number,\n cp2x: number,\n cp2y: number,\n endx: number,\n endy: number,\n ) =>\n (pct: number) => {\n const c1 = CB1(pct),\n c2 = CB2(pct),\n c3 = CB3(pct),\n c4 = CB4(pct);\n return new Point(\n endx * c1 + cp2x * c2 + cp1x * c3 + begx * c4,\n endy * c1 + cp2y * c2 + cp1y * c3 + begy * c4,\n );\n };\n\nconst QB1 = (t: number) => t ** 2;\nconst QB2 = (t: number) => 2 * t * (1 - t);\nconst QB3 = (t: number) => (1 - t) ** 2;\n\nconst getTangentCubicIterator =\n (\n p1x: number,\n p1y: number,\n p2x: number,\n p2y: number,\n p3x: number,\n p3y: number,\n p4x: number,\n p4y: number,\n ) =>\n (pct: number) => {\n const qb1 = QB1(pct),\n qb2 = QB2(pct),\n qb3 = QB3(pct),\n tangentX =\n 3 * (qb3 * (p2x - p1x) + qb2 * (p3x - p2x) + qb1 * (p4x - p3x)),\n tangentY =\n 3 * (qb3 * (p2y - p1y) + qb2 * (p3y - p2y) + qb1 * (p4y - p3y));\n return Math.atan2(tangentY, tangentX);\n };\n\nconst getPointOnQuadraticBezierIterator =\n (\n p1x: number,\n p1y: number,\n p2x: number,\n p2y: number,\n p3x: number,\n p3y: number,\n ) =>\n (pct: number) => {\n const c1 = QB1(pct),\n c2 = QB2(pct),\n c3 = QB3(pct);\n return new Point(\n p3x * c1 + p2x * c2 + p1x * c3,\n p3y * c1 + p2y * c2 + p1y * c3,\n );\n };\n\nconst getTangentQuadraticIterator =\n (\n p1x: number,\n p1y: number,\n p2x: number,\n p2y: number,\n p3x: number,\n p3y: number,\n ) =>\n (pct: number) => {\n const invT = 1 - pct,\n tangentX = 2 * (invT * (p2x - p1x) + pct * (p3x - p2x)),\n tangentY = 2 * (invT * (p2y - p1y) + pct * (p3y - p2y));\n return Math.atan2(tangentY, tangentX);\n };\n\n// this will run over a path segment (a cubic or quadratic segment) and approximate it\n// with 100 segments. This will good enough to calculate the length of the curve\nconst pathIterator = (\n iterator: (pct: number) => Point,\n x1: number,\n y1: number,\n) => {\n let tempP = new Point(x1, y1),\n tmpLen = 0;\n for (let perc = 1; perc <= 100; perc += 1) {\n const p = iterator(perc / 100);\n tmpLen += calcLineLength(tempP.x, tempP.y, p.x, p.y);\n tempP = p;\n }\n return tmpLen;\n};\n\n/**\n * Given a pathInfo, and a distance in pixels, find the percentage from 0 to 1\n * that correspond to that pixels run over the path.\n * The percentage will be then used to find the correct point on the canvas for the path.\n * @param {Array} segInfo fabricJS collection of information on a parsed path\n * @param {number} distance from starting point, in pixels.\n * @return {TPointAngle} info object with x and y ( the point on canvas ) and angle, the tangent on that point;\n */\nconst findPercentageForDistance = (\n segInfo: TCurveInfo<'Q' | 'C'>,\n distance: number,\n): TPointAngle => {\n let perc = 0,\n tmpLen = 0,\n tempP: XY = { x: segInfo.x, y: segInfo.y },\n p: XY = { ...tempP },\n nextLen: number,\n nextStep = 0.01,\n lastPerc = 0;\n // nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100\n // the path\n const iterator = segInfo.iterator,\n angleFinder = segInfo.angleFinder;\n while (tmpLen < distance && nextStep > 0.0001) {\n p = iterator(perc);\n lastPerc = perc;\n nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);\n // compare tmpLen each cycle with distance, decide next perc to test.\n if (nextLen + tmpLen > distance) {\n // we discard this step and we make smaller steps.\n perc -= nextStep;\n nextStep /= 2;\n } else {\n tempP = p;\n perc += nextStep;\n tmpLen += nextLen;\n }\n }\n return { ...p, angle: angleFinder(lastPerc) };\n};\n\n/**\n * Run over a parsed and simplified path and extract some information (length of each command and starting point)\n * @param {TSimplePathData} path parsed path commands\n * @return {TPathSegmentInfo[]} path commands information\n */\nexport const getPathSegmentsInfo = (\n path: TSimplePathData,\n): TPathSegmentInfo[] => {\n let totalLength = 0,\n //x2 and y2 are the coords of segment start\n //x1 and y1 are the coords of the current point\n x1 = 0,\n y1 = 0,\n x2 = 0,\n y2 = 0,\n iterator,\n tempInfo: TPathSegmentInfo;\n const info: TPathSegmentInfo[] = [];\n for (const current of path) {\n const basicInfo: TPathSegmentInfoCommon<keyof TPathSegmentCommandInfo> = {\n x: x1,\n y: y1,\n command: current[0],\n length: 0,\n };\n switch (\n current[0] //first letter\n ) {\n case 'M':\n tempInfo = <TPathSegmentInfoCommon<'M'>>basicInfo;\n tempInfo.x = x2 = x1 = current[1];\n tempInfo.y = y2 = y1 = current[2];\n break;\n case 'L':\n tempInfo = <TPathSegmentInfoCommon<'L'>>basicInfo;\n tempInfo.length = calcLineLength(x1, y1, current[1], current[2]);\n x1 = current[1];\n y1 = current[2];\n break;\n case 'C':\n iterator = getPointOnCubicBezierIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6],\n );\n tempInfo = <TCurveInfo<'C'>>basicInfo;\n tempInfo.iterator = iterator;\n tempInfo.angleFinder = getTangentCubicIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n current[5],\n current[6],\n );\n tempInfo.length = pathIterator(iterator, x1, y1);\n\n x1 = current[5];\n y1 = current[6];\n break;\n case 'Q':\n iterator = getPointOnQuadraticBezierIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n );\n tempInfo = <TCurveInfo<'Q'>>basicInfo;\n tempInfo.iterator = iterator;\n tempInfo.angleFinder = getTangentQuadraticIterator(\n x1,\n y1,\n current[1],\n current[2],\n current[3],\n current[4],\n );\n tempInfo.length = pathIterator(iterator, x1, y1);\n x1 = current[3];\n y1 = current[4];\n break;\n case 'Z':\n // we add those in order to ease calculations later\n tempInfo = <TEndPathInfo>basicInfo;\n tempInfo.destX = x2;\n tempInfo.destY = y2;\n tempInfo.length = calcLineLength(x1, y1, x2, y2);\n x1 = x2;\n y1 = y2;\n break;\n }\n totalLength += tempInfo.length;\n info.push(tempInfo);\n }\n info.push({ length: totalLength, x: x1, y: y1 });\n return info;\n};\n\n/**\n * Get the point on the path that is distance along the path\n * @param path\n * @param distance\n * @param infos\n */\nexport const getPointOnPath = (\n path: TSimplePathData,\n distance: number,\n infos: TPathSegmentInfo[] = getPathSegmentsInfo(path),\n): TPointAngle | undefined => {\n let i = 0;\n while (distance - infos[i].length > 0 && i < infos.length - 2) {\n distance -= infos[i].length;\n i++;\n }\n const segInfo = infos[i],\n segPercent = distance / segInfo.length,\n segment = path[i];\n\n switch (segInfo.command) {\n case 'M':\n return { x: segInfo.x, y: segInfo.y, angle: 0 };\n case 'Z':\n return {\n ...new Point(segInfo.x, segInfo.y).lerp(\n new Point(segInfo.destX, segInfo.destY),\n segPercent,\n ),\n angle: Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x),\n };\n case 'L':\n return {\n ...new Point(segInfo.x, segInfo.y).lerp(\n new Point(segment[1]!, segment[2]!),\n segPercent,\n ),\n angle: Math.atan2(segment[2]! - segInfo.y, segment[1]! - segInfo.x),\n };\n case 'C':\n return findPercentageForDistance(segInfo, distance);\n case 'Q':\n return findPercentageForDistance(segInfo, distance);\n default:\n // throw Error('Invalid command');\n }\n};\n\nconst rePathCmdAll = new RegExp(rePathCommand, 'gi');\nconst regExpArcCommandPoints = new RegExp(reArcCommandPoints, 'g');\nconst reMyNum = new RegExp(reNum, 'gi');\nconst 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} as const;\n/**\n *\n * @param {string} pathString\n * @return {TComplexPathData} An array of SVG path commands\n * @example <caption>Usage</caption>\n * parsePath('M 3 4 Q 3 5 2 1 4 0 Q 9 12 2 1 4 0') === [\n * ['M', 3, 4],\n * ['Q', 3, 5, 2, 1, 4, 0],\n * ['Q', 9, 12, 2, 1, 4, 0],\n * ];\n */\nexport const parsePath = (pathString: string): TComplexPathData => {\n const chain: TComplexPathData = [];\n const all = pathString.match(rePathCmdAll) ?? [];\n for (const matchStr of all) {\n // take match string and save the first letter as the command\n const commandLetter = matchStr[0] as TComplexParsedCommandType;\n // in case of Z we have very little to do\n if (commandLetter === 'z' || commandLetter === 'Z') {\n chain.push([commandLetter]);\n continue;\n }\n const commandLength =\n commandLengths[\n commandLetter.toLowerCase() as keyof typeof commandLengths\n ];\n\n let paramArr = [];\n if (commandLetter === 'a' || commandLetter === 'A') {\n // the arc command ha some peculariaties that requires a special regex other than numbers\n // it is possible to avoid using a space between the sweep and large arc flags, making them either\n // 00, 01, 10 or 11, making them identical to a plain number for the regex reMyNum\n // reset the regexp\n regExpArcCommandPoints.lastIndex = 0;\n for (let out = null; (out = regExpArcCommandPoints.exec(matchStr)); ) {\n paramArr.push(...out.slice(1));\n }\n } else {\n paramArr = matchStr.match(reMyNum) || [];\n }\n\n // inspect the length of paramArr, if is longer than commandLength\n // we are dealing with repeated commands\n for (let i = 0; i < paramArr.length; i += commandLength) {\n const newCommand = new Array(commandLength) as TComplexParsedCommand;\n const transformedCommand = repeatedCommands[commandLetter];\n newCommand[0] =\n i > 0 && transformedCommand ? transformedCommand : commandLetter;\n for (let j = 0; j < commandLength; j++) {\n newCommand[j + 1] = parseFloat(paramArr[i + j]);\n }\n chain.push(newCommand);\n }\n }\n return chain;\n};\n\n/**\n *\n * Converts points to a smooth SVG path\n * @param {XY[]} points Array of points\n * @param {number} [correction] Apply a correction to the path (usually we use `width / 1000`). If value is undefined 0 is used as the correction value.\n * @return {(string|number)[][]} An array of SVG path commands\n */\nexport const getSmoothPathFromPoints = (\n points: Point[],\n correction = 0,\n): TSimplePathData => {\n let p1 = new Point(points[0]),\n p2 = new Point(points[1]),\n multSignX = 1,\n multSignY = 0;\n const path: TSimplePathData = [],\n len = points.length,\n 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([\n 'M',\n p1.x - multSignX * correction,\n p1.y - multSignY * correction,\n ]);\n let i;\n for (i = 1; i < len; i++) {\n if (!p1.eq(p2)) {\n const 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([\n 'L',\n p1.x + multSignX * correction,\n p1.y + multSignY * correction,\n ]);\n return path;\n};\n\n/**\n * Transform a path by transforming each segment.\n * it has to be a simplified path or it won't work.\n * WARNING: this depends from pathOffset for correct operation\n * @param {TSimplePathData} path fabricJS parsed and simplified path commands\n * @param {TMat2D} transform matrix that represent the transformation\n * @param {Point} [pathOffset] `Path.pathOffset`\n * @returns {TSimplePathData} the transformed path\n */\nexport const transformPath = (\n path: TSimplePathData,\n transform: TMat2D,\n pathOffset: Point,\n): TSimplePathData => {\n if (pathOffset) {\n transform = multiplyTransformMatrices(transform, [\n 1,\n 0,\n 0,\n 1,\n -pathOffset.x,\n -pathOffset.y,\n ]);\n }\n return path.map((pathSegment) => {\n const newSegment: TSimpleParsedCommand = [...pathSegment];\n for (let i = 1; i < pathSegment.length - 1; i += 2) {\n // TODO: is there a way to get around casting to any?\n const { x, y } = transformPoint(\n {\n x: pathSegment[i] as number,\n y: pathSegment[i + 1] as number,\n },\n transform,\n );\n newSegment[i] = x;\n newSegment[i + 1] = y;\n }\n return newSegment;\n });\n};\n\n/**\n * Returns an array of path commands to create a regular polygon\n * @param {number} numVertexes\n * @param {number} radius\n * @returns {TSimplePathData} An array of SVG path commands\n */\nexport const getRegularPolygonPath = (\n numVertexes: number,\n radius: number,\n): TSimplePathData => {\n const interiorAngle = (Math.PI * 2) / numVertexes;\n // rotationAdjustment rotates the path by 1/2 the interior angle so that the polygon always has a flat side on the bottom\n // This isn't strictly necessary, but it's how we tend to think of and expect polygons to be drawn\n let rotationAdjustment = -halfPI;\n if (numVertexes % 2 === 0) {\n rotationAdjustment += interiorAngle / 2;\n }\n const d = new Array(numVertexes + 1);\n for (let i = 0; i < numVertexes; i++) {\n const rad = i * interiorAngle + rotationAdjustment;\n const { x, y } = new Point(cos(rad), sin(rad)).scalarMultiply(radius);\n d[i] = [i === 0 ? 'M' : 'L', x, y];\n }\n d[numVertexes] = ['Z'];\n return d;\n};\n\n/**\n * Join path commands to go back to svg format\n * @param {TSimplePathData} pathData fabricJS parsed path commands\n * @param {number} fractionDigits number of fraction digits to \"leave\"\n * @return {String} joined path 'M 0 0 L 20 30'\n */\nexport const joinPath = (pathData: TSimplePathData, fractionDigits?: number) =>\n pathData\n .map((segment) => {\n return segment\n .map((arg, i) => {\n if (i === 0) return arg;\n return fractionDigits === undefined\n ? arg\n : toFixed(arg, fractionDigits);\n })\n .join(' ');\n })\n .join(' ');\n","/**\n * Returns random number between 2 specified ones.\n * @param {Number} min lower limit\n * @param {Number} max upper limit\n * @return {Number} random value (between min and max)\n */\nexport const getRandomInt = (min: number, max: number): number =>\n Math.floor(Math.random() * (max - min + 1)) + min;\n","import { CENTER, SCALE_X, SCALE_Y } from '../constants';\nimport type { FabricImage, ParsedPAROffsets } from '../shapes/Image';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TMat2D } from '../typedefs';\nimport { qrDecompose } from './misc/matrix';\n\ntype FabricObjectWithTransformMatrix = FabricObject & {\n transformMatrix?: TMat2D;\n};\n\n/**\n * This function is an helper for svg import. it decompose the transformMatrix\n * and assign properties to object.\n * untransformed coordinates\n * @private\n */\nconst _assignTransformMatrixProps = (\n object: FabricObjectWithTransformMatrix,\n) => {\n if (object.transformMatrix) {\n const { scaleX, scaleY, angle, skewX } = qrDecompose(\n object.transformMatrix,\n );\n object.flipX = false;\n object.flipY = false;\n object.set(SCALE_X, scaleX);\n object.set(SCALE_Y, scaleY);\n object.angle = angle;\n object.skewX = skewX;\n object.skewY = 0;\n }\n};\n\n/**\n * This function is an helper for svg import. it removes the transform matrix\n * and set to object properties that fabricjs can handle\n * @private\n * @param {Object} preserveAspectRatioOptions\n */\nexport const removeTransformMatrixForSvgParsing = (\n object: FabricObjectWithTransformMatrix,\n preserveAspectRatioOptions?: ParsedPAROffsets,\n) => {\n let center = object._findCenterFromElement();\n if (object.transformMatrix) {\n _assignTransformMatrixProps(object);\n center = center.transform(object.transformMatrix);\n }\n delete object.transformMatrix;\n if (preserveAspectRatioOptions) {\n object.scaleX *= preserveAspectRatioOptions.scaleX;\n object.scaleY *= preserveAspectRatioOptions.scaleY;\n (object as FabricImage).cropX = preserveAspectRatioOptions.cropX;\n (object as FabricImage).cropY = preserveAspectRatioOptions.cropY;\n center.x += preserveAspectRatioOptions.offsetLeft;\n center.y += preserveAspectRatioOptions.offsetTop;\n object.width = preserveAspectRatioOptions.width;\n object.height = preserveAspectRatioOptions.height;\n }\n object.setPositionByOrigin(center, CENTER, CENTER);\n};\n","import type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { sendObjectToPlane } from './planeChange';\nimport { Group } from '../../shapes/Group';\n/**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them proir if necessary.\n *\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\n *\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\n *\n * @param {fabric.Object} c1\n * @param {fabric.Object} c2\n * @returns {fabric.Object} merged clip path\n */\nexport const mergeClipPaths = (c1: FabricObject, c2: FabricObject) => {\n let a = c1,\n b = c2;\n if (a.inverted && !b.inverted) {\n // case (2)\n a = c2;\n b = c1;\n }\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\n sendObjectToPlane(b, b.group?.calcTransformMatrix(), a.calcTransformMatrix());\n // assign the `inverted` prop to the wrapping group\n const inverted = a.inverted && b.inverted;\n if (inverted) {\n // case (1)\n a.inverted = b.inverted = false;\n }\n return new Group([a], { clipPath: b, inverted });\n};\n","// TODO this file needs to go away, cross browser style support is not fabricjs domain.\n\n/**\n * wrapper for setting element's style\n * @param {HTMLElement} element an HTMLElement\n * @param {Object} styles to apply to element\n */\nexport function setStyle(element: HTMLElement, styles: Record<string, string>) {\n const elementStyle = element.style;\n if (!elementStyle) {\n return;\n }\n Object.entries(styles).forEach(([property, value]) =>\n elementStyle.setProperty(property, value),\n );\n}\n","import { getEnv, getFabricDocument } from '../../env';\nimport type { TSize } from '../../typedefs';\nimport { createCanvasElement } from '../../util/misc/dom';\nimport { setStyle } from '../../util/internals/dom_style';\nimport type { CSSDimensions } from './util';\nimport { makeElementUnselectable, setCSSDimensions } from './util';\nimport type { CanvasItem } from './StaticCanvasDOMManager';\nimport { StaticCanvasDOMManager } from './StaticCanvasDOMManager';\nimport { setCanvasDimensions } from './util';\nimport { NONE } from '../../constants';\n\nexport class CanvasDOMManager extends StaticCanvasDOMManager {\n upper: CanvasItem;\n container: HTMLDivElement;\n\n constructor(\n arg0?: string | HTMLCanvasElement,\n {\n allowTouchScrolling = false,\n containerClass = '',\n }: {\n allowTouchScrolling?: boolean;\n /**\n * @deprecated here only for backward compatibility\n */\n containerClass?: string;\n } = {},\n ) {\n super(arg0);\n const { el: lowerCanvasEl } = this.lower;\n const upperCanvasEl = this.createUpperCanvas();\n this.upper = { el: upperCanvasEl, ctx: upperCanvasEl.getContext('2d')! };\n this.applyCanvasStyle(lowerCanvasEl, {\n allowTouchScrolling,\n });\n this.applyCanvasStyle(upperCanvasEl, {\n allowTouchScrolling,\n styles: {\n position: 'absolute',\n left: '0',\n top: '0',\n },\n });\n const container = this.createContainerElement();\n container.classList.add(containerClass);\n if (lowerCanvasEl.parentNode) {\n lowerCanvasEl.parentNode.replaceChild(container, lowerCanvasEl);\n }\n container.append(lowerCanvasEl, upperCanvasEl);\n this.container = container;\n }\n\n protected createUpperCanvas() {\n const { el: lowerCanvasEl } = this.lower;\n const el = createCanvasElement();\n // we assign the same classname of the lowerCanvas\n el.className = lowerCanvasEl.className;\n // but then we remove the lower-canvas specific className\n el.classList.remove('lower-canvas');\n // we add the specific upper-canvas class\n el.classList.add('upper-canvas');\n el.setAttribute('data-fabric', 'top');\n el.style.cssText = lowerCanvasEl.style.cssText;\n el.setAttribute('draggable', 'true');\n return el;\n }\n\n protected createContainerElement() {\n const container = getFabricDocument().createElement('div');\n container.setAttribute('data-fabric', 'wrapper');\n setStyle(container, {\n position: 'relative',\n });\n makeElementUnselectable(container);\n return container;\n }\n\n /**\n * @private\n * @param {HTMLCanvasElement} element canvas element to apply styles on\n */\n protected applyCanvasStyle(\n element: HTMLCanvasElement,\n options: {\n allowTouchScrolling?: boolean;\n styles?: Record<string, string>;\n },\n ) {\n const { styles, allowTouchScrolling } = options;\n setStyle(element, {\n ...styles,\n 'touch-action': allowTouchScrolling ? 'manipulation' : NONE,\n });\n makeElementUnselectable(element);\n }\n\n setDimensions(size: TSize, retinaScaling: number) {\n super.setDimensions(size, retinaScaling);\n const { el, ctx } = this.upper;\n setCanvasDimensions(el, ctx, size, retinaScaling);\n }\n\n setCSSDimensions(size: Partial<CSSDimensions>): void {\n super.setCSSDimensions(size);\n setCSSDimensions(this.upper.el, size);\n setCSSDimensions(this.container, size);\n }\n\n cleanupDOM(size: TSize) {\n const container = this.container,\n { el: lowerCanvasEl } = this.lower,\n { el: upperCanvasEl } = this.upper;\n super.cleanupDOM(size);\n container.removeChild(upperCanvasEl);\n container.removeChild(lowerCanvasEl);\n if (container.parentNode) {\n container.parentNode.replaceChild(lowerCanvasEl, container);\n }\n }\n\n dispose() {\n super.dispose();\n getEnv().dispose(this.upper.el);\n // @ts-expect-error disposing\n delete this.upper;\n // @ts-expect-error disposing\n delete this.container;\n }\n}\n","import type { ModifierKey, TOptionalModifierKey } from '../EventTypeDefs';\nimport type { TOptions } from '../typedefs';\nimport type { StaticCanvasOptions } from './StaticCanvasOptions';\n\nexport interface CanvasTransformOptions {\n /**\n * When true, objects can be transformed by one side (unproportionately)\n * when dragged on the corners that normally would not do that.\n * @type Boolean\n * @since fabric 4.0 // changed name and default value\n */\n uniformScaling: boolean;\n\n /**\n * Indicates which key switches uniform scaling.\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled.\n * totally wrong named. this sounds like `uniform scaling`\n * if Canvas.uniformScaling is true, pressing this will set it to false\n * and viceversa.\n * @since 1.6.2\n * @type ModifierKey\n */\n uniScaleKey: TOptionalModifierKey;\n\n /**\n * When true, objects use center point as the origin of scale transformation.\n * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n */\n centeredScaling: boolean;\n\n /**\n * When true, objects use center point as the origin of rotate transformation.\n * <b>Backwards incompatibility note:</b> This property replaces \"centerTransform\" (Boolean).\n * @since 1.3.4\n * @type Boolean\n */\n centeredRotation: boolean;\n\n /**\n * Indicates which key enable centered Transform\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled feature disabled.\n * @since 1.6.2\n * @type ModifierKey\n */\n centeredKey: TOptionalModifierKey;\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 ModifierKey\n */\n altActionKey: TOptionalModifierKey;\n}\n\nexport interface CanvasSelectionOptions {\n /**\n * Indicates whether group selection should be enabled\n * @type Boolean\n */\n selection: boolean;\n\n /**\n * Indicates which key or keys enable multiple click selection\n * Pass value as a string or array of strings\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * If `null` or empty or containing any other string that is not a modifier key\n * feature is disabled.\n * @since 1.6.2\n * @type ModifierKey|ModifierKey[]\n */\n selectionKey: TOptionalModifierKey | ModifierKey[];\n\n /**\n * Indicates which key enable alternative selection\n * in case of a target overlapping with active object and we don't want to loose the\n * active selection, we can press this modifier key and continue selecting the current\n * selected object also when is covered by another or many valid targets for selection.\n * values: 'altKey', 'shiftKey', 'ctrlKey'.\n * For a series of reason that come from the general expectations on how\n * things should work, this feature works only for preserveObjectStacking true.\n * If `null` or 'none' or any other string that is not a modifier key\n * feature is disabled.\n * @since 1.6.5\n * @type null|ModifierKey\n */\n altSelectionKey: TOptionalModifierKey;\n\n /**\n * Color of selection\n * @type String\n */\n selectionColor: string;\n\n /**\n * Default dash array pattern\n * If not empty the selection border is dashed\n * @type Array\n */\n selectionDashArray: number[];\n\n /**\n * Color of the border of selection (usually slightly darker than color of selection itself)\n * @type String\n */\n selectionBorderColor: string;\n\n /**\n * Width of a line used in object/group selection\n * @type Number\n */\n selectionLineWidth: number;\n\n /**\n * Select only shapes that are fully contained in the dragged selection rectangle.\n * @type Boolean\n */\n selectionFullyContained: boolean;\n}\n\nexport interface CanvasCursorOptions {\n /**\n * Default cursor value used when hovering over an object on canvas\n * @type CSSStyleDeclaration['cursor']\n * @default move\n */\n hoverCursor: CSSStyleDeclaration['cursor'];\n\n /**\n * Default cursor value used when moving an object on canvas\n * @type CSSStyleDeclaration['cursor']\n * @default move\n */\n moveCursor: CSSStyleDeclaration['cursor'];\n\n /**\n * Default cursor value used for the entire canvas\n * @type String\n * @default default\n */\n defaultCursor: CSSStyleDeclaration['cursor'];\n\n /**\n * Cursor value used during free drawing\n * @type String\n * @default crosshair\n */\n freeDrawingCursor: CSSStyleDeclaration['cursor'];\n\n /**\n * Cursor value used for disabled elements ( corners with disabled action )\n * @type String\n * @since 2.0.0\n * @default not-allowed\n */\n notAllowedCursor: CSSStyleDeclaration['cursor'];\n}\n\nexport interface TargetFindOptions {\n /**\n * When true, object detection happens on per-pixel basis rather than on per-bounding-box\n * @type Boolean\n */\n perPixelTargetFind: boolean;\n\n /**\n * Number of pixels around target pixel to tolerate (consider active) during object detection\n * @type Number\n */\n targetFindTolerance: number;\n\n /**\n * When true, target detection is skipped. Target detection will return always undefined.\n * click selection won't work anymore, events will fire with no targets.\n * if something is selected before setting it to true, it will be deselected at the first click.\n * area selection will still work. check the `selection` property too.\n * if you deactivate both, you should look into staticCanvas.\n * @type Boolean\n */\n skipTargetFind: boolean;\n}\n\nexport interface CanvasEventsOptions {\n /**\n * Indicates if the right click on canvas can output the context menu or not\n * The default value changed from false to true in Fabric 7.0\n * @see https://fabricjs.com/docs/upgrading/upgrading-to-fabric-70/\n * @deprecated since 7.0, Will be removed in Fabric 8.0\n * @type Boolean\n * @since 1.6.5\n */\n stopContextMenu: boolean;\n\n /**\n * Indicates if the canvas can fire right click events\n * The default value changed from false to true in Fabric 7.0\n * @see https://fabricjs.com/docs/upgrading/upgrading-to-fabric-70/\n * @deprecated since 7.0, Will be removed in Fabric 8.0\n * @type Boolean\n * @since 1.6.5\n */\n fireRightClick: boolean;\n\n /**\n * Indicates if the canvas can fire middle click events\n * The default value changed from false to true in Fabric 7.0\n * @see https://fabricjs.com/docs/upgrading/upgrading-to-fabric-70/\n * @deprecated since 7.0, Will be removed in Fabric 8.0\n * @type Boolean\n * @since 1.7.8\n */\n fireMiddleClick: boolean;\n\n /**\n * When the option is enabled, PointerEvent is used instead of TPointerEvent.\n * @type Boolean\n */\n enablePointerEvents: boolean;\n}\n\nexport interface CanvasOptions\n extends StaticCanvasOptions,\n CanvasTransformOptions,\n CanvasSelectionOptions,\n CanvasCursorOptions,\n TargetFindOptions,\n CanvasEventsOptions {\n /**\n * Default element class that's given to wrapper (div) element of canvas\n * @type String\n * @deprecated customize {@link CanvasDOMManager} instead or access {@link elements} directly\n */\n containerClass: string;\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 true\n */\n preserveObjectStacking: boolean;\n}\n\nexport type TCanvasOptions = TOptions<CanvasOptions>;\n\nexport const canvasDefaults: TOptions<CanvasOptions> = {\n uniformScaling: true,\n uniScaleKey: 'shiftKey',\n centeredScaling: false,\n centeredRotation: false,\n centeredKey: 'altKey',\n altActionKey: 'shiftKey',\n\n selection: true,\n selectionKey: 'shiftKey',\n selectionColor: 'rgba(100, 100, 255, 0.3)',\n selectionDashArray: [],\n selectionBorderColor: 'rgba(255, 255, 255, 0.3)',\n selectionLineWidth: 1,\n selectionFullyContained: false,\n\n hoverCursor: 'move',\n moveCursor: 'move',\n defaultCursor: 'default',\n freeDrawingCursor: 'crosshair',\n notAllowedCursor: 'not-allowed',\n\n perPixelTargetFind: false,\n targetFindTolerance: 0,\n skipTargetFind: false,\n\n stopContextMenu: true,\n fireRightClick: true,\n fireMiddleClick: true,\n enablePointerEvents: false,\n\n containerClass: 'canvas-container',\n preserveObjectStacking: true,\n};\n","import type { TransformActionHandler } from '../EventTypeDefs';\nimport { LEFT, TOP, MOVING } from '../constants';\nimport { fireEvent } from './fireEvent';\nimport { commonEventInfo, isLocked } from './util';\n\n/**\n * Action handler\n * @private\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if the translation occurred\n */\nexport const dragHandler: TransformActionHandler = (\n eventData,\n transform,\n x,\n y,\n) => {\n const { target, offsetX, offsetY } = transform,\n newLeft = x - offsetX,\n newTop = y - offsetY,\n moveX = !isLocked(target, 'lockMovementX') && target.left !== newLeft,\n moveY = !isLocked(target, 'lockMovementY') && target.top !== newTop;\n moveX && target.set(LEFT, newLeft);\n moveY && target.set(TOP, newTop);\n if (moveX || moveY) {\n fireEvent(MOVING, commonEventInfo(eventData, transform, x, y));\n }\n return moveX || moveY;\n};\n","import { Point } from '../Point';\nimport { Control } from './Control';\nimport type { TMat2D } from '../typedefs';\nimport type { Polyline } from '../shapes/Polyline';\nimport { multiplyTransformMatrices } from '../util/misc/matrix';\nimport type {\n TModificationEvents,\n TPointerEvent,\n Transform,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport { MODIFY_POLY } from '../constants';\n\nconst ACTION_NAME: TModificationEvents = MODIFY_POLY;\n\ntype TTransformAnchor = Transform & { pointIndex: number };\n\n/**\n * This function locates the controls.\n * It'll be used both for drawing and for interaction.\n */\nexport const createPolyPositionHandler = (pointIndex: number) => {\n return function (dim: Point, finalMatrix: TMat2D, polyObject: Polyline) {\n const { points, pathOffset } = polyObject;\n return new Point(points[pointIndex])\n .subtract(pathOffset)\n .transform(\n multiplyTransformMatrices(\n polyObject.getViewportTransform(),\n polyObject.calcTransformMatrix(),\n ),\n );\n };\n};\n\n/**\n * This function defines what the control does.\n * It'll be called on every mouse move after a control has been clicked and is being dragged.\n * The function receives as argument the mouse event, the current transform object\n * and the current position in canvas coordinate `transform.target` is a reference to the\n * current object being transformed.\n */\nexport const polyActionHandler = (\n eventData: TPointerEvent,\n transform: TTransformAnchor,\n x: number,\n y: number,\n) => {\n const { target, pointIndex } = transform;\n const poly = target as Polyline;\n const mouseLocalPosition = sendPointToPlane(\n new Point(x, y),\n undefined,\n poly.calcOwnMatrix(),\n );\n\n poly.points[pointIndex] = mouseLocalPosition.add(poly.pathOffset);\n poly.setDimensions();\n poly.set('dirty', true);\n return true;\n};\n\n/**\n * Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.\n */\nexport const factoryPolyActionHandler = (\n pointIndex: number,\n fn: TransformActionHandler<TTransformAnchor>,\n) => {\n return function (\n eventData: TPointerEvent,\n transform: Transform,\n x: number,\n y: number,\n ) {\n const poly = transform.target as Polyline,\n anchorPoint = new Point(\n poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1],\n ),\n anchorPointInParentPlane = anchorPoint\n .subtract(poly.pathOffset)\n .transform(poly.calcOwnMatrix()),\n actionPerformed = fn(eventData, { ...transform, pointIndex }, x, y);\n\n const newAnchorPointInParentPlane = anchorPoint\n .subtract(poly.pathOffset)\n .transform(poly.calcOwnMatrix());\n\n const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);\n poly.left -= diff.x;\n poly.top -= diff.y;\n\n return actionPerformed;\n };\n};\n\nexport const createPolyActionHandler = (pointIndex: number) =>\n wrapWithFireEvent(\n ACTION_NAME,\n factoryPolyActionHandler(pointIndex, polyActionHandler),\n );\n\nexport function createPolyControls(\n poly: Polyline,\n options?: Partial<Control>,\n): Record<string, Control>;\nexport function createPolyControls(\n numOfControls: number,\n options?: Partial<Control>,\n): Record<string, Control>;\nexport function createPolyControls(\n arg0: number | Polyline,\n options: Partial<Control> = {},\n) {\n const controls = {} as Record<string, Control>;\n for (\n let idx = 0;\n idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length);\n idx++\n ) {\n controls[`p${idx}`] = new Control({\n actionName: ACTION_NAME,\n positionHandler: createPolyPositionHandler(idx),\n actionHandler: createPolyActionHandler(idx),\n ...options,\n });\n }\n return controls;\n}\n","import { Point } from '../Point';\nimport { Control } from './Control';\nimport type { TMat2D } from '../typedefs';\nimport type { Path } from '../shapes/Path';\nimport { multiplyTransformMatrices } from '../util/misc/matrix';\nimport type {\n TModificationEvents,\n TPointerEvent,\n Transform,\n} from '../EventTypeDefs';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport type { TSimpleParseCommandType } from '../util/path/typedefs';\nimport type { ControlRenderingStyleOverride } from './controlRendering';\nimport { fireEvent } from './fireEvent';\nimport { commonEventInfo } from './util';\n\nconst ACTION_NAME: TModificationEvents = 'modifyPath' as const;\n\ntype TTransformAnchor = Transform;\n\nexport type PathPointControlStyle = {\n controlFill?: string;\n controlStroke?: string;\n connectionDashArray?: number[];\n};\n\nconst calcPathPointPosition = (\n pathObject: Path,\n commandIndex: number,\n pointIndex: number,\n) => {\n const { path, pathOffset } = pathObject;\n const command = path[commandIndex];\n return new Point(\n (command[pointIndex] as number) - pathOffset.x,\n (command[pointIndex + 1] as number) - pathOffset.y,\n ).transform(\n multiplyTransformMatrices(\n pathObject.getViewportTransform(),\n pathObject.calcTransformMatrix(),\n ),\n );\n};\n\nconst movePathPoint = (\n pathObject: Path,\n x: number,\n y: number,\n commandIndex: number,\n pointIndex: number,\n) => {\n const { path, pathOffset } = pathObject;\n\n const anchorCommand =\n path[(commandIndex > 0 ? commandIndex : path.length) - 1];\n const anchorPoint = new Point(\n anchorCommand[pointIndex] as number,\n anchorCommand[pointIndex + 1] as number,\n );\n\n const anchorPointInParentPlane = anchorPoint\n .subtract(pathOffset)\n .transform(pathObject.calcOwnMatrix());\n\n const mouseLocalPosition = sendPointToPlane(\n new Point(x, y),\n undefined,\n pathObject.calcOwnMatrix(),\n );\n\n path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;\n path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;\n pathObject.setDimensions();\n\n const newAnchorPointInParentPlane = anchorPoint\n .subtract(pathObject.pathOffset)\n .transform(pathObject.calcOwnMatrix());\n\n const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);\n pathObject.left -= diff.x;\n pathObject.top -= diff.y;\n pathObject.set('dirty', true);\n return true;\n};\n\n/**\n * This function locates the controls.\n * It'll be used both for drawing and for interaction.\n */\nfunction pathPositionHandler(\n this: PathPointControl,\n dim: Point,\n finalMatrix: TMat2D,\n pathObject: Path,\n) {\n const { commandIndex, pointIndex } = this;\n return calcPathPointPosition(pathObject, commandIndex, pointIndex);\n}\n\n/**\n * This function defines what the control does.\n * It'll be called on every mouse move after a control has been clicked and is being dragged.\n * The function receives as argument the mouse event, the current transform object\n * and the current position in canvas coordinate `transform.target` is a reference to the\n * current object being transformed.\n */\nfunction pathActionHandler(\n this: PathPointControl,\n eventData: TPointerEvent,\n transform: TTransformAnchor,\n x: number,\n y: number,\n) {\n const { target } = transform;\n const { commandIndex, pointIndex } = this;\n const actionPerformed = movePathPoint(\n target as Path,\n x,\n y,\n commandIndex,\n pointIndex,\n );\n if (actionPerformed) {\n fireEvent(this.actionName as TModificationEvents, {\n ...commonEventInfo(eventData, transform, x, y),\n commandIndex,\n pointIndex,\n });\n }\n return actionPerformed;\n}\n\nconst indexFromPrevCommand = (previousCommandType: TSimpleParseCommandType) =>\n previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;\n\nclass PathPointControl extends Control {\n declare commandIndex: number;\n declare pointIndex: number;\n declare controlFill: string;\n declare controlStroke: string;\n constructor(options?: Partial<PathPointControl>) {\n super(options);\n }\n\n render(\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride | undefined,\n fabricObject: Path,\n ) {\n const overrides: ControlRenderingStyleOverride = {\n ...styleOverride,\n cornerColor: this.controlFill,\n cornerStrokeColor: this.controlStroke,\n transparentCorners: !this.controlFill,\n };\n super.render(ctx, left, top, overrides, fabricObject);\n }\n}\n\nclass PathControlPointControl extends PathPointControl {\n declare connectionDashArray?: number[];\n declare connectToCommandIndex: number;\n declare connectToPointIndex: number;\n constructor(options?: Partial<PathControlPointControl>) {\n super(options);\n }\n\n render(\n this: PathControlPointControl,\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride | undefined,\n fabricObject: Path,\n ) {\n const { path } = fabricObject;\n const {\n commandIndex,\n pointIndex,\n connectToCommandIndex,\n connectToPointIndex,\n } = this;\n ctx.save();\n ctx.strokeStyle = this.controlStroke;\n if (this.connectionDashArray) {\n ctx.setLineDash(this.connectionDashArray);\n }\n const [commandType] = path[commandIndex];\n const point = calcPathPointPosition(\n fabricObject,\n connectToCommandIndex,\n connectToPointIndex,\n );\n\n if (commandType === 'Q') {\n // one control point connects to 2 points\n const point2 = calcPathPointPosition(\n fabricObject,\n commandIndex,\n pointIndex + 2,\n );\n ctx.moveTo(point2.x, point2.y);\n ctx.lineTo(left, top);\n } else {\n ctx.moveTo(left, top);\n }\n ctx.lineTo(point.x, point.y);\n ctx.stroke();\n ctx.restore();\n\n super.render(ctx, left, top, styleOverride, fabricObject);\n }\n}\n\nconst createControl = (\n commandIndexPos: number,\n pointIndexPos: number,\n isControlPoint: boolean,\n options: Partial<Control> & {\n controlPointStyle?: PathPointControlStyle;\n pointStyle?: PathPointControlStyle;\n },\n connectToCommandIndex?: number,\n connectToPointIndex?: number,\n) =>\n new (isControlPoint ? PathControlPointControl : PathPointControl)({\n commandIndex: commandIndexPos,\n pointIndex: pointIndexPos,\n actionName: ACTION_NAME,\n positionHandler: pathPositionHandler,\n actionHandler: pathActionHandler,\n connectToCommandIndex,\n connectToPointIndex,\n ...options,\n ...(isControlPoint ? options.controlPointStyle : options.pointStyle),\n } as Partial<PathControlPointControl>);\n\nexport function createPathControls(\n path: Path,\n options: Partial<Control> & {\n controlPointStyle?: PathPointControlStyle;\n pointStyle?: PathPointControlStyle;\n } = {},\n): Record<string, Control> {\n const controls = {} as Record<string, Control>;\n let previousCommandType: TSimpleParseCommandType = 'M';\n path.path.forEach((command, commandIndex) => {\n const commandType = command[0];\n\n if (commandType !== 'Z') {\n controls[`c_${commandIndex}_${commandType}`] = createControl(\n commandIndex,\n command.length - 2,\n false,\n options,\n );\n }\n switch (commandType) {\n case 'C':\n controls[`c_${commandIndex}_C_CP_1`] = createControl(\n commandIndex,\n 1,\n true,\n options,\n commandIndex - 1,\n indexFromPrevCommand(previousCommandType),\n );\n controls[`c_${commandIndex}_C_CP_2`] = createControl(\n commandIndex,\n 3,\n true,\n options,\n commandIndex,\n 5,\n );\n break;\n case 'Q':\n controls[`c_${commandIndex}_Q_CP_1`] = createControl(\n commandIndex,\n 1,\n true,\n options,\n commandIndex,\n 3,\n );\n break;\n }\n previousCommandType = commandType;\n });\n return controls;\n}\n","import { getActionFromCorner } from '../controls/util';\nimport { Point } from '../Point';\nimport { FabricObject } from '../shapes/Object/FabricObject';\nimport type {\n CanvasEvents,\n ModifierKey,\n TOptionalModifierKey,\n TPointerEvent,\n Transform,\n} from '../EventTypeDefs';\nimport {\n addTransformToObject,\n saveObjectTransform,\n} from '../util/misc/objectTransforms';\nimport type { TCanvasSizeOptions } from './StaticCanvas';\nimport { StaticCanvas } from './StaticCanvas';\nimport { isCollection } from '../Collection';\nimport { isTransparent } from '../util/misc/isTransparent';\nimport type {\n TMat2D,\n TOriginX,\n TOriginY,\n TSize,\n TSVGReviver,\n} from '../typedefs';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\nimport { getPointer, isTouchEvent } from '../util/dom_event';\nimport type { IText } from '../shapes/IText/IText';\nimport type { BaseBrush } from '../brushes/BaseBrush';\nimport { pick } from '../util/misc/pick';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport { cos, createCanvasElement, sin } from '../util';\nimport { CanvasDOMManager } from './DOMManagers/CanvasDOMManager';\nimport {\n BOTTOM,\n CENTER,\n LEFT,\n MODIFIED,\n RESIZING,\n RIGHT,\n ROTATE,\n SCALE,\n SCALE_X,\n SCALE_Y,\n SKEW_X,\n SKEW_Y,\n TOP,\n} from '../constants';\nimport type { CanvasOptions } from './CanvasOptions';\nimport { canvasDefaults } from './CanvasOptions';\nimport { Intersection } from '../Intersection';\nimport { isActiveSelection } from '../util/typeAssertions';\nimport { dragHandler } from '../controls';\nimport { type FabricImage } from '../shapes/Image';\n\nexport type TargetsInfo = {\n target?: FabricObject;\n subTargets: FabricObject[];\n};\n\nexport type TargetsInfoWithContainer = {\n // the target we think is the most continuing the selection action.\n // could be hoveredTarget or the currently selected object\n target?: FabricObject;\n // the nested targets under the pointer for container\n subTargets: FabricObject[];\n // the container for target, or target itself if there are no selectable nested targets\n container?: FabricObject;\n};\n\nexport type FullTargetsInfoWithContainer = TargetsInfoWithContainer & {\n // hoveredTarget\n currentTarget?: FabricObject;\n // the container for hoveredTarget, or container itself\n currentContainer?: FabricObject;\n // nested targets of current container\n currentSubTargets: FabricObject[];\n};\n\n/**\n * Canvas class\n * @class Canvas\n * @extends StaticCanvas\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-1#canvas}\n *\n * @fires object:modified at the end of a transform\n * @fires object:rotating while an object is being rotated from the control\n * @fires object:scaling while an object is being scaled by controls\n * @fires object:moving while an object is being dragged\n * @fires object:skewing while an object is being skewed from the controls\n *\n * @fires before:transform before a transform is is started\n * @fires before:selection:cleared\n * @fires selection:cleared\n * @fires selection:updated\n * @fires selection:created\n *\n * @fires path:created after a drawing operation ends and the path is added\n * @fires mouse:down\n * @fires mouse:move\n * @fires mouse:up\n * @fires mouse:down:before on mouse down, before the inner fabric logic runs\n * @fires mouse:move:before on mouse move, before the inner fabric logic runs\n * @fires mouse:up:before on mouse up, before the inner fabric logic runs\n * @fires mouse:over\n * @fires mouse:out\n * @fires mouse:dblclick whenever a native dbl click event fires on the canvas.\n *\n * @fires dragover\n * @fires dragenter\n * @fires dragleave\n * @fires drag:enter object drag enter\n * @fires drag:leave object drag leave\n * @fires drop:before before drop event. Prepare for the drop event (same native event).\n * @fires drop\n * @fires drop:after after drop event. Run logic on canvas after event has been accepted/declined (same native event).\n * @example\n * let a: fabric.Object, b: fabric.Object;\n * let flag = false;\n * canvas.add(a, b);\n * a.on('drop:before', opt => {\n * // we want a to accept the drop even though it's below b in the stack\n * flag = this.canDrop(opt.e);\n * });\n * b.canDrop = function(e) {\n * !flag && this.draggableTextDelegate.canDrop(e);\n * }\n * b.on('dragover', opt => b.set('fill', opt.dropTarget === b ? 'pink' : 'black'));\n * a.on('drop', opt => {\n * opt.e.defaultPrevented // drop occurred\n * opt.didDrop // drop occurred on canvas\n * opt.target // drop target\n * opt.target !== a && a.set('text', 'I lost');\n * });\n * canvas.on('drop:after', opt => {\n * // inform user who won\n * if(!opt.e.defaultPrevented) {\n * // no winners\n * }\n * else if(!opt.didDrop) {\n * // my objects didn't win, some other lucky object\n * }\n * else {\n * // we have a winner it's opt.target!!\n * }\n * })\n *\n * @fires after:render at the end of the render process, receives the context in the callback\n * @fires before:render at start the render process, receives the context in the callback\n *\n * @fires contextmenu:before\n * @fires contextmenu\n * @example\n * let handler;\n * targets.forEach(target => {\n * target.on('contextmenu:before', opt => {\n * // decide which target should handle the event before canvas hijacks it\n * if (someCaseHappens && opt.targets.includes(target)) {\n * handler = target;\n * }\n * });\n * target.on('contextmenu', opt => {\n * // do something fantastic\n * });\n * });\n * canvas.on('contextmenu', opt => {\n * if (!handler) {\n * // no one takes responsibility, it's always left to me\n * // let's show them how it's done!\n * }\n * });\n *\n */\nexport class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>\n extends StaticCanvas<EventSpec>\n implements Omit<CanvasOptions, 'enablePointerEvents'>\n{\n declare _objects: FabricObject[];\n\n // transform config\n declare uniformScaling: boolean;\n declare uniScaleKey: TOptionalModifierKey;\n declare centeredScaling: boolean;\n declare centeredRotation: boolean;\n declare centeredKey: TOptionalModifierKey;\n declare altActionKey: TOptionalModifierKey;\n\n // selection config\n declare selection: boolean;\n declare selectionKey: TOptionalModifierKey | ModifierKey[];\n declare altSelectionKey: TOptionalModifierKey;\n declare selectionColor: string;\n declare selectionDashArray: number[];\n declare selectionBorderColor: string;\n declare selectionLineWidth: number;\n declare selectionFullyContained: boolean;\n\n // cursors\n declare hoverCursor: CSSStyleDeclaration['cursor'];\n declare moveCursor: CSSStyleDeclaration['cursor'];\n declare defaultCursor: CSSStyleDeclaration['cursor'];\n declare freeDrawingCursor: CSSStyleDeclaration['cursor'];\n declare notAllowedCursor: CSSStyleDeclaration['cursor'];\n\n declare containerClass: string;\n\n // target find config\n declare perPixelTargetFind: boolean;\n declare targetFindTolerance: number;\n declare skipTargetFind: boolean;\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 * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-4#free_drawing}\n * @type Boolean\n */\n declare isDrawingMode: boolean;\n\n declare preserveObjectStacking: boolean;\n\n // event config\n declare stopContextMenu: boolean;\n declare fireRightClick: boolean;\n declare fireMiddleClick: boolean;\n\n /**\n * Keep track of the hovered target in the previous event\n * @type FabricObject | null\n * @private\n */\n declare _hoveredTarget?: FabricObject;\n\n /**\n * hold the list of nested targets hovered in the previous events\n * @type FabricObject[]\n * @private\n */\n _hoveredTargets: FabricObject[] = [];\n\n /**\n * hold the list of objects to render\n * @type FabricObject[]\n * @private\n */\n declare _objectsToRender?: FabricObject[];\n\n /**\n * hold a reference to a data structure that contains information\n * on the current on going transform\n * @type\n * @private\n */\n _currentTransform: Transform | null = null;\n\n /**\n * hold a reference to a data structure used to track the selection\n * box on canvas drag\n * on the current on going transform\n * x, y, deltaX and deltaY are in scene plane\n * @type\n * @private\n */\n protected _groupSelector: {\n x: number;\n y: number;\n deltaX: number;\n deltaY: number;\n } | null = null;\n\n /**\n * internal flag used to understand if the context top requires a cleanup\n * in case this is true, the contextTop will be cleared at the next render\n * @type boolean\n * @private\n */\n contextTopDirty = false;\n\n /**\n * During a mouse event we may need the pointer multiple times in multiple functions.\n * _scenePoint holds a reference to the pointer in fabricCanvas/design coordinates that is valid for the event\n * lifespan. Every fabricJS mouse event create and delete the cache every time\n * We do this because there are some HTML DOM inspection functions to get the actual pointer coordinates\n * @type {Point}\n */\n declare protected _scenePoint?: Point;\n\n /**\n * During a mouse event we may need the pointer multiple times in multiple functions.\n * _viewportPoint holds a reference to the pointer in html coordinates that is valid for the event\n * lifespan. Every fabricJS mouse event create and delete the cache every time\n * We do this because there are some HTML DOM inspection functions to get the actual pointer coordinates\n * @type {Point}\n */\n declare protected _viewportPoint?: Point;\n\n /**\n * Holds the informations we cache during an event lifespan\n * This data is needed many times during an event and we want to avoid to recalculate it\n * multuple times.\n */\n declare protected _targetInfo: FullTargetsInfoWithContainer | undefined;\n\n static ownDefaults = canvasDefaults;\n\n static getDefaults(): Record<string, any> {\n return { ...super.getDefaults(), ...SelectableCanvas.ownDefaults };\n }\n\n declare elements: CanvasDOMManager;\n get upperCanvasEl() {\n return this.elements.upper?.el;\n }\n get contextTop() {\n return this.elements.upper?.ctx;\n }\n get wrapperEl() {\n return this.elements.container;\n }\n declare private pixelFindCanvasEl: HTMLCanvasElement;\n declare private pixelFindContext: CanvasRenderingContext2D;\n\n declare protected _isCurrentlyDrawing: boolean;\n declare freeDrawingBrush?: BaseBrush;\n declare _activeObject?: FabricObject;\n\n protected initElements(el?: string | HTMLCanvasElement) {\n this.elements = new CanvasDOMManager(el, {\n allowTouchScrolling: this.allowTouchScrolling,\n containerClass: this.containerClass,\n });\n this._createCacheCanvas();\n }\n\n /**\n * @private\n * @param {FabricObject} obj Object that was added\n */\n _onObjectAdded(obj: FabricObject) {\n this._objectsToRender = undefined;\n super._onObjectAdded(obj);\n }\n\n /**\n * @private\n * @param {FabricObject} obj Object that was removed\n */\n _onObjectRemoved(obj: FabricObject) {\n this._objectsToRender = undefined;\n // removing active object should fire \"selection:cleared\" events\n if (obj === this._activeObject) {\n this.fire('before:selection:cleared', { deselected: [obj] });\n this._discardActiveObject();\n this.fire('selection:cleared', { deselected: [obj] });\n obj.fire('deselected', {\n target: obj,\n });\n }\n if (obj === this._hoveredTarget) {\n this._hoveredTarget = undefined;\n this._hoveredTargets = [];\n }\n super._onObjectRemoved(obj);\n }\n\n _onStackOrderChanged() {\n this._objectsToRender = undefined;\n super._onStackOrderChanged();\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(): FabricObject[] {\n const activeObject = this._activeObject;\n return !this.preserveObjectStacking && activeObject\n ? this._objects\n .filter((object) => !object.group && object !== activeObject)\n .concat(activeObject)\n : this._objects;\n }\n\n /**\n * Renders both the top canvas and the secondary container canvas.\n */\n renderAll() {\n this.cancelRequestedRender();\n if (this.destroyed) {\n return;\n }\n if (this.contextTopDirty && !this._groupSelector && !this.isDrawingMode) {\n this.clearContext(this.contextTop);\n this.contextTopDirty = false;\n }\n if (this.hasLostContext) {\n this.renderTopLayer(this.contextTop);\n this.hasLostContext = false;\n }\n !this._objectsToRender &&\n (this._objectsToRender = this._chooseObjectsToRender());\n this.renderCanvas(this.getContext(), this._objectsToRender);\n }\n\n /**\n * text selection is rendered by the active text instance during the rendering cycle\n */\n renderTopLayer(ctx: CanvasRenderingContext2D): void {\n ctx.save();\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this.freeDrawingBrush && this.freeDrawingBrush._render();\n this.contextTopDirty = true;\n }\n // we render the top context - last object\n if (this.selection && this._groupSelector) {\n this._drawSelection(ctx);\n this.contextTopDirty = true;\n }\n ctx.restore();\n }\n\n /**\n * Method to render only the top canvas.\n * Also used to render the group selection box.\n * Does not render text selection.\n */\n renderTop() {\n const ctx = this.contextTop;\n this.clearContext(ctx);\n this.renderTopLayer(ctx);\n // todo: how do i know if the after:render is for the top or normal contex?\n this.fire('after:render', { ctx });\n }\n\n /**\n * Set the canvas tolerance value for pixel taret find.\n * Use only integer numbers.\n * @private\n */\n setTargetFindTolerance(value: number) {\n value = Math.round(value);\n this.targetFindTolerance = value;\n const retina = this.getRetinaScaling();\n const size = Math.ceil((value * 2 + 1) * retina);\n this.pixelFindCanvasEl.width = this.pixelFindCanvasEl.height = size;\n this.pixelFindContext.scale(retina, retina);\n }\n\n /**\n * Returns true if object is transparent at a certain location\n * Clarification: this is `is target transparent at location X or are controls there`\n * @TODO this seems dumb that we treat controls with transparency. we can find controls\n * programmatically without painting them, the cache canvas optimization is always valid\n * @param {FabricObject} target Object to check\n * @param {Number} x Left coordinate in viewport space\n * @param {Number} y Top coordinate in viewport space\n * @return {Boolean}\n */\n isTargetTransparent(target: FabricObject, x: number, y: number): boolean {\n const tolerance = this.targetFindTolerance;\n const ctx = this.pixelFindContext;\n this.clearContext(ctx);\n ctx.save();\n ctx.translate(-x + tolerance, -y + tolerance);\n ctx.transform(...this.viewportTransform);\n const selectionBgc = target.selectionBackgroundColor;\n target.selectionBackgroundColor = '';\n target.render(ctx);\n target.selectionBackgroundColor = selectionBgc;\n ctx.restore();\n // our canvas is square, and made around tolerance.\n // so tolerance in this case also represent the center of the canvas.\n const enhancedTolerance = Math.round(tolerance * this.getRetinaScaling());\n return isTransparent(\n ctx,\n enhancedTolerance,\n enhancedTolerance,\n enhancedTolerance,\n );\n }\n\n /**\n * takes an event and determines if selection key has been pressed\n * @private\n * @param {TPointerEvent} e Event object\n */\n _isSelectionKeyPressed(e: TPointerEvent): boolean {\n const sKey = this.selectionKey;\n if (!sKey) {\n return false;\n }\n if (Array.isArray(sKey)) {\n return !!sKey.find((key) => !!key && e[key] === true);\n } else {\n return e[sKey];\n }\n }\n\n /**\n * @private\n * @param {TPointerEvent} e Event object\n * @param {FabricObject} target\n */\n _shouldClearSelection(\n e: TPointerEvent,\n target?: FabricObject,\n ): target is undefined {\n const activeObjects = this.getActiveObjects(),\n activeObject = this._activeObject;\n\n return !!(\n !target ||\n (target &&\n activeObject &&\n activeObjects.length > 1 &&\n activeObjects.indexOf(target) === -1 &&\n activeObject !== target &&\n !this._isSelectionKeyPressed(e)) ||\n (target && !target.evented) ||\n (target && !target.selectable && activeObject && activeObject !== target)\n );\n }\n\n /**\n * This method will take in consideration a modifier key pressed and the control we are\n * about to drag, and try to guess the anchor point ( origin ) of the transormation.\n * This should be really in the realm of controls, and we should remove specific code for legacy\n * embedded actions.\n * @TODO this probably deserve discussion/rediscovery and change/refactor\n * @private\n * @deprecated\n * @param {FabricObject} target\n * @param {string} action\n * @param {boolean} altKey\n * @returns {boolean} true if the transformation should be centered\n */\n private _shouldCenterTransform(\n target: FabricObject,\n action: string,\n modifierKeyPressed: boolean,\n ) {\n if (!target) {\n return;\n }\n\n let centerTransform;\n\n if (\n action === SCALE ||\n action === SCALE_X ||\n action === SCALE_Y ||\n action === RESIZING\n ) {\n centerTransform = this.centeredScaling || target.centeredScaling;\n } else if (action === ROTATE) {\n centerTransform = this.centeredRotation || target.centeredRotation;\n }\n\n return centerTransform ? !modifierKeyPressed : modifierKeyPressed;\n }\n\n /**\n * Given the control clicked, determine the origin of the transform.\n * This is bad because controls can totally have custom names\n * should disappear before release 4.0\n * @private\n * @deprecated\n */\n _getOriginFromCorner(\n target: FabricObject,\n controlName: string,\n ): { x: TOriginX; y: TOriginY } {\n const origin = {\n x: target.originX,\n y: target.originY,\n };\n\n if (!controlName) {\n return origin;\n }\n\n // is a left control ?\n if (['ml', 'tl', 'bl'].includes(controlName)) {\n origin.x = RIGHT;\n // is a right control ?\n } else if (['mr', 'tr', 'br'].includes(controlName)) {\n origin.x = LEFT;\n }\n // is a top control ?\n if (['tl', 'mt', 'tr'].includes(controlName)) {\n origin.y = BOTTOM;\n // is a bottom control ?\n } else if (['bl', 'mb', 'br'].includes(controlName)) {\n origin.y = TOP;\n }\n return origin;\n }\n\n /**\n * @private\n * @param {Event} e Event object\n * @param {FabricObject} target\n * @param {boolean} [alreadySelected] pass true to setup the active control\n */\n _setupCurrentTransform(\n e: TPointerEvent,\n target: FabricObject,\n alreadySelected: boolean,\n ): void {\n const pointer = target.group\n ? // transform pointer to target's containing coordinate plane\n sendPointToPlane(\n this.getScenePoint(e),\n undefined,\n target.group.calcTransformMatrix(),\n )\n : this.getScenePoint(e);\n const { key: corner = '', control } = target.getActiveControl() || {},\n actionHandler =\n alreadySelected && control\n ? control.getActionHandler(e, target, control)?.bind(control)\n : dragHandler,\n action = getActionFromCorner(alreadySelected, corner, e, target),\n altKey = e[this.centeredKey as ModifierKey],\n origin = this._shouldCenterTransform(target, action, altKey)\n ? ({ x: CENTER, y: CENTER } as const)\n : this._getOriginFromCorner(target, corner),\n {\n scaleX,\n scaleY,\n skewX,\n skewY,\n left,\n top,\n angle,\n width,\n height,\n cropX,\n cropY,\n } = target as FabricImage,\n /**\n * relative to target's containing coordinate plane\n * both agree on every point\n **/\n transform: Transform = {\n target,\n action,\n actionHandler,\n actionPerformed: false,\n corner,\n scaleX,\n scaleY,\n skewX,\n skewY,\n offsetX: pointer.x - left,\n offsetY: pointer.y - 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 theta: degreesToRadians(angle),\n width,\n height,\n shiftKey: e.shiftKey,\n altKey,\n original: {\n ...saveObjectTransform(target),\n originX: origin.x,\n originY: origin.y,\n cropX,\n cropY,\n },\n };\n\n this._currentTransform = transform;\n\n this.fire('before:transform', {\n e,\n transform,\n });\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(value: CSSStyleDeclaration['cursor']): void {\n this.upperCanvasEl.style.cursor = value;\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx to draw the selection on\n */\n _drawSelection(ctx: CanvasRenderingContext2D): void {\n const { x, y, deltaX, deltaY } = this._groupSelector!,\n start = new Point(x, y).transform(this.viewportTransform),\n extent = new Point(x + deltaX, y + deltaY).transform(\n this.viewportTransform,\n ),\n strokeOffset = this.selectionLineWidth / 2;\n let minX = Math.min(start.x, extent.x),\n minY = Math.min(start.y, extent.y),\n maxX = Math.max(start.x, extent.x),\n maxY = Math.max(start.y, extent.y);\n\n if (this.selectionColor) {\n ctx.fillStyle = this.selectionColor;\n ctx.fillRect(minX, minY, maxX - minX, maxY - minY);\n }\n\n if (!this.selectionLineWidth || !this.selectionBorderColor) {\n return;\n }\n ctx.lineWidth = this.selectionLineWidth;\n ctx.strokeStyle = this.selectionBorderColor;\n\n minX += strokeOffset;\n minY += strokeOffset;\n maxX -= strokeOffset;\n maxY -= strokeOffset;\n // selection border\n // @TODO: is _setLineDash still necessary on modern canvas?\n FabricObject.prototype._setLineDash.call(\n this,\n ctx,\n this.selectionDashArray,\n );\n ctx.strokeRect(minX, minY, maxX - minX, maxY - minY);\n }\n\n /**\n * This function is in charge of deciding which is the object that is the current target of an interaction event.\n * For interaction event we mean a pointer related action on the canvas.\n * Which is the\n * 11/09/2018 TODO: would be cool if findTarget could discern between being a full target\n * or the outside part of the corner.\n * @param {Event} e mouse event\n * @return {TargetsInfoWithContainer} the target found\n */\n findTarget(e: TPointerEvent): FullTargetsInfoWithContainer {\n // this._targetInfo is cached by _cacheTransformEventData\n // and destroyed by _resetTransformEventData\n if (this._targetInfo) {\n return this._targetInfo;\n }\n\n if (this.skipTargetFind) {\n return {\n subTargets: [],\n currentSubTargets: [],\n };\n }\n\n const pointer = this.getScenePoint(e),\n activeObject = this._activeObject,\n aObjects = this.getActiveObjects(),\n targetInfo = this.searchPossibleTargets(this._objects, pointer);\n\n const {\n subTargets: currentSubTargets,\n container: currentContainer,\n target: currentTarget,\n } = targetInfo;\n\n const fullTargetInfo: FullTargetsInfoWithContainer = {\n ...targetInfo,\n currentSubTargets,\n currentContainer,\n currentTarget,\n };\n\n // simplest case no active object, return a new target\n if (!activeObject) {\n return fullTargetInfo;\n }\n\n // check pointer is over active selection and possibly perform `subTargetCheck`\n const activeObjectTargetInfo: FullTargetsInfoWithContainer = {\n ...this.searchPossibleTargets([activeObject], pointer),\n currentSubTargets,\n currentContainer,\n currentTarget,\n };\n\n const activeObjectControl = activeObject.findControl(\n this.getViewportPoint(e),\n isTouchEvent(e),\n );\n\n // we are clicking exactly the control of an active object, shortcut to that object.\n if (activeObjectControl) {\n return {\n ...activeObjectTargetInfo,\n target: activeObject, // we override target in case we are in the outside part of the corner.\n };\n }\n\n // in case we are over the active object\n if (activeObjectTargetInfo.target) {\n if (aObjects.length > 1) {\n // in case of active selection and target hit over the activeSelection, just exit\n // TODO Verify if we need to override target with container\n return activeObjectTargetInfo;\n }\n // from here onward not an active selection, just an activeOject that maybe is a group\n\n // preserveObjectStacking is false, so activeObject is drawn on top, just return activeObject\n if (!this.preserveObjectStacking) {\n // TODO Verify if we need to override target with container\n return activeObjectTargetInfo;\n }\n\n // In case we are in preserveObjectStacking ( selection in stack )\n // there is the possibility to force with `altSelectionKey` to return the activeObject\n // from any point in the stack, even if we have another object completely on top of it.\n if (\n this.preserveObjectStacking &&\n e[this.altSelectionKey as ModifierKey]\n ) {\n // TODO Verify if we need to override target with container\n return activeObjectTargetInfo;\n }\n }\n\n // we have an active object, but we ruled out it being our target in any way.\n return fullTargetInfo;\n }\n\n /**\n * Checks if the point is inside the object selection area including padding\n * @param {FabricObject} obj Object to test against\n * @param {Object} [pointer] point in scene coordinates\n * @return {Boolean} true if point is contained within an area of given object\n * @private\n */\n private _pointIsInObjectSelectionArea(obj: FabricObject, point: Point) {\n // getCoords will already take care of group de-nesting\n let coords = obj.getCoords();\n const viewportZoom = this.getZoom();\n const padding = obj.padding / viewportZoom;\n if (padding) {\n const [tl, tr, br, bl] = coords;\n // what is the angle of the object?\n // we could use getTotalAngle, but is way easier to look at it\n // from how coords are oriented, since if something went wrong\n // at least we are consistent.\n const angleRadians = Math.atan2(tr.y - tl.y, tr.x - tl.x),\n cosP = cos(angleRadians) * padding,\n sinP = sin(angleRadians) * padding,\n cosPSinP = cosP + sinP,\n cosPMinusSinP = cosP - sinP;\n\n coords = [\n new Point(tl.x - cosPMinusSinP, tl.y - cosPSinP),\n new Point(tr.x + cosPSinP, tr.y - cosPMinusSinP),\n new Point(br.x + cosPMinusSinP, br.y + cosPSinP),\n new Point(bl.x - cosPSinP, bl.y + cosPMinusSinP),\n ];\n // in case of padding we calculate the new coords on the fly.\n // otherwise we have to maintain 2 sets of coordinates for everything.\n // we can reiterate on storing them.\n // if this is slow, for now the semplification is large and doesn't impact\n // rendering.\n // the idea behind this is that outside target check we don't need ot know\n // where those coords are\n }\n return Intersection.isPointInPolygon(point, coords);\n }\n\n /**\n * Checks point is inside the object selection condition. Either area with padding\n * or over pixels if perPixelTargetFind is enabled\n * @param {FabricObject} obj Object to test against\n * @param {Point} pointer point from scene.\n * @return {Boolean} true if point is contained within an area of given object\n * @private\n */\n _checkTarget(obj: FabricObject, pointer: Point): boolean {\n if (\n obj &&\n obj.visible &&\n obj.evented &&\n this._pointIsInObjectSelectionArea(obj, pointer)\n ) {\n if (\n (this.perPixelTargetFind || obj.perPixelTargetFind) &&\n !(obj as unknown as IText).isEditing\n ) {\n const viewportPoint = pointer.transform(this.viewportTransform);\n if (!this.isTargetTransparent(obj, viewportPoint.x, viewportPoint.y)) {\n return true;\n }\n } else {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Given an array of objects search possible targets under the pointer position\n * Returns an\n * @param {Array} objects objects array to look into\n * @param {Object} pointer x,y object of point of scene coordinates we want to check.\n * @param {Object} subTargets If passed, subtargets will be collected inside the array\n * @return {TargetsInfo} **top most object from given `objects`** that contains pointer\n * @private\n */\n _searchPossibleTargets(\n objects: FabricObject[],\n pointer: Point,\n subTargets: FabricObject[],\n ): TargetsInfo {\n let i = objects.length;\n // Do not check for currently grouped objects, since we check the parent group itself.\n // until we call this function specifically to search inside the activeGroup\n while (i--) {\n const target = objects[i];\n if (this._checkTarget(target, pointer)) {\n if (isCollection(target) && target.subTargetCheck) {\n const { target: subTarget } = this._searchPossibleTargets(\n target._objects,\n pointer,\n subTargets,\n );\n subTarget && subTargets.push(subTarget);\n }\n return {\n target,\n subTargets,\n };\n }\n }\n return {\n subTargets: [],\n };\n }\n\n /**\n * Search inside an objects array the fiurst object that contains pointer\n * Collect subTargets of that object inside the subTargets array passed as parameter\n * @param {FabricObject[]} objects objects array to look into\n * @param {Point} pointer coordinates from viewport to check.\n * @return {FabricObject} **top most object on screen** that contains pointer\n */\n searchPossibleTargets(\n objects: FabricObject[],\n pointer: Point,\n ): TargetsInfoWithContainer {\n const targetInfo: TargetsInfoWithContainer = this._searchPossibleTargets(\n objects,\n pointer,\n [],\n );\n\n // outermost target is the container.\n targetInfo.container = targetInfo.target;\n const { container, subTargets } = targetInfo;\n\n if (\n container &&\n isCollection(container) &&\n container.interactive &&\n subTargets[0]\n ) {\n /** subTargets[0] is the innermost nested target, but it could be inside non interactive groups\n * and so not a possible selection target.\n * We loop the array from the end that is outermost innertarget.\n */\n for (let i = subTargets.length - 1; i > 0; i--) {\n const t = subTargets[i];\n if (!(isCollection(t) && t.interactive)) {\n // one of the subtargets was not interactive. that is the last subtarget we can return.\n // we can't dig more deep;\n targetInfo.target = t;\n return targetInfo;\n }\n }\n targetInfo.target = subTargets[0];\n return targetInfo;\n }\n\n return targetInfo;\n }\n\n /**\n * @returns point existing in the same plane as the {@link HTMLCanvasElement},\n * `(0, 0)` being the top left corner of the {@link HTMLCanvasElement}.\n * This means that changes to the {@link viewportTransform} do not change the values of the point\n * and it remains unchanged from the viewer's perspective.\n *\n * @example\n * const scenePoint = sendPointToPlane(\n * this.getViewportPoint(e),\n * undefined,\n * canvas.viewportTransform\n * );\n *\n */\n getViewportPoint(e: TPointerEvent) {\n if (this._viewportPoint) {\n return this._viewportPoint;\n }\n return this._getPointerImpl(e, true);\n }\n\n /**\n * @returns point existing in the scene (the same plane as the plane {@link FabricObject#getCenterPoint} exists in).\n * This means that changes to the {@link viewportTransform} do not change the values of the point,\n * however, from the viewer's perspective, the point is changed.\n *\n * @example\n * const viewportPoint = sendPointToPlane(\n * this.getScenePoint(e),\n * canvas.viewportTransform\n * );\n *\n */\n getScenePoint(e: TPointerEvent) {\n if (this._scenePoint) {\n return this._scenePoint;\n }\n return this._getPointerImpl(e);\n }\n\n /**\n * Returns pointer relative to canvas.\n *\n * Use {@link getViewportPoint} or {@link getScenePoint} instead.\n *\n * @param {Event} e\n * @param {Boolean} [fromViewport] whether to return the point from the viewport or in the scene\n * @return {Point}\n */\n protected _getPointerImpl(e: TPointerEvent, fromViewport = false): Point {\n const upperCanvasEl = this.upperCanvasEl,\n bounds = upperCanvasEl.getBoundingClientRect();\n let pointer = getPointer(e),\n boundsWidth = bounds.width || 0,\n boundsHeight = bounds.height || 0;\n\n if (!boundsWidth || !boundsHeight) {\n if (TOP in bounds && BOTTOM in bounds) {\n boundsHeight = Math.abs(bounds.top - bounds.bottom);\n }\n if (RIGHT in bounds && LEFT in bounds) {\n boundsWidth = Math.abs(bounds.right - bounds.left);\n }\n }\n\n this.calcOffset();\n pointer.x = pointer.x - this._offset.left;\n pointer.y = pointer.y - this._offset.top;\n if (!fromViewport) {\n pointer = sendPointToPlane(pointer, undefined, this.viewportTransform);\n }\n\n const retinaScaling = this.getRetinaScaling();\n if (retinaScaling !== 1) {\n pointer.x /= retinaScaling;\n pointer.y /= retinaScaling;\n }\n\n // If bounds are not available (i.e. not visible), do not apply scale.\n const cssScale =\n boundsWidth === 0 || boundsHeight === 0\n ? new Point(1, 1)\n : new Point(\n upperCanvasEl.width / boundsWidth,\n upperCanvasEl.height / boundsHeight,\n );\n\n return pointer.multiply(cssScale);\n }\n\n /**\n * Internal use only\n * @protected\n */\n protected _setDimensionsImpl(\n dimensions: TSize,\n options?: TCanvasSizeOptions,\n ) {\n // @ts-expect-error this method exists in the subclass - should be moved or declared as abstract\n this._resetTransformEventData();\n super._setDimensionsImpl(dimensions, options);\n if (this._isCurrentlyDrawing) {\n this.freeDrawingBrush &&\n this.freeDrawingBrush._setBrushStyles(this.contextTop);\n }\n }\n\n protected _createCacheCanvas() {\n this.pixelFindCanvasEl = createCanvasElement();\n this.pixelFindContext = this.pixelFindCanvasEl.getContext('2d', {\n willReadFrequently: true,\n })!;\n this.setTargetFindTolerance(this.targetFindTolerance);\n }\n\n /**\n * Returns context of top canvas where interactions are drawn\n * @returns {CanvasRenderingContext2D}\n */\n getTopContext(): CanvasRenderingContext2D {\n return this.elements.upper.ctx;\n }\n\n /**\n * Returns context of canvas where object selection is drawn\n * @alias\n * @return {CanvasRenderingContext2D}\n */\n getSelectionContext(): CanvasRenderingContext2D {\n return this.elements.upper.ctx;\n }\n\n /**\n * Returns <canvas> element on which object selection is drawn\n * @return {HTMLCanvasElement}\n */\n getSelectionElement(): HTMLCanvasElement {\n return this.elements.upper.el;\n }\n\n /**\n * Returns currently active object\n * @return {FabricObject | null} active object\n */\n getActiveObject(): FabricObject | undefined {\n return this._activeObject;\n }\n\n /**\n * Returns an array with the current selected objects\n * @return {FabricObject[]} active objects array\n */\n getActiveObjects(): FabricObject[] {\n const active = this._activeObject;\n return isActiveSelection(active)\n ? active.getObjects()\n : active\n ? [active]\n : [];\n }\n\n /**\n * @private\n * Compares the old activeObject with the current one and fires correct events\n * @param {FabricObject[]} oldObjects old activeObject\n * @param {TPointerEvent} e mouse event triggering the selection events\n */\n _fireSelectionEvents(oldObjects: FabricObject[], e?: TPointerEvent) {\n let somethingChanged = false,\n invalidate = false;\n const objects = this.getActiveObjects(),\n added: FabricObject[] = [],\n removed: FabricObject[] = [];\n\n oldObjects.forEach((target) => {\n if (!objects.includes(target)) {\n somethingChanged = true;\n target.fire('deselected', {\n e,\n target,\n });\n removed.push(target);\n }\n });\n\n objects.forEach((target) => {\n if (!oldObjects.includes(target)) {\n somethingChanged = true;\n target.fire('selected', {\n e,\n target,\n });\n added.push(target);\n }\n });\n\n if (oldObjects.length > 0 && objects.length > 0) {\n invalidate = true;\n somethingChanged &&\n this.fire('selection:updated', {\n e,\n selected: added,\n deselected: removed,\n });\n } else if (objects.length > 0) {\n invalidate = true;\n this.fire('selection:created', {\n e,\n selected: added,\n });\n } else if (oldObjects.length > 0) {\n invalidate = true;\n this.fire('selection:cleared', {\n e,\n deselected: removed,\n });\n }\n invalidate && (this._objectsToRender = undefined);\n }\n\n /**\n * Sets given object as the only active object on canvas\n * @param {FabricObject} object Object to set as an active one\n * @param {TPointerEvent} [e] Event (passed along when firing \"object:selected\")\n * @return {Boolean} true if the object has been selected\n */\n setActiveObject(object: FabricObject, e?: TPointerEvent) {\n // we can't inline this, since _setActiveObject will change what getActiveObjects returns\n const currentActives = this.getActiveObjects();\n const selected = this._setActiveObject(object, e);\n this._fireSelectionEvents(currentActives, e);\n return selected;\n }\n\n /**\n * This is supposed to be equivalent to setActiveObject but without firing\n * any event. There is commitment to have this stay this way.\n * This is the functional part of setActiveObject.\n * @param {Object} object to set as active\n * @param {Event} [e] Event (passed along when firing \"object:selected\")\n * @return {Boolean} true if the object has been selected\n */\n _setActiveObject(object: FabricObject, e?: TPointerEvent) {\n const prevActiveObject = this._activeObject;\n if (prevActiveObject === object) {\n return false;\n }\n // after calling this._discardActiveObject, this,_activeObject could be undefined\n if (!this._discardActiveObject(e, object) && this._activeObject) {\n // refused to deselect\n return false;\n }\n if (object.onSelect({ e })) {\n return false;\n }\n\n this._activeObject = object;\n\n if (isActiveSelection(object) && prevActiveObject !== object) {\n object.set('canvas', this);\n }\n object.setCoords();\n\n return true;\n }\n\n /**\n * This is supposed to be equivalent to discardActiveObject but without firing\n * any selection events ( can still fire object transformation events ). There is commitment to have this stay this way.\n * This is the functional part of discardActiveObject.\n * @param {Event} [e] Event (passed along when firing \"object:deselected\")\n * @param {Object} object the next object to set as active, reason why we are discarding this\n * @return {Boolean} true if the active object has been discarded\n */\n _discardActiveObject(\n e?: TPointerEvent,\n object?: FabricObject,\n ): this is { _activeObject: undefined } {\n const obj = this._activeObject;\n if (obj) {\n // onDeselect return TRUE to cancel selection;\n if (obj.onDeselect({ e, object })) {\n return false;\n }\n if (this._currentTransform && this._currentTransform.target === obj) {\n this.endCurrentTransform(e);\n }\n if (isActiveSelection(obj) && obj === this._hoveredTarget) {\n this._hoveredTarget = undefined;\n }\n this._activeObject = undefined;\n return true;\n }\n return false;\n }\n\n /**\n * Discards currently active object and fire events. If the function is called by fabric\n * as a consequence of a mouse event, the event is passed as a parameter and\n * sent to the fire function for the custom events. When used as a method the\n * e param does not have any application.\n * @param {event} e\n * @return {Boolean} true if the active object has been discarded\n */\n discardActiveObject(e?: TPointerEvent): this is { _activeObject: undefined } {\n const currentActives = this.getActiveObjects(),\n activeObject = this.getActiveObject();\n if (currentActives.length) {\n this.fire('before:selection:cleared', {\n e,\n deselected: [activeObject!],\n });\n }\n const discarded = this._discardActiveObject(e);\n this._fireSelectionEvents(currentActives, e);\n return discarded;\n }\n\n /**\n * End the current transform.\n * You don't usually need to call this method unless you are interrupting a user initiated transform\n * because of some other event ( a press of key combination, or something that block the user UX )\n * @param {Event} [e] send the mouse event that generate the finalize down, so it can be used in the event\n */\n endCurrentTransform(e?: TPointerEvent) {\n const transform = this._currentTransform;\n this._finalizeCurrentTransform(e);\n if (transform && transform.target) {\n // this could probably go inside _finalizeCurrentTransform\n transform.target.isMoving = false;\n }\n this._currentTransform = null;\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(e?: TPointerEvent) {\n const transform = this._currentTransform!,\n target = transform.target,\n options = {\n e,\n target,\n transform,\n action: transform.action,\n };\n\n if (target._scaling) {\n target._scaling = false;\n }\n\n target.setCoords();\n\n if (transform.actionPerformed) {\n this.fire('object:modified', options);\n target.fire(MODIFIED, options);\n }\n }\n\n /**\n * Sets viewport transformation of this canvas instance\n * @param {Array} vpt a Canvas 2D API transform matrix\n */\n setViewportTransform(vpt: TMat2D) {\n super.setViewportTransform(vpt);\n const activeObject = this._activeObject;\n if (activeObject) {\n activeObject.setCoords();\n }\n }\n\n /**\n * @override clears active selection ref and interactive canvas elements and contexts\n */\n destroy() {\n // dispose of active selection\n const activeObject = this._activeObject;\n if (isActiveSelection(activeObject)) {\n activeObject.removeAll();\n activeObject.dispose();\n }\n\n delete this._activeObject;\n\n super.destroy();\n\n // free resources\n\n // pixel find canvas\n // @ts-expect-error disposing\n this.pixelFindContext = null;\n // @ts-expect-error disposing\n this.pixelFindCanvasEl = undefined;\n }\n\n /**\n * Clears all contexts (background, main, top) of an instance\n */\n clear() {\n // discard active object and fire events\n this.discardActiveObject();\n // make sure we clear the active object in case it refused to be discarded\n this._activeObject = undefined;\n this.clearContext(this.contextTop);\n super.clear();\n }\n\n /**\n * Draws objects' controls (borders/controls)\n * @param {CanvasRenderingContext2D} ctx Context to render controls on\n */\n drawControls(ctx: CanvasRenderingContext2D) {\n const activeObject = this._activeObject;\n\n if (activeObject) {\n activeObject._renderControls(ctx);\n }\n }\n\n /**\n * @private\n */\n protected _toObject(\n instance: FabricObject,\n methodName: 'toObject' | 'toDatalessObject',\n propertiesToInclude: string[],\n ): Record<string, any> {\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 const originalProperties = this._realizeGroupTransformOnObject(instance),\n object = super._toObject(instance, methodName, propertiesToInclude);\n //Undo the damage we did by changing all of its properties\n instance.set(originalProperties);\n return object;\n }\n\n /**\n * Realizes an object's group transformation on it\n * @private\n * @param {FabricObject} [instance] the object to transform (gets mutated)\n * @returns the original values of instance which were changed\n */\n private _realizeGroupTransformOnObject(\n instance: FabricObject,\n ): Partial<typeof instance> {\n const { group } = instance;\n if (group && isActiveSelection(group) && this._activeObject === group) {\n const layoutProps = [\n 'angle',\n 'flipX',\n 'flipY',\n LEFT,\n SCALE_X,\n SCALE_Y,\n SKEW_X,\n SKEW_Y,\n TOP,\n ] as (keyof typeof instance)[];\n const originalValues = pick<typeof instance>(instance, layoutProps);\n addTransformToObject(instance, group.calcOwnMatrix());\n return originalValues;\n } else {\n return {};\n }\n }\n\n /**\n * @private\n */\n _setSVGObject(\n markup: string[],\n instance: FabricObject,\n reviver?: TSVGReviver,\n ) {\n // If the object is in a selection group, simulate what would happen to that\n // object when the group is deselected\n const originalProperties = this._realizeGroupTransformOnObject(instance);\n super._setSVGObject(markup, instance, reviver);\n instance.set(originalProperties);\n }\n}\n","import type { TPointerEvent } from '../EventTypeDefs';\nimport type { ITextBehavior } from '../shapes/IText/ITextBehavior';\nimport { removeFromArray } from '../util/internals/removeFromArray';\nimport type { Canvas } from './Canvas';\n\n/**\n * In charge of synchronizing all interactive text instances of a canvas\n */\nexport class TextEditingManager {\n private targets: ITextBehavior[] = [];\n declare private target?: ITextBehavior;\n private __disposer: VoidFunction;\n\n constructor(canvas: Canvas) {\n const cb = () => {\n const { hiddenTextarea } =\n (canvas.getActiveObject() as ITextBehavior) || {};\n hiddenTextarea && hiddenTextarea.focus();\n };\n const el = canvas.upperCanvasEl;\n el.addEventListener('click', cb);\n this.__disposer = () => el.removeEventListener('click', cb);\n }\n\n exitTextEditing() {\n this.target = undefined;\n this.targets.forEach((target) => {\n if (target.isEditing) {\n target.exitEditing();\n }\n });\n }\n\n add(target: ITextBehavior) {\n this.targets.push(target);\n }\n\n remove(target: ITextBehavior) {\n this.unregister(target);\n removeFromArray(this.targets, target);\n }\n\n register(target: ITextBehavior) {\n this.target = target;\n }\n\n unregister(target: ITextBehavior) {\n if (target === this.target) {\n this.target = undefined;\n }\n }\n\n onMouseMove(e: TPointerEvent) {\n this.target?.isEditing && this.target.updateSelectionOnMouseMove(e);\n }\n\n clear() {\n this.targets = [];\n this.target = undefined;\n }\n\n dispose() {\n this.clear();\n this.__disposer();\n // @ts-expect-error disposing\n delete this.__disposer;\n }\n}\n","import { classRegistry } from '../ClassRegistry';\nimport { NONE } from '../constants';\nimport type {\n CanvasEvents,\n DragEventData,\n ObjectEvents,\n TEventsExtraData,\n TPointerEvent,\n TPointerEventNames,\n Transform,\n} from '../EventTypeDefs';\nimport { Point } from '../Point';\nimport type { ActiveSelection } from '../shapes/ActiveSelection';\nimport type { Group } from '../shapes/Group';\nimport type { IText } from '../shapes/IText/IText';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport { type TToCanvasElementOptions } from '../typedefs';\nimport { isTouchEvent, stopEvent } from '../util/dom_event';\nimport { getDocumentFromElement, getWindowFromElement } from '../util/dom_misc';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport { isActiveSelection } from '../util/typeAssertions';\nimport type { CanvasOptions, TCanvasOptions } from './CanvasOptions';\nimport { SelectableCanvas } from './SelectableCanvas';\nimport { TextEditingManager } from './TextEditingManager';\n\nconst addEventOptions = { passive: false } as EventListenerOptions;\n\nconst getEventPoints = (canvas: Canvas, e: TPointerEvent) => {\n const viewportPoint = canvas.getViewportPoint(e);\n const scenePoint = canvas.getScenePoint(e);\n return {\n viewportPoint,\n scenePoint,\n };\n};\n\n// just to be clear, the utils are now deprecated and those are here exactly as minifier helpers\n// because el.addEventListener can't me be minified while a const yes and we use it 47 times in this file.\n// few bytes but why give it away.\nconst addListener = (\n el: HTMLElement | Document,\n ...args: Parameters<HTMLElement['addEventListener']>\n) => el.addEventListener(...args);\nconst removeListener = (\n el: HTMLElement | Document,\n ...args: Parameters<HTMLElement['removeEventListener']>\n) => el.removeEventListener(...args);\n\nconst syntheticEventConfig = {\n mouse: {\n in: 'over',\n out: 'out',\n targetIn: 'mouseover',\n targetOut: 'mouseout',\n canvasIn: 'mouse:over',\n canvasOut: 'mouse:out',\n },\n drag: {\n in: 'enter',\n out: 'leave',\n targetIn: 'dragenter',\n targetOut: 'dragleave',\n canvasIn: 'drag:enter',\n canvasOut: 'drag:leave',\n },\n} as const;\n\ntype TSyntheticEventContext = {\n mouse: { e: TPointerEvent };\n drag: DragEventData;\n};\n\nexport class Canvas extends SelectableCanvas implements CanvasOptions {\n /**\n * Contains the id of the touch event that owns the fabric transform\n * @type Number\n * @private\n */\n declare mainTouchId?: number;\n\n declare enablePointerEvents: boolean;\n\n /**\n * Holds a reference to a setTimeout timer for event synchronization\n * @type number\n * @private\n */\n declare private _willAddMouseDown: number;\n\n /**\n * Holds a reference to an object on the canvas that is receiving the drag over event.\n * @type FabricObject\n * @private\n */\n declare private _draggedoverTarget?: FabricObject;\n\n /**\n * Holds a reference to an object on the canvas from where the drag operation started\n * @type FabricObject\n * @private\n */\n declare private _dragSource?: FabricObject;\n\n /**\n * Holds a reference to an object on the canvas that is the current drop target\n * May differ from {@link _draggedoverTarget}\n * @todo inspect whether {@link _draggedoverTarget} and {@link _dropTarget} should be merged somehow\n * @type FabricObject\n * @private\n */\n declare private _dropTarget: FabricObject<ObjectEvents> | undefined;\n\n /**\n * a boolean that keeps track of the click state during a cycle of mouse down/up.\n * If a mouse move occurs it becomes false.\n * Is true by default, turns false on mouse move.\n * Used to determine if a mouseUp is a click\n */\n private _isClick: boolean;\n\n textEditingManager = new TextEditingManager(this);\n\n constructor(el?: string | HTMLCanvasElement, options: TCanvasOptions = {}) {\n super(el, options);\n // bind event handlers\n (\n [\n '_onMouseDown',\n '_onTouchStart',\n '_onMouseMove',\n '_onMouseUp',\n '_onTouchEnd',\n '_onResize',\n // '_onGesture',\n // '_onDrag',\n // '_onShake',\n // '_onLongPress',\n // '_onOrientationChange',\n '_onMouseWheel',\n '_onMouseOut',\n '_onMouseEnter',\n '_onContextMenu',\n '_onClick',\n '_onDragStart',\n '_onDragEnd',\n '_onDragProgress',\n '_onDragOver',\n '_onDragEnter',\n '_onDragLeave',\n '_onDrop',\n ] as (keyof this)[]\n ).forEach((eventHandler) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n this[eventHandler] = (this[eventHandler] as Function).bind(this);\n });\n // register event handlers\n this.addOrRemove(addListener);\n }\n\n /**\n * return an event prefix pointer or mouse.\n * @private\n */\n private _getEventPrefix() {\n return this.enablePointerEvents ? 'pointer' : 'mouse';\n }\n\n addOrRemove(functor: any, forTouch = false) {\n const canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n functor(getWindowFromElement(canvasElement), 'resize', this._onResize);\n functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n functor(\n canvasElement,\n `${eventTypePrefix}move`,\n this._onMouseMove,\n addEventOptions,\n );\n functor(canvasElement, `${eventTypePrefix}out`, this._onMouseOut);\n functor(canvasElement, `${eventTypePrefix}enter`, this._onMouseEnter);\n functor(canvasElement, 'wheel', this._onMouseWheel, { passive: false });\n functor(canvasElement, 'contextmenu', this._onContextMenu);\n if (!forTouch) {\n functor(canvasElement, 'click', this._onClick);\n functor(canvasElement, 'dblclick', this._onClick);\n }\n functor(canvasElement, 'dragstart', this._onDragStart);\n functor(canvasElement, 'dragend', this._onDragEnd);\n functor(canvasElement, 'dragover', this._onDragOver);\n functor(canvasElement, 'dragenter', this._onDragEnter);\n functor(canvasElement, 'dragleave', this._onDragLeave);\n functor(canvasElement, 'drop', this._onDrop);\n if (!this.enablePointerEvents) {\n functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\n }\n }\n\n /**\n * Removes all event listeners, used when disposing the instance\n */\n removeListeners() {\n this.addOrRemove(removeListener);\n // if you dispose on a mouseDown, before mouse up, you need to clean document to...\n const eventTypePrefix = this._getEventPrefix();\n const doc = getDocumentFromElement(this.upperCanvasEl);\n removeListener(\n doc,\n `${eventTypePrefix}up`,\n this._onMouseUp as EventListener,\n );\n removeListener(\n doc,\n 'touchend',\n this._onTouchEnd as EventListener,\n addEventOptions,\n );\n removeListener(\n doc,\n `${eventTypePrefix}move`,\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n removeListener(\n doc,\n 'touchmove',\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n clearTimeout(this._willAddMouseDown);\n }\n\n /**\n * @private\n * @param {Event} [e] Event object fired on wheel event\n */\n private _onMouseWheel(e: MouseEvent) {\n this._cacheTransformEventData(e);\n this._handleEvent(e, 'wheel');\n this._resetTransformEventData();\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n private _onMouseOut(e: TPointerEvent) {\n const target = this._hoveredTarget;\n const shared = {\n e,\n ...getEventPoints(this, e),\n };\n this.fire('mouse:out', { ...shared, target });\n this._hoveredTarget = undefined;\n target && target.fire('mouseout', { ...shared });\n this._hoveredTargets.forEach((nestedTarget) => {\n this.fire('mouse:out', { ...shared, target: nestedTarget });\n nestedTarget && nestedTarget.fire('mouseout', { ...shared });\n });\n this._hoveredTargets = [];\n }\n\n /**\n * @private\n * Used when the mouse cursor enter the canvas from outside\n * @param {Event} e Event object fired on mouseenter\n */\n private _onMouseEnter(e: TPointerEvent) {\n // This find target and consequent 'mouse:over' is used to\n // clear old instances on hovered target.\n // calling findTarget has the side effect of killing target.__corner.\n // as a short term fix we are not firing this if we are currently transforming.\n // as a long term fix we need to separate the action of finding a target with the\n // side effects we added to it.\n const { target } = this.findTarget(e);\n // we fire the event only when there is no target, if there is a target, the specific\n // target event will fire.\n if (!this._currentTransform && !target) {\n this.fire('mouse:over', {\n e,\n ...getEventPoints(this, e),\n });\n this._hoveredTarget = undefined;\n this._hoveredTargets = [];\n }\n }\n\n /**\n * supports native like text dragging\n * @private\n * @param {DragEvent} e\n */\n private _onDragStart(e: DragEvent) {\n this._isClick = false;\n const activeObject = this.getActiveObject();\n if (activeObject && activeObject.onDragStart(e)) {\n this._dragSource = activeObject;\n const options = { e, target: activeObject };\n this.fire('dragstart', options);\n activeObject.fire('dragstart', options);\n addListener(\n this.upperCanvasEl,\n 'drag',\n this._onDragProgress as EventListener,\n );\n return;\n }\n stopEvent(e);\n }\n\n /**\n * First we clear top context where the effects are being rendered.\n * Then we render the effects.\n * Doing so will render the correct effect for all cases including an overlap between `source` and `target`.\n * @private\n */\n private _renderDragEffects(\n e: DragEvent,\n source?: FabricObject,\n target?: FabricObject,\n ) {\n let dirty = false;\n // clear top context\n const dropTarget = this._dropTarget;\n if (dropTarget && dropTarget !== source && dropTarget !== target) {\n dropTarget.clearContextTop();\n dirty = true;\n }\n source?.clearContextTop();\n target !== source && target?.clearContextTop();\n // render effects\n const ctx = this.contextTop;\n ctx.save();\n ctx.transform(...this.viewportTransform);\n if (source) {\n ctx.save();\n source.transform(ctx);\n source.renderDragSourceEffect(e);\n ctx.restore();\n dirty = true;\n }\n if (target) {\n ctx.save();\n target.transform(ctx);\n target.renderDropTargetEffect(e);\n ctx.restore();\n dirty = true;\n }\n ctx.restore();\n dirty && (this.contextTopDirty = true);\n }\n\n /**\n * supports native like text dragging\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag\n * @private\n * @param {DragEvent} e\n */\n private _onDragEnd(e: DragEvent) {\n const { currentSubTargets } = this.findTarget(e);\n const didDrop = !!e.dataTransfer && e.dataTransfer.dropEffect !== NONE,\n dropTarget = didDrop ? this._activeObject : undefined,\n options = {\n e,\n target: this._dragSource as FabricObject,\n subTargets: currentSubTargets,\n dragSource: this._dragSource as FabricObject,\n didDrop,\n dropTarget: dropTarget as FabricObject,\n };\n removeListener(\n this.upperCanvasEl,\n 'drag',\n this._onDragProgress as EventListener,\n );\n this.fire('dragend', options);\n this._dragSource && this._dragSource.fire('dragend', options);\n delete this._dragSource;\n // we need to call mouse up synthetically because the browser won't\n this._onMouseUp(e);\n }\n\n /**\n * fire `drag` event on canvas and drag source\n * @private\n * @param {DragEvent} e\n */\n private _onDragProgress(e: DragEvent) {\n const options = {\n e,\n target: this._dragSource,\n dragSource: this._dragSource,\n dropTarget: this._draggedoverTarget as FabricObject,\n };\n this.fire('drag', options);\n this._dragSource && this._dragSource.fire('drag', options);\n }\n\n /**\n * prevent default to allow drop event to be fired\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#specifying_drop_targets\n * @private\n * @param {DragEvent} [e] Event object fired on Event.js shake\n */\n private _onDragOver(e: DragEvent) {\n const eventType = 'dragover';\n const { currentContainer: target, currentSubTargets } = this.findTarget(e);\n const dragSource = this._dragSource as FabricObject;\n const options = {\n e,\n target,\n subTargets: currentSubTargets,\n dragSource,\n canDrop: false,\n dropTarget: undefined,\n };\n let dropTarget;\n // fire on canvas\n this.fire(eventType, options);\n // make sure we fire dragenter events before dragover\n // if dragleave is needed, object will not fire dragover so we don't need to trouble ourselves with it\n this._fireEnterLeaveEvents(e, target, options);\n if (target) {\n if (target.canDrop(e)) {\n dropTarget = target;\n }\n target.fire(eventType, options);\n }\n // propagate the event to subtargets\n for (let i = 0; i < currentSubTargets.length; i++) {\n const subTarget = currentSubTargets[i];\n // accept event only if previous targets didn't (the accepting target calls `preventDefault` to inform that the event is taken)\n // TODO: verify if those should loop in inverse order then?\n // what is the order of subtargets?\n if (subTarget.canDrop(e)) {\n dropTarget = subTarget;\n }\n subTarget.fire(eventType, options);\n }\n // render drag effects now that relations between source and target is clear\n this._renderDragEffects(e, dragSource, dropTarget);\n this._dropTarget = dropTarget;\n }\n\n /**\n * fire `dragleave` on `dragover` targets\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n */\n private _onDragEnter(e: DragEvent) {\n const { currentContainer, currentSubTargets } = this.findTarget(e);\n const options = {\n e,\n target: currentContainer,\n subTargets: currentSubTargets,\n dragSource: this._dragSource,\n };\n this.fire('dragenter', options);\n // fire dragenter on targets\n this._fireEnterLeaveEvents(e, currentContainer, options);\n }\n\n /**\n * fire `dragleave` on `dragover` targets\n * @private\n * @param {Event} [e] Event object fired on Event.js shake\n */\n private _onDragLeave(e: DragEvent) {\n const { currentSubTargets } = this.findTarget(e);\n const options = {\n e,\n target: this._draggedoverTarget,\n subTargets: currentSubTargets,\n dragSource: this._dragSource,\n };\n this.fire('dragleave', options);\n\n // fire dragleave on targets\n this._fireEnterLeaveEvents(e, undefined, options);\n this._renderDragEffects(e, this._dragSource);\n this._dropTarget = undefined;\n this._hoveredTargets = [];\n }\n\n /**\n * `drop:before` is a an event that allows you to schedule logic\n * before the `drop` event. Prefer `drop` event always, but if you need\n * to run some drop-disabling logic on an event, since there is no way\n * to handle event handlers ordering, use `drop:before`\n * @private\n * @param {Event} e\n */\n private _onDrop(e: DragEvent) {\n const { currentContainer, currentSubTargets } = this.findTarget(e);\n const options = this._basicEventHandler('drop:before', {\n e,\n target: currentContainer,\n subTargets: currentSubTargets,\n dragSource: this._dragSource,\n ...getEventPoints(this, e),\n });\n // will be set by the drop target\n options.didDrop = false;\n // will be set by the drop target, used in case options.target refuses the drop\n options.dropTarget = undefined;\n // fire `drop`\n this._basicEventHandler('drop', options);\n // inform canvas of the drop\n // we do this because canvas was unaware of what happened at the time the `drop` event was fired on it\n // use for side effects\n this.fire('drop:after', options);\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n private _onContextMenu(e: TPointerEvent): false {\n const { target, subTargets } = this.findTarget(e);\n const options = this._basicEventHandler('contextmenu:before', {\n e,\n target,\n subTargets,\n });\n // TODO: this line is silly because the dev can subscribe to the event and prevent it themselves\n this.stopContextMenu && stopEvent(e);\n this._basicEventHandler('contextmenu', options);\n return false;\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n private _onClick(e: TPointerEvent) {\n const clicks = e.detail;\n if (clicks > 3 || clicks < 2) return;\n this._cacheTransformEventData(e);\n clicks == 2 && e.type === 'dblclick' && this._handleEvent(e, 'dblclick');\n clicks == 3 && this._handleEvent(e, 'tripleclick');\n this._resetTransformEventData();\n }\n\n /**\n * This supports gesture event firing\n * It is a method to keep some code organized, it exposes private methods\n * in a way that works and still keep them private\n * This is supposed to mirror _handleEvent\n */\n fireEventFromPointerEvent(\n e: TPointerEvent,\n eventName: keyof CanvasEvents,\n secondaryName: keyof ObjectEvents,\n extraData:\n | Record<string, unknown>\n | { rotation: number }\n | { ping: number } = {},\n ) {\n this._cacheTransformEventData(e);\n const { target, subTargets } = this.findTarget(e),\n options = {\n e,\n target,\n subTargets,\n ...getEventPoints(this, e),\n transform: this._currentTransform,\n ...extraData,\n };\n this.fire(eventName, options);\n // this may be a little be more complicated of what we want to handle\n target && target.fire(secondaryName, options);\n for (let i = 0; i < subTargets.length; i++) {\n subTargets[i] !== target && subTargets[i].fire(secondaryName, options);\n }\n this._resetTransformEventData();\n }\n\n /**\n * Return a the id of an event.\n * returns either the pointerId or the identifier or 0 for the mouse event\n * @private\n * @param {Event} evt Event object\n */\n getPointerId(evt: TouchEvent | PointerEvent): number {\n const changedTouches = (evt as TouchEvent).changedTouches;\n\n if (changedTouches) {\n return changedTouches[0] && changedTouches[0].identifier;\n }\n\n if (this.enablePointerEvents) {\n return (evt as PointerEvent).pointerId;\n }\n\n return -1;\n }\n\n /**\n * Determines if an event has the id of the event that is considered main\n * @private\n * @param {evt} event Event object\n */\n _isMainEvent(evt: TPointerEvent): boolean {\n if ((evt as PointerEvent).isPrimary === true) {\n return true;\n }\n if ((evt as PointerEvent).isPrimary === false) {\n return false;\n }\n if (evt.type === 'touchend' && (evt as TouchEvent).touches.length === 0) {\n return true;\n }\n if ((evt as TouchEvent).changedTouches) {\n return (\n (evt as TouchEvent).changedTouches[0].identifier === this.mainTouchId\n );\n }\n return true;\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onTouchStart(e: TouchEvent) {\n this._cacheTransformEventData(e);\n // we will prevent scrolling if allowTouchScrolling is not enabled and\n let shouldPreventScrolling = !this.allowTouchScrolling;\n const currentActiveObject = this._activeObject;\n if (this.mainTouchId === undefined) {\n this.mainTouchId = this.getPointerId(e);\n }\n this.__onMouseDown(e);\n const { target } = this.findTarget(e);\n // after executing fabric logic for mouse down let's see\n // if we didn't change target or if we are drawing\n // we want to prevent scrolling anyway\n if (\n this.isDrawingMode ||\n (currentActiveObject && target === currentActiveObject)\n ) {\n shouldPreventScrolling = true;\n }\n // prevent default, will block scrolling from start\n shouldPreventScrolling && e.preventDefault();\n const canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n const doc = getDocumentFromElement(canvasElement);\n addListener(\n doc,\n 'touchend',\n this._onTouchEnd as EventListener,\n addEventOptions,\n );\n // if we scroll don't register the touch move event\n shouldPreventScrolling &&\n addListener(\n doc,\n 'touchmove',\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n // Unbind mousedown to prevent double triggers from touch devices\n removeListener(\n canvasElement,\n `${eventTypePrefix}down`,\n this._onMouseDown as EventListener,\n );\n this._resetTransformEventData();\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDown(e: TPointerEvent) {\n this._cacheTransformEventData(e);\n this.__onMouseDown(e);\n const canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n // switch from moving on the canvas element to moving on the document\n removeListener(\n canvasElement,\n `${eventTypePrefix}move`,\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n const doc = getDocumentFromElement(canvasElement);\n addListener(doc, `${eventTypePrefix}up`, this._onMouseUp as EventListener);\n addListener(\n doc,\n `${eventTypePrefix}move`,\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n this._resetTransformEventData();\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onTouchEnd(e: TouchEvent) {\n if (e.touches.length > 0) {\n // if there are still touches stop here\n return;\n }\n this._cacheTransformEventData(e);\n this.__onMouseUp(e);\n this._resetTransformEventData();\n delete this.mainTouchId;\n const eventTypePrefix = this._getEventPrefix();\n const doc = getDocumentFromElement(this.upperCanvasEl);\n removeListener(\n doc,\n 'touchend',\n this._onTouchEnd as EventListener,\n addEventOptions,\n );\n removeListener(\n doc,\n 'touchmove',\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n if (this._willAddMouseDown) {\n clearTimeout(this._willAddMouseDown);\n }\n this._willAddMouseDown = setTimeout(() => {\n // Wait 400ms before rebinding mousedown to prevent double triggers\n // from touch devices\n addListener(\n this.upperCanvasEl,\n `${eventTypePrefix}down`,\n this._onMouseDown as EventListener,\n );\n this._willAddMouseDown = 0;\n }, 400) as unknown as number;\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mouseup\n */\n _onMouseUp(e: TPointerEvent) {\n this._cacheTransformEventData(e);\n this.__onMouseUp(e);\n const canvasElement = this.upperCanvasEl,\n eventTypePrefix = this._getEventPrefix();\n if (this._isMainEvent(e)) {\n const doc = getDocumentFromElement(this.upperCanvasEl);\n removeListener(\n doc,\n `${eventTypePrefix}up`,\n this._onMouseUp as EventListener,\n );\n removeListener(\n doc,\n `${eventTypePrefix}move`,\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n addListener(\n canvasElement,\n `${eventTypePrefix}move`,\n this._onMouseMove as EventListener,\n addEventOptions,\n );\n }\n this._resetTransformEventData();\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMove(e: TPointerEvent) {\n this._cacheTransformEventData(e);\n\n const activeObject = this.getActiveObject();\n !this.allowTouchScrolling &&\n (!activeObject ||\n // a drag event sequence is started by the active object flagging itself on mousedown / mousedown:before\n // we must not prevent the event's default behavior in order for the window to start dragging\n !activeObject.shouldStartDragging(e)) &&\n e.preventDefault &&\n e.preventDefault();\n this.__onMouseMove(e);\n this._resetTransformEventData();\n }\n\n /**\n * @private\n */\n _onResize() {\n this.calcOffset();\n this._resetTransformEventData();\n }\n\n /**\n * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n * @private\n * @param {Object} target\n */\n _shouldRender(target: FabricObject | undefined) {\n const activeObject = this.getActiveObject();\n // if just one of them is available or if they are both but are different objects\n // this covers: switch of target, from target to no target, selection of target\n // multiSelection with key and mouse\n return (\n !!activeObject !== !!target ||\n (activeObject && target && activeObject !== target)\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(e: TPointerEvent) {\n this._handleEvent(e, 'up:before');\n\n const transform = this._currentTransform;\n const isClick = this._isClick;\n const { target } = this.findTarget(e);\n\n // if right/middle click just fire events and return\n // target undefined will make the _handleEvent search the target\n const { button } = e as MouseEvent;\n if (button) {\n ((this.fireMiddleClick && button === 1) ||\n (this.fireRightClick && button === 2)) &&\n this._handleEvent(e, 'up');\n return;\n }\n\n if (this.isDrawingMode && this._isCurrentlyDrawing) {\n this._onMouseUpInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n let shouldRender = false;\n if (transform) {\n this._finalizeCurrentTransform(e);\n shouldRender = transform.actionPerformed;\n }\n if (!isClick) {\n const targetWasActive = target === this._activeObject;\n this.handleSelection(e);\n if (!shouldRender) {\n shouldRender =\n this._shouldRender(target) ||\n (!targetWasActive && target === this._activeObject);\n }\n }\n let pointer, corner;\n if (target) {\n const found = target.findControl(\n this.getViewportPoint(e),\n isTouchEvent(e),\n );\n const { key, control } = found || {};\n corner = key;\n if (\n target.selectable &&\n target !== this._activeObject &&\n target.activeOn === 'up'\n ) {\n this.setActiveObject(target, e);\n shouldRender = true;\n } else if (control) {\n const mouseUpHandler = control.getMouseUpHandler(e, target, control);\n if (mouseUpHandler) {\n pointer = this.getScenePoint(e);\n mouseUpHandler.call(control, e, transform!, pointer.x, pointer.y);\n }\n }\n target.isMoving = false;\n }\n // if we are ending up a transform on a different control or a new object\n // fire the original mouse up from the corner that started the transform\n if (\n transform &&\n (transform.target !== target || transform.corner !== corner)\n ) {\n const originalControl =\n transform.target && transform.target.controls[transform.corner],\n originalMouseUpHandler =\n originalControl &&\n originalControl.getMouseUpHandler(\n e,\n transform.target,\n originalControl,\n );\n pointer = pointer || this.getScenePoint(e);\n originalMouseUpHandler &&\n originalMouseUpHandler.call(\n originalControl,\n e,\n transform,\n pointer.x,\n pointer.y,\n );\n }\n this._setCursorFromEvent(e, target);\n this._handleEvent(e, 'up');\n this._groupSelector = null;\n this._currentTransform = null;\n // reset the target information about which corner is selected\n target && (target.__corner = undefined);\n if (shouldRender) {\n this.requestRenderAll();\n } else if (!isClick && !(this._activeObject as IText)?.isEditing) {\n this.renderTop();\n }\n }\n\n _basicEventHandler<T extends keyof (CanvasEvents | ObjectEvents)>(\n eventType: T,\n options: (CanvasEvents & ObjectEvents)[T],\n ) {\n const { target, subTargets = [] } = options as {\n target?: FabricObject;\n subTargets: FabricObject[];\n };\n this.fire(eventType, options);\n target && target.fire(eventType, options);\n for (let i = 0; i < subTargets.length; i++) {\n subTargets[i] !== target && subTargets[i].fire(eventType, options);\n }\n return options;\n }\n\n /**\n * @private\n * Handle event firing for target and subtargets\n * @param {TPointerEvent} e event from mouse\n * @param {TPointerEventNames} eventType\n */\n _handleEvent<T extends TPointerEventNames>(\n e: TPointerEvent,\n eventType: T,\n extraData?: TEventsExtraData[T],\n ) {\n const { target, subTargets } = this.findTarget(e),\n options: CanvasEvents[`mouse:${T}`] = {\n e,\n target,\n subTargets,\n ...getEventPoints(this, e),\n transform: this._currentTransform,\n ...(eventType === 'down:before' || eventType === 'down'\n ? extraData\n : {}),\n } as CanvasEvents[`mouse:${T}`];\n if (eventType === 'up:before' || eventType === 'up') {\n (options as CanvasEvents[`mouse:up`]).isClick = this._isClick;\n }\n\n this.fire(`mouse:${eventType}`, options);\n // this may be a little be more complicated of what we want to handle\n target && target.fire(`mouse${eventType}`, options);\n for (let i = 0; i < subTargets.length; i++) {\n subTargets[i] !== target &&\n subTargets[i].fire(`mouse${eventType}`, options);\n }\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousedown\n */\n _onMouseDownInDrawingMode(e: TPointerEvent) {\n this._isCurrentlyDrawing = true;\n if (this.getActiveObject()) {\n this.discardActiveObject(e);\n this.requestRenderAll();\n }\n // TODO: this is a scene point so it should be renamed\n const pointer = this.getScenePoint(e);\n this.freeDrawingBrush &&\n this.freeDrawingBrush.onMouseDown(pointer, { e, pointer });\n this._handleEvent(e, 'down', { alreadySelected: false });\n }\n\n /**\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n _onMouseMoveInDrawingMode(e: TPointerEvent) {\n if (this._isCurrentlyDrawing) {\n const pointer = this.getScenePoint(e);\n this.freeDrawingBrush &&\n this.freeDrawingBrush.onMouseMove(pointer, {\n e,\n // this is an absolute pointer, the naming is wrong\n pointer,\n });\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(e: TPointerEvent) {\n const pointer = this.getScenePoint(e);\n if (this.freeDrawingBrush) {\n this._isCurrentlyDrawing = !!this.freeDrawingBrush.onMouseUp({\n e: e,\n // this is an absolute pointer, the naming is wrong\n pointer,\n });\n } else {\n this._isCurrentlyDrawing = false;\n }\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(e: TPointerEvent) {\n this._isClick = true;\n this._handleEvent(e, 'down:before');\n\n let { target } = this.findTarget(e);\n let alreadySelected = !!target && target === this._activeObject;\n // if right/middle click just fire events\n const { button } = e as MouseEvent;\n if (button) {\n ((this.fireMiddleClick && button === 1) ||\n (this.fireRightClick && button === 2)) &&\n this._handleEvent(e, 'down', {\n alreadySelected,\n });\n return;\n }\n\n if (this.isDrawingMode) {\n this._onMouseDownInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n\n // ignore if some object is being transformed at this moment\n if (this._currentTransform) {\n return;\n }\n\n let shouldRender = this._shouldRender(target);\n let grouped = false;\n if (this.handleMultiSelection(e, target)) {\n // active object might have changed while grouping\n target = this._activeObject;\n grouped = true;\n shouldRender = true;\n } else if (this._shouldClearSelection(e, target)) {\n this.discardActiveObject(e);\n }\n // we start a group selector rectangle if\n // selection is enabled\n // and there is no target, or the following 3 conditions are satisfied:\n // target is not selectable ( otherwise we selected it )\n // target is not editing\n // target is not already selected ( otherwise we drag )\n if (\n this.selection &&\n (!target ||\n (!target.selectable &&\n !(target as IText).isEditing &&\n target !== this._activeObject))\n ) {\n const p = this.getScenePoint(e);\n this._groupSelector = {\n x: p.x,\n y: p.y,\n deltaY: 0,\n deltaX: 0,\n };\n }\n\n // check again because things could have changed\n alreadySelected = !!target && target === this._activeObject;\n if (target) {\n if (target.selectable && target.activeOn === 'down') {\n this.setActiveObject(target, e);\n }\n const handle = target.findControl(\n this.getViewportPoint(e),\n isTouchEvent(e),\n );\n if (target === this._activeObject && (handle || !grouped)) {\n this._setupCurrentTransform(e, target, alreadySelected);\n const control = handle ? handle.control : undefined,\n pointer = this.getScenePoint(e),\n mouseDownHandler =\n control && control.getMouseDownHandler(e, target, control);\n mouseDownHandler &&\n mouseDownHandler.call(\n control,\n e,\n this._currentTransform!,\n pointer.x,\n pointer.y,\n );\n }\n }\n // we clear `_objectsToRender` in case of a change in order to repopulate it at rendering\n // run before firing the `down` event to give the dev a chance to populate it themselves\n shouldRender && (this._objectsToRender = undefined);\n this._handleEvent(e, 'down', { alreadySelected: alreadySelected });\n // we must renderAll so that we update the visuals\n shouldRender && this.requestRenderAll();\n }\n\n /**\n * reset cache form common information needed during event processing\n * @private\n */\n _resetTransformEventData() {\n this._targetInfo = this._viewportPoint = this._scenePoint = undefined;\n }\n\n /**\n * Cache common information needed during event processing\n * @private\n * @param {Event} e Event object fired on event\n */\n _cacheTransformEventData(e: TPointerEvent) {\n // reset in order to avoid stale caching\n this._resetTransformEventData();\n this._viewportPoint = this.getViewportPoint(e);\n this._scenePoint = sendPointToPlane(\n this._viewportPoint,\n undefined,\n this.viewportTransform,\n );\n this._targetInfo = this.findTarget(e);\n // TODO: investigate better if this can be made less implicit in the code\n if (this._currentTransform) {\n this._targetInfo.target = this._currentTransform.target;\n }\n }\n\n /**\n * Method that defines the actions when mouse is hovering the canvas.\n * The currentTransform parameter will define whether the user is rotating/scaling/translating\n * an image or neither of them (only hovering). A group selection is also possible and would cancel\n * all any other type of action.\n * In case of an image transformation only the top canvas will be rendered.\n * @private\n * @param {Event} e Event object fired on mousemove\n */\n __onMouseMove(e: TPointerEvent) {\n this._isClick = false;\n this._handleEvent(e, 'move:before');\n\n if (this.isDrawingMode) {\n this._onMouseMoveInDrawingMode(e);\n return;\n }\n\n if (!this._isMainEvent(e)) {\n return;\n }\n\n const groupSelector = this._groupSelector;\n\n // We initially clicked in an empty area, so we draw a box for multiple selection\n if (groupSelector) {\n const pointer = this.getScenePoint(e);\n\n groupSelector.deltaX = pointer.x - groupSelector.x;\n groupSelector.deltaY = pointer.y - groupSelector.y;\n\n this.renderTop();\n } else if (!this._currentTransform) {\n const { target } = this.findTarget(e);\n this._setCursorFromEvent(e, target);\n this._fireOverOutEvents(e, target);\n } else {\n this._transformObject(e);\n }\n this.textEditingManager.onMouseMove(e);\n this._handleEvent(e, 'move');\n }\n\n /**\n * Manage the mouseout, mouseover events for the fabric object on the canvas\n * @param {Fabric.Object} target the target where the target from the mousemove event\n * @param {Event} e Event object fired on mousemove\n * @private\n */\n _fireOverOutEvents(e: TPointerEvent, target?: FabricObject) {\n const { _hoveredTarget, _hoveredTargets } = this,\n { subTargets } = this.findTarget(e),\n length = Math.max(_hoveredTargets.length, subTargets.length);\n\n this.fireSyntheticInOutEvents('mouse', {\n e,\n target,\n oldTarget: _hoveredTarget,\n fireCanvas: true,\n });\n for (let i = 0; i < length; i++) {\n if (\n subTargets[i] === target ||\n (_hoveredTargets[i] && _hoveredTargets[i] === _hoveredTarget)\n ) {\n continue;\n }\n this.fireSyntheticInOutEvents('mouse', {\n e,\n target: subTargets[i],\n oldTarget: _hoveredTargets[i],\n });\n }\n this._hoveredTarget = target;\n this._hoveredTargets = subTargets;\n }\n\n /**\n * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\n * @param {Fabric.Object} target the target where the target from the onDrag event\n * @param {Object} data Event object fired on dragover\n * @private\n */\n _fireEnterLeaveEvents(\n e: TPointerEvent,\n target: FabricObject | undefined,\n data: DragEventData,\n ) {\n const draggedoverTarget = this._draggedoverTarget,\n _hoveredTargets = this._hoveredTargets,\n { subTargets } = this.findTarget(e),\n length = Math.max(_hoveredTargets.length, subTargets.length);\n\n this.fireSyntheticInOutEvents('drag', {\n ...data,\n target,\n oldTarget: draggedoverTarget,\n fireCanvas: true,\n });\n for (let i = 0; i < length; i++) {\n this.fireSyntheticInOutEvents('drag', {\n ...data,\n target: subTargets[i],\n oldTarget: _hoveredTargets[i],\n });\n }\n this._draggedoverTarget = target;\n }\n\n /**\n * Manage the synthetic in/out events for the fabric objects on the canvas\n * @param {Fabric.Object} target the target where the target from the supported events\n * @param {Object} data Event object fired\n * @param {Object} config configuration for the function to work\n * @param {String} config.targetName property on the canvas where the old target is stored\n * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\n * @param {String} config.evtOut name of the event to fire for out\n * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\n * @param {String} config.evtIn name of the event to fire for in\n * @private\n */\n fireSyntheticInOutEvents<T extends keyof TSyntheticEventContext>(\n type: T,\n {\n target,\n oldTarget,\n fireCanvas,\n e,\n ...data\n }: TSyntheticEventContext[T] & {\n target?: FabricObject;\n oldTarget?: FabricObject;\n fireCanvas?: boolean;\n },\n ) {\n const { targetIn, targetOut, canvasIn, canvasOut } =\n syntheticEventConfig[type];\n const targetChanged = oldTarget !== target;\n\n if (oldTarget && targetChanged) {\n const outOpt: CanvasEvents[typeof canvasOut] = {\n ...data,\n e,\n target: oldTarget,\n nextTarget: target,\n ...getEventPoints(this, e),\n };\n fireCanvas && this.fire(canvasOut, outOpt);\n oldTarget.fire(targetOut, outOpt);\n }\n if (target && targetChanged) {\n const inOpt: CanvasEvents[typeof canvasIn] = {\n ...data,\n e,\n target,\n previousTarget: oldTarget,\n ...getEventPoints(this, e),\n };\n fireCanvas && this.fire(canvasIn, inOpt);\n target.fire(targetIn, inOpt);\n }\n }\n\n /**\n * @private\n * @param {Event} e Event fired on mousemove\n */\n _transformObject(e: TPointerEvent) {\n const scenePoint = this.getScenePoint(e),\n transform = this._currentTransform!,\n target = transform.target,\n // transform pointer to target's containing coordinate plane\n // both pointer and object should agree on every point\n localPointer = target.group\n ? sendPointToPlane(\n scenePoint,\n undefined,\n target.group.calcTransformMatrix(),\n )\n : scenePoint;\n transform.shiftKey = e.shiftKey;\n transform.altKey = !!this.centeredKey && e[this.centeredKey];\n\n this._performTransformAction(e, transform, localPointer);\n transform.actionPerformed && this.requestRenderAll();\n }\n\n /**\n * @private\n */\n _performTransformAction(\n e: TPointerEvent,\n transform: Transform,\n pointer: Point,\n ) {\n const { action, actionHandler, target } = transform;\n\n const actionPerformed =\n !!actionHandler && actionHandler(e, transform, pointer.x, pointer.y);\n actionPerformed && target.setCoords();\n\n // this object could be created from the function in the control handlers\n if (action === 'drag' && actionPerformed) {\n transform.target.isMoving = true;\n this.setCursor(transform.target.moveCursor || this.moveCursor);\n }\n transform.actionPerformed = transform.actionPerformed || actionPerformed;\n }\n\n /**\n * 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(e: TPointerEvent, target?: FabricObject) {\n if (!target) {\n this.setCursor(this.defaultCursor);\n return;\n }\n let hoverCursor = target.hoverCursor || this.hoverCursor;\n const activeSelection = isActiveSelection(this._activeObject)\n ? this._activeObject\n : null,\n // only show proper corner when group selection is not active\n corner =\n (!activeSelection || target.group !== activeSelection) &&\n // here we call findTargetCorner always with undefined for the touch parameter.\n // we assume that if you are using a cursor you do not need to interact with\n // the bigger touch area.\n target.findControl(this.getViewportPoint(e));\n\n if (!corner) {\n if ((target as Group).subTargetCheck) {\n // hoverCursor should come from top-most subTarget,\n // so we walk the array backwards\n const { subTargets } = this.findTarget(e);\n subTargets\n .concat()\n .reverse()\n .forEach((_target) => {\n hoverCursor = _target.hoverCursor || hoverCursor;\n });\n }\n this.setCursor(hoverCursor);\n } else {\n const { control, coord } = corner;\n this.setCursor(control.cursorStyleHandler(e, control, target, coord));\n }\n }\n\n /**\n * ## Handles multiple selection\n * - toggles `target` selection (selects/deselects `target` if it isn't/is selected respectively)\n * - sets the active object in case it is not set or in case there is a single active object left under active selection.\n * ---\n * - If the active object is the active selection we add/remove `target` from it\n * - If not, add the active object and `target` to the active selection and make it the active object.\n * @TODO rewrite this after find target is refactored\n * @private\n * @param {TPointerEvent} e Event object\n * @param {FabricObject} target target of event to select/deselect\n * @returns true if grouping occurred\n */\n protected handleMultiSelection(e: TPointerEvent, target?: FabricObject) {\n const activeObject = this._activeObject;\n const isAS = isActiveSelection(activeObject);\n if (\n // check if an active object exists on canvas and if the user is pressing the `selectionKey` while canvas supports multi selection.\n !!activeObject &&\n this._isSelectionKeyPressed(e) &&\n this.selection &&\n // on top of that the user also has to hit a target that is selectable.\n !!target &&\n target.selectable &&\n // group target and active object only if they are different objects\n // else we try to find a subtarget of `ActiveSelection`\n (activeObject !== target || isAS) &&\n // make sure `activeObject` and `target` aren't ancestors of each other in case `activeObject` is not `ActiveSelection`\n // if it is then we want to remove `target` from it\n (isAS ||\n (!target.isDescendantOf(activeObject) &&\n !activeObject.isDescendantOf(target))) &&\n // target accepts selection\n !target.onSelect({ e }) &&\n // make sure we are not on top of a control\n !activeObject.getActiveControl()\n ) {\n if (isAS) {\n const prevActiveObjects = activeObject.getObjects();\n let subTargets: FabricObject[] = [];\n // const { subTargets: testSubTargets } = this.findTarget(e);\n if (target === activeObject) {\n const pointer = this.getScenePoint(e);\n let targetInfo = this.searchPossibleTargets(\n prevActiveObjects,\n pointer,\n );\n // console.log(testSubTargets.includes(targetInfo.target));\n if (targetInfo.target) {\n target = targetInfo.target;\n subTargets = targetInfo.subTargets;\n } else {\n targetInfo = this.searchPossibleTargets(this._objects, pointer);\n target = targetInfo.target;\n subTargets = targetInfo.subTargets;\n }\n // if nothing is found bail out\n if (!target || !target.selectable) {\n return false;\n }\n }\n if (target.group === activeObject) {\n // `target` is part of active selection => remove it\n activeObject.remove(target);\n this._hoveredTarget = target;\n this._hoveredTargets = subTargets;\n // if after removing an object we are left with one only...\n if (activeObject.size() === 1) {\n // activate last remaining object\n // deselecting the active selection will remove the remaining object from it\n this._setActiveObject(activeObject.item(0), e);\n }\n } else {\n // `target` isn't part of active selection => add it\n activeObject.multiSelectAdd(target);\n this._hoveredTarget = activeObject;\n this._hoveredTargets = subTargets;\n }\n this._fireSelectionEvents(prevActiveObjects, e);\n } else {\n (activeObject as IText).isEditing &&\n (activeObject as IText).exitEditing();\n // add the active object and the target to the active selection and set it as the active object\n const klass =\n classRegistry.getClass<typeof ActiveSelection>('ActiveSelection');\n const newActiveSelection = new klass([], {\n /**\n * it is crucial to pass the canvas ref before calling {@link ActiveSelection#multiSelectAdd}\n * since it uses {@link FabricObject#isInFrontOf} which relies on the canvas ref\n */\n canvas: this,\n });\n newActiveSelection.multiSelectAdd(activeObject, target);\n this._hoveredTarget = newActiveSelection;\n // ISSUE 4115: should we consider subTargets here?\n // this._hoveredTargets = [];\n // this._hoveredTargets = this.targets.concat();\n this._setActiveObject(newActiveSelection, e);\n this._fireSelectionEvents([activeObject], e);\n }\n return true;\n }\n return false;\n }\n\n /**\n * ## Handles selection\n * - selects objects that are contained in (and possibly intersecting) the selection bounding box\n * - sets the active object\n * ---\n * runs on mouse up after a mouse move\n */\n protected handleSelection(e: TPointerEvent) {\n if (!this.selection || !this._groupSelector) {\n return false;\n }\n const { x, y, deltaX, deltaY } = this._groupSelector,\n point1 = new Point(x, y),\n point2 = point1.add(new Point(deltaX, deltaY)),\n tl = point1.min(point2),\n br = point1.max(point2),\n size = br.subtract(tl);\n\n const collectedObjects = this.collectObjects(\n {\n left: tl.x,\n top: tl.y,\n width: size.x,\n height: size.y,\n },\n { includeIntersecting: !this.selectionFullyContained },\n ) as FabricObject[];\n\n const objects =\n // though this method runs only after mouse move the pointer could do a mouse up on the same position as mouse down\n // should it be handled as is?\n point1.eq(point2)\n ? collectedObjects[0]\n ? [collectedObjects[0]]\n : []\n : collectedObjects.length > 1\n ? collectedObjects\n .filter((object) => !object.onSelect({ e }))\n .reverse()\n : // `setActiveObject` will call `onSelect(collectedObjects[0])` in this case\n collectedObjects;\n\n // set active object\n if (objects.length === 1) {\n // set as active object\n this.setActiveObject(objects[0], e);\n } else if (objects.length > 1) {\n // add to active selection and make it the active object\n const klass =\n classRegistry.getClass<typeof ActiveSelection>('ActiveSelection');\n this.setActiveObject(new klass(objects, { canvas: this }), e);\n }\n\n // cleanup\n this._groupSelector = null;\n return true;\n }\n\n /**\n * Wraps the original toCanvasElement with a function that removes\n * the context top for the time the function is run.\n * So we avoid painting side effects on the upper canvas when exporting\n */\n toCanvasElement(\n multiplier = 1,\n options?: TToCanvasElementOptions,\n ): HTMLCanvasElement {\n const { upper } = this.elements;\n upper.ctx = undefined as unknown as CanvasRenderingContext2D;\n const htmlElement = super.toCanvasElement(multiplier, options);\n upper.ctx = upper.el.getContext('2d')!;\n return htmlElement;\n }\n\n /**\n * @override clear {@link textEditingManager}\n */\n clear() {\n this.textEditingManager.clear();\n super.clear();\n }\n\n /**\n * @override clear {@link textEditingManager}\n */\n destroy() {\n this.removeListeners();\n this.textEditingManager.dispose();\n super.destroy();\n }\n}\n","export const linearDefaultCoords = {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n};\n\nexport const radialDefaultCoords = {\n ...linearDefaultCoords,\n r1: 0,\n r2: 0,\n};\n","/**\n *\n * @param value value to check if NaN\n * @param [valueIfNaN]\n * @returns `fallback` is `value is NaN\n */\nexport const ifNaN = (value: number, valueIfNaN?: number) => {\n return isNaN(value) && typeof valueIfNaN === 'number' ? valueIfNaN : value;\n};\n","import { ifNaN } from '../util/internals/ifNaN';\nimport { capValue } from '../util/misc/capValue';\n\n/**\n * Will loosely accept as percent numbers that are not like\n * 3.4a%. This function does not check for the correctness of a percentage\n * but it checks that values that are in theory correct are or arent percentages\n */\nexport function isPercent(value: string | null) {\n // /%$/ Matches strings that end with a percent sign (%)\n return value && /%$/.test(value) && Number.isFinite(parseFloat(value));\n}\n\n/**\n * Parse a percentage value in an svg.\n * @param value\n * @param fallback in case of not possible to parse the number\n * @returns ∈ [0, 1]\n */\nexport function parsePercent(\n value: string | number | null | undefined,\n valueIfNaN?: number,\n): number {\n const parsed =\n typeof value === 'number'\n ? value\n : typeof value === 'string'\n ? parseFloat(value) / (isPercent(value) ? 100 : 1)\n : NaN;\n return capValue(0, ifNaN(parsed, valueIfNaN), 1);\n}\n","import { Color } from '../../color/Color';\nimport { parsePercent } from '../../parser/percent';\nimport { ifNaN } from '../../util/internals/ifNaN';\nimport type { ColorStop } from '../typedefs';\n\nconst RE_KEY_VALUE_PAIRS = /\\s*;\\s*/;\nconst RE_KEY_VALUE = /\\s*:\\s*/;\n\nfunction parseColorStop(el: SVGStopElement, opacityMultiplier: number) {\n let colorValue, opacityValue;\n const style = el.getAttribute('style');\n if (style) {\n const keyValuePairs = style.split(RE_KEY_VALUE_PAIRS);\n\n if (keyValuePairs[keyValuePairs.length - 1] === '') {\n keyValuePairs.pop();\n }\n\n for (let i = keyValuePairs.length; i--; ) {\n const [key, value] = keyValuePairs[i]\n .split(RE_KEY_VALUE)\n .map((s) => s.trim());\n if (key === 'stop-color') {\n colorValue = value;\n } else if (key === 'stop-opacity') {\n opacityValue = value;\n }\n }\n }\n\n colorValue = colorValue || el.getAttribute('stop-color') || 'rgb(0,0,0)';\n opacityValue = ifNaN(\n parseFloat(opacityValue || el.getAttribute('stop-opacity') || ''),\n 1,\n );\n\n const color = new Color(colorValue);\n\n color.setAlpha(color.getAlpha() * opacityValue * opacityMultiplier);\n\n return {\n offset: parsePercent(el.getAttribute('offset'), 0),\n color: color.toRgba(),\n };\n}\n\nexport function parseColorStops(\n el: SVGGradientElement,\n opacityAttr: string | null,\n) {\n const colorStops: ColorStop[] = [],\n colorStopEls = el.getElementsByTagName('stop'),\n multiplier = parsePercent(opacityAttr, 1);\n for (let i = colorStopEls.length; i--; ) {\n colorStops.push(parseColorStop(colorStopEls[i], multiplier));\n }\n return colorStops;\n}\n","import type { GradientType, GradientUnits } from '../typedefs';\n\nexport function parseType(el: SVGGradientElement): GradientType {\n return el.nodeName === 'linearGradient' || el.nodeName === 'LINEARGRADIENT'\n ? 'linear'\n : 'radial';\n}\n\nexport function parseGradientUnits(el: SVGGradientElement): GradientUnits {\n return el.getAttribute('gradientUnits') === 'userSpaceOnUse'\n ? 'pixels'\n : 'percentage';\n}\n","import { isPercent } from '../../parser/percent';\nimport type { TSize } from '../../typedefs';\nimport type { GradientCoords, GradientType, GradientUnits } from '../typedefs';\nimport { parseGradientUnits, parseType } from './misc';\n\nfunction convertPercentUnitsToValues<\n T extends GradientType,\n K extends keyof GradientCoords<T>,\n>(\n valuesToConvert: Record<K, string | number>,\n { width, height, gradientUnits }: TSize & { gradientUnits: GradientUnits },\n) {\n let finalValue;\n return (Object.entries(valuesToConvert) as [K, string | number][]).reduce(\n (acc, [prop, propValue]) => {\n if (propValue === 'Infinity') {\n finalValue = 1;\n } else if (propValue === '-Infinity') {\n finalValue = 0;\n } else {\n const isString = typeof propValue === 'string';\n finalValue = isString ? parseFloat(propValue) : propValue;\n if (isString && isPercent(propValue)) {\n finalValue *= 0.01;\n if (gradientUnits === 'pixels') {\n // then we need to fix those percentages here in svg parsing\n if (prop === 'x1' || prop === 'x2' || prop === 'r2') {\n finalValue *= width;\n }\n if (prop === 'y1' || prop === 'y2') {\n finalValue *= height;\n }\n }\n }\n }\n acc[prop] = finalValue;\n return acc;\n },\n {} as Record<K, number>,\n );\n}\n\nfunction getValue(el: SVGGradientElement, key: string) {\n return el.getAttribute(key);\n}\n\nexport function parseLinearCoords(el: SVGGradientElement) {\n return {\n x1: getValue(el, 'x1') || 0,\n y1: getValue(el, 'y1') || 0,\n x2: getValue(el, 'x2') || '100%',\n y2: getValue(el, 'y2') || 0,\n };\n}\n\nexport function parseRadialCoords(el: SVGGradientElement) {\n return {\n x1: getValue(el, 'fx') || getValue(el, 'cx') || '50%',\n y1: getValue(el, 'fy') || getValue(el, 'cy') || '50%',\n r1: 0,\n x2: getValue(el, 'cx') || '50%',\n y2: getValue(el, 'cy') || '50%',\n r2: getValue(el, 'r') || '50%',\n };\n}\n\nexport function parseCoords(el: SVGGradientElement, size: TSize) {\n return convertPercentUnitsToValues(\n parseType(el) === 'linear' ? parseLinearCoords(el) : parseRadialCoords(el),\n {\n ...size,\n gradientUnits: parseGradientUnits(el),\n },\n );\n}\n","import { iMatrix } from '../constants';\nimport { parseTransformAttribute } from '../parser/parseTransformAttribute';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TMat2D } from '../typedefs';\nimport { uid } from '../util/internals/uid';\nimport { pick } from '../util/misc/pick';\nimport { matrixToSVG } from '../util/misc/svgExport';\nimport { linearDefaultCoords, radialDefaultCoords } from './constants';\nimport { parseColorStops } from './parser/parseColorStops';\nimport { parseCoords } from './parser/parseCoords';\nimport { parseType, parseGradientUnits } from './parser/misc';\nimport type {\n ColorStop,\n GradientCoords,\n GradientOptions,\n GradientType,\n GradientUnits,\n SVGOptions,\n SerializedGradientProps,\n} from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { isPath } from '../util/typeAssertions';\n\n/**\n * Gradient class\n * @class Gradient\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#gradients}\n */\nexport class Gradient<\n S,\n T extends GradientType = S extends GradientType ? S : 'linear',\n> {\n /**\n * Horizontal offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n declare offsetX: number;\n\n /**\n * Vertical offset for aligning gradients coming from SVG when outside pathgroups\n * @type Number\n * @default 0\n */\n declare offsetY: number;\n\n /**\n * A transform matrix to apply to the gradient before painting.\n * Imported from svg gradients, is not applied with the current transform in the center.\n * Before this transform is applied, the origin point is at the top left corner of the object\n * plus the addition of offsetY and offsetX.\n * @type Number[]\n * @default null\n */\n declare gradientTransform?: TMat2D;\n\n /**\n * coordinates units for coords.\n * If `pixels`, the number of coords are in the same unit of width / height.\n * If set as `percentage` the coords are still a number, but 1 means 100% of width\n * for the X and 100% of the height for the y. It can be bigger than 1 and negative.\n * allowed values pixels or percentage.\n * @type GradientUnits\n * @default 'pixels'\n */\n declare gradientUnits: GradientUnits;\n\n /**\n * Gradient type linear or radial\n * @type GradientType\n * @default 'linear'\n */\n declare type: T;\n\n /**\n * Defines how the gradient is located in space and spread\n * @type GradientCoords\n */\n declare coords: GradientCoords<T>;\n\n /**\n * Defines how many colors a gradient has and how they are located on the axis\n * defined by coords\n * @type GradientCoords\n */\n declare colorStops: ColorStop[];\n\n /**\n * If true, this object will not be exported during the serialization of a canvas\n * @type boolean\n */\n declare excludeFromExport?: boolean;\n\n /**\n * ID used for SVG export functionalities\n * @type number | string\n */\n declare readonly id: string | number;\n\n static type = 'Gradient';\n\n constructor(options: GradientOptions<T>) {\n const {\n type = 'linear' as T,\n gradientUnits = 'pixels',\n coords = {},\n colorStops = [],\n offsetX = 0,\n offsetY = 0,\n gradientTransform,\n id,\n } = options || {};\n Object.assign(this, {\n type,\n gradientUnits,\n coords: {\n ...(type === 'radial' ? radialDefaultCoords : linearDefaultCoords),\n ...coords,\n },\n colorStops,\n offsetX,\n offsetY,\n gradientTransform,\n id: id ? `${id}_${uid()}` : uid(),\n });\n }\n\n /**\n * Adds another colorStop\n * @param {Record<string, string>} colorStop Object with offset and color\n * @return {Gradient} thisArg\n */\n addColorStop(colorStops: Record<string, string>) {\n for (const position in colorStops) {\n this.colorStops.push({\n offset: parseFloat(position),\n color: colorStops[position],\n });\n }\n return this;\n }\n\n /**\n * Returns object representation of a gradient\n * @param {string[]} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {object}\n */\n toObject(\n propertiesToInclude?: (keyof this | string)[],\n ): SerializedGradientProps<T> {\n return {\n ...pick(this, propertiesToInclude as (keyof this)[]),\n type: this.type,\n coords: { ...this.coords },\n colorStops: this.colorStops.map((colorStop) => ({ ...colorStop })),\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n gradientUnits: this.gradientUnits,\n gradientTransform: this.gradientTransform\n ? [...this.gradientTransform]\n : undefined,\n };\n }\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of an gradient\n * @param {FabricObject} object Object to create a gradient for\n * @return {String} SVG representation of an gradient (linear/radial)\n */\n toSVG(\n object: FabricObject,\n {\n additionalTransform: preTransform,\n }: { additionalTransform?: string } = {},\n ) {\n const markup = [],\n transform = (\n this.gradientTransform\n ? this.gradientTransform.concat()\n : iMatrix.concat()\n ) as TMat2D,\n gradientUnits =\n this.gradientUnits === 'pixels'\n ? 'userSpaceOnUse'\n : 'objectBoundingBox';\n // colorStops must be sorted ascending, and guarded against deep mutations\n const colorStops = this.colorStops\n .map((colorStop) => ({ ...colorStop }))\n .sort((a, b) => {\n return a.offset - b.offset;\n });\n\n let offsetX = -this.offsetX,\n offsetY = -this.offsetY;\n if (gradientUnits === 'objectBoundingBox') {\n offsetX /= object.width;\n offsetY /= object.height;\n } else {\n offsetX += object.width / 2;\n offsetY += object.height / 2;\n }\n // todo what about polygon/polyline?\n if (isPath(object) && this.gradientUnits !== 'percentage') {\n offsetX -= object.pathOffset.x;\n offsetY -= object.pathOffset.y;\n }\n transform[4] -= offsetX;\n transform[5] -= offsetY;\n\n const commonAttributes = [\n `id=\"SVGID_${this.id}\"`,\n `gradientUnits=\"${gradientUnits}\"`,\n `gradientTransform=\"${\n preTransform ? preTransform + ' ' : ''\n }${matrixToSVG(transform)}\"`,\n '',\n ].join(' ');\n\n if (this.type === 'linear') {\n const { x1, y1, x2, y2 } = this.coords;\n markup.push(\n '<linearGradient ',\n commonAttributes,\n ' x1=\"',\n x1,\n '\" y1=\"',\n y1,\n '\" x2=\"',\n x2,\n '\" y2=\"',\n y2,\n '\">\\n',\n );\n } else if (this.type === 'radial') {\n const { x1, y1, x2, y2, r1, r2 } = this\n .coords as GradientCoords<'radial'>;\n const needsSwap = r1 > r2;\n // svg radial gradient has just 1 radius. the biggest.\n markup.push(\n '<radialGradient ',\n commonAttributes,\n ' cx=\"',\n needsSwap ? x1 : x2,\n '\" cy=\"',\n needsSwap ? y1 : y2,\n '\" r=\"',\n needsSwap ? r1 : r2,\n '\" fx=\"',\n needsSwap ? x2 : x1,\n '\" fy=\"',\n needsSwap ? y2 : y1,\n '\">\\n',\n );\n if (needsSwap) {\n // svg goes from internal to external radius. if radius are inverted, swap color stops.\n colorStops.reverse(); // mutates array\n colorStops.forEach((colorStop) => {\n colorStop.offset = 1 - colorStop.offset;\n });\n }\n const minRadius = Math.min(r1, r2);\n if (minRadius > 0) {\n // i have to shift all colorStops and add new one in 0.\n const maxRadius = Math.max(r1, r2),\n percentageShift = minRadius / maxRadius;\n colorStops.forEach((colorStop) => {\n colorStop.offset += percentageShift * (1 - colorStop.offset);\n });\n }\n }\n\n colorStops.forEach(({ color, offset }) => {\n markup.push(\n `<stop offset=\"${offset * 100}%\" style=\"stop-color:${color};\"/>\\n`,\n );\n });\n\n markup.push(\n this.type === 'linear' ? '</linearGradient>' : '</radialGradient>',\n '\\n',\n );\n\n return markup.join('');\n }\n /* _TO_SVG_END_ */\n\n /**\n * Returns an instance of CanvasGradient\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {CanvasGradient}\n */\n toLive(ctx: CanvasRenderingContext2D): CanvasGradient {\n const { x1, y1, x2, y2, r1, r2 } = this.coords as GradientCoords<'radial'>;\n const gradient =\n this.type === 'linear'\n ? ctx.createLinearGradient(x1, y1, x2, y2)\n : ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);\n\n this.colorStops.forEach(({ color, offset }) => {\n gradient.addColorStop(offset, color);\n });\n\n return gradient;\n }\n\n static async fromObject(\n options: GradientOptions<'linear'>,\n ): Promise<Gradient<'linear'>>;\n static async fromObject(\n options: GradientOptions<'radial'>,\n ): Promise<Gradient<'radial'>>;\n static async fromObject(\n options: GradientOptions<'linear'> | GradientOptions<'radial'>,\n ) {\n const { colorStops, gradientTransform } = options;\n return new this({\n ...options,\n colorStops: colorStops\n ? colorStops.map((colorStop) => ({ ...colorStop }))\n : undefined,\n gradientTransform: gradientTransform ? [...gradientTransform] : undefined,\n });\n }\n\n /* _FROM_SVG_START_ */\n /**\n * Returns {@link Gradient} instance from an SVG element\n * @param {SVGGradientElement} el SVG gradient element\n * @param {FabricObject} instance\n * @param {String} opacity A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity.\n * @param {SVGOptions} svgOptions an object containing the size of the SVG in order to parse correctly gradients\n * that uses gradientUnits as 'userSpaceOnUse' and percentages.\n * @return {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 * @example\n *\n * <linearGradient id=\"linearGrad1\">\n * <stop offset=\"0%\" stop-color=\"white\"/>\n * <stop offset=\"100%\" stop-color=\"black\"/>\n * </linearGradient>\n *\n * OR\n *\n * <linearGradient id=\"linearGrad2\">\n * <stop offset=\"0\" style=\"stop-color:rgb(255,255,255)\"/>\n * <stop offset=\"1\" style=\"stop-color:rgb(0,0,0)\"/>\n * </linearGradient>\n *\n * OR\n *\n * <radialGradient id=\"radialGrad1\">\n * <stop offset=\"0%\" stop-color=\"white\" stop-opacity=\"1\" />\n * <stop offset=\"50%\" stop-color=\"black\" stop-opacity=\"0.5\" />\n * <stop offset=\"100%\" stop-color=\"white\" stop-opacity=\"1\" />\n * </radialGradient>\n *\n * OR\n *\n * <radialGradient id=\"radialGrad2\">\n * <stop offset=\"0\" stop-color=\"rgb(255,255,255)\" />\n * <stop offset=\"0.5\" stop-color=\"rgb(0,0,0)\" />\n * <stop offset=\"1\" stop-color=\"rgb(255,255,255)\" />\n * </radialGradient>\n *\n */\n static fromElement(\n el: SVGGradientElement,\n instance: FabricObject,\n svgOptions: SVGOptions,\n ): Gradient<GradientType> {\n const gradientUnits = parseGradientUnits(el);\n const center = instance._findCenterFromElement();\n return new this({\n id: el.getAttribute('id') || undefined,\n type: parseType(el),\n coords: parseCoords(el, {\n width: svgOptions.viewBoxWidth || svgOptions.width,\n height: svgOptions.viewBoxHeight || svgOptions.height,\n }),\n colorStops: parseColorStops(el, svgOptions.opacity),\n gradientUnits,\n gradientTransform: parseTransformAttribute(\n el.getAttribute('gradientTransform') || '',\n ),\n ...(gradientUnits === 'pixels'\n ? {\n offsetX: instance.width / 2 - center.x,\n offsetY: instance.height / 2 - center.y,\n }\n : {\n offsetX: 0,\n offsetY: 0,\n }),\n });\n }\n /* _FROM_SVG_END_ */\n}\n\nclassRegistry.setClass(Gradient, 'gradient');\nclassRegistry.setClass(Gradient, 'linear');\nclassRegistry.setClass(Gradient, 'radial');\n","import { config } from '../config';\nimport type { Abortable, TCrossOrigin, TMat2D, TSize } from '../typedefs';\nimport { ifNaN } from '../util/internals/ifNaN';\nimport { uid } from '../util/internals/uid';\nimport { loadImage } from '../util/misc/objectEnlive';\nimport { pick } from '../util/misc/pick';\nimport { toFixed } from '../util/misc/toFixed';\nimport { classRegistry } from '../ClassRegistry';\nimport type {\n PatternRepeat,\n PatternOptions,\n SerializedPatternOptions,\n} from './types';\nimport { log } from '../util/internals/console';\n\n/**\n * @see {@link http://fabric5.fabricjs.com/patterns demo}\n * @see {@link http://fabric5.fabricjs.com/dynamic-patterns demo}\n */\nexport class Pattern {\n static type = 'Pattern';\n\n /**\n * Legacy identifier of the class. Prefer using this.constructor.type 'Pattern'\n * or utils like isPattern, or instance of to indentify a pattern in your code.\n * Will be removed in future versiones\n * @TODO add sustainable warning message\n * @type string\n * @deprecated\n */\n get type() {\n return 'pattern';\n }\n\n set type(value) {\n log('warn', 'Setting type has no effect', value);\n }\n\n /**\n * @type PatternRepeat\n * @defaults\n */\n repeat: PatternRepeat = 'repeat';\n\n /**\n * Pattern horizontal offset from object's left/top corner\n * @type Number\n */\n offsetX = 0;\n\n /**\n * Pattern vertical offset from object's left/top corner\n * @type Number\n */\n offsetY = 0;\n\n /**\n * @type TCrossOrigin\n */\n crossOrigin: TCrossOrigin = '';\n\n /**\n * transform matrix to change the pattern, imported from svgs.\n * @todo verify if using the identity matrix as default makes the rest of the code more easy\n * @type Array\n */\n declare patternTransform?: TMat2D;\n\n /**\n * The actual pixel source of the pattern\n */\n declare source: CanvasImageSource;\n\n /**\n * If true, this object will not be exported during the serialization of a canvas\n * @type boolean\n */\n declare excludeFromExport?: boolean;\n\n /**\n * ID used for SVG export functionalities\n * @type number\n */\n declare readonly id: number;\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n * @param {option.source} [source] the pattern source, eventually empty or a drawable\n */\n constructor(options: PatternOptions) {\n this.id = uid();\n Object.assign(this, options);\n }\n\n /**\n * @returns true if {@link source} is an <img> element\n */\n isImageSource(): this is { source: HTMLImageElement } {\n return (\n !!this.source && typeof (this.source as HTMLImageElement).src === 'string'\n );\n }\n\n /**\n * @returns true if {@link source} is a <canvas> element\n */\n isCanvasSource(): this is { source: HTMLCanvasElement } {\n return !!this.source && !!(this.source as HTMLCanvasElement).toDataURL;\n }\n\n sourceToString(): string {\n return this.isImageSource()\n ? this.source.src\n : this.isCanvasSource()\n ? this.source.toDataURL()\n : '';\n }\n\n /**\n * Returns an instance of CanvasPattern\n * @param {CanvasRenderingContext2D} ctx Context to create pattern\n * @return {CanvasPattern}\n */\n toLive(ctx: CanvasRenderingContext2D): CanvasPattern | null {\n if (\n // if the image failed to load, return, and allow rest to continue loading\n !this.source ||\n // if an image\n (this.isImageSource() &&\n (!this.source.complete ||\n this.source.naturalWidth === 0 ||\n this.source.naturalHeight === 0))\n ) {\n return null;\n }\n\n return ctx.createPattern(this.source, this.repeat)!;\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(propertiesToInclude: string[] = []): Record<string, any> {\n const { repeat, crossOrigin } = this;\n return {\n ...pick(this, propertiesToInclude as (keyof this)[]),\n type: 'pattern',\n source: this.sourceToString(),\n repeat,\n crossOrigin,\n offsetX: toFixed(this.offsetX, config.NUM_FRACTION_DIGITS),\n offsetY: toFixed(this.offsetY, config.NUM_FRACTION_DIGITS),\n patternTransform: this.patternTransform\n ? [...this.patternTransform]\n : null,\n };\n }\n\n /* _TO_SVG_START_ */\n /**\n * Returns SVG representation of a pattern\n */\n toSVG({ width, height }: TSize): string {\n const { source: patternSource, repeat, id } = this,\n patternOffsetX = ifNaN(this.offsetX / width, 0),\n patternOffsetY = ifNaN(this.offsetY / height, 0),\n patternWidth =\n repeat === 'repeat-y' || repeat === 'no-repeat'\n ? 1 + Math.abs(patternOffsetX || 0)\n : ifNaN((patternSource as HTMLImageElement).width / width, 0),\n patternHeight =\n repeat === 'repeat-x' || repeat === 'no-repeat'\n ? 1 + Math.abs(patternOffsetY || 0)\n : ifNaN((patternSource as HTMLImageElement).height / height, 0);\n\n return [\n `<pattern id=\"SVGID_${id}\" x=\"${patternOffsetX}\" y=\"${patternOffsetY}\" width=\"${patternWidth}\" height=\"${patternHeight}\">`,\n `<image x=\"0\" y=\"0\" width=\"${\n (patternSource as HTMLImageElement).width\n }\" height=\"${\n (patternSource as HTMLImageElement).height\n }\" xlink:href=\"${this.sourceToString()}\"></image>`,\n `</pattern>`,\n '',\n ].join('\\n');\n }\n /* _TO_SVG_END_ */\n\n static async fromObject(\n {\n type,\n source,\n patternTransform,\n ...otherOptions\n }: SerializedPatternOptions,\n options?: Abortable,\n ): Promise<Pattern> {\n const img = await loadImage(source, {\n ...options,\n crossOrigin: otherOptions.crossOrigin,\n });\n return new this({\n ...otherOptions,\n patternTransform:\n patternTransform && (patternTransform.slice(0) as TMat2D),\n source: img,\n });\n }\n}\n\nclassRegistry.setClass(Pattern);\n// kept for compatibility reason\nclassRegistry.setClass(Pattern, 'pattern');\n","import { Color } from '../color/Color';\nimport type { Point } from '../Point';\nimport type { Shadow } from '../Shadow';\nimport type { Canvas } from '../canvas/Canvas';\nimport type { TBrushEventData } from './typedefs';\n\n/**\n * @see {@link http://fabric5.fabricjs.com/freedrawing|Freedrawing demo}\n */\nexport abstract class BaseBrush {\n /**\n * Color of a brush\n * @type String\n */\n color = 'rgb(0, 0, 0)';\n\n /**\n * Width of a brush, has to be a Number, no string literals\n * @type Number\n */\n width = 1;\n\n /**\n * Shadow object representing shadow of this shape.\n * <b>Backwards incompatibility note:</b> This property replaces \"shadowColor\" (String), \"shadowOffsetX\" (Number),\n * \"shadowOffsetY\" (Number) and \"shadowBlur\" (Number) since v1.2.12\n * @type Shadow\n */\n shadow: Shadow | null = null;\n\n /**\n * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n * @type String\n */\n strokeLineCap: CanvasLineCap = 'round';\n\n /**\n * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\n * @type String\n */\n strokeLineJoin: CanvasLineJoin = 'round';\n\n /**\n * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\n * @type Number\n */\n strokeMiterLimit = 10;\n\n /**\n * Stroke Dash Array.\n * @type Array\n */\n strokeDashArray: number[] | null = null;\n\n /**\n * When `true`, the free drawing is limited to the whiteboard size. Default to false.\n * @type Boolean\n * @default false\n */\n\n limitedToCanvasSize = false;\n\n /**\n * @todo add type\n */\n declare canvas: Canvas;\n\n constructor(canvas: Canvas) {\n this.canvas = canvas;\n }\n\n abstract _render(): void;\n abstract onMouseDown(pointer: Point, ev: TBrushEventData): void;\n abstract onMouseMove(pointer: Point, ev: TBrushEventData): void;\n /**\n * @returns true if brush should continue blocking interaction\n */\n abstract onMouseUp(ev: TBrushEventData): boolean | void;\n\n /**\n * Sets brush styles\n * @private\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles(ctx: CanvasRenderingContext2D) {\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.width;\n ctx.lineCap = this.strokeLineCap;\n ctx.miterLimit = this.strokeMiterLimit;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.setLineDash(this.strokeDashArray || []);\n }\n\n /**\n * Sets the transformation on given context\n * @param {CanvasRenderingContext2D} ctx context to render on\n * @private\n */\n protected _saveAndTransform(ctx: CanvasRenderingContext2D) {\n const v = this.canvas.viewportTransform;\n ctx.save();\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n }\n\n protected needsFullRender() {\n const color = new Color(this.color);\n return color.getAlpha() < 1 || !!this.shadow;\n }\n\n /**\n * Sets brush shadow styles\n * @private\n */\n protected _setShadow() {\n if (!this.shadow || !this.canvas) {\n return;\n }\n\n const canvas = this.canvas,\n shadow = this.shadow,\n ctx = canvas.contextTop,\n zoom = canvas.getZoom() * canvas.getRetinaScaling();\n\n ctx.shadowColor = shadow.color;\n ctx.shadowBlur = shadow.blur * zoom;\n ctx.shadowOffsetX = shadow.offsetX * zoom;\n ctx.shadowOffsetY = shadow.offsetY * zoom;\n }\n\n /**\n * Removes brush shadow styles\n * @private\n */\n protected _resetShadow() {\n const ctx = this.canvas.contextTop;\n\n ctx.shadowColor = '';\n ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;\n }\n\n /**\n * Check is pointer is outside canvas boundaries\n * @param {Object} pointer\n * @private\n */\n protected _isOutSideCanvas(pointer: Point) {\n return (\n pointer.x < 0 ||\n pointer.x > this.canvas.getWidth() ||\n pointer.y < 0 ||\n pointer.y > this.canvas.getHeight()\n );\n }\n}\n","import { config } from '../config';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type { XY } from '../Point';\nimport { Point } from '../Point';\nimport { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints';\nimport { toFixed } from '../util/misc/toFixed';\nimport {\n getBoundsOfCurve,\n joinPath,\n makePathSimpler,\n parsePath,\n} from '../util/path';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type {\n TComplexPathData,\n TPathSegmentInfo,\n TSimplePathData,\n} from '../util/path/typedefs';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport type {\n TBBox,\n TClassProperties,\n TSVGReviver,\n TOptions,\n} from '../typedefs';\nimport { CENTER, LEFT, TOP } from '../constants';\nimport type { CSSRules } from '../parser/typedefs';\n\ninterface UniquePathProps {\n sourcePath?: string;\n path?: TSimplePathData;\n}\n\nexport interface SerializedPathProps\n extends SerializedObjectProps,\n UniquePathProps {}\n\nexport interface PathProps extends FabricObjectProps, UniquePathProps {}\n\nexport interface IPathBBox extends TBBox {\n left: number;\n top: number;\n pathOffset: Point;\n}\n\nexport class Path<\n Props extends TOptions<PathProps> = Partial<PathProps>,\n SProps extends SerializedPathProps = SerializedPathProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n> extends FabricObject<Props, SProps, EventSpec> {\n /**\n * Array of path points\n * @type Array\n */\n declare path: TSimplePathData;\n\n declare pathOffset: Point;\n\n declare sourcePath?: string;\n\n declare segmentsInfo?: TPathSegmentInfo[];\n\n static type = 'Path';\n\n static cacheProperties = [...cacheProperties, 'path', 'fillRule'];\n\n /**\n * Constructor\n * @param {TComplexPathData} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {Partial<PathProps>} [options] Options object\n * @return {Path} thisArg\n */\n constructor(\n path: TComplexPathData | string,\n // todo: evaluate this spread here\n { path: _, left, top, ...options }: Partial<Props> = {},\n ) {\n super();\n Object.assign(this, Path.ownDefaults);\n this.setOptions(options);\n this._setPath(path || [], true);\n typeof left === 'number' && this.set(LEFT, left);\n typeof top === 'number' && this.set(TOP, top);\n }\n\n /**\n * @private\n * @param {TComplexPathData | string} path Path data (sequence of coordinates and corresponding \"command\" tokens)\n * @param {boolean} [adjustPosition] pass true to reposition the object according to the bounding box\n * @returns {Point} top left position of the bounding box, useful for complementary positioning\n */\n _setPath(path: TComplexPathData | string, adjustPosition?: boolean) {\n this.path = makePathSimpler(Array.isArray(path) ? path : parsePath(path));\n this.setBoundingBox(adjustPosition);\n }\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates, by look at the polyline/polygon points.\n * @private\n * @return {Point} center point from element coordinates\n */\n _findCenterFromElement(): Point {\n const bbox = this._calcBoundsFromPath();\n return new Point(bbox.left + bbox.width / 2, bbox.top + bbox.height / 2);\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _renderPathCommands(ctx: CanvasRenderingContext2D) {\n const l = -this.pathOffset.x,\n t = -this.pathOffset.y;\n\n ctx.beginPath();\n\n for (const command of this.path) {\n switch (\n command[0] // first letter\n ) {\n case 'L': // lineto, absolute\n ctx.lineTo(command[1] + l, command[2] + t);\n break;\n\n case 'M': // moveTo, absolute\n ctx.moveTo(command[1] + l, command[2] + t);\n break;\n\n case 'C': // bezierCurveTo, absolute\n ctx.bezierCurveTo(\n command[1] + l,\n command[2] + t,\n command[3] + l,\n command[4] + t,\n command[5] + l,\n command[6] + t,\n );\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n ctx.quadraticCurveTo(\n command[1] + l,\n command[2] + t,\n command[3] + l,\n command[4] + t,\n );\n break;\n\n case 'Z':\n ctx.closePath();\n break;\n }\n }\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render path on\n */\n _render(ctx: CanvasRenderingContext2D) {\n this._renderPathCommands(ctx);\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Returns string representation of an instance\n * @return {string} string representation of an instance\n */\n toString() {\n return `#<Path (${this.complexity()}): { \"top\": ${this.top}, \"left\": ${\n this.left\n } }>`;\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return {\n ...super.toObject(propertiesToInclude),\n path: this.path.map((pathCmd) => pathCmd.slice()),\n };\n }\n\n /**\n * Returns dataless object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toDatalessObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n const o = this.toObject<T, K>(propertiesToInclude);\n if (this.sourcePath) {\n delete o.path;\n o.sourcePath = this.sourcePath;\n }\n return o;\n }\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const path = joinPath(this.path, config.NUM_FRACTION_DIGITS);\n return [\n '<path ',\n 'COMMON_PARTS',\n `d=\"${path}\" stroke-linecap=\"round\" />\\n`,\n ];\n }\n\n /**\n * @private\n * @return the path command's translate transform attribute\n */\n _getOffsetTransform() {\n const digits = config.NUM_FRACTION_DIGITS;\n return ` translate(${toFixed(-this.pathOffset.x, digits)}, ${toFixed(\n -this.pathOffset.y,\n digits,\n )})`;\n }\n\n /**\n * Returns svg clipPath representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {string} svg representation of an instance\n */\n toClipPathSVG(reviver?: TSVGReviver): string {\n const additionalTransform = this._getOffsetTransform();\n return (\n '\\t' +\n this._createBaseClipPathSVGMarkup(this._toSVG(), {\n reviver,\n additionalTransform: additionalTransform,\n })\n );\n }\n\n /**\n * Returns svg representation of an instance\n * @param {Function} [reviver] Method for further parsing of svg representation.\n * @return {string} svg representation of an instance\n */\n toSVG(reviver?: TSVGReviver): string {\n const additionalTransform = this._getOffsetTransform();\n return this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n additionalTransform: additionalTransform,\n });\n }\n\n /**\n * Returns number representation of an instance complexity\n * @return {number} complexity of this instance\n */\n complexity() {\n return this.path.length;\n }\n\n setDimensions() {\n this.setBoundingBox();\n }\n\n setBoundingBox(adjustPosition?: boolean) {\n const { width, height, pathOffset } = this._calcDimensions();\n this.set({ width, height, pathOffset });\n // using pathOffset because it match the use case.\n // if pathOffset change here we need to use left + width/2 , top + height/2\n adjustPosition && this.setPositionByOrigin(pathOffset, CENTER, CENTER);\n }\n\n _calcBoundsFromPath(): TBBox {\n const bounds: XY[] = [];\n let subpathStartX = 0,\n subpathStartY = 0,\n x = 0, // current x\n y = 0; // current y\n\n for (const command of this.path) {\n // current instruction\n switch (\n command[0] // first letter\n ) {\n case 'L': // lineto, absolute\n x = command[1];\n y = command[2];\n bounds.push({ x: subpathStartX, y: subpathStartY }, { x, y });\n break;\n\n case 'M': // moveTo, absolute\n x = command[1];\n y = command[2];\n subpathStartX = x;\n subpathStartY = y;\n break;\n\n case 'C': // bezierCurveTo, absolute\n bounds.push(\n ...getBoundsOfCurve(\n x,\n y,\n command[1],\n command[2],\n command[3],\n command[4],\n command[5],\n command[6],\n ),\n );\n x = command[5];\n y = command[6];\n break;\n\n case 'Q': // quadraticCurveTo, absolute\n bounds.push(\n ...getBoundsOfCurve(\n x,\n y,\n command[1],\n command[2],\n command[1],\n command[2],\n command[3],\n command[4],\n ),\n );\n x = command[3];\n y = command[4];\n break;\n\n case 'Z':\n x = subpathStartX;\n y = subpathStartY;\n break;\n }\n }\n return makeBoundingBoxFromPoints(bounds);\n }\n\n /**\n * @private\n */\n _calcDimensions(): IPathBBox {\n const bbox = this._calcBoundsFromPath();\n\n return {\n ...bbox,\n pathOffset: new Point(\n bbox.left + bbox.width / 2,\n bbox.top + bbox.height / 2,\n ),\n };\n }\n\n /**\n * List of attribute names to account for when parsing SVG element (used by `Path.fromElement`)\n * @see http://www.w3.org/TR/SVG/paths.html#PathElement\n */\n static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES, 'd'];\n\n /**\n * Creates an instance of Path from an object\n * @param {Object} object\n * @returns {Promise<Path>}\n */\n static fromObject<T extends TOptions<SerializedPathProps>>(object: T) {\n return this._fromObject<Path>(object, {\n extraParam: 'path',\n });\n }\n\n /**\n * Creates an instance of Path from an SVG <path> element\n * @param {HTMLElement} element to parse\n * @param {Partial<PathProps>} [options] Options object\n */\n static async fromElement(\n element: HTMLElement | SVGElement,\n options?: Partial<PathProps>,\n cssRules?: CSSRules,\n ) {\n const { d, ...parsedAttributes } = parseAttributes(\n element,\n this.ATTRIBUTE_NAMES,\n cssRules,\n );\n return new this(d, {\n ...parsedAttributes,\n ...options,\n // we pass undefined to instruct the constructor to position the object using the bbox\n left: undefined,\n top: undefined,\n });\n }\n}\n\nclassRegistry.setClass(Path);\nclassRegistry.setSVGClass(Path);\n\n/* _FROM_SVG_START_ */\n","import type { ModifierKey, TEvent } from '../EventTypeDefs';\nimport type { Point } from '../Point';\nimport { Shadow } from '../Shadow';\nimport { Path } from '../shapes/Path';\nimport { getSmoothPathFromPoints, joinPath } from '../util/path';\nimport type { Canvas } from '../canvas/Canvas';\nimport { BaseBrush } from './BaseBrush';\nimport type { TSimplePathData } from '../util/path/typedefs';\n\n/**\n * @private\n * @param {TSimplePathData} pathData SVG path commands\n * @returns {boolean}\n */\nfunction isEmptySVGPath(pathData: TSimplePathData): boolean {\n return joinPath(pathData) === 'M 0 0 Q 0 0 0 0 L 0 0';\n}\n\nexport class PencilBrush extends BaseBrush {\n /**\n * Discard points that are less than `decimate` pixel distant from each other\n * @type Number\n * @default 0.4\n */\n decimate = 0.4;\n\n /**\n * Draws a straight line between last recorded point to current pointer\n * Used for `shift` functionality\n *\n * @type boolean\n * @default false\n */\n drawStraightLine = false;\n\n /**\n * The event modifier key that makes the brush draw a straight line.\n * If `null` or 'none' or any other string that is not a modifier key the feature is disabled.\n * @type {ModifierKey | undefined | null}\n */\n straightLineKey: ModifierKey | undefined | null = 'shiftKey';\n\n declare protected _points: Point[];\n declare protected _hasStraightLine: boolean;\n declare protected oldEnd?: Point;\n\n constructor(canvas: Canvas) {\n super(canvas);\n this._points = [];\n this._hasStraightLine = false;\n }\n\n needsFullRender() {\n return super.needsFullRender() || this._hasStraightLine;\n }\n\n static drawSegment(ctx: CanvasRenderingContext2D, p1: Point, p2: Point) {\n const midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n return midPoint;\n }\n\n /**\n * Invoked on mouse down\n * @param {Point} pointer\n */\n onMouseDown(pointer: Point, { e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return;\n }\n this.drawStraightLine = !!this.straightLineKey && e[this.straightLineKey];\n this._prepareForDrawing(pointer);\n // capture coordinates immediately\n // this allows to draw dots (when movement never occurs)\n this._addPoint(pointer);\n this._render();\n }\n\n /**\n * Invoked on mouse move\n * @param {Point} pointer\n */\n onMouseMove(pointer: Point, { e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return;\n }\n this.drawStraightLine = !!this.straightLineKey && e[this.straightLineKey];\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n if (this._addPoint(pointer) && this._points.length > 1) {\n if (this.needsFullRender()) {\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n } else {\n const points = this._points,\n length = points.length,\n ctx = this.canvas.contextTop;\n // draw the curve update\n this._saveAndTransform(ctx);\n if (this.oldEnd) {\n ctx.beginPath();\n ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\n }\n this.oldEnd = PencilBrush.drawSegment(\n ctx,\n points[length - 2],\n points[length - 1],\n );\n ctx.stroke();\n ctx.restore();\n }\n }\n }\n\n /**\n * Invoked on mouse up\n */\n onMouseUp({ e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return true;\n }\n this.drawStraightLine = false;\n this.oldEnd = undefined;\n this._finalizeAndAddPath();\n\n return false;\n }\n\n /**\n * @private\n * @param {Point} pointer Actual mouse position related to the canvas.\n */\n _prepareForDrawing(pointer: Point) {\n this._reset();\n this._addPoint(pointer);\n this.canvas.contextTop.moveTo(pointer.x, pointer.y);\n }\n\n /**\n * @private\n * @param {Point} point Point to be added to points array\n */\n _addPoint(point: Point) {\n if (\n this._points.length > 1 &&\n point.eq(this._points[this._points.length - 1])\n ) {\n return false;\n }\n if (this.drawStraightLine && this._points.length > 1) {\n this._hasStraightLine = true;\n this._points.pop();\n }\n this._points.push(point);\n return true;\n }\n\n /**\n * Clear points array and set contextTop canvas style.\n * @private\n */\n _reset() {\n this._points = [];\n this._setBrushStyles(this.canvas.contextTop);\n this._setShadow();\n this._hasStraightLine = false;\n }\n\n /**\n * Draw a smooth path on the topCanvas using quadraticCurveTo\n * @private\n * @param {CanvasRenderingContext2D} [ctx]\n */\n _render(ctx: CanvasRenderingContext2D = this.canvas.contextTop) {\n let p1 = this._points[0],\n p2 = this._points[1];\n this._saveAndTransform(ctx);\n ctx.beginPath();\n //if we only have 2 points in the path and they are the same\n //it means that the user only clicked the canvas without moving the mouse\n //then we should be drawing a dot. A path isn't drawn between two identical dots\n //that's why we set them apart a bit\n if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {\n const width = this.width / 1000;\n p1.x -= width;\n p2.x += width;\n }\n ctx.moveTo(p1.x, p1.y);\n\n for (let i = 1; i < this._points.length; i++) {\n // we pick the point between pi + 1 & pi + 2 as the\n // end point and p1 as our control point.\n PencilBrush.drawSegment(ctx, p1, p2);\n p1 = this._points[i];\n p2 = this._points[i + 1];\n }\n // Draw last line as a straight line while\n // we wait for the next point to be able to calculate\n // the bezier control point\n ctx.lineTo(p1.x, p1.y);\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * Converts points to SVG path\n * @param {Point[]} points Array of points\n * @return {TSimplePathData} SVG path commands\n */\n convertPointsToSVGPath(points: Point[]): TSimplePathData {\n const correction = this.width / 1000;\n return getSmoothPathFromPoints(points, correction);\n }\n\n /**\n * Creates a Path object to add on canvas\n * @param {TSimplePathData} pathData Path data\n * @return {Path} Path to add on canvas\n */\n createPath(pathData: TSimplePathData): Path {\n const path = new Path(pathData, {\n fill: null,\n stroke: this.color,\n strokeWidth: this.width,\n strokeLineCap: this.strokeLineCap,\n strokeMiterLimit: this.strokeMiterLimit,\n strokeLineJoin: this.strokeLineJoin,\n strokeDashArray: this.strokeDashArray,\n });\n if (this.shadow) {\n this.shadow.affectStroke = true;\n path.shadow = new Shadow(this.shadow);\n }\n\n return path;\n }\n\n /**\n * Decimate points array with the decimate value\n */\n decimatePoints(points: Point[], distance: number) {\n if (points.length <= 2) {\n return points;\n }\n let lastPoint = points[0],\n cDistance;\n const zoom = this.canvas.getZoom(),\n adjustedDistance = Math.pow(distance / zoom, 2),\n l = points.length - 1,\n newPoints = [lastPoint];\n // TODO investigate why this is not i < l\n for (let i = 1; i < l - 1; i++) {\n cDistance =\n Math.pow(lastPoint.x - points[i].x, 2) +\n Math.pow(lastPoint.y - points[i].y, 2);\n if (cDistance >= adjustedDistance) {\n lastPoint = points[i];\n newPoints.push(lastPoint);\n }\n }\n // Add the last point from the original line to the end of the array.\n // This ensures decimate doesn't delete the last point on the line, and ensures the line is > 1 point.\n newPoints.push(points[l]);\n return newPoints;\n }\n\n /**\n * On mouseup after drawing the path on contextTop canvas\n * we use the points captured to create an new Path object\n * and add it to the canvas.\n */\n _finalizeAndAddPath() {\n const ctx = this.canvas.contextTop;\n ctx.closePath();\n if (this.decimate) {\n this._points = this.decimatePoints(this._points, this.decimate);\n }\n const pathData = this.convertPointsToSVGPath(this._points);\n if (isEmptySVGPath(pathData)) {\n // do not create 0 width/height paths, as they are\n // rendered inconsistently across browsers\n // Firefox 4, for example, renders a dot,\n // whereas Chrome 10 renders nothing\n this.canvas.requestRenderAll();\n return;\n }\n\n const path = this.createPath(pathData);\n this.canvas.clearContext(this.canvas.contextTop);\n this.canvas.fire('before:path:created', { path: path });\n this.canvas.add(path);\n this.canvas.requestRenderAll();\n path.setCoords();\n this._resetShadow();\n\n // fire event 'path' created\n this.canvas.fire('path:created', { path: path });\n }\n}\n","import type { ObjectEvents } from '../EventTypeDefs';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { cos } from '../util/misc/cos';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\nimport { sin } from '../util/misc/sin';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { CSSRules } from '../parser/typedefs';\nimport { SCALE_X, SCALE_Y } from '../constants';\n\ninterface UniqueCircleProps {\n /**\n * Radius of this circle\n * @type Number\n * @default 0\n */\n radius: number;\n\n /**\n * Angle for the start of the circle, in degrees.\n * @type TDegree 0 - 359\n * @default 0\n */\n startAngle: number;\n\n /**\n * Angle for the end of the circle, in degrees\n * @type TDegree 1 - 360\n * @default 360\n */\n endAngle: number;\n\n /**\n * Orientation for the direction of the circle.\n * Setting to true will switch the arc of the circle to traverse from startAngle to endAngle in a counter-clockwise direction.\n * Note: this will only change how the circle is drawn, and does not affect rotational transformation.\n * @default false\n */\n counterClockwise: boolean;\n}\n\nexport interface SerializedCircleProps\n extends SerializedObjectProps,\n UniqueCircleProps {}\n\nexport interface CircleProps extends FabricObjectProps, UniqueCircleProps {}\n\nconst CIRCLE_PROPS = [\n 'radius',\n 'startAngle',\n 'endAngle',\n 'counterClockwise',\n] as const;\n\nexport const circleDefaultValues: Partial<TClassProperties<Circle>> = {\n radius: 0,\n startAngle: 0,\n endAngle: 360,\n counterClockwise: false,\n};\n\nexport class Circle<\n Props extends TOptions<CircleProps> = Partial<CircleProps>,\n SProps extends SerializedCircleProps = SerializedCircleProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements UniqueCircleProps\n{\n declare radius: number;\n declare startAngle: number;\n declare endAngle: number;\n declare counterClockwise: boolean;\n\n static type = 'Circle';\n\n static cacheProperties = [...cacheProperties, ...CIRCLE_PROPS];\n\n static ownDefaults = circleDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Circle.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(this, Circle.ownDefaults);\n this.setOptions(options);\n }\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n */\n _set(key: string, value: any) {\n super._set(key, value);\n\n if (key === 'radius') {\n this.setRadius(value);\n }\n\n return this;\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n ctx.beginPath();\n ctx.arc(\n 0,\n 0,\n this.radius,\n degreesToRadians(this.startAngle),\n degreesToRadians(this.endAngle),\n this.counterClockwise,\n );\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Returns horizontal radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusX(): number {\n return this.get('radius') * this.get(SCALE_X);\n }\n\n /**\n * Returns vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRadiusY(): number {\n return this.get('radius') * this.get(SCALE_Y);\n }\n\n /**\n * Sets radius of an object (and updates width accordingly)\n */\n setRadius(value: number) {\n this.radius = value;\n this.set({ width: value * 2, height: value * 2 });\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<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject([...CIRCLE_PROPS, ...propertiesToInclude]);\n }\n\n /* _TO_SVG_START_ */\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG(): string[] {\n const angle = (this.endAngle - this.startAngle) % 360;\n\n if (angle === 0) {\n return [\n '<circle ',\n 'COMMON_PARTS',\n 'cx=\"0\" cy=\"0\" ',\n 'r=\"',\n `${this.radius}`,\n '\" />\\n',\n ];\n } else {\n const { radius } = this;\n const start = degreesToRadians(this.startAngle),\n end = degreesToRadians(this.endAngle),\n startX = cos(start) * radius,\n startY = sin(start) * radius,\n endX = cos(end) * radius,\n endY = sin(end) * radius,\n largeFlag = angle > 180 ? 1 : 0,\n sweepFlag = this.counterClockwise ? 0 : 1;\n return [\n `<path d=\"M ${startX} ${startY} A ${radius} ${radius} 0 ${largeFlag} ${sweepFlag} ${endX} ${endY}\" `,\n 'COMMON_PARTS',\n ' />\\n',\n ];\n }\n }\n /* _TO_SVG_END_ */\n\n /* _FROM_SVG_START_ */\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link Circle.fromElement})\n * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement\n */\n static ATTRIBUTE_NAMES = ['cx', 'cy', 'r', ...SHARED_ATTRIBUTES];\n\n /**\n * Returns {@link Circle} instance from an SVG element\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Partial Circle object to default missing properties on the element.\n * @throws {Error} If value of `r` attribute is missing or invalid\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable,\n cssRules?: CSSRules,\n ): Promise<Circle> {\n const {\n left = 0,\n top = 0,\n radius = 0,\n ...otherParsedAttributes\n } = parseAttributes(\n element,\n this.ATTRIBUTE_NAMES,\n cssRules,\n ) as Partial<CircleProps>;\n\n // this probably requires to be fixed for default origins not being top/left.\n\n return new this({\n ...otherParsedAttributes,\n radius,\n left: left - radius,\n top: top - radius,\n });\n }\n\n /* _FROM_SVG_END_ */\n\n /**\n * @todo how do we declare this??\n */\n static fromObject<T extends TOptions<SerializedCircleProps>>(object: T) {\n return super._fromObject<Circle>(object);\n }\n}\n\nclassRegistry.setClass(Circle);\nclassRegistry.setSVGClass(Circle);\n","import { Color } from '../color/Color';\nimport type { Point } from '../Point';\nimport { Shadow } from '../Shadow';\nimport { Circle } from '../shapes/Circle';\nimport { Group } from '../shapes/Group';\nimport { getRandomInt } from '../util/internals/getRandomInt';\nimport type { Canvas } from '../canvas/Canvas';\nimport { BaseBrush } from './BaseBrush';\nimport type { CircleBrushPoint } from './typedefs';\nimport { CENTER } from '../constants';\n\nexport class CircleBrush extends BaseBrush {\n /**\n * Width of a brush\n * @type Number\n */\n width = 10;\n\n declare points: CircleBrushPoint[];\n\n constructor(canvas: Canvas) {\n super(canvas);\n this.points = [];\n }\n\n /**\n * Invoked inside on mouse down and mouse move\n * @param {Point} pointer\n */\n drawDot(pointer: Point) {\n const point = this.addPoint(pointer),\n ctx = this.canvas.contextTop;\n this._saveAndTransform(ctx);\n this.dot(ctx, point);\n ctx.restore();\n }\n\n dot(ctx: CanvasRenderingContext2D, point: CircleBrushPoint) {\n ctx.fillStyle = point.fill;\n ctx.beginPath();\n ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);\n ctx.closePath();\n ctx.fill();\n }\n\n /**\n * Invoked on mouse down\n */\n onMouseDown(pointer: Point) {\n this.points = [];\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n this.drawDot(pointer);\n }\n\n /**\n * Render the full state of the brush\n * @private\n */\n _render() {\n const ctx = this.canvas.contextTop,\n points = this.points;\n this._saveAndTransform(ctx);\n for (let i = 0; i < points.length; i++) {\n this.dot(ctx, points[i]);\n }\n ctx.restore();\n }\n\n /**\n * Invoked on mouse move\n * @param {Point} pointer\n */\n onMouseMove(pointer: Point) {\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n if (this.needsFullRender()) {\n this.canvas.clearContext(this.canvas.contextTop);\n this.addPoint(pointer);\n this._render();\n } else {\n this.drawDot(pointer);\n }\n }\n\n /**\n * Invoked on mouse up\n */\n onMouseUp() {\n const originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n this.canvas.renderOnAddRemove = false;\n\n const circles: Circle[] = [];\n\n for (let i = 0; i < this.points.length; i++) {\n const point = this.points[i],\n circle = new Circle({\n radius: point.radius,\n left: point.x,\n top: point.y,\n originX: CENTER,\n originY: CENTER,\n fill: point.fill,\n });\n\n this.shadow && (circle.shadow = new Shadow(this.shadow));\n\n circles.push(circle);\n }\n const group = new Group(circles, { canvas: this.canvas });\n\n this.canvas.fire('before:path:created', { path: group });\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.requestRenderAll();\n }\n\n /**\n * @param {Object} pointer\n * @return {Point} Just added pointer point\n */\n addPoint({ x, y }: Point) {\n const pointerPoint: CircleBrushPoint = {\n x,\n y,\n radius: getRandomInt(Math.max(0, this.width - 20), this.width + 20) / 2,\n fill: new Color(this.color).setAlpha(getRandomInt(0, 100) / 100).toRgba(),\n };\n\n this.points.push(pointerPoint);\n\n return pointerPoint;\n }\n}\n","import type { Point } from '../Point';\nimport { Group } from '../shapes/Group';\nimport { Shadow } from '../Shadow';\nimport { Rect } from '../shapes/Rect';\nimport { getRandomInt } from '../util/internals/getRandomInt';\nimport type { Canvas } from '../canvas/Canvas';\nimport { BaseBrush } from './BaseBrush';\nimport type { SprayBrushPoint } from './typedefs';\nimport { CENTER } from '../constants';\n\n/**\n *\n * @param rects\n * @returns\n */\nfunction getUniqueRects(rects: Rect[]) {\n const uniqueRects: Record<string, boolean> = {};\n const uniqueRectsArray: Rect[] = [];\n\n for (let i = 0, key: string; i < rects.length; i++) {\n key = `${rects[i].left}${rects[i].top}`;\n if (!uniqueRects[key]) {\n uniqueRects[key] = true;\n uniqueRectsArray.push(rects[i]);\n }\n }\n\n return uniqueRectsArray;\n}\n\nexport class SprayBrush extends BaseBrush {\n /**\n * Width of a spray\n * @type Number\n */\n width = 10;\n\n /**\n * Density of a spray (number of dots per chunk)\n * @type Number\n */\n density = 20;\n\n /**\n * Width of spray dots\n * @type Number\n */\n dotWidth = 1;\n\n /**\n * Width variance of spray dots\n * @type Number\n */\n dotWidthVariance = 1;\n\n /**\n * Whether opacity of a dot should be random\n * @type Boolean\n */\n randomOpacity = false;\n\n /**\n * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n * @type Boolean\n */\n optimizeOverlapping = true;\n\n declare private sprayChunks: SprayBrushPoint[][];\n\n declare private sprayChunk: SprayBrushPoint[];\n\n /**\n * Constructor\n * @param {Canvas} canvas\n * @return {SprayBrush} Instance of a spray brush\n */\n constructor(canvas: Canvas) {\n super(canvas);\n this.sprayChunks = [];\n this.sprayChunk = [];\n }\n\n /**\n * Invoked on mouse down\n * @param {Point} pointer\n */\n onMouseDown(pointer: Point) {\n this.sprayChunks = [];\n this.canvas.clearContext(this.canvas.contextTop);\n this._setShadow();\n\n this.addSprayChunk(pointer);\n this.renderChunck(this.sprayChunk);\n }\n\n /**\n * Invoked on mouse move\n * @param {Point} pointer\n */\n onMouseMove(pointer: Point) {\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n this.addSprayChunk(pointer);\n this.renderChunck(this.sprayChunk);\n }\n\n /**\n * Invoked on mouse up\n */\n onMouseUp() {\n const originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n this.canvas.renderOnAddRemove = false;\n\n const rects: Rect[] = [];\n\n for (let i = 0; i < this.sprayChunks.length; i++) {\n const sprayChunk = this.sprayChunks[i];\n for (let j = 0; j < sprayChunk.length; j++) {\n const chunck = sprayChunk[j];\n const rect = new Rect({\n width: chunck.width,\n height: chunck.width,\n left: chunck.x + 1,\n top: chunck.y + 1,\n originX: CENTER,\n originY: CENTER,\n fill: this.color,\n });\n rects.push(rect);\n }\n }\n\n const group = new Group(\n this.optimizeOverlapping ? getUniqueRects(rects) : rects,\n {\n objectCaching: true,\n subTargetCheck: false,\n interactive: false,\n },\n );\n this.shadow && group.set('shadow', new Shadow(this.shadow));\n this.canvas.fire('before:path:created', { path: group });\n this.canvas.add(group);\n this.canvas.fire('path:created', { path: group });\n\n this.canvas.clearContext(this.canvas.contextTop);\n this._resetShadow();\n this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n this.canvas.requestRenderAll();\n }\n\n renderChunck(sprayChunck: SprayBrushPoint[]) {\n const ctx = this.canvas.contextTop;\n ctx.fillStyle = this.color;\n\n this._saveAndTransform(ctx);\n\n for (let i = 0; i < sprayChunck.length; i++) {\n const point = sprayChunck[i];\n ctx.globalAlpha = point.opacity;\n ctx.fillRect(point.x, point.y, point.width, point.width);\n }\n\n ctx.restore();\n }\n\n /**\n * Render all spray chunks\n */\n _render() {\n const ctx = this.canvas.contextTop;\n ctx.fillStyle = this.color;\n\n this._saveAndTransform(ctx);\n\n for (let i = 0; i < this.sprayChunks.length; i++) {\n this.renderChunck(this.sprayChunks[i]);\n }\n ctx.restore();\n }\n\n /**\n * @param {Point} pointer\n */\n addSprayChunk(pointer: Point) {\n this.sprayChunk = [];\n const radius = this.width / 2;\n\n for (let i = 0; i < this.density; i++) {\n this.sprayChunk.push({\n x: getRandomInt(pointer.x - radius, pointer.x + radius),\n y: getRandomInt(pointer.y - radius, pointer.y + radius),\n width: this.dotWidthVariance\n ? getRandomInt(\n // bottom clamp width to 1\n Math.max(1, this.dotWidth - this.dotWidthVariance),\n this.dotWidth + this.dotWidthVariance,\n )\n : this.dotWidth,\n opacity: this.randomOpacity ? getRandomInt(0, 100) / 100 : 1,\n });\n }\n\n this.sprayChunks.push(this.sprayChunk);\n }\n}\n","import { Pattern } from '../Pattern';\nimport { createCanvasElement } from '../util/misc/dom';\nimport type { Canvas } from '../canvas/Canvas';\nimport { PencilBrush } from './PencilBrush';\nimport type { TSimplePathData } from '../util/path/typedefs';\n\nexport class PatternBrush extends PencilBrush {\n declare source?: CanvasImageSource;\n\n constructor(canvas: Canvas) {\n super(canvas);\n }\n\n getPatternSrc() {\n const dotWidth = 20,\n dotDistance = 5,\n patternCanvas = createCanvasElement(),\n patternCtx = patternCanvas.getContext('2d');\n\n patternCanvas.width = patternCanvas.height = dotWidth + dotDistance;\n if (patternCtx) {\n patternCtx.fillStyle = this.color;\n patternCtx.beginPath();\n patternCtx.arc(\n dotWidth / 2,\n dotWidth / 2,\n dotWidth / 2,\n 0,\n Math.PI * 2,\n false,\n );\n patternCtx.closePath();\n patternCtx.fill();\n }\n return patternCanvas;\n }\n\n /**\n * Creates \"pattern\" instance property\n * @param {CanvasRenderingContext2D} ctx\n */\n getPattern(ctx: CanvasRenderingContext2D) {\n return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');\n }\n\n /**\n * Sets brush styles\n * @param {CanvasRenderingContext2D} ctx\n */\n _setBrushStyles(ctx: CanvasRenderingContext2D) {\n super._setBrushStyles(ctx);\n const pattern = this.getPattern(ctx);\n pattern && (ctx.strokeStyle = pattern);\n }\n\n /**\n * Creates path\n */\n createPath(pathData: TSimplePathData) {\n const path = super.createPath(pathData),\n topLeft = path._getLeftTopCoords().scalarAdd(path.strokeWidth / 2);\n\n path.stroke = new Pattern({\n source: this.source || this.getPatternSrc(),\n offsetX: -topLeft.x,\n offsetY: -topLeft.y,\n });\n return path;\n }\n}\n","import { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport { Point } from '../Point';\nimport { isFiller } from '../util/typeAssertions';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport { makeBoundingBoxFromPoints } from '../util';\nimport { CENTER, LEFT, TOP } from '../constants';\nimport type { CSSRules } from '../parser/typedefs';\n\n// @TODO this code is terrible and Line should be a special case of polyline.\n\nconst coordProps = ['x1', 'x2', 'y1', 'y2'] as const;\n\ninterface UniqueLineProps {\n x1: number;\n x2: number;\n y1: number;\n y2: number;\n}\n\nexport interface SerializedLineProps\n extends SerializedObjectProps,\n UniqueLineProps {}\n\n/**\n * A Class to draw a line\n * A bunch of methods will be added to Polyline to handle the line case\n * The line class is very strange to work with, is all special, it hardly aligns\n * to what a developer want everytime there is an angle\n * @deprecated\n */\nexport class Line<\n Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>,\n SProps extends SerializedLineProps = SerializedLineProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements UniqueLineProps\n{\n /**\n * x value or first line edge\n * @type number\n */\n declare x1: number;\n\n /**\n * y value or first line edge\n * @type number\n */\n declare y1: number;\n\n /**\n * x value or second line edge\n * @type number\n */\n declare x2: number;\n\n /**\n * y value or second line edge\n * @type number\n */\n declare y2: number;\n\n static type = 'Line';\n\n static cacheProperties = [...cacheProperties, ...coordProps];\n /**\n * Constructor\n * @param {Array} [points] Array of points\n * @param {Object} [options] Options object\n * @return {Line} thisArg\n */\n constructor([x1, y1, x2, y2] = [0, 0, 0, 0], options: Partial<Props> = {}) {\n super();\n Object.assign(this, Line.ownDefaults);\n this.setOptions(options);\n this.x1 = x1;\n this.x2 = x2;\n this.y1 = y1;\n this.y2 = y2;\n this._setWidthHeight();\n const { left, top } = options;\n typeof left === 'number' && this.set(LEFT, left);\n typeof top === 'number' && this.set(TOP, top);\n }\n\n /**\n * @private\n * @param {Object} [options] Options\n */\n _setWidthHeight() {\n const { x1, y1, x2, y2 } = this;\n this.width = Math.abs(x2 - x1);\n this.height = Math.abs(y2 - y1);\n const { left, top, width, height } = makeBoundingBoxFromPoints([\n { x: x1, y: y1 },\n { x: x2, y: y2 },\n ]);\n const position = new Point(left + width / 2, top + height / 2);\n this.setPositionByOrigin(position, CENTER, CENTER);\n }\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n */\n _set(key: string, value: any) {\n super._set(key, value);\n if (coordProps.includes(key as keyof UniqueLineProps)) {\n // this doesn't make sense very much, since setting x1 when top or left\n // are already set, is just going to show a strange result since the\n // line will move way more than the developer expect.\n // in fabric5 it worked only when the line didn't have extra transformations,\n // in fabric6 too. With extra transform they behave bad in different ways.\n // This needs probably a good rework or a tutorial if you have to create a dynamic line\n this._setWidthHeight();\n }\n return this;\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n ctx.beginPath();\n\n const p = this.calcLinePoints();\n ctx.moveTo(p.x1, p.y1);\n ctx.lineTo(p.x2, p.y2);\n\n ctx.lineWidth = this.strokeWidth;\n\n // TODO: test this\n // make sure setting \"fill\" changes color of a line\n // (by copying fillStyle to strokeStyle, since line is stroked, not filled)\n const origStrokeStyle = ctx.strokeStyle;\n if (isFiller(this.stroke)) {\n ctx.strokeStyle = this.stroke.toLive(ctx)!;\n } else {\n ctx.strokeStyle = this.stroke ?? ctx.fillStyle;\n }\n this.stroke && this._renderStroke(ctx);\n ctx.strokeStyle = origStrokeStyle;\n }\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates\n * @private\n * @return {Point} center point from element coordinates\n */\n _findCenterFromElement(): Point {\n return new Point((this.x1 + this.x2) / 2, (this.y1 + this.y2) / 2);\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<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return {\n ...super.toObject(propertiesToInclude),\n ...this.calcLinePoints(),\n };\n }\n\n /*\n * Calculate object dimensions from its properties\n * @private\n */\n _getNonTransformedDimensions(): Point {\n const dim = super._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 * Those points are simply placed around the center,\n * This is not useful outside internal render functions and svg output\n * Is not meant to be for the developer.\n * @private\n */\n calcLinePoints(): UniqueLineProps {\n const { x1: _x1, x2: _x2, y1: _y1, y2: _y2, width, height } = this;\n const xMult = _x1 <= _x2 ? -1 : 1,\n yMult = _y1 <= _y2 ? -1 : 1,\n x1 = (xMult * width) / 2,\n y1 = (yMult * height) / 2,\n x2 = (xMult * -width) / 2,\n y2 = (yMult * -height) / 2;\n\n return {\n x1,\n x2,\n y1,\n y2,\n };\n }\n\n /* _FROM_SVG_START_ */\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const { x1, x2, y1, y2 } = this.calcLinePoints();\n return [\n '<line ',\n 'COMMON_PARTS',\n `x1=\"${x1}\" y1=\"${y1}\" x2=\"${x2}\" y2=\"${y2}\" />\\n`,\n ];\n }\n\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement})\n * @see http://www.w3.org/TR/SVG/shapes.html#LineElement\n */\n static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat(coordProps);\n\n /**\n * Returns Line instance from an SVG element\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n * @param {Function} [callback] callback function invoked after parsing\n */\n static async fromElement(\n element: HTMLElement,\n options?: Abortable,\n cssRules?: CSSRules,\n ) {\n const {\n x1 = 0,\n y1 = 0,\n x2 = 0,\n y2 = 0,\n ...parsedAttributes\n } = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);\n return new this([x1, y1, x2, y2], parsedAttributes);\n }\n\n /* _FROM_SVG_END_ */\n\n /**\n * Returns Line instance from an object representation\n * @param {Object} object Object to create an instance from\n * @returns {Promise<Line>}\n */\n static fromObject<T extends TOptions<SerializedLineProps>>({\n x1,\n y1,\n x2,\n y2,\n ...object\n }: T) {\n return this._fromObject<Line>(\n {\n ...object,\n points: [x1, y1, x2, y2],\n },\n {\n extraParam: 'points',\n },\n );\n }\n}\n\nclassRegistry.setClass(Line);\nclassRegistry.setSVGClass(Line);\n","import { classRegistry } from '../ClassRegistry';\nimport { FabricObject } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { TClassProperties, TOptions } from '../typedefs';\nimport type { ObjectEvents } from '../EventTypeDefs';\n\nexport const triangleDefaultValues: Partial<TClassProperties<Triangle>> = {\n width: 100,\n height: 100,\n};\n\nexport class Triangle<\n Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>,\n SProps extends SerializedObjectProps = SerializedObjectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements FabricObjectProps\n{\n static type = 'Triangle';\n\n static ownDefaults = triangleDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return { ...super.getDefaults(), ...Triangle.ownDefaults };\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(this, Triangle.ownDefaults);\n this.setOptions(options);\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n const widthBy2 = this.width / 2,\n heightBy2 = this.height / 2;\n\n ctx.beginPath();\n ctx.moveTo(-widthBy2, heightBy2);\n ctx.lineTo(0, -heightBy2);\n ctx.lineTo(widthBy2, heightBy2);\n ctx.closePath();\n\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const widthBy2 = this.width / 2,\n heightBy2 = this.height / 2,\n points = `${-widthBy2} ${heightBy2},0 ${-heightBy2},${widthBy2} ${heightBy2}`;\n return ['<polygon ', 'COMMON_PARTS', 'points=\"', points, '\" />'];\n }\n}\n\nclassRegistry.setClass(Triangle);\nclassRegistry.setSVGClass(Triangle);\n","import { SCALE_X, SCALE_Y, twoMathPi } from '../constants';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport type { CSSRules } from '../parser/typedefs';\n\nexport const ellipseDefaultValues: Partial<TClassProperties<Ellipse>> = {\n rx: 0,\n ry: 0,\n};\n\ninterface UniqueEllipseProps {\n rx: number;\n ry: number;\n}\n\nexport interface SerializedEllipseProps\n extends SerializedObjectProps,\n UniqueEllipseProps {}\n\nexport interface EllipseProps extends FabricObjectProps, UniqueEllipseProps {}\n\nconst ELLIPSE_PROPS = ['rx', 'ry'] as const;\n\nexport class Ellipse<\n Props extends TOptions<EllipseProps> = Partial<EllipseProps>,\n SProps extends SerializedEllipseProps = SerializedEllipseProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements EllipseProps\n{\n /**\n * Horizontal radius\n * @type Number\n */\n declare rx: number;\n\n /**\n * Vertical radius\n * @type Number\n */\n declare ry: number;\n\n static type = 'Ellipse';\n\n static cacheProperties = [...cacheProperties, ...ELLIPSE_PROPS];\n\n static ownDefaults = ellipseDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Ellipse.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor(options?: Props) {\n super();\n Object.assign(this, Ellipse.ownDefaults);\n this.setOptions(options);\n }\n\n /**\n * @private\n * @param {String} key\n * @param {*} value\n * @return {Ellipse} thisArg\n */\n _set(key: string, value: any) {\n super._set(key, value);\n switch (key) {\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 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() {\n return this.get('rx') * this.get(SCALE_X);\n }\n\n /**\n * Returns Vertical radius of an object (according to how an object is scaled)\n * @return {Number}\n */\n getRy() {\n return this.get('ry') * this.get(SCALE_Y);\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<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject([...ELLIPSE_PROPS, ...propertiesToInclude]);\n }\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG(): string[] {\n return [\n '<ellipse ',\n 'COMMON_PARTS',\n `cx=\"0\" cy=\"0\" rx=\"${this.rx}\" ry=\"${this.ry}\" />\\n`,\n ];\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n ctx.beginPath();\n ctx.save();\n ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);\n ctx.arc(0, 0, this.rx, 0, twoMathPi, false);\n ctx.restore();\n this._renderPaintInOrder(ctx);\n }\n\n /* _FROM_SVG_START_ */\n\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link Ellipse.fromElement})\n * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement\n */\n static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES, 'cx', 'cy', 'rx', 'ry'];\n\n /**\n * Returns {@link Ellipse} instance from an SVG element\n * @param {HTMLElement} element Element to parse\n * @return {Ellipse}\n */\n static async fromElement(\n element: HTMLElement,\n options?: Abortable,\n cssRules?: CSSRules,\n ) {\n const parsedAttributes = parseAttributes(\n element,\n this.ATTRIBUTE_NAMES,\n cssRules,\n );\n\n parsedAttributes.left = (parsedAttributes.left || 0) - parsedAttributes.rx;\n parsedAttributes.top = (parsedAttributes.top || 0) - parsedAttributes.ry;\n return new this(parsedAttributes);\n }\n\n /* _FROM_SVG_END_ */\n}\n\nclassRegistry.setClass(Ellipse);\nclassRegistry.setSVGClass(Ellipse);\n","import { config } from '../config';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport { parsePointsAttribute } from '../parser/parsePointsAttribute';\nimport type { XY } from '../Point';\nimport { Point } from '../Point';\nimport type { Abortable, TClassProperties, TOptions } from '../typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints';\nimport { calcDimensionsMatrix, transformPoint } from '../util/misc/matrix';\nimport { projectStrokeOnPoints } from '../util/misc/projectStroke';\nimport type { TProjectStrokeOnPointsOptions } from '../util/misc/projectStroke/types';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\nimport { toFixed } from '../util/misc/toFixed';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport {\n CENTER,\n LEFT,\n SCALE_X,\n SCALE_Y,\n SKEW_X,\n SKEW_Y,\n TOP,\n} from '../constants';\nimport type { CSSRules } from '../parser/typedefs';\n\nexport const polylineDefaultValues: Partial<TClassProperties<Polyline>> = {\n /**\n * @deprecated transient option soon to be removed in favor of a different design\n */\n exactBoundingBox: false,\n};\n\nexport interface SerializedPolylineProps extends SerializedObjectProps {\n points: XY[];\n}\n\nexport class Polyline<\n Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>,\n SProps extends SerializedPolylineProps = SerializedPolylineProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n> extends FabricObject<Props, SProps, EventSpec> {\n /**\n * Points array\n * @type Array\n */\n declare points: XY[];\n\n /**\n * WARNING: Feature in progress\n * Calculate the exact bounding box taking in account strokeWidth on acute angles\n * this will be turned to true by default on fabric 6.0\n * maybe will be left in as an optimization since calculations may be slow\n * @deprecated transient option soon to be removed in favor of a different design\n * @type Boolean\n * @default false\n */\n declare exactBoundingBox: boolean;\n\n declare private initialized: true | undefined;\n\n static ownDefaults = polylineDefaultValues;\n\n static type = 'Polyline';\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Polyline.ownDefaults,\n };\n }\n\n /**\n * A list of properties that if changed trigger a recalculation of dimensions\n * @todo check if you really need to recalculate for all cases\n */\n static layoutProperties: (keyof Polyline)[] = [\n SKEW_X,\n SKEW_Y,\n 'strokeLineCap',\n 'strokeLineJoin',\n 'strokeMiterLimit',\n 'strokeWidth',\n 'strokeUniform',\n 'points',\n ];\n\n declare pathOffset: Point;\n\n declare strokeOffset: Point;\n\n static cacheProperties = [...cacheProperties, 'points'];\n\n strokeDiff: Point;\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 {Polyline} thisArg\n * @example\n * var poly = new 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 constructor(points: XY[] = [], options: Props = {} as Props) {\n super();\n Object.assign(this, Polyline.ownDefaults);\n this.setOptions(options);\n this.points = points;\n const { left, top } = options;\n this.initialized = true;\n this.setBoundingBox(true);\n typeof left === 'number' && this.set(LEFT, left);\n typeof top === 'number' && this.set(TOP, top);\n }\n\n protected isOpen() {\n return true;\n }\n\n private _projectStrokeOnPoints(options: TProjectStrokeOnPointsOptions) {\n return projectStrokeOnPoints(this.points, options, this.isOpen());\n }\n\n /**\n * Calculate the polygon bounding box\n * @private\n */\n _calcDimensions(options?: Partial<TProjectStrokeOnPointsOptions>) {\n options = {\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n strokeLineCap: this.strokeLineCap,\n strokeLineJoin: this.strokeLineJoin,\n strokeMiterLimit: this.strokeMiterLimit,\n strokeUniform: this.strokeUniform,\n strokeWidth: this.strokeWidth,\n ...(options || {}),\n };\n const points = this.exactBoundingBox\n ? this._projectStrokeOnPoints(\n options as TProjectStrokeOnPointsOptions,\n ).map((projection) => projection.projectedPoint)\n : this.points;\n if (points.length === 0) {\n return {\n left: 0,\n top: 0,\n width: 0,\n height: 0,\n pathOffset: new Point(),\n strokeOffset: new Point(),\n strokeDiff: new Point(),\n };\n }\n const bbox = makeBoundingBoxFromPoints(points),\n // Remove scale effect, since it's applied after\n matrix = calcDimensionsMatrix({ ...options, scaleX: 1, scaleY: 1 }),\n bboxNoStroke = makeBoundingBoxFromPoints(\n this.points.map((p) => transformPoint(p, matrix, true)),\n ),\n scale = new Point(this.scaleX, this.scaleY);\n let offsetX = bbox.left + bbox.width / 2,\n offsetY = bbox.top + bbox.height / 2;\n if (this.exactBoundingBox) {\n offsetX = offsetX - offsetY * Math.tan(degreesToRadians(this.skewX));\n // Order of those assignments is important.\n // offsetY relies on offsetX being already changed by the line above\n offsetY = offsetY - offsetX * Math.tan(degreesToRadians(this.skewY));\n }\n\n return {\n ...bbox,\n pathOffset: new Point(offsetX, offsetY),\n strokeOffset: new Point(bboxNoStroke.left, bboxNoStroke.top)\n .subtract(new Point(bbox.left, bbox.top))\n .multiply(scale),\n strokeDiff: new Point(bbox.width, bbox.height)\n .subtract(new Point(bboxNoStroke.width, bboxNoStroke.height))\n .multiply(scale),\n };\n }\n\n /**\n * This function is an helper for svg import. it returns the center of the object in the svg\n * untransformed coordinates, by look at the polyline/polygon points.\n * @private\n * @return {Point} center point from element coordinates\n */\n _findCenterFromElement(): Point {\n const bbox = makeBoundingBoxFromPoints(this.points);\n return new Point(bbox.left + bbox.width / 2, bbox.top + bbox.height / 2);\n }\n\n setDimensions() {\n this.setBoundingBox();\n }\n\n setBoundingBox(adjustPosition?: boolean) {\n const { left, top, width, height, pathOffset, strokeOffset, strokeDiff } =\n this._calcDimensions();\n this.set({ width, height, pathOffset, strokeOffset, strokeDiff });\n adjustPosition &&\n this.setPositionByOrigin(\n new Point(left + width / 2, top + height / 2),\n CENTER,\n CENTER,\n );\n }\n\n /**\n * @deprecated intermidiate method to be removed, do not use\n */\n protected isStrokeAccountedForInDimensions() {\n return this.exactBoundingBox;\n }\n\n /**\n * @override stroke is taken in account in size\n */\n _getNonTransformedDimensions() {\n return this.exactBoundingBox\n ? // TODO: fix this\n new Point(this.width, this.height)\n : super._getNonTransformedDimensions();\n }\n\n /**\n * @override stroke and skewing are taken into account when projecting stroke on points,\n * therefore we don't want the default calculation to account for skewing as well.\n * Though it is possible to pass `width` and `height` in `options`, doing so is very strange, use with discretion.\n *\n * @private\n */\n _getTransformedDimensions(options: any = {}) {\n if (this.exactBoundingBox) {\n let size: Point;\n /* When `strokeUniform = true`, any changes to the properties require recalculating the `width` and `height` because\n the stroke projections are affected.\n When `strokeUniform = false`, we don't need to recalculate for scale transformations, as the effect of scale on\n projections follows a linear function (e.g. scaleX of 2 just multiply width by 2)*/\n if (\n Object.keys(options).some(\n (key) =>\n this.strokeUniform ||\n (this.constructor as typeof Polyline).layoutProperties.includes(\n key as keyof TProjectStrokeOnPointsOptions,\n ),\n )\n ) {\n const { width, height } = this._calcDimensions(options);\n size = new Point(options.width ?? width, options.height ?? height);\n } else {\n size = new Point(\n options.width ?? this.width,\n options.height ?? this.height,\n );\n }\n return size.multiply(\n new Point(options.scaleX || this.scaleX, options.scaleY || this.scaleY),\n );\n } else {\n return super._getTransformedDimensions(options);\n }\n }\n\n /**\n * Recalculates dimensions when changing skew and scale\n * @private\n */\n _set(key: string, value: any) {\n const changed = this.initialized && this[key as keyof this] !== value;\n const output = super._set(key, value);\n if (\n this.exactBoundingBox &&\n changed &&\n (((key === SCALE_X || key === SCALE_Y) &&\n this.strokeUniform &&\n (this.constructor as typeof Polyline).layoutProperties.includes(\n 'strokeUniform',\n )) ||\n (this.constructor as typeof Polyline).layoutProperties.includes(\n key as keyof Polyline,\n ))\n ) {\n this.setDimensions();\n }\n return output;\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<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return {\n ...super.toObject(propertiesToInclude),\n points: this.points.map(({ x, y }) => ({ x, y })),\n };\n }\n\n /**\n * Returns svg representation of an instance\n * @return {Array} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const points = [],\n diffX = this.pathOffset.x,\n diffY = this.pathOffset.y,\n NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;\n\n for (let i = 0, len = this.points.length; i < len; i++) {\n points.push(\n toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS),\n ',',\n toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS),\n ' ',\n );\n }\n return [\n `<${\n (this.constructor as typeof Polyline).type.toLowerCase() as\n | 'polyline'\n | 'polygon'\n } `,\n 'COMMON_PARTS',\n `points=\"${points.join('')}\" />\\n`,\n ];\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n const len = this.points.length,\n x = this.pathOffset.x,\n y = this.pathOffset.y;\n\n if (!len || isNaN(this.points[len - 1].y)) {\n // do not draw if no points or odd points\n // NaN comes from parseFloat of a empty string in parser\n return;\n }\n ctx.beginPath();\n ctx.moveTo(this.points[0].x - x, this.points[0].y - y);\n for (let i = 0; i < len; i++) {\n const point = this.points[i];\n ctx.lineTo(point.x - x, point.y - y);\n }\n !this.isOpen() && ctx.closePath();\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity of this instance\n */\n complexity(): number {\n return this.points.length;\n }\n\n /* _FROM_SVG_START_ */\n\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link Polyline.fromElement})\n * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement\n */\n static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES];\n\n /**\n * Returns Polyline instance from an SVG element\n * @param {HTMLElement} element Element to parser\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement | SVGElement,\n options?: Abortable,\n cssRules?: CSSRules,\n ) {\n const points = parsePointsAttribute(element.getAttribute('points')),\n // we omit left and top to instruct the constructor to position the object using the bbox\n\n { left, top, ...parsedAttributes } = parseAttributes(\n element,\n this.ATTRIBUTE_NAMES,\n cssRules,\n );\n return new this(points, {\n ...parsedAttributes,\n ...options,\n });\n }\n\n /* _FROM_SVG_END_ */\n\n /**\n * Returns Polyline instance from an object representation\n * @param {Object} object Object to create an instance from\n * @returns {Promise<Polyline>}\n */\n static fromObject<T extends TOptions<SerializedPolylineProps>>(object: T) {\n return this._fromObject<Polyline>(object, {\n extraParam: 'points',\n });\n }\n}\n\nclassRegistry.setClass(Polyline);\nclassRegistry.setSVGClass(Polyline);\n","import type { XY } from '../Point';\n\n/**\n * Parses \"points\" attribute, returning an array of values\n * @param {String} points points attribute string\n * @return {Array} array of points\n */\nexport function parsePointsAttribute(points: string | null): XY[] {\n // points attribute is required and must not be empty\n if (!points) {\n return [];\n }\n\n // replace commas with whitespace and remove bookending whitespace\n const pointsSplit: string[] = points.replace(/,/g, ' ').trim().split(/\\s+/);\n\n const parsedPoints = [];\n\n for (let i = 0; i < pointsSplit.length; i += 2) {\n parsedPoints.push({\n x: parseFloat(pointsSplit[i]),\n y: parseFloat(pointsSplit[i + 1]),\n });\n }\n\n // odd number of points is an error\n // if (parsedPoints.length % 2 !== 0) {\n // return null;\n // }\n return parsedPoints;\n}\n","import { classRegistry } from '../ClassRegistry';\nimport { Polyline, polylineDefaultValues } from './Polyline';\n\nexport class Polygon extends Polyline {\n static ownDefaults = polylineDefaultValues;\n\n static type = 'Polygon';\n\n protected isOpen() {\n return false;\n }\n}\n\nclassRegistry.setClass(Polygon);\nclassRegistry.setSVGClass(Polygon);\n","import type { ObjectEvents } from '../../EventTypeDefs';\nimport type { FabricObjectProps, SerializedObjectProps } from '../Object/types';\nimport type { TOptions } from '../../typedefs';\nimport { FabricObject } from '../Object/FabricObject';\nimport { styleProperties } from './constants';\nimport type { StylePropertiesType } from './constants';\nimport type { FabricText } from './Text';\nimport { pick } from '../../util';\nimport { pickBy } from '../../util/misc/pick';\n\nexport type CompleteTextStyleDeclaration = Pick<\n FabricText,\n StylePropertiesType\n>;\n\nexport type TextStyleDeclaration = Partial<CompleteTextStyleDeclaration>;\n\nexport type TextStyle = {\n [line: number | string]: { [char: number | string]: TextStyleDeclaration };\n};\n\nexport abstract class StyledText<\n Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>,\n SProps extends SerializedObjectProps = SerializedObjectProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n> extends FabricObject<Props, SProps, EventSpec> {\n declare abstract styles: TextStyle;\n declare protected abstract _textLines: string[][];\n declare protected _forceClearCache: boolean;\n static _styleProperties: Readonly<StylePropertiesType[]> = styleProperties;\n abstract get2DCursorLocation(\n selectionStart: number,\n skipWrapping?: boolean,\n ): { charIndex: number; lineIndex: number };\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex?: number): boolean {\n if (!this.styles) {\n return true;\n }\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n return true;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n return true;\n }\n\n /**\n * Returns true if object has a style property or has it ina specified line\n * This function is used to detect if a text will use a particular property or not.\n * @param {String} property to check for\n * @param {Number} lineIndex to check the style on\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex?: number): boolean {\n if (!this.styles) {\n return false;\n }\n if (typeof lineIndex !== 'undefined' && !this.styles[lineIndex]) {\n return false;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { 0: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n if (typeof obj[p1][p2][property] !== 'undefined') {\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Check if characters in a text have a value for a property\n * whose value matches the textbox's value for that property. If so,\n * the character-level property is deleted. If the character\n * has no other properties, then it is also deleted. Finally,\n * if the line containing that character has no other characters\n * then it also is deleted.\n */\n cleanStyle(property: keyof TextStyleDeclaration) {\n if (!this.styles) {\n return false;\n }\n const obj = this.styles;\n let stylesCount = 0,\n letterCount,\n stylePropertyValue,\n allStyleObjectPropertiesMatch = true,\n graphemeCount = 0;\n for (const p1 in obj) {\n letterCount = 0;\n for (const p2 in obj[p1]) {\n const styleObject = obj[p1][p2] || {},\n stylePropertyHasBeenSet = styleObject[property] !== undefined;\n\n stylesCount++;\n\n if (stylePropertyHasBeenSet) {\n if (!stylePropertyValue) {\n stylePropertyValue = styleObject[property];\n } else if (styleObject[property] !== stylePropertyValue) {\n allStyleObjectPropertiesMatch = false;\n }\n\n if (styleObject[property] === this[property as keyof this]) {\n delete styleObject[property];\n }\n } else {\n allStyleObjectPropertiesMatch = false;\n }\n\n if (Object.keys(styleObject).length !== 0) {\n letterCount++;\n } else {\n delete obj[p1][p2];\n }\n }\n\n if (letterCount === 0) {\n delete obj[p1];\n }\n }\n // if every grapheme has the same style set then\n // delete those styles and set it on the parent\n for (let i = 0; i < this._textLines.length; i++) {\n graphemeCount += this._textLines[i].length;\n }\n if (allStyleObjectPropertiesMatch && stylesCount === graphemeCount) {\n this[property as keyof this] = stylePropertyValue as any;\n this.removeStyle(property);\n }\n }\n\n /**\n * Remove a style property or properties from all individual character styles\n * in a text object. Deletes the character style object if it contains no other style\n * props. Deletes a line style object if it contains no other character styles.\n *\n * @param {String} props The property to remove from character styles.\n */\n removeStyle(property: keyof TextStyleDeclaration) {\n if (!this.styles) {\n return;\n }\n const obj = this.styles;\n let line, lineNum, charNum;\n for (lineNum in obj) {\n line = obj[lineNum];\n for (charNum in line) {\n delete line[charNum][property];\n if (Object.keys(line[charNum]).length === 0) {\n delete line[charNum];\n }\n }\n if (Object.keys(line).length === 0) {\n delete obj[lineNum];\n }\n }\n }\n\n private _extendStyles(index: number, style: TextStyleDeclaration): void {\n const { lineIndex, charIndex } = this.get2DCursorLocation(index);\n\n if (!this._getLineStyle(lineIndex)) {\n this._setLineStyle(lineIndex);\n }\n\n const newStyle = pickBy(\n {\n // first create a new object that is a merge of existing and new\n ...this._getStyleDeclaration(lineIndex, charIndex),\n ...style,\n // use the predicate to discard undefined values\n },\n (value) => value !== undefined,\n );\n\n // finally assign to the old position the new style\n this._setStyleDeclaration(lineIndex, charIndex, newStyle);\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, if not specified startIndex + 1\n * @param {Boolean} [complete] get full style or not\n * @return {Array} styles an array with one, zero or more Style objects\n */\n getSelectionStyles(\n startIndex: number,\n endIndex?: number,\n complete?: boolean,\n ): TextStyleDeclaration[] {\n const styles: TextStyleDeclaration[] = [];\n for (let i = startIndex; i < (endIndex || startIndex); i++) {\n styles.push(this.getStyleAtPosition(i, complete));\n }\n return styles;\n }\n\n /**\n * Gets style of a current selection/cursor position\n * @param {Number} position to get styles at\n * @param {Boolean} [complete] full style if true\n * @return {Object} style Style object at a specified index\n * @private\n */\n getStyleAtPosition(position: number, complete?: boolean) {\n const { lineIndex, charIndex } = this.get2DCursorLocation(position);\n return complete\n ? this.getCompleteStyleDeclaration(lineIndex, charIndex)\n : this._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * Sets style of a current selection, if no selection exist, do not set anything.\n * @param {Object} styles Styles object\n * @param {Number} startIndex Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at, if not specified startIndex + 1\n */\n setSelectionStyles(styles: object, startIndex: number, endIndex?: number) {\n for (let i = startIndex; i < (endIndex || startIndex); i++) {\n this._extendStyles(i, styles);\n }\n /* not included in _extendStyles to avoid clearing cache more than once */\n this._forceClearCache = true;\n }\n\n /**\n * Get a reference, not a clone, to the style object for a given character,\n * if no style is set for a line or char, return a new empty object.\n * This is tricky and confusing because when you get an empty object you can't\n * determine if it is a reference or a new one.\n * @TODO this should always return a reference or always a clone or undefined when necessary.\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n const lineStyle = this.styles && this.styles[lineIndex];\n return lineStyle ? (lineStyle[charIndex] ?? {}) : {};\n }\n\n /**\n * return a new object that contains all the style property for a character\n * the object returned is newly created\n * @param {Number} lineIndex of the line where the character is\n * @param {Number} charIndex position of the character on the line\n * @return {Object} style object\n */\n getCompleteStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): CompleteTextStyleDeclaration {\n return {\n ...pick(\n this,\n (this.constructor as typeof StyledText)\n ._styleProperties as (keyof this)[],\n ),\n ...this._getStyleDeclaration(lineIndex, charIndex),\n } as CompleteTextStyleDeclaration;\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n this.styles[lineIndex][charIndex] = style;\n }\n\n /**\n *\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n delete this.styles[lineIndex][charIndex];\n }\n\n /**\n * @param {Number} lineIndex\n * @return {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n return !!this.styles[lineIndex];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n this.styles[lineIndex] = {};\n }\n\n protected _deleteLineStyle(lineIndex: number) {\n delete this.styles[lineIndex];\n }\n}\n","import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport { JUSTIFY } from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = / +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n color: string,\n left: number,\n top: number,\n width: number,\n height: number,\n) {\n return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n const offsets = this._getSVGLeftTopOffsets(),\n textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n return this._wrapSVGTextAndBg(textAndBg);\n }\n\n toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n reviver,\n noStyle: true,\n withShadow: true,\n }),\n path = this.path;\n if (path) {\n return (\n textSvg +\n path._createBaseSVGMarkup(path._toSVG(), {\n reviver,\n withShadow: true,\n additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n })\n );\n }\n return textSvg;\n }\n\n private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n return {\n textLeft: -this.width / 2,\n textTop: -this.height / 2,\n lineTop: this.getHeightOfLine(0),\n };\n }\n\n private _wrapSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n {\n textBgRects,\n textSpans,\n }: {\n textSpans: string[];\n textBgRects: string[];\n },\n ) {\n const noShadow = true,\n textDecoration = this.getSvgTextDecoration(this);\n return [\n textBgRects.join(''),\n '\\t\\t<text xml:space=\"preserve\" ',\n `font-family=\"${this.fontFamily.replace(dblQuoteRegex, \"'\")}\" `,\n `font-size=\"${this.fontSize}\" `,\n this.fontStyle ? `font-style=\"${this.fontStyle}\" ` : '',\n this.fontWeight ? `font-weight=\"${this.fontWeight}\" ` : '',\n textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n this.direction === 'rtl' ? `direction=\"${this.direction}\" ` : '',\n 'style=\"',\n this.getSvgStyles(noShadow),\n '\"',\n this.addPaintOrder(),\n ' >',\n textSpans.join(''),\n '</text>\\n',\n ];\n }\n\n /**\n * @private\n * @param {Number} textTopOffset Text top offset\n * @param {Number} textLeftOffset Text left offset\n * @return {Object}\n */\n private _getSVGTextAndBg(\n this: TextSVGExportMixin & FabricText,\n textTopOffset: number,\n textLeftOffset: number,\n ) {\n const textSpans: string[] = [],\n textBgRects: string[] = [];\n let height = textTopOffset,\n lineOffset;\n\n // bounding-box background\n this.backgroundColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n this.backgroundColor,\n -this.width / 2,\n -this.height / 2,\n this.width,\n this.height,\n ),\n );\n\n // text and text-background\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n lineOffset = this._getLineLeftOffset(i);\n if (this.direction === 'rtl') {\n lineOffset += this.width;\n }\n if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n this._setSVGTextLineBg(\n textBgRects,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n }\n this._setSVGTextLineText(\n textSpans,\n i,\n textLeftOffset + lineOffset,\n height,\n );\n height += this.getHeightOfLine(i);\n }\n\n return {\n textSpans,\n textBgRects,\n };\n }\n\n private _createTextCharSpan(\n this: TextSVGExportMixin & FabricText,\n char: string,\n styleDecl: TextStyleDeclaration,\n left: number,\n top: number,\n charBox: GraphemeBBox,\n ) {\n const numFractionDigit = config.NUM_FRACTION_DIGITS;\n const styleProps = this.getSvgSpanStyles(\n styleDecl,\n char !== char.trim() || !!char.match(multipleSpacesRegex),\n ),\n fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n dy = styleDecl.deltaY,\n dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n { angle, renderLeft, renderTop, width } = charBox;\n let angleAttr = '';\n if (renderLeft !== undefined) {\n const wBy2 = width / 2;\n angle &&\n (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n m[4] = renderLeft!;\n m[5] = renderTop!;\n const renderPoint = new Point(-wBy2, 0).transform(m);\n left = renderPoint.x;\n top = renderPoint.y;\n }\n\n return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n top,\n numFractionDigit,\n )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n }\n\n private _setSVGTextLineText(\n this: TextSVGExportMixin & FabricText,\n textSpans: string[],\n lineIndex: number,\n textLeftOffset: number,\n textTopOffset: number,\n ) {\n const lineHeight = this.getHeightOfLine(lineIndex),\n isJustify = this.textAlign.includes(JUSTIFY),\n line = this._textLines[lineIndex];\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n style,\n boxWidth = 0,\n timeToRender;\n\n textTopOffset +=\n (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || this.path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i];\n if (boxWidth === 0) {\n textLeftOffset += charBox.kernedWidth - charBox.width;\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing or a path, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n }\n if (timeToRender) {\n style = this._getStyleDeclaration(lineIndex, i);\n textSpans.push(\n this._createTextCharSpan(\n charsToRender,\n style,\n textLeftOffset,\n textTopOffset,\n charBox,\n ),\n );\n charsToRender = '';\n actualStyle = nextStyle;\n if (this.direction === 'rtl') {\n textLeftOffset -= boxWidth;\n } else {\n textLeftOffset += boxWidth;\n }\n boxWidth = 0;\n }\n }\n }\n\n private _setSVGTextLineBg(\n this: TextSVGExportMixin & FabricText,\n textBgRects: (string | number)[],\n i: number,\n leftOffset: number,\n textTopOffset: number,\n ) {\n const line = this._textLines[i],\n heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n let boxWidth = 0,\n boxStart = 0,\n currentColor,\n lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n for (let j = 0; j < line.length; j++) {\n const { left, width, kernedWidth } = this.__charBounds[i][j];\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (currentColor !== lastColor) {\n lastColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n boxStart = left;\n boxWidth = width;\n lastColor = currentColor;\n } else {\n boxWidth += kernedWidth;\n }\n }\n currentColor &&\n textBgRects.push(\n ...createSVGInlineRect(\n lastColor,\n leftOffset + boxStart,\n textTopOffset,\n boxWidth,\n heightOfLine,\n ),\n );\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Boolean} skipShadow a boolean to skip shadow filter output\n * @return {String}\n */\n getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; white-space: pre;`;\n }\n\n /**\n * Returns styles-string for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n * @return {String}\n */\n getSvgSpanStyles(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n useWhiteSpace?: boolean,\n ) {\n const {\n fontFamily,\n strokeWidth,\n stroke,\n fill,\n fontSize,\n fontStyle,\n fontWeight,\n textDecorationThickness,\n linethrough,\n overline,\n underline,\n } = style;\n\n const textDecoration = this.getSvgTextDecoration({\n underline: underline ?? this.underline,\n overline: overline ?? this.overline,\n linethrough: linethrough ?? this.linethrough,\n });\n const thickness = textDecorationThickness || this.textDecorationThickness;\n return [\n stroke ? colorPropToSVG(STROKE, stroke) : '',\n strokeWidth ? `stroke-width: ${strokeWidth}; ` : '',\n fontFamily\n ? `font-family: ${\n !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n ? `'${fontFamily}'`\n : fontFamily\n }; `\n : '',\n fontSize ? `font-size: ${fontSize}px; ` : '',\n fontStyle ? `font-style: ${fontStyle}; ` : '',\n fontWeight ? `font-weight: ${fontWeight}; ` : '',\n textDecoration\n ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%; `\n : '',\n fill ? colorPropToSVG(FILL, fill) : '',\n useWhiteSpace ? 'white-space: pre; ' : '',\n ].join('');\n }\n\n /**\n * Returns text-decoration property for svg-export\n * @param {Object} style the object from which to retrieve style properties\n * @return {String}\n */\n getSvgTextDecoration(\n this: TextSVGExportMixin & FabricText,\n style: TextStyleDeclaration,\n ) {\n return (['overline', 'underline', 'line-through'] as const)\n .filter(\n (decoration) =>\n style[\n decoration.replace('-', '') as\n | 'overline'\n | 'underline'\n | 'linethrough'\n ],\n )\n .join(' ');\n }\n}\n","import { cache } from '../../cache';\nimport type { NORMAL } from '../../constants';\nimport { DEFAULT_SVG_FONT_SIZE, FILL, LTR, RTL, STROKE } from '../../constants';\nimport type { ObjectEvents } from '../../EventTypeDefs';\nimport type {\n CompleteTextStyleDeclaration,\n TextStyle,\n TextStyleDeclaration,\n} from './StyledText';\nimport { StyledText } from './StyledText';\nimport { SHARED_ATTRIBUTES } from '../../parser/attributes';\nimport { parseAttributes } from '../../parser/parseAttributes';\nimport type {\n Abortable,\n TCacheCanvasDimensions,\n TClassProperties,\n TFiller,\n TOptions,\n} from '../../typedefs';\nimport { classRegistry } from '../../ClassRegistry';\nimport { graphemeSplit } from '../../util/lang_string';\nimport { createCanvasElementFor } from '../../util/misc/dom';\nimport type { TextStyleArray } from '../../util/misc/textStyles';\nimport {\n hasStyleChanged,\n stylesFromArray,\n stylesToArray,\n} from '../../util/misc/textStyles';\nimport { getPathSegmentsInfo, getPointOnPath } from '../../util/path';\nimport { cacheProperties } from '../Object/FabricObject';\nimport type { Path } from '../Path';\nimport { TextSVGExportMixin } from './TextSVGExportMixin';\nimport { applyMixins } from '../../util/applyMixins';\nimport type { FabricObjectProps, SerializedObjectProps } from '../Object/types';\nimport type { StylePropertiesType } from './constants';\nimport {\n additionalProps,\n textDefaultValues,\n textLayoutProperties,\n JUSTIFY,\n JUSTIFY_CENTER,\n JUSTIFY_LEFT,\n JUSTIFY_RIGHT,\n TEXT_DECORATION_THICKNESS,\n} from './constants';\nimport { CENTER, LEFT, RIGHT, TOP, BOTTOM } from '../../constants';\nimport { isFiller } from '../../util/typeAssertions';\nimport type { Gradient } from '../../gradient/Gradient';\nimport type { Pattern } from '../../Pattern';\nimport type { CSSRules } from '../../parser/typedefs';\nimport { normalizeWs } from '../../util/internals/normalizeWhiteSpace';\n\nlet measuringContext: CanvasRenderingContext2D | null;\n\n/**\n * Return a context for measurement of text string.\n * if created it gets stored for reuse\n */\nfunction getMeasuringContext() {\n if (!measuringContext) {\n const canvas = createCanvasElementFor({\n width: 0,\n height: 0,\n });\n measuringContext = canvas.getContext('2d');\n }\n return measuringContext;\n}\n\nexport type TPathSide = 'left' | 'right';\n\nexport type TPathAlign = 'baseline' | 'center' | 'ascender' | 'descender';\n\nexport type TextLinesInfo = {\n lines: string[];\n graphemeLines: string[][];\n graphemeText: string[];\n _unwrappedLines: string[][];\n};\n\nexport type TextAlign =\n | typeof LEFT\n | typeof CENTER\n | typeof RIGHT\n | typeof JUSTIFY\n | typeof JUSTIFY_LEFT\n | typeof JUSTIFY_CENTER\n | typeof JUSTIFY_RIGHT;\n\nexport type FontStyle = '' | typeof NORMAL | 'italic' | 'oblique';\n\n/**\n * Measure and return the info of a single grapheme.\n * needs the the info of previous graphemes already filled\n * Override to customize measuring\n */\nexport type GraphemeBBox = {\n width: number;\n height: number;\n kernedWidth: number;\n left: number;\n deltaY: number;\n renderLeft?: number;\n renderTop?: number;\n angle?: number;\n};\n\n// @TODO this is not complete\ninterface UniqueTextProps {\n charSpacing: number;\n lineHeight: number;\n fontSize: number;\n fontWeight: string | number;\n fontFamily: string;\n fontStyle: FontStyle;\n pathSide: TPathSide;\n pathAlign: TPathAlign;\n underline: boolean;\n overline: boolean;\n linethrough: boolean;\n textAlign: TextAlign;\n direction: CanvasDirection;\n path?: Path;\n textDecorationThickness: number;\n}\n\nexport interface SerializedTextProps\n extends SerializedObjectProps,\n UniqueTextProps {\n styles: TextStyleArray | TextStyle;\n}\n\nexport interface TextProps extends FabricObjectProps, UniqueTextProps {\n styles: TextStyle;\n}\n\n/**\n * Text class\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#text}\n */\nexport class FabricText<\n Props extends TOptions<TextProps> = Partial<TextProps>,\n SProps extends SerializedTextProps = SerializedTextProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends StyledText<Props, SProps, EventSpec>\n implements UniqueTextProps\n{\n /**\n * Properties that requires a text layout recalculation when changed\n * @type string[]\n * @protected\n */\n static textLayoutProperties: string[] = textLayoutProperties;\n\n /**\n * @private\n */\n declare _reNewline: RegExp;\n\n /**\n * Use this regular expression to filter for whitespaces that is not a new line.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n declare _reSpacesAndTabs: RegExp;\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 declare _reSpaceAndTab: RegExp;\n\n /**\n * Use this regular expression to filter consecutive groups of non spaces.\n * Mostly used when text is 'justify' aligned.\n * @private\n */\n declare _reWords: RegExp;\n\n declare text: string;\n\n /**\n * Font size (in pixels)\n * @type Number\n */\n declare fontSize: number;\n\n /**\n * Font weight (e.g. bold, normal, 400, 600, 800)\n * @type {(Number|String)}\n */\n declare fontWeight: string | number;\n\n /**\n * Font family\n * @type String\n */\n declare fontFamily: string;\n\n /**\n * Text decoration underline.\n * @type Boolean\n */\n declare underline: boolean;\n\n /**\n * Text decoration overline.\n * @type Boolean\n */\n declare overline: boolean;\n\n /**\n * Text decoration linethrough.\n * @type Boolean\n */\n declare linethrough: boolean;\n\n /**\n * Text alignment. Possible values: \"left\", \"center\", \"right\", \"justify\",\n * \"justify-left\", \"justify-center\" or \"justify-right\".\n * @type TextAlign\n */\n declare textAlign: TextAlign;\n\n /**\n * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n * @type FontStyle\n */\n declare fontStyle: FontStyle;\n\n /**\n * Line height\n * @type Number\n */\n declare lineHeight: number;\n\n /**\n * Superscript schema object (minimum overlap)\n */\n declare superscript: {\n /**\n * fontSize factor\n * @default 0.6\n */\n size: number;\n /**\n * baseline-shift factor (upwards)\n * @default -0.35\n */\n baseline: number;\n };\n\n /**\n * Subscript schema object (minimum overlap)\n */\n declare subscript: {\n /**\n * fontSize factor\n * @default 0.6\n */\n size: number;\n /**\n * baseline-shift factor (downwards)\n * @default 0.11\n */\n baseline: number;\n };\n\n /**\n * Background color of text lines\n * @type String\n */\n declare textBackgroundColor: string;\n\n declare styles: TextStyle;\n\n /**\n * Path that the text should follow.\n * since 4.6.0 the path will be drawn automatically.\n * if you want to make the path visible, give it a stroke and strokeWidth or fill value\n * if you want it to be hidden, assign visible = false to the path.\n * This feature is in BETA, and SVG import/export is not yet supported.\n * @type Path\n * @example\n * const textPath = new Text('Text on a path', {\n * top: 150,\n * left: 150,\n * textAlign: 'center',\n * charSpacing: -50,\n * path: new Path('M 0 0 C 50 -100 150 -100 200 0', {\n * strokeWidth: 1,\n * visible: false\n * }),\n * pathSide: 'left',\n * pathStartOffset: 0\n * });\n */\n declare path?: Path;\n\n /**\n * The text decoration tickness for underline, overline and strikethrough\n * The tickness is expressed in thousandths of fontSize ( em ).\n * The original value was 1/15 that translates to 66.6667 thousandths.\n * The choice of unit of measure is to align with charSpacing.\n * You can slim the tickness without issues, while large underline or overline may end up\n * outside the bounding box of the text. In order to fix that a bigger refactor of the code\n * is needed and is out of scope for now. If you need such large overline on the first line\n * of text or large underline on the last line of text, consider disabling caching as a\n * workaround\n * @default 66.667\n */\n declare textDecorationThickness: number;\n\n /**\n * Offset amount for text path starting position\n * Only used when text has a path\n */\n declare pathStartOffset: number;\n\n /**\n * Which side of the path the text should be drawn on.\n * Only used when text has a path\n * @type {TPathSide} 'left|right'\n */\n declare pathSide: TPathSide;\n\n /**\n * How text is aligned to the path. This property determines\n * the perpendicular position of each character relative to the path.\n * (one of \"baseline\", \"center\", \"ascender\", \"descender\")\n * This feature is in BETA, and its behavior may change\n * @type TPathAlign\n */\n declare pathAlign: TPathAlign;\n\n /**\n * @private\n */\n declare _fontSizeFraction: number;\n\n /**\n * @private\n */\n declare offsets: { underline: number; linethrough: number; overline: number };\n\n /**\n * Text Line proportion to font Size (in pixels)\n * @type Number\n */\n declare _fontSizeMult: number;\n\n /**\n * additional space between characters\n * expressed in thousands of em unit\n * @type Number\n */\n declare charSpacing: number;\n\n /**\n * Baseline shift, styles only, keep at 0 for the main text object\n * @type {Number}\n */\n declare deltaY: number;\n\n /**\n * WARNING: EXPERIMENTAL. NOT SUPPORTED YET\n * determine the direction of the text.\n * This has to be set manually together with textAlign and originX for proper\n * experience.\n * some interesting link for the future\n * https://www.w3.org/International/questions/qa-bidi-unicode-controls\n * @since 4.5.0\n * @type {CanvasDirection} 'ltr|rtl'\n */\n declare direction: CanvasDirection;\n\n /**\n * contains characters bounding boxes\n * This variable is considered to be protected.\n * But for how mixins are implemented right now, we can't leave it private\n * @protected\n */\n __charBounds: GraphemeBBox[][] = [];\n\n /**\n * use this size when measuring text. To avoid IE11 rounding errors\n * @type {Number}\n * @readonly\n * @private\n */\n declare CACHE_FONT_SIZE: number;\n\n /**\n * contains the min text width to avoid getting 0\n * @type {Number}\n */\n declare MIN_TEXT_WIDTH: number;\n\n /**\n * contains the the text of the object, divided in lines as they are displayed\n * on screen. Wrapping will divide the text independently of line breaks\n * @type {string[]}\n */\n declare textLines: string[];\n\n /**\n * same as textlines, but each line is an array of graphemes as split by splitByGrapheme\n * @type {string[]}\n */\n declare _textLines: string[][];\n\n declare _unwrappedTextLines: string[][];\n declare _text: string[];\n declare cursorWidth: number;\n declare __lineHeights: number[];\n declare __lineWidths: number[];\n declare initialized?: true;\n\n static cacheProperties = [...cacheProperties, ...additionalProps];\n\n static ownDefaults = textDefaultValues;\n\n static type = 'Text';\n\n static getDefaults(): Record<string, any> {\n return { ...super.getDefaults(), ...FabricText.ownDefaults };\n }\n\n constructor(text: string, options?: Props) {\n super();\n Object.assign(this, FabricText.ownDefaults);\n this.setOptions(options);\n if (!this.styles) {\n this.styles = {};\n }\n this.text = text;\n this.initialized = true;\n if (this.path) {\n this.setPathInfo();\n }\n this.initDimensions();\n this.setCoords();\n }\n\n /**\n * If text has a path, it will add the extra information needed\n * for path and text calculations\n */\n setPathInfo() {\n const path = this.path;\n if (path) {\n path.segmentsInfo = getPathSegmentsInfo(path.path);\n }\n }\n\n /**\n * @private\n * Divides text into lines of text and lines of graphemes.\n */\n _splitText(): TextLinesInfo {\n const newLines = this._splitTextIntoLines(this.text);\n this.textLines = newLines.lines;\n this._textLines = newLines.graphemeLines;\n this._unwrappedTextLines = newLines._unwrappedLines;\n this._text = newLines.graphemeText;\n return newLines;\n }\n\n /**\n * Initialize or update text dimensions.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n */\n initDimensions() {\n this._splitText();\n this._clearCache();\n this.dirty = true;\n if (this.path) {\n this.width = this.path.width;\n this.height = this.path.height;\n } else {\n this.width =\n this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH;\n this.height = this.calcTextHeight();\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n }\n\n /**\n * Enlarge space boxes and shift the others\n */\n enlargeSpaces() {\n let diffSpace,\n currentLineWidth,\n numberOfSpaces,\n accumulatedSpace,\n line,\n charBound,\n spaces;\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n if (\n this.textAlign !== JUSTIFY &&\n (i === len - 1 || this.isEndOfWrapping(i))\n ) {\n continue;\n }\n accumulatedSpace = 0;\n line = this._textLines[i];\n currentLineWidth = this.getLineWidth(i);\n if (\n currentLineWidth < this.width &&\n (spaces = this.textLines[i].match(this._reSpacesAndTabs))\n ) {\n numberOfSpaces = spaces.length;\n diffSpace = (this.width - currentLineWidth) / numberOfSpaces;\n for (let j = 0; j <= line.length; j++) {\n charBound = this.__charBounds[i][j];\n if (this._reSpaceAndTab.test(line[j])) {\n charBound.width += diffSpace;\n charBound.kernedWidth += diffSpace;\n charBound.left += accumulatedSpace;\n accumulatedSpace += diffSpace;\n } else {\n charBound.left += accumulatedSpace;\n }\n }\n }\n }\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n return lineIndex === this._textLines.length - 1;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * It return always 1 for text and Itext. Textbox has its own implementation\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1;\n missingNewlineOffset(_lineIndex: number): 1 {\n return 1;\n }\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor\n * @param {Number} selectionStart\n * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\n */\n get2DCursorLocation(selectionStart: number, skipWrapping?: boolean) {\n const lines = skipWrapping ? this._unwrappedTextLines : this._textLines;\n let i: number;\n for (i = 0; i < lines.length; i++) {\n if (selectionStart <= lines[i].length) {\n return {\n lineIndex: i,\n charIndex: selectionStart,\n };\n }\n selectionStart -=\n lines[i].length + this.missingNewlineOffset(i, skipWrapping);\n }\n return {\n lineIndex: i - 1,\n charIndex:\n lines[i - 1].length < selectionStart\n ? lines[i - 1].length\n : selectionStart,\n };\n }\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of text object\n */\n toString(): string {\n return `#<Text (${this.complexity()}): { \"text\": \"${\n this.text\n }\", \"fontFamily\": \"${this.fontFamily}\" }>`;\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(): TCacheCanvasDimensions {\n const dims = super._getCacheCanvasDimensions();\n const 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(ctx: CanvasRenderingContext2D) {\n const path = this.path;\n path && !path.isNotVisible() && path._render(ctx);\n this._setTextStyles(ctx);\n this._renderTextLinesBackground(ctx);\n this._renderTextDecoration(ctx, 'underline');\n this._renderText(ctx);\n this._renderTextDecoration(ctx, 'overline');\n this._renderTextDecoration(ctx, 'linethrough');\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderText(ctx: CanvasRenderingContext2D) {\n if (this.paintFirst === STROKE) {\n this._renderTextStroke(ctx);\n this._renderTextFill(ctx);\n } else {\n this._renderTextFill(ctx);\n this._renderTextStroke(ctx);\n }\n }\n\n /**\n * Set the font parameter of the context with the object properties or with charStyle\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} [charStyle] object with font style properties\n * @param {String} [charStyle.fontFamily] Font Family\n * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )\n * @param {String} [charStyle.fontWeight] Font weight\n * @param {String} [charStyle.fontStyle] Font style (italic|normal)\n */\n _setTextStyles(\n ctx: CanvasRenderingContext2D,\n charStyle?: any,\n forMeasuring?: boolean,\n ) {\n ctx.textBaseline = 'alphabetic';\n if (this.path) {\n switch (this.pathAlign) {\n case CENTER:\n ctx.textBaseline = 'middle';\n break;\n case 'ascender':\n ctx.textBaseline = TOP;\n break;\n case 'descender':\n ctx.textBaseline = BOTTOM;\n break;\n }\n }\n ctx.font = this._getFontDeclaration(charStyle, forMeasuring);\n }\n\n /**\n * calculate and return the text Width measuring each line.\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @return {Number} Maximum width of Text object\n */\n calcTextWidth(): number {\n let maxWidth = this.getLineWidth(0);\n\n for (let i = 1, len = this._textLines.length; i < len; i++) {\n const currentLineWidth = this.getLineWidth(i);\n if (currentLineWidth > maxWidth) {\n maxWidth = currentLineWidth;\n }\n }\n return maxWidth;\n }\n\n /**\n * @private\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} line Text to render\n * @param {Number} left Left position of text\n * @param {Number} top Top position of text\n * @param {Number} lineIndex Index of a line in a text\n */\n _renderTextLine(\n method: 'fillText' | 'strokeText',\n ctx: CanvasRenderingContext2D,\n line: string[],\n left: number,\n top: number,\n lineIndex: number,\n ) {\n this._renderChars(method, ctx, line, left, top, lineIndex);\n }\n\n /**\n * Renders the text background for lines, taking care of style\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextLinesBackground(ctx: CanvasRenderingContext2D) {\n if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {\n return;\n }\n const originalFill = ctx.fillStyle,\n leftOffset = this._getLeftOffset();\n let lineTopOffset = this._getTopOffset();\n\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n const heightOfLine = this.getHeightOfLine(i);\n if (\n !this.textBackgroundColor &&\n !this.styleHas('textBackgroundColor', i)\n ) {\n lineTopOffset += heightOfLine;\n continue;\n }\n const jlen = this._textLines[i].length;\n const lineLeftOffset = this._getLineLeftOffset(i);\n let boxWidth = 0;\n let boxStart = 0;\n let drawStart;\n let currentColor;\n let lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n const bgHeight = this.getHeightOfLineImpl(i);\n for (let j = 0; j < jlen; j++) {\n // at this point charbox are either standard or full with pathInfo if there is a path.\n const charBox = this.__charBounds[i][j] as Required<GraphemeBBox>;\n currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n if (this.path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillStyle = currentColor;\n currentColor &&\n ctx.fillRect(\n -charBox.width / 2,\n -bgHeight * (1 - this._fontSizeFraction),\n charBox.width,\n bgHeight,\n );\n ctx.restore();\n } else if (currentColor !== lastColor) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === RTL) {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = lastColor;\n lastColor &&\n ctx.fillRect(drawStart, lineTopOffset, boxWidth, bgHeight);\n boxStart = charBox.left;\n boxWidth = charBox.width;\n lastColor = currentColor;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n }\n if (currentColor && !this.path) {\n drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === RTL) {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentColor;\n ctx.fillRect(drawStart, lineTopOffset, boxWidth, bgHeight);\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 * measure and return the width of a single character.\n * possibly overridden to accommodate different measure logic or\n * to hook some external lib for character measurement\n * @private\n * @param {String} _char, char to be measured\n * @param {Object} charStyle style of char to be measured\n * @param {String} [previousChar] previous char\n * @param {Object} [prevCharStyle] style of previous char\n */\n _measureChar(\n _char: string,\n charStyle: CompleteTextStyleDeclaration,\n previousChar: string | undefined,\n prevCharStyle: CompleteTextStyleDeclaration | Record<string, never>,\n ) {\n const fontCache = cache.getFontCache(charStyle),\n fontDeclaration = this._getFontDeclaration(charStyle),\n couple = previousChar ? previousChar + _char : _char,\n stylesAreEqual =\n previousChar &&\n fontDeclaration === this._getFontDeclaration(prevCharStyle),\n fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE;\n let width: number | undefined,\n coupleWidth: number | undefined,\n previousWidth: number | undefined,\n kernedWidth: number | undefined;\n\n if (previousChar && fontCache.has(previousChar)) {\n previousWidth = fontCache.get(previousChar);\n }\n if (fontCache.has(_char)) {\n kernedWidth = width = fontCache.get(_char);\n }\n if (stylesAreEqual && fontCache.has(couple)) {\n coupleWidth = fontCache.get(couple)!;\n kernedWidth = coupleWidth - previousWidth!;\n }\n if (\n width === undefined ||\n previousWidth === undefined ||\n coupleWidth === undefined\n ) {\n const ctx = getMeasuringContext()!;\n // send a TRUE to specify measuring font size CACHE_FONT_SIZE\n this._setTextStyles(ctx, charStyle, true);\n if (width === undefined) {\n kernedWidth = width = ctx.measureText(_char).width;\n fontCache.set(_char, width);\n }\n if (previousWidth === undefined && stylesAreEqual && previousChar) {\n previousWidth = ctx.measureText(previousChar).width;\n fontCache.set(previousChar, previousWidth);\n }\n if (stylesAreEqual && coupleWidth === undefined) {\n // we can measure the kerning couple and subtract the width of the previous character\n coupleWidth = ctx.measureText(couple).width;\n fontCache.set(couple, coupleWidth);\n // safe to use the non-null since if undefined we defined it before.\n kernedWidth = coupleWidth - previousWidth!;\n }\n }\n return {\n width: width * fontMultiplier,\n kernedWidth: kernedWidth! * fontMultiplier,\n };\n }\n\n /**\n * Computes height of character at given position\n * @param {Number} line the line index number\n * @param {Number} _char the character index number\n * @return {Number} fontSize of the character\n */\n getHeightOfChar(line: number, _char: number): number {\n return this.getValueOfPropertyAt(line, _char, 'fontSize');\n }\n\n /**\n * measure a text line measuring all characters.\n * @param {Number} lineIndex line number\n */\n measureLine(lineIndex: number) {\n const lineInfo = this._measureLine(lineIndex);\n if (this.charSpacing !== 0) {\n lineInfo.width -= this._getWidthOfCharSpacing();\n }\n if (lineInfo.width < 0) {\n lineInfo.width = 0;\n }\n return lineInfo;\n }\n\n /**\n * measure every grapheme of a line, populating __charBounds\n * @param {Number} lineIndex\n * @return {Object} object.width total width of characters\n * @return {Object} object.numOfSpaces length of chars that match this._reSpacesAndTabs\n */\n _measureLine(lineIndex: number) {\n let width = 0,\n prevGrapheme: string | undefined,\n graphemeInfo: GraphemeBBox | undefined;\n\n const reverse = this.pathSide === RIGHT,\n path = this.path,\n line = this._textLines[lineIndex],\n llength = line.length,\n lineBounds = new Array<GraphemeBBox>(llength);\n\n this.__charBounds[lineIndex] = lineBounds;\n for (let i = 0; i < llength; i++) {\n const grapheme = line[i];\n graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme);\n lineBounds[i] = graphemeInfo;\n width += graphemeInfo.kernedWidth;\n prevGrapheme = grapheme;\n }\n // this latest bound box represent the last character of the line\n // to simplify cursor handling in interactive mode.\n lineBounds[llength] = {\n left: graphemeInfo ? graphemeInfo.left + graphemeInfo.width : 0,\n width: 0,\n kernedWidth: 0,\n height: this.fontSize,\n deltaY: 0,\n } as GraphemeBBox;\n if (path && path.segmentsInfo) {\n let positionInPath = 0;\n const totalPathLength =\n path.segmentsInfo[path.segmentsInfo.length - 1].length;\n switch (this.textAlign) {\n case LEFT:\n positionInPath = reverse ? totalPathLength - width : 0;\n break;\n case CENTER:\n positionInPath = (totalPathLength - width) / 2;\n break;\n case RIGHT:\n positionInPath = reverse ? 0 : totalPathLength - width;\n break;\n //todo - add support for justify\n }\n positionInPath += this.pathStartOffset * (reverse ? -1 : 1);\n for (\n let i = reverse ? llength - 1 : 0;\n reverse ? i >= 0 : i < llength;\n reverse ? i-- : i++\n ) {\n graphemeInfo = lineBounds[i];\n if (positionInPath > totalPathLength) {\n positionInPath %= totalPathLength;\n } else if (positionInPath < 0) {\n positionInPath += totalPathLength;\n }\n // it would probably much faster to send all the grapheme position for a line\n // and calculate path position/angle at once.\n this._setGraphemeOnPath(positionInPath, graphemeInfo);\n positionInPath += graphemeInfo.kernedWidth;\n }\n }\n return { width: width, numOfSpaces: 0 };\n }\n\n /**\n * Calculate the angle and the left,top position of the char that follow a path.\n * It appends it to graphemeInfo to be reused later at rendering\n * @private\n * @param {Number} positionInPath to be measured\n * @param {GraphemeBBox} graphemeInfo current grapheme box information\n * @param {Object} startingPoint position of the point\n */\n _setGraphemeOnPath(positionInPath: number, graphemeInfo: GraphemeBBox) {\n const centerPosition = positionInPath + graphemeInfo.kernedWidth / 2,\n path = this.path!;\n\n // we are at currentPositionOnPath. we want to know what point on the path is.\n const info = getPointOnPath(path.path, centerPosition, path.segmentsInfo)!;\n graphemeInfo.renderLeft = info.x - path.pathOffset.x;\n graphemeInfo.renderTop = info.y - path.pathOffset.y;\n graphemeInfo.angle = info.angle + (this.pathSide === RIGHT ? Math.PI : 0);\n }\n\n /**\n *\n * @param {String} grapheme to be measured\n * @param {Number} lineIndex index of the line where the char is\n * @param {Number} charIndex position in the line\n * @param {String} [prevGrapheme] character preceding the one to be measured\n * @returns {GraphemeBBox} grapheme bbox\n */\n _getGraphemeBox(\n grapheme: string,\n lineIndex: number,\n charIndex: number,\n prevGrapheme?: string,\n skipLeft?: boolean,\n ): GraphemeBBox {\n const style = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n prevStyle = prevGrapheme\n ? this.getCompleteStyleDeclaration(lineIndex, charIndex - 1)\n : {},\n info = this._measureChar(grapheme, style, prevGrapheme, prevStyle);\n let kernedWidth = info.kernedWidth,\n width = info.width,\n charSpacing;\n\n if (this.charSpacing !== 0) {\n charSpacing = this._getWidthOfCharSpacing();\n width += charSpacing;\n kernedWidth += charSpacing;\n }\n\n const box: GraphemeBBox = {\n width,\n left: 0,\n height: style.fontSize,\n kernedWidth,\n deltaY: style.deltaY,\n };\n if (charIndex > 0 && !skipLeft) {\n const previousBox = this.__charBounds[lineIndex][charIndex - 1];\n box.left =\n previousBox.left + previousBox.width + info.kernedWidth - info.width;\n }\n return box;\n }\n\n /**\n * Calculate height of line at 'lineIndex',\n * without the lineHeigth multiplication factor\n * @private\n * @param {Number} lineIndex index of line to calculate\n * @return {Number}\n */\n private getHeightOfLineImpl(lineIndex: number): number {\n const lh = this.__lineHeights;\n if (lh[lineIndex]) {\n return lh[lineIndex];\n }\n\n // char 0 is measured before the line cycle because it needs to char\n // emptylines\n let maxHeight = this.getHeightOfChar(lineIndex, 0);\n for (let i = 1, len = this._textLines[lineIndex].length; i < len; i++) {\n maxHeight = Math.max(this.getHeightOfChar(lineIndex, i), maxHeight);\n }\n\n return (lh[lineIndex] = maxHeight * this._fontSizeMult);\n }\n\n /**\n * Calculate height of line at 'lineIndex'\n * @param {Number} lineIndex index of line to calculate\n * @return {Number}\n */\n getHeightOfLine(lineIndex: number): number {\n return this.getHeightOfLineImpl(lineIndex) * this.lineHeight;\n }\n\n /**\n * Calculate text box height\n */\n calcTextHeight() {\n let height = 0;\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n height +=\n i === len - 1 ? this.getHeightOfLineImpl(i) : this.getHeightOfLine(i);\n }\n return height;\n }\n\n /**\n * @private\n * @return {Number} Left offset\n */\n _getLeftOffset(): number {\n return this.direction === LTR ? -this.width / 2 : this.width / 2;\n }\n\n /**\n * @private\n * @return {Number} Top offset\n */\n _getTopOffset(): number {\n return -this.height / 2;\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {String} method Method name (\"fillText\" or \"strokeText\")\n */\n _renderTextCommon(\n ctx: CanvasRenderingContext2D,\n method: 'fillText' | 'strokeText',\n ) {\n ctx.save();\n let lineHeights = 0;\n const left = this._getLeftOffset(),\n top = this._getTopOffset();\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n this._renderTextLine(\n method,\n ctx,\n this._textLines[i],\n left + this._getLineLeftOffset(i),\n top + lineHeights + this.getHeightOfLineImpl(i),\n i,\n );\n lineHeights += this.getHeightOfLine(i);\n }\n ctx.restore();\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextFill(ctx: CanvasRenderingContext2D) {\n if (!this.fill && !this.styleHas(FILL)) {\n return;\n }\n\n this._renderTextCommon(ctx, 'fillText');\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextStroke(ctx: CanvasRenderingContext2D) {\n if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {\n return;\n }\n\n if (this.shadow && !this.shadow.affectStroke) {\n this._removeShadow(ctx);\n }\n\n ctx.save();\n this._setLineDash(ctx, this.strokeDashArray);\n ctx.beginPath();\n this._renderTextCommon(ctx, 'strokeText');\n ctx.closePath();\n ctx.restore();\n }\n\n /**\n * @private\n * @param {String} method fillText or strokeText.\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Array} line Content of the line, splitted in an array by grapheme\n * @param {Number} left\n * @param {Number} top\n * @param {Number} lineIndex\n */\n _renderChars(\n method: 'fillText' | 'strokeText',\n ctx: CanvasRenderingContext2D,\n line: Array<any>,\n left: number,\n top: number,\n lineIndex: number,\n ) {\n const isJustify = this.textAlign.includes(JUSTIFY),\n path = this.path,\n shortCut =\n !isJustify &&\n this.charSpacing === 0 &&\n this.isEmptyStyles(lineIndex) &&\n !path,\n isLtr = this.direction === LTR,\n sign = this.direction === LTR ? 1 : -1,\n // this was changed in the PR #7674\n // currentDirection = ctx.canvas.getAttribute('dir');\n currentDirection = ctx.direction;\n\n let actualStyle,\n nextStyle,\n charsToRender = '',\n charBox,\n boxWidth = 0,\n timeToRender,\n drawingLeft;\n\n ctx.save();\n if (currentDirection !== this.direction) {\n ctx.canvas.setAttribute('dir', isLtr ? LTR : RTL);\n ctx.direction = isLtr ? LTR : RTL;\n ctx.textAlign = isLtr ? LEFT : RIGHT;\n }\n top -= this.getHeightOfLineImpl(lineIndex) * this._fontSizeFraction;\n if (shortCut) {\n // render all the line in one pass without checking\n // drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);\n this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top);\n ctx.restore();\n return;\n }\n for (let i = 0, len = line.length - 1; i <= len; i++) {\n timeToRender = i === len || this.charSpacing || path;\n charsToRender += line[i];\n charBox = this.__charBounds[lineIndex][i] as Required<GraphemeBBox>;\n if (boxWidth === 0) {\n left += sign * (charBox.kernedWidth - charBox.width);\n boxWidth += charBox.width;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n if (isJustify && !timeToRender) {\n if (this._reSpaceAndTab.test(line[i])) {\n timeToRender = true;\n }\n }\n if (!timeToRender) {\n // if we have charSpacing, we render char by char\n actualStyle =\n actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n timeToRender = hasStyleChanged(actualStyle, nextStyle, false);\n }\n if (timeToRender) {\n if (path) {\n ctx.save();\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n this._renderChar(\n method,\n ctx,\n lineIndex,\n i,\n charsToRender,\n -boxWidth / 2,\n 0,\n );\n ctx.restore();\n } else {\n drawingLeft = left;\n this._renderChar(\n method,\n ctx,\n lineIndex,\n i,\n charsToRender,\n drawingLeft,\n top,\n );\n }\n charsToRender = '';\n actualStyle = nextStyle;\n left += sign * boxWidth;\n boxWidth = 0;\n }\n }\n ctx.restore();\n }\n\n /**\n * This function try to patch the missing gradientTransform on canvas gradients.\n * transforming a context to transform the gradient, is going to transform the stroke too.\n * we want to transform the gradient but not the stroke operation, so we create\n * a transformed gradient on a pattern and then we use the pattern instead of the gradient.\n * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size\n * is limited.\n * @private\n * @param {TFiller} filler a fabric gradient instance\n * @return {CanvasPattern} a pattern to use as fill/stroke style\n */\n _applyPatternGradientTransformText(filler: TFiller) {\n // TODO: verify compatibility with strokeUniform\n const width = this.width + this.strokeWidth,\n height = this.height + this.strokeWidth,\n pCanvas = createCanvasElementFor({\n width,\n height,\n }),\n pCtx = pCanvas.getContext('2d')!;\n pCanvas.width = width;\n pCanvas.height = height;\n pCtx.beginPath();\n pCtx.moveTo(0, 0);\n pCtx.lineTo(width, 0);\n pCtx.lineTo(width, height);\n pCtx.lineTo(0, height);\n pCtx.closePath();\n pCtx.translate(width / 2, height / 2);\n pCtx.fillStyle = filler.toLive(pCtx)!;\n this._applyPatternGradientTransform(pCtx, filler);\n pCtx.fill();\n return pCtx.createPattern(pCanvas, 'no-repeat')!;\n }\n\n handleFiller<T extends 'fill' | 'stroke'>(\n ctx: CanvasRenderingContext2D,\n property: `${T}Style`,\n filler: TFiller | string,\n ): { offsetX: number; offsetY: number } {\n let offsetX: number, offsetY: number;\n if (isFiller(filler)) {\n if (\n (filler as Gradient<'linear'>).gradientUnits === 'percentage' ||\n (filler as Gradient<'linear'>).gradientTransform ||\n (filler as Pattern).patternTransform\n ) {\n // need to transform gradient in a pattern.\n // this is a slow process. If you are hitting this codepath, and the object\n // is not using caching, you should consider switching it on.\n // we need a canvas as big as the current object caching canvas.\n offsetX = -this.width / 2;\n offsetY = -this.height / 2;\n ctx.translate(offsetX, offsetY);\n ctx[property] = this._applyPatternGradientTransformText(filler);\n return { offsetX, offsetY };\n } else {\n // is a simple gradient or pattern\n ctx[property] = filler.toLive(ctx)!;\n return this._applyPatternGradientTransform(ctx, filler);\n }\n } else {\n // is a color\n ctx[property] = filler;\n }\n return { offsetX: 0, offsetY: 0 };\n }\n\n /**\n * This function prepare the canvas for a stroke style, and stroke and strokeWidth\n * need to be sent in as defined\n * @param {CanvasRenderingContext2D} ctx\n * @param {CompleteTextStyleDeclaration} style with stroke and strokeWidth defined\n * @returns\n */\n _setStrokeStyles(\n ctx: CanvasRenderingContext2D,\n {\n stroke,\n strokeWidth,\n }: Pick<CompleteTextStyleDeclaration, 'stroke' | 'strokeWidth'>,\n ) {\n ctx.lineWidth = strokeWidth;\n ctx.lineCap = this.strokeLineCap;\n ctx.lineDashOffset = this.strokeDashOffset;\n ctx.lineJoin = this.strokeLineJoin;\n ctx.miterLimit = this.strokeMiterLimit;\n return this.handleFiller(ctx, 'strokeStyle', stroke!);\n }\n\n /**\n * This function prepare the canvas for a ill style, and fill\n * need to be sent in as defined\n * @param {CanvasRenderingContext2D} ctx\n * @param {CompleteTextStyleDeclaration} style with ill defined\n * @returns\n */\n _setFillStyles(ctx: CanvasRenderingContext2D, { fill }: Pick<this, 'fill'>) {\n return this.handleFiller(ctx, 'fillStyle', fill!);\n }\n\n /**\n * @private\n * @param {String} method\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {String} _char\n * @param {Number} left Left coordinate\n * @param {Number} top Top coordinate\n * @param {Number} lineHeight Height of the line\n */\n _renderChar(\n method: 'fillText' | 'strokeText',\n ctx: CanvasRenderingContext2D,\n lineIndex: number,\n charIndex: number,\n _char: string,\n left: number,\n top: number,\n ) {\n const decl = this._getStyleDeclaration(lineIndex, charIndex),\n fullDecl = this.getCompleteStyleDeclaration(lineIndex, charIndex),\n shouldFill = method === 'fillText' && fullDecl.fill,\n shouldStroke =\n method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth;\n\n if (!shouldStroke && !shouldFill) {\n return;\n }\n ctx.save();\n\n ctx.font = this._getFontDeclaration(fullDecl);\n\n if (decl.textBackgroundColor) {\n this._removeShadow(ctx);\n }\n if (decl.deltaY) {\n top += decl.deltaY;\n }\n\n if (shouldFill) {\n const fillOffsets = this._setFillStyles(ctx, fullDecl);\n ctx.fillText(\n _char,\n left - fillOffsets.offsetX,\n top - fillOffsets.offsetY,\n );\n }\n\n if (shouldStroke) {\n const strokeOffsets = this._setStrokeStyles(ctx, fullDecl);\n ctx.strokeText(\n _char,\n left - strokeOffsets.offsetX,\n top - strokeOffsets.offsetY,\n );\n }\n\n ctx.restore();\n }\n\n /**\n * Turns the character into a 'superior figure' (i.e. 'superscript')\n * @param {Number} start selection start\n * @param {Number} end selection end\n */\n setSuperscript(start: number, end: number) {\n this._setScript(start, end, this.superscript);\n }\n\n /**\n * Turns the character into an 'inferior figure' (i.e. 'subscript')\n * @param {Number} start selection start\n * @param {Number} end selection end\n */\n setSubscript(start: number, end: number) {\n this._setScript(start, end, this.subscript);\n }\n\n /**\n * Applies 'schema' at given position\n * @private\n * @param {Number} start selection start\n * @param {Number} end selection end\n * @param {Number} schema\n */\n protected _setScript(\n start: number,\n end: number,\n schema: {\n size: number;\n baseline: number;\n },\n ) {\n const loc = this.get2DCursorLocation(start, true),\n fontSize = this.getValueOfPropertyAt(\n loc.lineIndex,\n loc.charIndex,\n 'fontSize',\n ),\n dy = this.getValueOfPropertyAt(loc.lineIndex, loc.charIndex, 'deltaY'),\n style = {\n fontSize: fontSize * schema.size,\n deltaY: dy + fontSize * schema.baseline,\n };\n this.setSelectionStyles(style, start, end);\n }\n\n /**\n * @private\n * @param {Number} lineIndex index text line\n * @return {Number} Line left offset\n */\n _getLineLeftOffset(lineIndex: number): number {\n const lineWidth = this.getLineWidth(lineIndex),\n lineDiff = this.width - lineWidth,\n textAlign = this.textAlign,\n direction = this.direction,\n isEndOfWrapping = this.isEndOfWrapping(lineIndex);\n let leftOffset = 0;\n if (\n textAlign === JUSTIFY ||\n (textAlign === JUSTIFY_CENTER && !isEndOfWrapping) ||\n (textAlign === JUSTIFY_RIGHT && !isEndOfWrapping) ||\n (textAlign === JUSTIFY_LEFT && !isEndOfWrapping)\n ) {\n return 0;\n }\n if (textAlign === CENTER) {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === RIGHT) {\n leftOffset = lineDiff;\n }\n if (textAlign === JUSTIFY_CENTER) {\n leftOffset = lineDiff / 2;\n }\n if (textAlign === JUSTIFY_RIGHT) {\n leftOffset = lineDiff;\n }\n if (direction === RTL) {\n if (textAlign === RIGHT || textAlign === JUSTIFY_RIGHT) {\n leftOffset = 0;\n } else if (textAlign === LEFT || textAlign === JUSTIFY_LEFT) {\n leftOffset = -lineDiff;\n } else if (textAlign === CENTER || textAlign === JUSTIFY_CENTER) {\n leftOffset = -lineDiff / 2;\n }\n }\n return leftOffset;\n }\n\n /**\n * @private\n */\n _clearCache() {\n this._forceClearCache = false;\n this.__lineWidths = [];\n this.__lineHeights = [];\n this.__charBounds = [];\n }\n\n /**\n * Measure a single line given its index. Used to calculate the initial\n * text bounding box. The values are calculated and stored in __lineWidths cache.\n * @private\n * @param {Number} lineIndex line number\n * @return {Number} Line width\n */\n getLineWidth(lineIndex: number): number {\n if (this.__lineWidths[lineIndex] !== undefined) {\n return this.__lineWidths[lineIndex];\n }\n\n const { width } = this.measureLine(lineIndex);\n this.__lineWidths[lineIndex] = width;\n return width;\n }\n\n _getWidthOfCharSpacing() {\n if (this.charSpacing !== 0) {\n return (this.fontSize * this.charSpacing) / 1000;\n }\n return 0;\n }\n\n /**\n * Retrieves the value of property at given character position\n * @param {Number} lineIndex the line number\n * @param {Number} charIndex the character number\n * @param {String} property the property name\n * @returns the value of 'property'\n */\n getValueOfPropertyAt<T extends StylePropertiesType>(\n lineIndex: number,\n charIndex: number,\n property: T,\n ): this[T] {\n const charStyle = this._getStyleDeclaration(lineIndex, charIndex);\n return (charStyle[property] ?? this[property]) as this[T];\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _renderTextDecoration(\n ctx: CanvasRenderingContext2D,\n type: 'underline' | 'linethrough' | 'overline',\n ) {\n if (!this[type] && !this.styleHas(type)) {\n return;\n }\n let topOffset = this._getTopOffset();\n const leftOffset = this._getLeftOffset(),\n path = this.path,\n charSpacing = this._getWidthOfCharSpacing(),\n offsetAligner =\n type === 'linethrough' ? 0.5 : type === 'overline' ? 1 : 0,\n offsetY = this.offsets[type];\n for (let i = 0, len = this._textLines.length; i < len; i++) {\n const heightOfLine = this.getHeightOfLine(i);\n if (!this[type] && !this.styleHas(type, i)) {\n topOffset += heightOfLine;\n continue;\n }\n const line = this._textLines[i];\n const maxHeight = heightOfLine / this.lineHeight;\n const lineLeftOffset = this._getLineLeftOffset(i);\n let boxStart = 0;\n let boxWidth = 0;\n let lastDecoration = this.getValueOfPropertyAt(i, 0, type);\n let lastFill = this.getValueOfPropertyAt(i, 0, FILL);\n let lastTickness = this.getValueOfPropertyAt(\n i,\n 0,\n TEXT_DECORATION_THICKNESS,\n );\n let currentDecoration = lastDecoration;\n let currentFill = lastFill;\n let currentTickness = lastTickness;\n const top = topOffset + maxHeight * (1 - this._fontSizeFraction);\n let size = this.getHeightOfChar(i, 0);\n let dy = this.getValueOfPropertyAt(i, 0, 'deltaY');\n for (let j = 0, jlen = line.length; j < jlen; j++) {\n const charBox = this.__charBounds[i][j] as Required<GraphemeBBox>;\n currentDecoration = this.getValueOfPropertyAt(i, j, type);\n currentFill = this.getValueOfPropertyAt(i, j, FILL);\n currentTickness = this.getValueOfPropertyAt(\n i,\n j,\n TEXT_DECORATION_THICKNESS,\n );\n const currentSize = this.getHeightOfChar(i, j);\n const currentDy = this.getValueOfPropertyAt(i, j, 'deltaY');\n if (path && currentDecoration && currentFill) {\n const finalTickness = (this.fontSize * currentTickness) / 1000;\n ctx.save();\n // bug? verify lastFill is a valid fill here.\n ctx.fillStyle = lastFill as string;\n ctx.translate(charBox.renderLeft, charBox.renderTop);\n ctx.rotate(charBox.angle);\n ctx.fillRect(\n -charBox.kernedWidth / 2,\n offsetY * currentSize + currentDy - offsetAligner * finalTickness,\n charBox.kernedWidth,\n finalTickness,\n );\n ctx.restore();\n } else if (\n (currentDecoration !== lastDecoration ||\n currentFill !== lastFill ||\n currentSize !== size ||\n currentTickness !== lastTickness ||\n currentDy !== dy) &&\n boxWidth > 0\n ) {\n const finalTickness = (this.fontSize * lastTickness) / 1000;\n let drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === RTL) {\n drawStart = this.width - drawStart - boxWidth;\n }\n if (lastDecoration && lastFill && lastTickness) {\n // bug? verify lastFill is a valid fill here.\n ctx.fillStyle = lastFill as string;\n ctx.fillRect(\n drawStart,\n top + offsetY * size + dy - offsetAligner * finalTickness,\n boxWidth,\n finalTickness,\n );\n }\n boxStart = charBox.left;\n boxWidth = charBox.width;\n lastDecoration = currentDecoration;\n lastTickness = currentTickness;\n lastFill = currentFill;\n size = currentSize;\n dy = currentDy;\n } else {\n boxWidth += charBox.kernedWidth;\n }\n }\n let drawStart = leftOffset + lineLeftOffset + boxStart;\n if (this.direction === RTL) {\n drawStart = this.width - drawStart - boxWidth;\n }\n ctx.fillStyle = currentFill as string;\n const finalTickness = (this.fontSize * currentTickness) / 1000;\n currentDecoration &&\n currentFill &&\n currentTickness &&\n ctx.fillRect(\n drawStart,\n top + offsetY * size + dy - offsetAligner * finalTickness,\n boxWidth - charSpacing,\n finalTickness,\n );\n topOffset += heightOfLine;\n }\n // if there is text background color no\n // other shadows should be casted\n this._removeShadow(ctx);\n }\n\n /**\n * return font declaration string for canvas context\n * @param {Object} [styleObject] object\n * @returns {String} font declaration formatted for canvas context.\n */\n _getFontDeclaration(\n {\n fontFamily = this.fontFamily,\n fontStyle = this.fontStyle,\n fontWeight = this.fontWeight,\n fontSize = this.fontSize,\n }: Partial<\n Pick<\n TextStyleDeclaration,\n 'fontFamily' | 'fontStyle' | 'fontWeight' | 'fontSize'\n >\n > = {},\n forMeasuring?: boolean,\n ): string {\n const parsedFontFamily =\n fontFamily.includes(\"'\") ||\n fontFamily.includes('\"') ||\n fontFamily.includes(',') ||\n FabricText.genericFonts.includes(fontFamily.toLowerCase())\n ? fontFamily\n : `\"${fontFamily}\"`;\n return [\n fontStyle,\n fontWeight,\n `${forMeasuring ? this.CACHE_FONT_SIZE : fontSize}px`,\n parsedFontFamily,\n ].join(' ');\n }\n\n /**\n * Renders text instance on a specified context\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render(ctx: CanvasRenderingContext2D) {\n if (!this.visible) {\n return;\n }\n if (\n this.canvas &&\n this.canvas.skipOffscreen &&\n !this.group &&\n !this.isOnScreen()\n ) {\n return;\n }\n if (this._forceClearCache) {\n this.initDimensions();\n }\n super.render(ctx);\n }\n\n /**\n * Override this method to customize grapheme splitting\n * @todo the util `graphemeSplit` needs to be injectable in some way.\n * is more comfortable to inject the correct util rather than having to override text\n * in the middle of the prototype chain\n * @param {string} value\n * @returns {string[]} array of graphemes\n */\n graphemeSplit(value: string): string[] {\n return graphemeSplit(value);\n }\n\n /**\n * Returns the text as an array of lines.\n * @param {String} text text to split\n * @returns Lines in the text\n */\n _splitTextIntoLines(text: string): TextLinesInfo {\n const lines = text.split(this._reNewline),\n newLines = new Array<string[]>(lines.length),\n newLine = ['\\n'];\n let newText: string[] = [];\n for (let i = 0; i < lines.length; i++) {\n newLines[i] = this.graphemeSplit(lines[i]);\n newText = newText.concat(newLines[i], newLine);\n }\n newText.pop();\n return {\n _unwrappedLines: newLines,\n lines: lines,\n graphemeText: newText,\n graphemeLines: newLines,\n };\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return {\n ...super.toObject([...additionalProps, ...propertiesToInclude] as K[]),\n styles: stylesToArray(this.styles, this.text),\n ...(this.path ? { path: this.path.toObject() } : {}),\n };\n }\n\n set(key: string | any, value?: any) {\n const { textLayoutProperties } = this.constructor as typeof FabricText;\n super.set(key, value);\n let needsDims = false;\n let isAddingPath = false;\n if (typeof key === 'object') {\n for (const _key in key) {\n if (_key === 'path') {\n this.setPathInfo();\n }\n needsDims = needsDims || textLayoutProperties.includes(_key);\n isAddingPath = isAddingPath || _key === 'path';\n }\n } else {\n needsDims = textLayoutProperties.includes(key);\n isAddingPath = key === 'path';\n }\n if (isAddingPath) {\n this.setPathInfo();\n }\n if (needsDims && this.initialized) {\n this.initDimensions();\n this.setCoords();\n }\n return this;\n }\n\n /**\n * Returns complexity of an instance\n * @return {Number} complexity\n */\n complexity(): number {\n return 1;\n }\n\n /**\n * List of generic font families\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name\n */\n static genericFonts = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n 'emoji',\n 'fangsong',\n ];\n\n /* _FROM_SVG_START_ */\n\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link FabricText.fromElement})\n * @see: http://www.w3.org/TR/SVG/text.html#TextElement\n */\n static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat(\n 'x',\n 'y',\n 'dx',\n 'dy',\n 'font-family',\n 'font-style',\n 'font-weight',\n 'font-size',\n 'letter-spacing',\n 'text-decoration',\n 'text-anchor',\n );\n\n /**\n * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n */\n static async fromElement(\n element: HTMLElement | SVGElement,\n options?: Abortable,\n cssRules?: CSSRules,\n ) {\n const parsedAttributes = parseAttributes(\n element,\n FabricText.ATTRIBUTE_NAMES,\n cssRules,\n );\n\n const {\n textAnchor = LEFT as typeof LEFT | typeof CENTER | typeof RIGHT,\n textDecoration = '',\n dx = 0,\n dy = 0,\n top = 0,\n left = 0,\n fontSize = DEFAULT_SVG_FONT_SIZE,\n strokeWidth = 1,\n ...restOfOptions\n } = { ...options, ...parsedAttributes };\n\n const textContent = normalizeWs(element.textContent || '').trim();\n\n // this code here is probably the usual issue for SVG center find\n // this can later looked at again and probably removed.\n\n const text = new this(textContent, {\n left: left + dx,\n top: top + dy,\n underline: textDecoration.includes('underline'),\n overline: textDecoration.includes('overline'),\n linethrough: textDecoration.includes('line-through'),\n // we initialize this as 0\n strokeWidth: 0,\n fontSize,\n ...restOfOptions,\n }),\n textHeightScaleFactor = text.getScaledHeight() / text.height,\n lineHeightDiff =\n (text.height + text.strokeWidth) * text.lineHeight - text.height,\n scaledDiff = lineHeightDiff * textHeightScaleFactor,\n textHeight = text.getScaledHeight() + scaledDiff;\n\n let offX = 0;\n /*\n Adjust positioning:\n x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n fabric output by default at top, left.\n */\n if (textAnchor === CENTER) {\n offX = text.getScaledWidth() / 2;\n }\n if (textAnchor === RIGHT) {\n offX = text.getScaledWidth();\n }\n text.set({\n left: text.left - offX,\n top:\n text.top -\n (textHeight - text.fontSize * (0.07 + text._fontSizeFraction)) /\n text.lineHeight,\n strokeWidth,\n });\n return text;\n }\n\n /* _FROM_SVG_END_ */\n\n /**\n * Returns FabricText instance from an object representation\n * @param {Object} object plain js Object to create an instance from\n * @returns {Promise<FabricText>}\n */\n static fromObject<\n T extends TOptions<SerializedTextProps>,\n S extends FabricText,\n >(object: T) {\n return this._fromObject<S>(\n {\n ...object,\n styles: stylesFromArray(object.styles || {}, object.text),\n },\n {\n extraParam: 'text',\n },\n );\n }\n}\n\napplyMixins(FabricText, [TextSVGExportMixin]);\nclassRegistry.setClass(FabricText);\nclassRegistry.setSVGClass(FabricText);\n","import type {\n DragEventData,\n DropEventData,\n TPointerEvent,\n} from '../../EventTypeDefs';\nimport { Point } from '../../Point';\nimport type { IText } from './IText';\nimport { setStyle } from '../../util/internals/dom_style';\nimport { cloneStyles } from '../../util/internals/cloneStyles';\nimport type { TextStyleDeclaration } from '../Text/StyledText';\nimport { getDocumentFromElement } from '../../util/dom_misc';\nimport { CHANGED, NONE } from '../../constants';\n\n/**\n * #### Dragging IText/Textbox Lifecycle\n * - {@link start} is called from `mousedown` {@link IText#_mouseDownHandler} and determines if dragging should start by testing {@link isPointerOverSelection}\n * - if true `mousedown` {@link IText#_mouseDownHandler} is blocked to keep selection\n * - if the pointer moves, canvas fires numerous mousemove {@link Canvas#_onMouseMove} that we make sure **aren't** prevented ({@link IText#shouldStartDragging}) in order for the window to start a drag session\n * - once/if the session starts canvas calls {@link onDragStart} on the active object to determine if dragging should occur\n * - canvas fires relevant drag events that are handled by the handlers defined in this scope\n * - {@link end} is called from `mouseup` {@link IText#mouseUpHandler}, blocking IText default click behavior\n * - in case the drag session didn't occur, {@link end} handles a click, since logic to do so was blocked during `mousedown`\n */\nexport class DraggableTextDelegate {\n readonly target: IText;\n private __mouseDownInPlace = false;\n private __dragStartFired = false;\n private __isDraggingOver = false;\n private __dragStartSelection?: {\n selectionStart: number;\n selectionEnd: number;\n };\n private __dragImageDisposer?: VoidFunction;\n private _dispose?: () => void;\n\n constructor(target: IText) {\n this.target = target;\n const disposers = [\n this.target.on('dragenter', this.dragEnterHandler.bind(this)),\n this.target.on('dragover', this.dragOverHandler.bind(this)),\n this.target.on('dragleave', this.dragLeaveHandler.bind(this)),\n this.target.on('dragend', this.dragEndHandler.bind(this)),\n this.target.on('drop', this.dropHandler.bind(this)),\n ];\n this._dispose = () => {\n disposers.forEach((d) => d());\n this._dispose = undefined;\n };\n }\n\n isPointerOverSelection(e: TPointerEvent) {\n const target = this.target;\n const newSelection = target.getSelectionStartFromPointer(e);\n return (\n target.isEditing &&\n newSelection >= target.selectionStart &&\n newSelection <= target.selectionEnd &&\n target.selectionStart < target.selectionEnd\n );\n }\n\n /**\n * @public override this method to disable dragging and default to mousedown logic\n */\n start(e: TPointerEvent) {\n return (this.__mouseDownInPlace = this.isPointerOverSelection(e));\n }\n\n /**\n * @public override this method to disable dragging without discarding selection\n */\n isActive() {\n return this.__mouseDownInPlace;\n }\n\n /**\n * Ends interaction and sets cursor in case of a click\n * @returns true if was active\n */\n end(e: TPointerEvent) {\n const active = this.isActive();\n if (active && !this.__dragStartFired) {\n // mousedown has been blocked since `active` is true => cursor has not been set.\n // `__dragStartFired` is false => dragging didn't occur, pointer didn't move and is over selection.\n // meaning this is actually a click, `active` is a false positive.\n this.target.setCursorByClick(e);\n this.target.initDelayedCursor(true);\n }\n this.__mouseDownInPlace = false;\n this.__dragStartFired = false;\n this.__isDraggingOver = false;\n return active;\n }\n\n getDragStartSelection() {\n return this.__dragStartSelection;\n }\n\n /**\n * Override to customize the drag image\n * https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage\n */\n setDragImage(\n e: DragEvent,\n {\n selectionStart,\n selectionEnd,\n }: {\n selectionStart: number;\n selectionEnd: number;\n },\n ) {\n const target = this.target;\n const canvas = target.canvas!;\n const flipFactor = new Point(target.flipX ? -1 : 1, target.flipY ? -1 : 1);\n const boundaries = target._getCursorBoundaries(selectionStart);\n const selectionPosition = new Point(\n boundaries.left + boundaries.leftOffset,\n boundaries.top + boundaries.topOffset,\n ).multiply(flipFactor);\n const pos = selectionPosition.transform(target.calcTransformMatrix());\n const pointer = canvas.getScenePoint(e);\n const diff = pointer.subtract(pos);\n const retinaScaling = target.getCanvasRetinaScaling();\n const bbox = target.getBoundingRect();\n const correction = pos.subtract(new Point(bbox.left, bbox.top));\n const vpt = canvas.viewportTransform;\n const offset = correction.add(diff).transform(vpt, true);\n // prepare instance for drag image snapshot by making all non selected text invisible\n const bgc = target.backgroundColor;\n const styles = cloneStyles(target.styles);\n target.backgroundColor = '';\n const styleOverride = {\n stroke: 'transparent',\n fill: 'transparent',\n textBackgroundColor: 'transparent',\n };\n target.setSelectionStyles(styleOverride, 0, selectionStart);\n target.setSelectionStyles(styleOverride, selectionEnd, target.text.length);\n target.dirty = true;\n const dragImage = target.toCanvasElement({\n enableRetinaScaling: canvas.enableRetinaScaling,\n viewportTransform: true,\n });\n // restore values\n target.backgroundColor = bgc;\n target.styles = styles;\n target.dirty = true;\n // position drag image offscreen\n setStyle(dragImage, {\n position: 'fixed',\n left: `${-dragImage.width}px`,\n border: NONE,\n width: `${dragImage.width / retinaScaling}px`,\n height: `${dragImage.height / retinaScaling}px`,\n });\n this.__dragImageDisposer && this.__dragImageDisposer();\n this.__dragImageDisposer = () => {\n dragImage.remove();\n };\n getDocumentFromElement(\n (e.target || this.target.hiddenTextarea)! as HTMLElement,\n ).body.appendChild(dragImage);\n e.dataTransfer?.setDragImage(dragImage, offset.x, offset.y);\n }\n\n /**\n * @returns {boolean} determines whether {@link target} should/shouldn't become a drag source\n */\n onDragStart(e: DragEvent): boolean {\n this.__dragStartFired = true;\n const target = this.target;\n const active = this.isActive();\n if (active && e.dataTransfer) {\n const selection = (this.__dragStartSelection = {\n selectionStart: target.selectionStart,\n selectionEnd: target.selectionEnd,\n });\n const value = target._text\n .slice(selection.selectionStart, selection.selectionEnd)\n .join('');\n const data = { text: target.text, value, ...selection };\n e.dataTransfer.setData('text/plain', value);\n e.dataTransfer.setData(\n 'application/fabric',\n JSON.stringify({\n value: value,\n styles: target.getSelectionStyles(\n selection.selectionStart,\n selection.selectionEnd,\n true,\n ),\n }),\n );\n e.dataTransfer.effectAllowed = 'copyMove';\n this.setDragImage(e, data);\n }\n target.abortCursorAnimation();\n return active;\n }\n\n /**\n * use {@link targetCanDrop} to respect overriding\n * @returns {boolean} determines whether {@link target} should/shouldn't become a drop target\n */\n canDrop(e: DragEvent): boolean {\n if (\n this.target.editable &&\n !this.target.getActiveControl() &&\n !e.defaultPrevented\n ) {\n if (this.isActive() && this.__dragStartSelection) {\n // drag source trying to drop over itself\n // allow dropping only outside of drag start selection\n const index = this.target.getSelectionStartFromPointer(e);\n const dragStartSelection = this.__dragStartSelection;\n return (\n index < dragStartSelection.selectionStart ||\n index > dragStartSelection.selectionEnd\n );\n }\n return true;\n }\n return false;\n }\n\n /**\n * in order to respect overriding {@link IText#canDrop} we call that instead of calling {@link canDrop} directly\n */\n protected targetCanDrop(e: DragEvent) {\n return this.target.canDrop(e);\n }\n\n dragEnterHandler({ e }: DragEventData) {\n const canDrop = this.targetCanDrop(e);\n if (!this.__isDraggingOver && canDrop) {\n this.__isDraggingOver = true;\n }\n }\n\n dragOverHandler(ev: DragEventData) {\n const { e } = ev;\n const canDrop = this.targetCanDrop(e);\n if (!this.__isDraggingOver && canDrop) {\n this.__isDraggingOver = true;\n } else if (this.__isDraggingOver && !canDrop) {\n // drop state has changed\n this.__isDraggingOver = false;\n }\n if (this.__isDraggingOver) {\n // can be dropped, inform browser\n e.preventDefault();\n // inform event subscribers\n ev.canDrop = true;\n ev.dropTarget = this.target;\n }\n }\n\n dragLeaveHandler() {\n if (this.__isDraggingOver || this.isActive()) {\n this.__isDraggingOver = false;\n }\n }\n\n /**\n * Override the `text/plain | application/fabric` types of {@link DragEvent#dataTransfer}\n * in order to change the drop value or to customize styling respectively, by listening to the `drop:before` event\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#performing_a_drop\n */\n dropHandler(ev: DropEventData) {\n const { e } = ev;\n const didDrop = e.defaultPrevented;\n this.__isDraggingOver = false;\n // inform browser that the drop has been accepted\n e.preventDefault();\n let insert = e.dataTransfer?.getData('text/plain');\n if (insert && !didDrop) {\n const target = this.target;\n const canvas = target.canvas!;\n let insertAt = target.getSelectionStartFromPointer(e);\n const { styles } = (\n e.dataTransfer!.types.includes('application/fabric')\n ? JSON.parse(e.dataTransfer!.getData('application/fabric'))\n : {}\n ) as { styles: TextStyleDeclaration[] };\n const trailing = insert[Math.max(0, insert.length - 1)];\n const selectionStartOffset = 0;\n // drag and drop in same instance\n if (this.__dragStartSelection) {\n const selectionStart = this.__dragStartSelection.selectionStart;\n const selectionEnd = this.__dragStartSelection.selectionEnd;\n if (insertAt > selectionStart && insertAt <= selectionEnd) {\n insertAt = selectionStart;\n } else if (insertAt > selectionEnd) {\n insertAt -= selectionEnd - selectionStart;\n }\n target.removeChars(selectionStart, selectionEnd);\n // prevent `dragend` from handling event\n delete this.__dragStartSelection;\n }\n // remove redundant line break\n if (\n target._reNewline.test(trailing) &&\n (target._reNewline.test(target._text[insertAt]) ||\n insertAt === target._text.length)\n ) {\n insert = insert.trimEnd();\n }\n // inform subscribers\n ev.didDrop = true;\n ev.dropTarget = target;\n // finalize\n target.insertChars(insert, styles, insertAt);\n // can this part be moved in an outside event? andrea to check.\n canvas.setActiveObject(target);\n target.enterEditing(e);\n target.selectionStart = Math.min(\n insertAt + selectionStartOffset,\n target._text.length,\n );\n target.selectionEnd = Math.min(\n target.selectionStart + insert.length,\n target._text.length,\n );\n target.hiddenTextarea!.value = target.text;\n target._updateTextarea();\n target.hiddenTextarea!.focus();\n target.fire(CHANGED, {\n index: insertAt + selectionStartOffset,\n action: 'drop',\n });\n canvas.fire('text:changed', { target });\n canvas.contextTopDirty = true;\n canvas.requestRenderAll();\n }\n }\n\n /**\n * fired only on the drag source after drop (if occurred)\n * handle changes to the drag source in case of a drop on another object or a cancellation\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag\n */\n dragEndHandler({ e }: DragEventData) {\n if (this.isActive() && this.__dragStartFired) {\n // once the drop event finishes we check if we need to change the drag source\n // if the drag source received the drop we bail out since the drop handler has already handled logic\n if (this.__dragStartSelection) {\n const target = this.target;\n const canvas = this.target.canvas!;\n const { selectionStart, selectionEnd } = this.__dragStartSelection;\n const dropEffect = e.dataTransfer?.dropEffect || NONE;\n if (dropEffect === NONE) {\n // pointer is back over selection\n target.selectionStart = selectionStart;\n target.selectionEnd = selectionEnd;\n target._updateTextarea();\n target.hiddenTextarea!.focus();\n } else {\n target.clearContextTop();\n if (dropEffect === 'move') {\n target.removeChars(selectionStart, selectionEnd);\n target.selectionStart = target.selectionEnd = selectionStart;\n target.hiddenTextarea &&\n (target.hiddenTextarea.value = target.text);\n target._updateTextarea();\n target.fire(CHANGED, {\n index: selectionStart,\n action: 'dragend',\n });\n canvas.fire('text:changed', { target });\n canvas.requestRenderAll();\n }\n target.exitEditing();\n }\n }\n }\n\n this.__dragImageDisposer && this.__dragImageDisposer();\n delete this.__dragImageDisposer;\n delete this.__dragStartSelection;\n this.__isDraggingOver = false;\n }\n\n dispose() {\n this._dispose && this._dispose();\n }\n}\n","import type { ObjectEvents, TPointerEvent } from '../../EventTypeDefs';\nimport { Point } from '../../Point';\nimport type { FabricObject } from '../Object/FabricObject';\nimport { FabricText } from '../Text/Text';\nimport { animate } from '../../util/animation/animate';\nimport type { TOnAnimationChangeCallback } from '../../util/animation/types';\nimport type { ValueAnimation } from '../../util/animation/ValueAnimation';\nimport type { TextStyleDeclaration } from '../Text/StyledText';\nimport type { SerializedTextProps, TextProps } from '../Text/Text';\nimport type { TOptions, TOriginX } from '../../typedefs';\nimport { getDocumentFromElement } from '../../util/dom_misc';\nimport { LEFT, LTR, MODIFIED, RIGHT, reNewline } from '../../constants';\nimport type { IText } from './IText';\nimport { JUSTIFY } from '../Text/constants';\n\n/**\n * extend this regex to support non english languages\n *\n * - ` ` Matches a SPACE character (char code 32).\n * - `\\n` Matches a LINE FEED character (char code 10).\n * - `\\.` Matches a \".\" character (char code 46).\n * - `,` Matches a \",\" character (char code 44).\n * - `;` Matches a \";\" character (char code 59).\n * - `!` Matches a \"!\" character (char code 33).\n * - `\\?` Matches a \"?\" character (char code 63).\n * - `\\-` Matches a \"-\" character (char code 45).\n */\n// eslint-disable-next-line no-useless-escape\nconst reNonWord = /[ \\n\\.,;!\\?\\-]/;\n\nexport type ITextEvents = ObjectEvents & {\n 'selection:changed': never;\n changed: never | { index: number; action: string };\n 'editing:entered': never | { e: TPointerEvent };\n 'editing:exited': never;\n};\n\nexport abstract class ITextBehavior<\n Props extends TOptions<TextProps> = Partial<TextProps>,\n SProps extends SerializedTextProps = SerializedTextProps,\n EventSpec extends ITextEvents = ITextEvents,\n> extends FabricText<Props, SProps, EventSpec> {\n declare abstract isEditing: boolean;\n declare abstract cursorDelay: number;\n declare abstract selectionStart: number;\n declare abstract selectionEnd: number;\n declare abstract cursorDuration: number;\n declare abstract editable: boolean;\n declare abstract editingBorderColor: string;\n\n declare abstract compositionStart: number;\n declare abstract compositionEnd: number;\n\n declare abstract hiddenTextarea: HTMLTextAreaElement | null;\n\n /**\n * Helps determining when the text is in composition, so that the cursor\n * rendering is altered.\n */\n declare protected inCompositionMode: boolean;\n\n declare protected _reSpace: RegExp;\n declare private _currentTickState?: ValueAnimation;\n declare private _currentTickCompleteState?: ValueAnimation;\n protected _currentCursorOpacity = 1;\n declare private _textBeforeEdit: string;\n declare protected __selectionStartOnMouseDown: number;\n\n /**\n * Keeps track if the IText object was selected before the actual click.\n * This because we want to delay enter editing by a click.\n */\n declare protected selected: boolean;\n declare protected cursorOffsetCache: { left?: number; top?: number };\n declare protected _savedProps?: {\n hasControls: boolean;\n borderColor: string;\n lockMovementX: boolean;\n lockMovementY: boolean;\n selectable: boolean;\n hoverCursor: CSSStyleDeclaration['cursor'] | null;\n defaultCursor?: CSSStyleDeclaration['cursor'];\n moveCursor?: CSSStyleDeclaration['cursor'];\n };\n declare protected _selectionDirection: 'left' | 'right' | null;\n\n abstract initHiddenTextarea(): void;\n abstract _fireSelectionChanged(): void;\n abstract renderCursorOrSelection(): void;\n abstract getSelectionStartFromPointer(e: TPointerEvent): number;\n abstract _getCursorBoundaries(\n index: number,\n skipCaching?: boolean,\n ): {\n left: number;\n top: number;\n leftOffset: number;\n topOffset: number;\n };\n\n /**\n * Initializes all the interactive behavior of IText\n */\n initBehavior() {\n this._tick = this._tick.bind(this);\n this._onTickComplete = this._onTickComplete.bind(this);\n this.updateSelectionOnMouseMove =\n this.updateSelectionOnMouseMove.bind(this);\n }\n\n onDeselect(options?: { e?: TPointerEvent; object?: FabricObject }) {\n this.isEditing && this.exitEditing();\n this.selected = false;\n return super.onDeselect(options);\n }\n\n /**\n * @private\n */\n _animateCursor({\n toValue,\n duration,\n delay,\n onComplete,\n }: {\n toValue: number;\n duration: number;\n delay?: number;\n onComplete?: TOnAnimationChangeCallback<number>;\n }) {\n return animate({\n startValue: this._currentCursorOpacity,\n endValue: toValue,\n duration,\n delay,\n onComplete,\n abort: () =>\n !this.canvas ||\n // we do not want to animate a selection, only cursor\n this.selectionStart !== this.selectionEnd,\n onChange: (value) => {\n this._currentCursorOpacity = value;\n this.renderCursorOrSelection();\n },\n });\n }\n\n /**\n * changes the cursor from visible to invisible\n */\n private _tick(delay?: number) {\n this._currentTickState = this._animateCursor({\n toValue: 0,\n duration: this.cursorDuration / 2,\n delay: Math.max(delay || 0, 100),\n onComplete: this._onTickComplete,\n });\n }\n\n /**\n * Changes the cursor from invisible to visible\n */\n private _onTickComplete() {\n this._currentTickCompleteState?.abort();\n this._currentTickCompleteState = this._animateCursor({\n toValue: 1,\n duration: this.cursorDuration,\n onComplete: this._tick,\n });\n }\n\n /**\n * Initializes delayed cursor\n */\n initDelayedCursor(restart?: boolean) {\n this.abortCursorAnimation();\n this._tick(restart ? 0 : this.cursorDelay);\n }\n\n /**\n * Aborts cursor animation, clears all timeouts and clear textarea context if necessary\n */\n abortCursorAnimation() {\n let shouldClear = false;\n [this._currentTickState, this._currentTickCompleteState].forEach(\n (cursorAnimation) => {\n if (cursorAnimation && !cursorAnimation.isDone()) {\n shouldClear = true;\n cursorAnimation.abort();\n }\n },\n );\n\n this._currentCursorOpacity = 1;\n\n // make sure we clear context even if instance is not editing\n if (shouldClear) {\n this.clearContextTop();\n }\n }\n\n /**\n * Restart tue cursor animation if either is in complete state ( between animations )\n * or if it never started before\n */\n restartCursorIfNeeded() {\n if (\n [this._currentTickState, this._currentTickCompleteState].some(\n (cursorAnimation) => !cursorAnimation || cursorAnimation.isDone(),\n )\n ) {\n this.initDelayedCursor();\n }\n }\n\n /**\n * Selects entire text\n */\n selectAll() {\n this.selectionStart = 0;\n this.selectionEnd = this._text.length;\n this._fireSelectionChanged();\n this._updateTextarea();\n return this;\n }\n\n /**\n * Selects entire text and updates the visual state\n */\n cmdAll() {\n this.selectAll();\n this.renderCursorOrSelection();\n }\n\n /**\n * Returns selected text\n * @return {String}\n */\n getSelectedText(): string {\n return this._text.slice(this.selectionStart, this.selectionEnd).join('');\n }\n\n /**\n * Find new selection index representing start of current word according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findWordBoundaryLeft(startFrom: number): number {\n let offset = 0,\n index = startFrom - 1;\n\n // remove space before cursor first\n if (this._reSpace.test(this._text[index])) {\n while (this._reSpace.test(this._text[index])) {\n offset++;\n index--;\n }\n }\n while (/\\S/.test(this._text[index]) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n }\n\n /**\n * Find new selection index representing end of current word according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findWordBoundaryRight(startFrom: number): number {\n let offset = 0,\n index = startFrom;\n\n // remove space after cursor first\n if (this._reSpace.test(this._text[index])) {\n while (this._reSpace.test(this._text[index])) {\n offset++;\n index++;\n }\n }\n while (/\\S/.test(this._text[index]) && index < this._text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n }\n\n /**\n * Find new selection index representing start of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryLeft(startFrom: number): number {\n let offset = 0,\n index = startFrom - 1;\n\n while (!/\\n/.test(this._text[index]) && index > -1) {\n offset++;\n index--;\n }\n\n return startFrom - offset;\n }\n\n /**\n * Find new selection index representing end of current line according to current selection index\n * @param {Number} startFrom Current selection index\n * @return {Number} New selection index\n */\n findLineBoundaryRight(startFrom: number): number {\n let offset = 0,\n index = startFrom;\n\n while (!/\\n/.test(this._text[index]) && index < this._text.length) {\n offset++;\n index++;\n }\n\n return startFrom + offset;\n }\n\n /**\n * Finds index corresponding to beginning or end of a word\n * @param {Number} selectionStart Index of a character\n * @param {Number} direction 1 or -1\n * @return {Number} Index of the beginning or end of a word\n */\n searchWordBoundary(selectionStart: number, direction: 1 | -1): number {\n const text = this._text;\n // if we land on a space we move the cursor backwards\n // if we are searching boundary end we move the cursor backwards ONLY if we don't land on a line break\n let index =\n selectionStart > 0 &&\n this._reSpace.test(text[selectionStart]) &&\n (direction === -1 || !reNewline.test(text[selectionStart - 1]))\n ? selectionStart - 1\n : selectionStart,\n _char = text[index];\n while (index > 0 && index < text.length && !reNonWord.test(_char)) {\n index += direction;\n _char = text[index];\n }\n if (direction === -1 && reNonWord.test(_char)) {\n index++;\n }\n return index;\n }\n\n /**\n * Selects the word that contains the char at index selectionStart\n * @param {Number} selectionStart Index of a character\n */\n selectWord(selectionStart?: number) {\n selectionStart = selectionStart ?? this.selectionStart;\n // search backwards\n const newSelectionStart = this.searchWordBoundary(selectionStart, -1),\n // search forward\n newSelectionEnd = Math.max(\n newSelectionStart,\n this.searchWordBoundary(selectionStart, 1),\n );\n\n this.selectionStart = newSelectionStart;\n this.selectionEnd = newSelectionEnd;\n this._fireSelectionChanged();\n this._updateTextarea();\n // remove next major, for now it renders twice :(\n this.renderCursorOrSelection();\n }\n\n /**\n * Selects the line that contains selectionStart\n * @param {Number} selectionStart Index of a character\n */\n selectLine(selectionStart?: number) {\n selectionStart = selectionStart ?? this.selectionStart;\n const 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 */\n enterEditing(e?: TPointerEvent) {\n if (this.isEditing || !this.editable) {\n return;\n }\n this.enterEditingImpl();\n this.fire('editing:entered', e ? { e } : undefined);\n this._fireSelectionChanged();\n if (this.canvas) {\n this.canvas.fire('text:editing:entered', {\n target: this as unknown as IText,\n e,\n });\n this.canvas.requestRenderAll();\n }\n }\n\n /**\n * runs the actual logic that enter from editing state, see {@link enterEditing}\n */\n enterEditingImpl() {\n if (this.canvas) {\n this.canvas.calcOffset();\n this.canvas.textEditingManager.exitTextEditing();\n }\n\n this.isEditing = true;\n\n this.initHiddenTextarea();\n this.hiddenTextarea!.focus();\n this.hiddenTextarea!.value = this.text;\n this._updateTextarea();\n this._saveEditingProps();\n this._setEditingProps();\n this._textBeforeEdit = this.text;\n\n this._tick();\n }\n\n /**\n * called by {@link Canvas#textEditingManager}\n */\n updateSelectionOnMouseMove(e: TPointerEvent) {\n if (this.getActiveControl()) {\n return;\n }\n\n const el = this.hiddenTextarea!;\n // regain focus\n getDocumentFromElement(el).activeElement !== el && el.focus();\n\n const newSelectionStart = this.getSelectionStartFromPointer(e),\n currentStart = this.selectionStart,\n currentEnd = this.selectionEnd;\n if (\n (newSelectionStart !== this.__selectionStartOnMouseDown ||\n currentStart === currentEnd) &&\n (currentStart === newSelectionStart || currentEnd === newSelectionStart)\n ) {\n return;\n }\n if (newSelectionStart > this.__selectionStartOnMouseDown) {\n this.selectionStart = this.__selectionStartOnMouseDown;\n this.selectionEnd = newSelectionStart;\n } else {\n this.selectionStart = newSelectionStart;\n this.selectionEnd = this.__selectionStartOnMouseDown;\n }\n if (\n this.selectionStart !== currentStart ||\n this.selectionEnd !== currentEnd\n ) {\n this._fireSelectionChanged();\n this._updateTextarea();\n this.renderCursorOrSelection();\n }\n }\n\n /**\n * @private\n */\n _setEditingProps() {\n this.hoverCursor = 'text';\n\n if (this.canvas) {\n this.canvas.defaultCursor = this.canvas.moveCursor = 'text';\n }\n\n this.borderColor = this.editingBorderColor;\n this.hasControls = this.selectable = false;\n this.lockMovementX = this.lockMovementY = true;\n }\n\n /**\n * convert from textarea to grapheme indexes\n */\n fromStringToGraphemeSelection(start: number, end: number, text: string) {\n const smallerTextStart = text.slice(0, start),\n graphemeStart = this.graphemeSplit(smallerTextStart).length;\n if (start === end) {\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n }\n const smallerTextEnd = text.slice(start, end),\n graphemeEnd = this.graphemeSplit(smallerTextEnd).length;\n return {\n selectionStart: graphemeStart,\n selectionEnd: graphemeStart + graphemeEnd,\n };\n }\n\n /**\n * convert from fabric to textarea values\n */\n fromGraphemeToStringSelection(\n start: number,\n end: number,\n graphemes: string[],\n ) {\n const smallerTextStart = graphemes.slice(0, start),\n graphemeStart = smallerTextStart.join('').length;\n if (start === end) {\n return { selectionStart: graphemeStart, selectionEnd: graphemeStart };\n }\n const smallerTextEnd = graphemes.slice(start, end),\n graphemeEnd = smallerTextEnd.join('').length;\n return {\n selectionStart: graphemeStart,\n selectionEnd: graphemeStart + graphemeEnd,\n };\n }\n\n /**\n * @private\n */\n _updateTextarea() {\n this.cursorOffsetCache = {};\n if (!this.hiddenTextarea) {\n return;\n }\n if (!this.inCompositionMode) {\n const newSelection = this.fromGraphemeToStringSelection(\n this.selectionStart,\n this.selectionEnd,\n this._text,\n );\n this.hiddenTextarea.selectionStart = newSelection.selectionStart;\n this.hiddenTextarea.selectionEnd = newSelection.selectionEnd;\n }\n this.updateTextareaPosition();\n }\n\n /**\n * This function updates the text value from the hidden textarea and recalculates the text bounding box\n * size and position.\n * It is called by fabricJS internals, do not use it directly.\n * @private\n */\n updateFromTextArea() {\n const { hiddenTextarea, direction, textAlign, inCompositionMode } = this;\n if (!hiddenTextarea) {\n return;\n }\n // we want to anchor the textarea position depending on text alignment\n // or in case of text justify depending on ltr/rtl direction.\n // this.textAlign.replace('justify-', '') leverages the fact that our textAlign values all contain the word left/right/center,\n // that match the originX values.\n const anchorX: TOriginX =\n textAlign !== JUSTIFY\n ? (textAlign.replace('justify-', '') as TOriginX)\n : direction === LTR\n ? LEFT\n : RIGHT;\n const originalPosition = this.getPositionByOrigin(anchorX, 'top');\n this.cursorOffsetCache = {};\n this.text = hiddenTextarea.value;\n this.set('dirty', true);\n this.initDimensions();\n this.setPositionByOrigin(originalPosition, anchorX, 'top');\n this.setCoords();\n const newSelection = this.fromStringToGraphemeSelection(\n hiddenTextarea.selectionStart,\n hiddenTextarea.selectionEnd,\n hiddenTextarea.value,\n );\n this.selectionEnd = this.selectionStart = newSelection.selectionEnd;\n if (!inCompositionMode) {\n this.selectionStart = newSelection.selectionStart;\n }\n this.updateTextareaPosition();\n }\n\n /**\n * @private\n */\n updateTextareaPosition() {\n if (this.selectionStart === this.selectionEnd) {\n const style = this._calcTextareaPosition();\n this.hiddenTextarea!.style.left = style.left;\n this.hiddenTextarea!.style.top = style.top;\n }\n }\n\n /**\n * @private\n * @return {Object} style contains style for hiddenTextarea\n */\n _calcTextareaPosition() {\n if (!this.canvas) {\n return { left: '1px', top: '1px' };\n }\n const desiredPosition = this.inCompositionMode\n ? this.compositionStart\n : this.selectionStart,\n boundaries = this._getCursorBoundaries(desiredPosition),\n cursorLocation = this.get2DCursorLocation(desiredPosition),\n lineIndex = cursorLocation.lineIndex,\n charIndex = cursorLocation.charIndex,\n charHeight =\n this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize') *\n this.lineHeight,\n leftOffset = boundaries.leftOffset,\n retinaScaling = this.getCanvasRetinaScaling(),\n upperCanvas = this.canvas.upperCanvasEl,\n upperCanvasWidth = upperCanvas.width / retinaScaling,\n upperCanvasHeight = upperCanvas.height / retinaScaling,\n maxWidth = upperCanvasWidth - charHeight,\n maxHeight = upperCanvasHeight - charHeight;\n\n const p = new Point(\n boundaries.left + leftOffset,\n boundaries.top + boundaries.topOffset + charHeight,\n )\n .transform(this.calcTransformMatrix())\n .transform(this.canvas.viewportTransform)\n .multiply(\n new Point(\n upperCanvas.clientWidth / upperCanvasWidth,\n upperCanvas.clientHeight / upperCanvasHeight,\n ),\n );\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 {\n left: `${p.x}px`,\n top: `${p.y}px`,\n fontSize: `${charHeight}px`,\n charHeight: charHeight,\n };\n }\n\n /**\n * @private\n */\n _saveEditingProps() {\n this._savedProps = {\n hasControls: this.hasControls,\n borderColor: this.borderColor,\n lockMovementX: this.lockMovementX,\n lockMovementY: this.lockMovementY,\n hoverCursor: this.hoverCursor,\n selectable: this.selectable,\n defaultCursor: this.canvas && this.canvas.defaultCursor,\n moveCursor: this.canvas && this.canvas.moveCursor,\n };\n }\n\n /**\n * @private\n */\n _restoreEditingProps() {\n if (!this._savedProps) {\n return;\n }\n\n this.hoverCursor = this._savedProps.hoverCursor;\n this.hasControls = this._savedProps.hasControls;\n this.borderColor = this._savedProps.borderColor;\n this.selectable = this._savedProps.selectable;\n this.lockMovementX = this._savedProps.lockMovementX;\n this.lockMovementY = this._savedProps.lockMovementY;\n\n if (this.canvas) {\n this.canvas.defaultCursor =\n this._savedProps.defaultCursor || this.canvas.defaultCursor;\n this.canvas.moveCursor =\n this._savedProps.moveCursor || this.canvas.moveCursor;\n }\n\n delete this._savedProps;\n }\n\n /**\n * runs the actual logic that exits from editing state, see {@link exitEditing}\n * But it does not fire events\n */\n exitEditingImpl() {\n const hiddenTextarea = this.hiddenTextarea;\n this.selected = false;\n this.isEditing = false;\n\n if (hiddenTextarea) {\n hiddenTextarea.blur && hiddenTextarea.blur();\n hiddenTextarea.parentNode &&\n hiddenTextarea.parentNode.removeChild(hiddenTextarea);\n }\n this.hiddenTextarea = null;\n this.abortCursorAnimation();\n this.selectionStart !== this.selectionEnd && this.clearContextTop();\n this.selectionEnd = this.selectionStart;\n this._restoreEditingProps();\n if (this._forceClearCache) {\n this.initDimensions();\n this.setCoords();\n }\n }\n\n /**\n * Exits from editing state and fires relevant events\n */\n exitEditing() {\n const isTextChanged = this._textBeforeEdit !== this.text;\n this.exitEditingImpl();\n\n this.fire('editing:exited');\n isTextChanged && this.fire(MODIFIED);\n if (this.canvas) {\n this.canvas.fire('text:editing:exited', {\n target: this as unknown as IText,\n });\n // todo: evaluate add an action to this event\n isTextChanged && this.canvas.fire('object:modified', { target: this });\n }\n return this;\n }\n\n /**\n * @private\n */\n _removeExtraneousStyles() {\n for (const prop in this.styles) {\n if (!this._textLines[prop as unknown as number]) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * remove and reflow a style block from start to end.\n * @param {Number} start linear start position for removal (included in removal)\n * @param {Number} end linear end position for removal ( excluded from removal )\n */\n removeStyleFromTo(start: number, end: number) {\n const { lineIndex: lineStart, charIndex: charStart } =\n this.get2DCursorLocation(start, true),\n { lineIndex: lineEnd, charIndex: charEnd } = this.get2DCursorLocation(\n end,\n true,\n );\n if (lineStart !== lineEnd) {\n // step1 remove the trailing of lineStart\n if (this.styles[lineStart]) {\n for (\n let i = charStart;\n i < this._unwrappedTextLines[lineStart].length;\n i++\n ) {\n delete this.styles[lineStart][i];\n }\n }\n // step2 move the trailing of lineEnd to lineStart if needed\n if (this.styles[lineEnd]) {\n for (\n let i = charEnd;\n i < this._unwrappedTextLines[lineEnd].length;\n i++\n ) {\n const styleObj = this.styles[lineEnd][i];\n if (styleObj) {\n this.styles[lineStart] || (this.styles[lineStart] = {});\n this.styles[lineStart][charStart + i - charEnd] = styleObj;\n }\n }\n }\n // step3 detects lines will be completely removed.\n for (let i = lineStart + 1; i <= lineEnd; i++) {\n delete this.styles[i];\n }\n // step4 shift remaining lines.\n this.shiftLineStyles(lineEnd, lineStart - lineEnd);\n } else {\n // remove and shift left on the same line\n if (this.styles[lineStart]) {\n const styleObj = this.styles[lineStart];\n const diff = charEnd - charStart;\n for (let i = charStart; i < charEnd; i++) {\n delete styleObj[i];\n }\n for (const char in this.styles[lineStart]) {\n const numericChar = parseInt(char, 10);\n if (numericChar >= charEnd) {\n styleObj[numericChar - diff] = styleObj[char];\n delete styleObj[char];\n }\n }\n }\n }\n }\n\n /**\n * Shifts line styles up or down\n * @param {Number} lineIndex Index of a line\n * @param {Number} offset Can any number?\n */\n shiftLineStyles(lineIndex: number, offset: number) {\n const clonedStyles = Object.assign({}, this.styles);\n for (const line in this.styles) {\n const numericLine = parseInt(line, 10);\n if (numericLine > lineIndex) {\n this.styles[numericLine + offset] = clonedStyles[numericLine];\n if (!clonedStyles[numericLine - offset]) {\n delete this.styles[numericLine];\n }\n }\n }\n }\n\n /**\n * Handle insertion of more consecutive style lines for when one or more\n * newlines gets added to the text. Since current style needs to be shifted\n * first we shift the current style of the number lines needed, then we add\n * new lines from the last to the first.\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Number} qty number of lines to add\n * @param {Array} copiedStyle Array of objects styles\n */\n insertNewlineStyleObject(\n lineIndex: number,\n charIndex: number,\n qty: number,\n copiedStyle?: { [index: number]: TextStyleDeclaration },\n ) {\n const newLineStyles: { [index: number]: TextStyleDeclaration } = {};\n const originalLineLength = this._unwrappedTextLines[lineIndex].length;\n const isEndOfLine = originalLineLength === charIndex;\n\n let someStyleIsCarryingOver = false;\n qty || (qty = 1);\n this.shiftLineStyles(lineIndex, qty);\n const currentCharStyle = this.styles[lineIndex]\n ? this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1]\n : undefined;\n\n // we clone styles of all chars\n // after cursor onto the current line\n for (const index in this.styles[lineIndex]) {\n const numIndex = parseInt(index, 10);\n if (numIndex >= charIndex) {\n someStyleIsCarryingOver = true;\n newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index];\n // remove lines from the previous line since they're on a new line now\n if (!(isEndOfLine && charIndex === 0)) {\n delete this.styles[lineIndex][index];\n }\n }\n }\n let styleCarriedOver = false;\n if (someStyleIsCarryingOver && !isEndOfLine) {\n // if is end of line, the extra style we copied\n // is probably not something we want\n this.styles[lineIndex + qty] = newLineStyles;\n styleCarriedOver = true;\n }\n if (styleCarriedOver || originalLineLength > charIndex) {\n // skip the last line of since we already prepared it.\n // or contains text without style that we don't want to style\n // just because it changed lines\n qty--;\n }\n // for the all the lines or all the other lines\n // we clone current char style onto the next (otherwise empty) line\n while (qty > 0) {\n if (copiedStyle && copiedStyle[qty - 1]) {\n this.styles[lineIndex + qty] = {\n 0: { ...copiedStyle[qty - 1] },\n };\n } else if (currentCharStyle) {\n this.styles[lineIndex + qty] = {\n 0: { ...currentCharStyle },\n };\n } else {\n delete this.styles[lineIndex + qty];\n }\n qty--;\n }\n this._forceClearCache = true;\n }\n\n /**\n * Inserts style object for a given line/char index\n * @param {Number} lineIndex Index of a line\n * @param {Number} charIndex Index of a char\n * @param {Number} quantity number Style object to insert, if given\n * @param {Array} copiedStyle array of style objects\n */\n insertCharStyleObject(\n lineIndex: number,\n charIndex: number,\n quantity: number,\n copiedStyle?: TextStyleDeclaration[],\n ) {\n if (!this.styles) {\n this.styles = {};\n }\n const currentLineStyles = this.styles[lineIndex],\n currentLineStylesCloned = currentLineStyles\n ? { ...currentLineStyles }\n : {};\n\n quantity || (quantity = 1);\n // shift all char styles by quantity forward\n // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4\n for (const index in currentLineStylesCloned) {\n const numericIndex = parseInt(index, 10);\n if (numericIndex >= charIndex) {\n currentLineStyles[numericIndex + quantity] =\n currentLineStylesCloned[numericIndex];\n // only delete the style if there was nothing moved there\n if (!currentLineStylesCloned[numericIndex - quantity]) {\n delete currentLineStyles[numericIndex];\n }\n }\n }\n this._forceClearCache = true;\n if (copiedStyle) {\n while (quantity--) {\n if (!Object.keys(copiedStyle[quantity]).length) {\n continue;\n }\n if (!this.styles[lineIndex]) {\n this.styles[lineIndex] = {};\n }\n this.styles[lineIndex][charIndex + quantity] = {\n ...copiedStyle[quantity],\n };\n }\n return;\n }\n if (!currentLineStyles) {\n return;\n }\n const newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1];\n while (newStyle && quantity--) {\n this.styles[lineIndex][charIndex + quantity] = { ...newStyle };\n }\n }\n\n /**\n * Inserts style object(s)\n * @param {Array} insertedText Characters at the location where style is inserted\n * @param {Number} start cursor index for inserting style\n * @param {Array} [copiedStyle] array of style objects to insert.\n */\n insertNewStyleBlock(\n insertedText: string[],\n start: number,\n copiedStyle?: TextStyleDeclaration[],\n ) {\n const cursorLoc = this.get2DCursorLocation(start, true),\n addedLines = [0];\n let linesLength = 0;\n // get an array of how many char per lines are being added.\n for (let i = 0; i < insertedText.length; i++) {\n if (insertedText[i] === '\\n') {\n linesLength++;\n addedLines[linesLength] = 0;\n } else {\n addedLines[linesLength]++;\n }\n }\n // for the first line copy the style from the current char position.\n if (addedLines[0] > 0) {\n this.insertCharStyleObject(\n cursorLoc.lineIndex,\n cursorLoc.charIndex,\n addedLines[0],\n copiedStyle,\n );\n copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);\n }\n linesLength &&\n this.insertNewlineStyleObject(\n cursorLoc.lineIndex,\n cursorLoc.charIndex + addedLines[0],\n linesLength,\n );\n let i;\n for (i = 1; i < linesLength; i++) {\n if (addedLines[i] > 0) {\n this.insertCharStyleObject(\n cursorLoc.lineIndex + i,\n 0,\n addedLines[i],\n copiedStyle,\n );\n } else if (copiedStyle) {\n // this test is required in order to close #6841\n // when a pasted buffer begins with a newline then\n // this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]\n // may be undefined for some reason\n if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {\n this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];\n }\n }\n copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);\n }\n if (addedLines[i] > 0) {\n this.insertCharStyleObject(\n cursorLoc.lineIndex + i,\n 0,\n addedLines[i],\n copiedStyle,\n );\n }\n }\n\n /**\n * Removes characters from start/end\n * start/end ar per grapheme position in _text array.\n *\n * @param {Number} start\n * @param {Number} end default to start + 1\n */\n removeChars(start: number, end: number = start + 1) {\n this.removeStyleFromTo(start, end);\n this._text.splice(start, end - start);\n this.text = this._text.join('');\n this.set('dirty', true);\n this.initDimensions();\n this.setCoords();\n this._removeExtraneousStyles();\n }\n\n /**\n * insert characters at start position, before start position.\n * start equal 1 it means the text get inserted between actual grapheme 0 and 1\n * if style array is provided, it must be as the same length of text in graphemes\n * if end is provided and is bigger than start, old text is replaced.\n * start/end ar per grapheme position in _text array.\n *\n * @param {String} text text to insert\n * @param {Array} style array of style objects\n * @param {Number} start\n * @param {Number} end default to start + 1\n */\n insertChars(\n text: string,\n style: TextStyleDeclaration[] | undefined,\n start: number,\n end: number = start,\n ) {\n if (end > start) {\n this.removeStyleFromTo(start, end);\n }\n const graphemes = this.graphemeSplit(text);\n this.insertNewStyleBlock(graphemes, start, style);\n this._text = [\n ...this._text.slice(0, start),\n ...graphemes,\n ...this._text.slice(end),\n ];\n this.text = this._text.join('');\n this.set('dirty', true);\n this.initDimensions();\n this.setCoords();\n this._removeExtraneousStyles();\n }\n\n /**\n * Set the selectionStart and selectionEnd according to the new position of cursor\n * mimic the key - mouse navigation when shift is pressed.\n */\n setSelectionStartEndWithShift(\n start: number,\n end: number,\n newSelection: number,\n ) {\n if (newSelection <= start) {\n if (end === start) {\n this._selectionDirection = LEFT;\n } else if (this._selectionDirection === RIGHT) {\n this._selectionDirection = LEFT;\n this.selectionEnd = start;\n }\n this.selectionStart = newSelection;\n } else if (newSelection > start && newSelection < end) {\n if (this._selectionDirection === RIGHT) {\n this.selectionEnd = newSelection;\n } else {\n this.selectionStart = newSelection;\n }\n } else {\n // newSelection is > selection start and end\n if (end === start) {\n this._selectionDirection = RIGHT;\n } else if (this._selectionDirection === LEFT) {\n this._selectionDirection = RIGHT;\n this.selectionStart = end;\n }\n this.selectionEnd = newSelection;\n }\n }\n}\n","import { config } from '../../config';\nimport { getFabricDocument, getEnv } from '../../env';\nimport { capValue } from '../../util/misc/capValue';\nimport type { ITextEvents } from './ITextBehavior';\nimport { ITextBehavior } from './ITextBehavior';\nimport type { TKeyMapIText } from './constants';\nimport type { TOptions } from '../../typedefs';\nimport type { TextProps, SerializedTextProps } from '../Text/Text';\nimport { getDocumentFromElement } from '../../util/dom_misc';\nimport { CHANGED, LEFT, RIGHT } from '../../constants';\nimport type { IText } from './IText';\nimport type { TextStyleDeclaration } from '../Text/StyledText';\n\nexport abstract class ITextKeyBehavior<\n Props extends TOptions<TextProps> = Partial<TextProps>,\n SProps extends SerializedTextProps = SerializedTextProps,\n EventSpec extends ITextEvents = ITextEvents,\n> extends ITextBehavior<Props, SProps, EventSpec> {\n /**\n * For functionalities on keyDown\n * Map a special key to a function of the instance/prototype\n * If you need different behavior for ESC or TAB or arrows, you have to change\n * this map setting the name of a function that you build on the 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 = Object.assign({}, this.keysMap);\n * The function must be in IText.prototype.myFunction And will receive event as args[0]\n */\n declare keysMap: TKeyMapIText;\n\n declare keysMapRtl: TKeyMapIText;\n\n /**\n * For functionalities on keyUp + ctrl || cmd\n */\n declare ctrlKeysMapUp: TKeyMapIText;\n\n /**\n * For functionalities on keyDown + ctrl || cmd\n */\n declare ctrlKeysMapDown: TKeyMapIText;\n\n declare hiddenTextarea: HTMLTextAreaElement | null;\n\n /**\n * DOM container to append the hiddenTextarea.\n * An alternative to attaching to the document.body.\n * Useful to reduce laggish redraw of the full document.body tree and\n * also with modals event capturing that won't let the textarea take focus.\n * @type HTMLElement\n */\n declare hiddenTextareaContainer?: HTMLElement | null;\n\n declare private _clickHandlerInitialized: boolean;\n declare private _copyDone: boolean;\n declare private fromPaste: boolean;\n\n /**\n * Initializes hidden textarea (needed to bring up keyboard in iOS)\n */\n initHiddenTextarea() {\n const doc =\n (this.canvas && getDocumentFromElement(this.canvas.getElement())) ||\n getFabricDocument();\n const textarea = doc.createElement('textarea');\n Object.entries({\n autocapitalize: 'off',\n autocorrect: 'off',\n autocomplete: 'off',\n spellcheck: 'false',\n 'data-fabric': 'textarea',\n wrap: 'off',\n name: 'fabricTextarea',\n }).map(([attribute, value]) => textarea.setAttribute(attribute, value));\n const { top, left, fontSize } = this._calcTextareaPosition();\n // line-height: 1px; was removed from the style to fix this:\n // https://bugs.chromium.org/p/chromium/issues/detail?id=870966\n textarea.style.cssText = `position: absolute; top: ${top}; left: ${left}; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px; padding-top: ${fontSize};`;\n\n (this.hiddenTextareaContainer || doc.body).appendChild(textarea);\n\n Object.entries({\n blur: 'blur',\n keydown: 'onKeyDown',\n keyup: 'onKeyUp',\n input: 'onInput',\n copy: 'copy',\n cut: 'copy',\n paste: 'paste',\n compositionstart: 'onCompositionStart',\n compositionupdate: 'onCompositionUpdate',\n compositionend: 'onCompositionEnd',\n } as Record<string, keyof this>).map(([eventName, handler]) =>\n textarea.addEventListener(\n eventName,\n (this[handler] as EventListener).bind(this),\n ),\n );\n this.hiddenTextarea = textarea;\n }\n\n /**\n * Override this method to customize cursor behavior on textbox blur\n */\n blur() {\n this.abortCursorAnimation();\n }\n\n /**\n * Handles keydown event\n * only used for arrows and combination of modifier keys.\n * @param {KeyboardEvent} e Event object\n */\n onKeyDown(e: KeyboardEvent) {\n if (!this.isEditing) {\n return;\n }\n const keyMap = this.direction === 'rtl' ? this.keysMapRtl : this.keysMap;\n if (e.keyCode in keyMap) {\n (this[keyMap[e.keyCode] as keyof this] as (arg: KeyboardEvent) => void)(\n e,\n );\n } else if (e.keyCode in this.ctrlKeysMapDown && (e.ctrlKey || e.metaKey)) {\n (\n this[this.ctrlKeysMapDown[e.keyCode] as keyof this] as (\n arg: KeyboardEvent,\n ) => void\n )(e);\n } else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n if (e.keyCode >= 33 && e.keyCode <= 40) {\n // if i press an arrow key just update selection\n this.inCompositionMode = false;\n this.clearContextTop();\n this.renderCursorOrSelection();\n } else {\n this.canvas && this.canvas.requestRenderAll();\n }\n }\n\n /**\n * Handles keyup event\n * We handle KeyUp because ie11 and edge have difficulties copy/pasting\n * if a copy/cut event fired, keyup is dismissed\n * @param {KeyboardEvent} e Event object\n */\n onKeyUp(e: KeyboardEvent) {\n if (!this.isEditing || this._copyDone || this.inCompositionMode) {\n this._copyDone = false;\n return;\n }\n if (e.keyCode in this.ctrlKeysMapUp && (e.ctrlKey || e.metaKey)) {\n (\n this[this.ctrlKeysMapUp[e.keyCode] as keyof this] as (\n arg: KeyboardEvent,\n ) => void\n )(e);\n } else {\n return;\n }\n e.stopImmediatePropagation();\n e.preventDefault();\n this.canvas && this.canvas.requestRenderAll();\n }\n\n /**\n * Handles onInput event\n * @param {Event} e Event object\n */\n onInput(this: this & { hiddenTextarea: HTMLTextAreaElement }, e: Event) {\n const fromPaste = this.fromPaste;\n const { value, selectionStart, selectionEnd } = this.hiddenTextarea;\n this.fromPaste = false;\n e && e.stopPropagation();\n if (!this.isEditing) {\n return;\n }\n const updateAndFire = () => {\n this.updateFromTextArea();\n this.fire(CHANGED);\n if (this.canvas) {\n this.canvas.fire('text:changed', { target: this as unknown as IText });\n this.canvas.requestRenderAll();\n }\n };\n if (this.hiddenTextarea.value === '') {\n this.styles = {};\n updateAndFire();\n return;\n }\n // decisions about style changes.\n const nextText = this._splitTextIntoLines(value).graphemeText,\n charCount = this._text.length,\n nextCharCount = nextText.length,\n _selectionStart = this.selectionStart,\n _selectionEnd = this.selectionEnd,\n selection = _selectionStart !== _selectionEnd;\n let copiedStyle: TextStyleDeclaration[] | undefined,\n removedText,\n charDiff = nextCharCount - charCount,\n removeFrom,\n removeTo;\n\n const textareaSelection = this.fromStringToGraphemeSelection(\n selectionStart,\n selectionEnd,\n value,\n );\n const backDelete = _selectionStart > textareaSelection.selectionStart;\n\n if (selection) {\n removedText = this._text.slice(_selectionStart, _selectionEnd);\n charDiff += _selectionEnd - _selectionStart;\n } else if (nextCharCount < charCount) {\n if (backDelete) {\n removedText = this._text.slice(_selectionEnd + charDiff, _selectionEnd);\n } else {\n removedText = this._text.slice(\n _selectionStart,\n _selectionStart - charDiff,\n );\n }\n }\n const insertedText = nextText.slice(\n textareaSelection.selectionEnd - charDiff,\n textareaSelection.selectionEnd,\n );\n if (removedText && removedText.length) {\n if (insertedText.length) {\n // let's copy some style before deleting.\n // we want to copy the style before the cursor OR the style at the cursor if selection\n // is bigger than 0.\n copiedStyle = this.getSelectionStyles(\n _selectionStart,\n _selectionStart + 1,\n false,\n );\n // now duplicate the style one for each inserted text.\n copiedStyle = insertedText.map(\n () =>\n // this return an array of references, but that is fine since we are\n // copying the style later.\n copiedStyle![0],\n );\n }\n if (selection) {\n removeFrom = _selectionStart;\n removeTo = _selectionEnd;\n } else if (backDelete) {\n // detect differences between forwardDelete and backDelete\n removeFrom = _selectionEnd - removedText.length;\n removeTo = _selectionEnd;\n } else {\n removeFrom = _selectionEnd;\n removeTo = _selectionEnd + removedText.length;\n }\n this.removeStyleFromTo(removeFrom, removeTo);\n }\n if (insertedText.length) {\n const { copyPasteData } = getEnv();\n if (\n fromPaste &&\n insertedText.join('') === copyPasteData.copiedText &&\n !config.disableStyleCopyPaste\n ) {\n copiedStyle = copyPasteData.copiedTextStyle;\n }\n this.insertNewStyleBlock(insertedText, _selectionStart, copiedStyle);\n }\n updateAndFire();\n }\n\n /**\n * Composition start\n */\n onCompositionStart() {\n this.inCompositionMode = true;\n }\n\n /**\n * Composition end\n */\n onCompositionEnd() {\n this.inCompositionMode = false;\n }\n\n onCompositionUpdate({ target }: CompositionEvent) {\n const { selectionStart, selectionEnd } = target as HTMLTextAreaElement;\n this.compositionStart = selectionStart;\n this.compositionEnd = selectionEnd;\n this.updateTextareaPosition();\n }\n\n /**\n * Copies selected text\n */\n copy() {\n if (this.selectionStart === this.selectionEnd) {\n //do not cut-copy if no selection\n return;\n }\n const { copyPasteData } = getEnv();\n copyPasteData.copiedText = this.getSelectedText();\n if (!config.disableStyleCopyPaste) {\n copyPasteData.copiedTextStyle = this.getSelectionStyles(\n this.selectionStart,\n this.selectionEnd,\n true,\n );\n } else {\n copyPasteData.copiedTextStyle = undefined;\n }\n this._copyDone = true;\n }\n\n /**\n * Pastes text\n */\n paste() {\n this.fromPaste = true;\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(lineIndex: number, charIndex: number): number {\n let widthBeforeCursor = this._getLineLeftOffset(lineIndex),\n bound;\n\n if (charIndex > 0) {\n bound = this.__charBounds[lineIndex][charIndex - 1];\n widthBeforeCursor += bound.left + bound.width;\n }\n return widthBeforeCursor;\n }\n\n /**\n * Gets start offset of a selection\n * @param {KeyboardEvent} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getDownCursorOffset(e: KeyboardEvent, isRight: boolean): number {\n const 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 (\n lineIndex === this._textLines.length - 1 ||\n e.metaKey ||\n e.keyCode === 34\n ) {\n // move to the end of a text\n return this._text.length - selectionProp;\n }\n const charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex + 1, widthBeforeCursor),\n textAfterCursor = this._textLines[lineIndex].slice(charIndex);\n return (\n textAfterCursor.length +\n indexOnOtherLine +\n 1 +\n this.missingNewlineOffset(lineIndex)\n );\n }\n\n /**\n * private\n * Helps finding if the offset should be counted from Start or End\n * @param {KeyboardEvent} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n _getSelectionForOffset(e: KeyboardEvent, isRight: boolean): number {\n if (e.shiftKey && this.selectionStart !== this.selectionEnd && isRight) {\n return this.selectionEnd;\n } else {\n return this.selectionStart;\n }\n }\n\n /**\n * @param {KeyboardEvent} e Event object\n * @param {Boolean} isRight\n * @return {Number}\n */\n getUpCursorOffset(e: KeyboardEvent, isRight: boolean): number {\n const 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 const charIndex = cursorLocation.charIndex,\n widthBeforeCursor = this._getWidthBeforeCursor(lineIndex, charIndex),\n indexOnOtherLine = this._getIndexOnLine(lineIndex - 1, widthBeforeCursor),\n textBeforeCursor = this._textLines[lineIndex].slice(0, charIndex),\n missingNewlineOffset = this.missingNewlineOffset(lineIndex - 1);\n // return a negative offset\n return (\n -this._textLines[lineIndex - 1].length +\n indexOnOtherLine -\n textBeforeCursor.length +\n (1 - missingNewlineOffset)\n );\n }\n\n /**\n * for a given width it founds the matching character.\n * @private\n */\n _getIndexOnLine(lineIndex: number, width: number) {\n const line = this._textLines[lineIndex],\n lineLeftOffset = this._getLineLeftOffset(lineIndex);\n let widthOfCharsOnLine = lineLeftOffset,\n indexOnLine = 0,\n charWidth,\n foundMatch;\n\n for (let j = 0, jlen = line.length; j < jlen; j++) {\n charWidth = this.__charBounds[lineIndex][j].width;\n widthOfCharsOnLine += charWidth;\n if (widthOfCharsOnLine > width) {\n foundMatch = true;\n const leftEdge = widthOfCharsOnLine - charWidth,\n rightEdge = widthOfCharsOnLine,\n offsetFromLeftEdge = Math.abs(leftEdge - width),\n offsetFromRightEdge = Math.abs(rightEdge - width);\n\n indexOnLine = offsetFromRightEdge < offsetFromLeftEdge ? j : j - 1;\n break;\n }\n }\n\n // reached end\n if (!foundMatch) {\n indexOnLine = line.length - 1;\n }\n\n return indexOnLine;\n }\n\n /**\n * Moves cursor down\n * @param {KeyboardEvent} e Event object\n */\n moveCursorDown(e: KeyboardEvent) {\n if (\n this.selectionStart >= this._text.length &&\n this.selectionEnd >= this._text.length\n ) {\n return;\n }\n this._moveCursorUpOrDown('Down', e);\n }\n\n /**\n * Moves cursor up\n * @param {KeyboardEvent} e Event object\n */\n moveCursorUp(e: KeyboardEvent) {\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 {KeyboardEvent} e Event object\n */\n _moveCursorUpOrDown(direction: 'Up' | 'Down', e: KeyboardEvent) {\n const offset = this[`get${direction}CursorOffset`](\n e,\n this._selectionDirection === RIGHT,\n );\n if (e.shiftKey) {\n this.moveCursorWithShift(offset);\n } else {\n this.moveCursorWithoutShift(offset);\n }\n if (offset !== 0) {\n const max = this.text.length;\n this.selectionStart = capValue(0, this.selectionStart, max);\n this.selectionEnd = capValue(0, this.selectionEnd, max);\n // TODO fix: abort and init should be an alternative depending\n // on selectionStart/End being equal or different\n this.abortCursorAnimation();\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(offset: number) {\n const newSelection =\n this._selectionDirection === LEFT\n ? this.selectionStart + offset\n : this.selectionEnd + offset;\n this.setSelectionStartEndWithShift(\n this.selectionStart,\n this.selectionEnd,\n newSelection,\n );\n return offset !== 0;\n }\n\n /**\n * Moves cursor up without shift\n * @param {Number} offset\n */\n moveCursorWithoutShift(offset: number) {\n if (offset < 0) {\n this.selectionStart += offset;\n this.selectionEnd = this.selectionStart;\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 {KeyboardEvent} e Event object\n */\n moveCursorLeft(e: KeyboardEvent) {\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 * @todo refactor not to use method name composition\n */\n _move(\n e: KeyboardEvent,\n prop: 'selectionStart' | 'selectionEnd',\n direction: 'Left' | 'Right',\n ): boolean {\n let newValue: number | undefined;\n if (e.altKey) {\n newValue = this[`findWordBoundary${direction}`](this[prop]);\n } else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36) {\n newValue = this[`findLineBoundary${direction}`](this[prop]);\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 return false;\n }\n\n /**\n * @private\n */\n _moveLeft(e: KeyboardEvent, prop: 'selectionStart' | 'selectionEnd') {\n return this._move(e, prop, 'Left');\n }\n\n /**\n * @private\n */\n _moveRight(e: KeyboardEvent, prop: 'selectionStart' | 'selectionEnd') {\n return this._move(e, prop, 'Right');\n }\n\n /**\n * Moves cursor left without keeping selection\n * @param {KeyboardEvent} e\n */\n moveCursorLeftWithoutShift(e: KeyboardEvent) {\n let 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 (\n this.selectionEnd === this.selectionStart &&\n this.selectionStart !== 0\n ) {\n change = this._moveLeft(e, 'selectionStart');\n }\n this.selectionEnd = this.selectionStart;\n return change;\n }\n\n /**\n * Moves cursor left while keeping selection\n * @param {KeyboardEvent} e\n */\n moveCursorLeftWithShift(e: KeyboardEvent) {\n if (\n this._selectionDirection === RIGHT &&\n this.selectionStart !== this.selectionEnd\n ) {\n return this._moveLeft(e, 'selectionEnd');\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 {KeyboardEvent} e Event object\n */\n moveCursorRight(e: KeyboardEvent) {\n if (\n this.selectionStart >= this._text.length &&\n this.selectionEnd >= this._text.length\n ) {\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 {KeyboardEvent} e Event object\n */\n _moveCursorLeftOrRight(direction: 'Left' | 'Right', e: KeyboardEvent) {\n const actionName = `moveCursor${direction}${\n e.shiftKey ? 'WithShift' : 'WithoutShift'\n }` as const;\n this._currentCursorOpacity = 1;\n if (this[actionName](e)) {\n // TODO fix: abort and init should be an alternative depending\n // on selectionStart/End being equal or different\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 {KeyboardEvent} e\n */\n moveCursorRightWithShift(e: KeyboardEvent) {\n if (\n this._selectionDirection === LEFT &&\n this.selectionStart !== this.selectionEnd\n ) {\n return this._moveRight(e, 'selectionStart');\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 {KeyboardEvent} e Event object\n */\n moveCursorRightWithoutShift(e: KeyboardEvent) {\n let 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 } else {\n this.selectionStart = this.selectionEnd;\n }\n return changed;\n }\n}\n","import type {\n ObjectPointerEvents,\n TPointerEvent,\n TPointerEventInfo,\n} from '../../EventTypeDefs';\nimport { Point } from '../../Point';\nimport { invertTransform } from '../../util/misc/matrix';\nimport { DraggableTextDelegate } from './DraggableTextDelegate';\nimport type { ITextEvents } from './ITextBehavior';\nimport { ITextKeyBehavior } from './ITextKeyBehavior';\nimport type { TOptions } from '../../typedefs';\nimport type { TextProps, SerializedTextProps } from '../Text/Text';\nimport type { IText } from './IText';\n/**\n * `LEFT_CLICK === 0`\n */\nconst notALeftClick = (e: Event) => !!(e as MouseEvent).button;\n\nexport abstract class ITextClickBehavior<\n Props extends TOptions<TextProps> = Partial<TextProps>,\n SProps extends SerializedTextProps = SerializedTextProps,\n EventSpec extends ITextEvents = ITextEvents,\n> extends ITextKeyBehavior<Props, SProps, EventSpec> {\n protected draggableTextDelegate: DraggableTextDelegate;\n\n initBehavior() {\n // Initializes event handlers related to cursor or selection\n this.on('mousedown', this._mouseDownHandler);\n this.on('mouseup', this.mouseUpHandler);\n this.on('mousedblclick', this.doubleClickHandler);\n this.on('mousetripleclick', this.tripleClickHandler);\n\n this.draggableTextDelegate = new DraggableTextDelegate(\n this as unknown as IText,\n );\n\n super.initBehavior();\n }\n\n /**\n * If this method returns true a mouse move operation over a text selection\n * will not prevent the native mouse event allowing the browser to start a drag operation.\n * shouldStartDragging can be read 'do not prevent default for mouse move event'\n * To prevent drag and drop between objects both shouldStartDragging and onDragStart should return false\n * @returns\n */\n shouldStartDragging() {\n return this.draggableTextDelegate.isActive();\n }\n\n /**\n * @public override this method to control whether instance should/shouldn't become a drag source,\n * @see also {@link DraggableTextDelegate#isActive}\n * To prevent drag and drop between objects both shouldStartDragging and onDragStart should return false\n * @returns {boolean} should handle event\n */\n onDragStart(e: DragEvent) {\n return this.draggableTextDelegate.onDragStart(e);\n }\n\n /**\n * @public override this method to control whether instance should/shouldn't become a drop target\n */\n canDrop(e: DragEvent) {\n return this.draggableTextDelegate.canDrop(e);\n }\n\n /**\n * Default handler for double click, select a word\n */\n doubleClickHandler(options: TPointerEventInfo) {\n if (!this.isEditing) {\n return;\n }\n this.selectWord(this.getSelectionStartFromPointer(options.e));\n this.renderCursorOrSelection();\n }\n\n /**\n * Default handler for triple click, select a line\n */\n tripleClickHandler(options: TPointerEventInfo) {\n if (!this.isEditing) {\n return;\n }\n this.selectLine(this.getSelectionStartFromPointer(options.e));\n this.renderCursorOrSelection();\n }\n\n /**\n * Default event handler for the basic functionalities needed on _mouseDown\n * can be overridden to do something different.\n * Scope of this implementation is: find the click position, set selectionStart\n * find selectionEnd, initialize the drawing of either cursor or selection area\n * initializing a mousedDown on a text area will cancel fabricjs knowledge of\n * current compositionMode. It will be set to false.\n */\n _mouseDownHandler({ e, alreadySelected }: ObjectPointerEvents['mousedown']) {\n if (\n !this.canvas ||\n !this.editable ||\n notALeftClick(e) ||\n this.getActiveControl()\n ) {\n return;\n }\n\n if (this.draggableTextDelegate.start(e)) {\n return;\n }\n\n this.canvas.textEditingManager.register(this);\n\n if (alreadySelected) {\n this.inCompositionMode = false;\n this.setCursorByClick(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 this.selected ||= alreadySelected || this.isEditing;\n }\n\n /**\n * standard handler for mouse up, overridable\n * @private\n */\n mouseUpHandler({ e, transform }: ObjectPointerEvents['mouseup']) {\n const didDrag = this.draggableTextDelegate.end(e);\n\n if (this.canvas) {\n this.canvas.textEditingManager.unregister(this);\n\n const activeObject = this.canvas._activeObject;\n if (activeObject && activeObject !== this) {\n // avoid running this logic when there is an active object\n // this because is possible with shift click and fast clicks,\n // to rapidly deselect and reselect this object and trigger an enterEdit\n return;\n }\n }\n\n if (\n !this.editable ||\n (this.group && !this.group.interactive) ||\n (transform && transform.actionPerformed) ||\n notALeftClick(e) ||\n didDrag\n ) {\n return;\n }\n\n if (this.selected && !this.getActiveControl()) {\n this.enterEditing(e);\n if (this.selectionStart === this.selectionEnd) {\n this.initDelayedCursor(true);\n } else {\n this.renderCursorOrSelection();\n }\n }\n }\n\n /**\n * Changes cursor location in a text depending on passed pointer (x/y) object\n * @param {TPointerEvent} e Event object\n */\n setCursorByClick(e: TPointerEvent) {\n const newSelection = this.getSelectionStartFromPointer(e),\n start = this.selectionStart,\n end = this.selectionEnd;\n if (e.shiftKey) {\n this.setSelectionStartEndWithShift(start, end, newSelection);\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 {TPointerEvent} e Event object\n * @return {Number} Index of a character\n */\n getSelectionStartFromPointer(e: TPointerEvent): number {\n const mouseOffset = this.canvas!.getScenePoint(e)\n .transform(invertTransform(this.calcTransformMatrix()))\n .add(new Point(-this._getLeftOffset(), -this._getTopOffset()));\n let height = 0,\n charIndex = 0,\n lineIndex = 0;\n\n for (let i = 0; i < this._textLines.length; i++) {\n if (height <= mouseOffset.y) {\n height += this.getHeightOfLine(i);\n lineIndex = i;\n if (i > 0) {\n charIndex +=\n this._textLines[i - 1].length + this.missingNewlineOffset(i - 1);\n }\n } else {\n break;\n }\n }\n const lineLeftOffset = Math.abs(this._getLineLeftOffset(lineIndex));\n let width = lineLeftOffset;\n const charLength = this._textLines[lineIndex].length;\n const chars = this.__charBounds[lineIndex];\n for (let j = 0; j < charLength; j++) {\n // i removed something about flipX here, check.\n const charWidth = chars[j].kernedWidth;\n const widthAfter = width + charWidth;\n if (mouseOffset.x <= widthAfter) {\n // if the pointer is closer to the end of the char we increment charIndex\n // in order to position the cursor after the char\n if (\n Math.abs(mouseOffset.x - widthAfter) <=\n Math.abs(mouseOffset.x - width)\n ) {\n charIndex++;\n }\n break;\n }\n width = widthAfter;\n charIndex++;\n }\n\n return Math.min(\n // if object is horizontally flipped, mirror cursor location from the end\n this.flipX ? charLength - charIndex : charIndex,\n this._text.length,\n );\n }\n}\n","export type TKeyMapIText = Record<\n KeyboardEvent['keyCode'],\n CursorHandlingMethods\n>;\n\nexport type CursorHandlingMethods =\n | 'moveCursorUp'\n | 'moveCursorDown'\n | 'moveCursorLeft'\n | 'moveCursorRight'\n | 'exitEditing'\n | 'copy'\n | 'cut'\n | 'cmdAll';\n\nconst MOVE_CURSOR_UP: CursorHandlingMethods = 'moveCursorUp';\nconst MOVE_CURSOR_DOWN: CursorHandlingMethods = 'moveCursorDown';\nconst MOVE_CURSOR_LEFT: CursorHandlingMethods = 'moveCursorLeft';\nconst MOVE_CURSOR_RIGHT: CursorHandlingMethods = 'moveCursorRight';\nconst EXIT_EDITING: CursorHandlingMethods = 'exitEditing';\n\n// @TODO look into import { Key } from 'ts-key-enum';\n// and transition from keyCode to Key\n// also reduce string duplication\nexport const keysMap: TKeyMapIText = {\n 9: EXIT_EDITING,\n 27: EXIT_EDITING,\n 33: MOVE_CURSOR_UP,\n 34: MOVE_CURSOR_DOWN,\n 35: MOVE_CURSOR_RIGHT,\n 36: MOVE_CURSOR_LEFT,\n 37: MOVE_CURSOR_LEFT,\n 38: MOVE_CURSOR_UP,\n 39: MOVE_CURSOR_RIGHT,\n 40: MOVE_CURSOR_DOWN,\n};\n\nexport const keysMapRtl: TKeyMapIText = {\n 9: EXIT_EDITING,\n 27: EXIT_EDITING,\n 33: MOVE_CURSOR_UP,\n 34: MOVE_CURSOR_DOWN,\n 35: MOVE_CURSOR_LEFT,\n 36: MOVE_CURSOR_RIGHT,\n 37: MOVE_CURSOR_RIGHT,\n 38: MOVE_CURSOR_UP,\n 39: MOVE_CURSOR_LEFT,\n 40: MOVE_CURSOR_DOWN,\n};\n\n/**\n * For functionalities on keyUp + ctrl || cmd\n */\nexport const ctrlKeysMapUp: TKeyMapIText = {\n 67: 'copy',\n // there was a reason this wasn't deleted. for now leave it here\n 88: 'cut',\n};\n\n/**\n * For functionalities on keyDown + ctrl || cmd\n */\nexport const ctrlKeysMapDown: TKeyMapIText = {\n 65: 'cmdAll',\n};\n","import type { StaticCanvas } from '../../canvas/StaticCanvas';\n\n/**\n * Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.\n * setTransform is used since this utility will RESET the ctx transform to the basic value\n * of retina scaling and viewport transform\n * It is not meant to be added to other transforms, it is used internally to preapre canvases to draw\n * @param ctx\n * @param canvas\n */\nexport const applyCanvasTransform = (\n ctx: CanvasRenderingContext2D,\n canvas: StaticCanvas,\n) => {\n const scale = canvas.getRetinaScaling();\n ctx.setTransform(scale, 0, 0, scale, 0, 0);\n const v = canvas.viewportTransform;\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n};\n","import { Canvas } from '../../canvas/Canvas';\nimport type { ITextEvents } from './ITextBehavior';\nimport { ITextClickBehavior } from './ITextClickBehavior';\nimport {\n ctrlKeysMapDown,\n ctrlKeysMapUp,\n keysMap,\n keysMapRtl,\n} from './constants';\nimport type { TClassProperties, TFiller, TOptions } from '../../typedefs';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { SerializedTextProps, TextProps } from '../Text/Text';\nimport {\n JUSTIFY,\n JUSTIFY_CENTER,\n JUSTIFY_LEFT,\n JUSTIFY_RIGHT,\n} from '../Text/constants';\nimport { CENTER, FILL, LEFT, RIGHT, RTL } from '../../constants';\nimport type { ObjectToCanvasElementOptions } from '../Object/Object';\nimport type { FabricObject } from '../Object/FabricObject';\nimport { createCanvasElementFor } from '../../util/misc/dom';\nimport { applyCanvasTransform } from '../../util/internals/applyCanvasTransform';\n\nexport type CursorBoundaries = {\n left: number;\n top: number;\n leftOffset: number;\n topOffset: number;\n};\n\nexport type CursorRenderingData = {\n color: string;\n opacity: number;\n left: number;\n top: number;\n width: number;\n height: number;\n};\n\n// Declare IText protected properties to workaround TS\nconst protectedDefaultValues = {\n _selectionDirection: null,\n _reSpace: /\\s|\\r?\\n/,\n inCompositionMode: false,\n};\n\nexport const iTextDefaultValues: Partial<TClassProperties<IText>> = {\n selectionStart: 0,\n selectionEnd: 0,\n selectionColor: 'rgba(17,119,255,0.3)',\n isEditing: false,\n editable: true,\n editingBorderColor: 'rgba(102,153,255,0.25)',\n cursorWidth: 2,\n cursorColor: '',\n cursorDelay: 1000,\n cursorDuration: 600,\n caching: true,\n hiddenTextareaContainer: null,\n keysMap,\n keysMapRtl,\n ctrlKeysMapDown,\n ctrlKeysMapUp,\n ...protectedDefaultValues,\n};\n\n// @TODO this is not complete\ninterface UniqueITextProps {\n selectionStart: number;\n selectionEnd: number;\n}\n\nexport interface SerializedITextProps\n extends SerializedTextProps,\n UniqueITextProps {}\n\nexport interface ITextProps extends TextProps, UniqueITextProps {}\n\n/**\n * @fires changed\n * @fires selection:changed\n * @fires editing:entered\n * @fires editing:exited\n * @fires dragstart\n * @fires drag drag event firing on the drag source\n * @fires dragend\n * @fires copy\n * @fires cut\n * @fires paste\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 */\nexport class IText<\n Props extends TOptions<ITextProps> = Partial<ITextProps>,\n SProps extends SerializedITextProps = SerializedITextProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends ITextClickBehavior<Props, SProps, EventSpec>\n implements UniqueITextProps\n{\n /**\n * Index where text selection starts (or where cursor is when there is no selection)\n * @type Number\n */\n declare selectionStart: number;\n\n /**\n * Index where text selection ends\n * @type Number\n */\n declare selectionEnd: number;\n\n declare compositionStart: number;\n\n declare compositionEnd: number;\n\n /**\n * Color of text selection\n * @type String\n */\n declare selectionColor: string;\n\n /**\n * Indicates whether text is in editing mode\n * @type Boolean\n */\n declare isEditing: boolean;\n\n /**\n * Indicates whether a text can be edited\n * @type Boolean\n */\n declare editable: boolean;\n\n /**\n * Border color of text object while it's in editing mode\n * @type String\n */\n declare editingBorderColor: string;\n\n /**\n * Width of cursor (in px)\n * @type Number\n */\n declare cursorWidth: number;\n\n /**\n * Color of text cursor color in editing mode.\n * if not set (default) will take color from the text.\n * if set to a color value that fabric can understand, it will\n * be used instead of the color of the text at the current position.\n * @type String\n */\n declare cursorColor: string;\n\n /**\n * Delay between cursor blink (in ms)\n * @type Number\n */\n declare cursorDelay: number;\n\n /**\n * Duration of cursor fade in (in ms)\n * @type Number\n */\n declare cursorDuration: number;\n\n declare compositionColor: string;\n\n /**\n * Indicates whether internal text char widths can be cached\n * @type Boolean\n */\n declare caching: boolean;\n\n static ownDefaults = iTextDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return { ...super.getDefaults(), ...IText.ownDefaults };\n }\n\n static type = 'IText';\n\n get type() {\n const type = super.type;\n // backward compatibility\n return type === 'itext' ? 'i-text' : type;\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...IText.ownDefaults, ...options } as Props);\n this.initBehavior();\n }\n\n /**\n * While editing handle differently\n * @private\n * @param {string} key\n * @param {*} value\n */\n _set(key: string, value: any) {\n if (this.isEditing && this._savedProps && key in this._savedProps) {\n // @ts-expect-error irritating TS\n this._savedProps[key] = value;\n return this;\n }\n if (key === 'canvas') {\n this.canvas instanceof Canvas &&\n this.canvas.textEditingManager.remove(this);\n value instanceof Canvas && value.textEditingManager.add(this);\n }\n return super._set(key, value);\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(index: number) {\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(index: number) {\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 protected _updateAndFire(\n property: 'selectionStart' | 'selectionEnd',\n index: number,\n ) {\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() {\n this.fire('selection:changed');\n this.canvas && this.canvas.fire('text:selection:changed', { target: this });\n }\n\n /**\n * Initialize text dimensions. Render all text on given context\n * or on a offscreen canvas to get the text width with measureText.\n * Updates this.width and this.height with the proper values.\n * Does not return dimensions.\n * @private\n */\n initDimensions() {\n this.isEditing && this.initDelayedCursor();\n super.initDimensions();\n }\n\n /**\n * Gets style of a current selection/cursor (at the start position)\n * if startIndex or endIndex are not provided, selectionStart or selectionEnd will be used.\n * @param {Number} startIndex Start index to get styles at\n * @param {Number} endIndex End index to get styles at, if not specified selectionEnd or startIndex + 1\n * @param {Boolean} [complete] get full style or not\n * @return {Array} styles an array with one, zero or more Style objects\n */\n getSelectionStyles(\n startIndex: number = this.selectionStart || 0,\n endIndex: number = this.selectionEnd,\n complete?: boolean,\n ) {\n return super.getSelectionStyles(startIndex, endIndex, complete);\n }\n\n /**\n * Sets style of a current selection, if no selection exist, do not set anything.\n * @param {Object} [styles] Styles object\n * @param {Number} [startIndex] Start index to get styles at\n * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1\n */\n setSelectionStyles(\n styles: object,\n startIndex: number = this.selectionStart || 0,\n endIndex: number = this.selectionEnd,\n ) {\n return super.setSelectionStyles(styles, startIndex, endIndex);\n }\n\n /**\n * Returns 2d representation (lineIndex and charIndex) of cursor (or selection start)\n * @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used.\n * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.\n */\n get2DCursorLocation(\n selectionStart = this.selectionStart,\n skipWrapping?: boolean,\n ) {\n return super.get2DCursorLocation(selectionStart, skipWrapping);\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n render(ctx: CanvasRenderingContext2D) {\n super.render(ctx);\n // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor\n // the correct position but not at every cursor animation.\n this.cursorOffsetCache = {};\n this.renderCursorOrSelection();\n }\n\n /**\n * @override block cursor/selection logic while rendering the exported canvas\n * @todo this workaround should be replaced with a more robust solution\n */\n toCanvasElement(options?: ObjectToCanvasElementOptions): HTMLCanvasElement {\n const isEditing = this.isEditing;\n this.isEditing = false;\n const canvas = super.toCanvasElement(options);\n this.isEditing = isEditing;\n return canvas;\n }\n\n /**\n * Renders cursor or selection (depending on what exists)\n * it does on the contextTop. If contextTop is not available, do nothing.\n */\n renderCursorOrSelection() {\n if (!this.isEditing || !this.canvas) {\n return;\n }\n const ctx = this.clearContextTop(true);\n if (!ctx) {\n return;\n }\n const boundaries = this._getCursorBoundaries();\n\n const ancestors = this.findAncestorsWithClipPath();\n const hasAncestorsWithClipping = ancestors.length > 0;\n let drawingCtx: CanvasRenderingContext2D = ctx;\n let drawingCanvas: HTMLCanvasElement | undefined = undefined;\n if (hasAncestorsWithClipping) {\n // we have some clipPath, we need to draw the selection on an intermediate layer.\n drawingCanvas = createCanvasElementFor(ctx.canvas);\n drawingCtx = drawingCanvas.getContext('2d')!;\n applyCanvasTransform(drawingCtx, this.canvas);\n const m = this.calcTransformMatrix();\n drawingCtx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n }\n\n if (this.selectionStart === this.selectionEnd && !this.inCompositionMode) {\n this.renderCursor(drawingCtx, boundaries);\n } else {\n this.renderSelection(drawingCtx, boundaries);\n }\n\n if (hasAncestorsWithClipping) {\n // we need a neutral context.\n // this won't work for nested clippaths in which a clippath\n // has its own clippath\n for (const ancestor of ancestors) {\n const clipPath = ancestor.clipPath!;\n const clippingCanvas = createCanvasElementFor(ctx.canvas);\n const clippingCtx = clippingCanvas.getContext('2d')!;\n applyCanvasTransform(clippingCtx, this.canvas);\n // position the ctx in the center of the outer ancestor\n if (!clipPath.absolutePositioned) {\n const m = ancestor.calcTransformMatrix();\n clippingCtx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);\n }\n clipPath.transform(clippingCtx);\n // we assign an empty drawing context, we don't plan to have this working for nested clippaths for now\n clipPath.drawObject(clippingCtx, true, {});\n this.drawClipPathOnCache(drawingCtx, clipPath, clippingCanvas);\n }\n }\n\n if (hasAncestorsWithClipping) {\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(drawingCanvas!, 0, 0);\n }\n\n this.canvas.contextTopDirty = true;\n ctx.restore();\n }\n\n /**\n * Finds and returns an array of clip paths that are applied to the parent\n * group(s) of the current FabricObject instance. The object's hierarchy is\n * traversed upwards (from the current object towards the root of the canvas),\n * checking each parent object for the presence of a `clipPath` that is not\n * absolutely positioned.\n */\n findAncestorsWithClipPath(): FabricObject[] {\n const clipPathAncestors: FabricObject[] = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let obj: FabricObject | undefined = this;\n while (obj) {\n if (obj.clipPath) {\n clipPathAncestors.push(obj);\n }\n obj = obj.parent;\n }\n\n return clipPathAncestors;\n }\n\n /**\n * Returns cursor boundaries (left, top, leftOffset, topOffset)\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 * @private\n * @param {number} [index] index from start\n * @param {boolean} [skipCaching]\n */\n _getCursorBoundaries(\n index: number = this.selectionStart,\n skipCaching?: boolean,\n ): CursorBoundaries {\n const left = this._getLeftOffset(),\n top = this._getTopOffset(),\n offsets = this._getCursorBoundariesOffsets(index, skipCaching);\n return {\n left: left,\n top: top,\n leftOffset: offsets.left,\n topOffset: offsets.top,\n };\n }\n\n /**\n * Caches and returns cursor left/top offset relative to instance's center point\n * @private\n * @param {number} index index from start\n * @param {boolean} [skipCaching]\n */\n _getCursorBoundariesOffsets(\n index: number,\n skipCaching?: boolean,\n ): { left: number; top: number } {\n if (skipCaching) {\n return this.__getCursorBoundariesOffsets(index);\n }\n if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {\n return this.cursorOffsetCache as { left: number; top: number };\n }\n return (this.cursorOffsetCache = this.__getCursorBoundariesOffsets(index));\n }\n\n /**\n * Calculates cursor left/top offset relative to instance's center point\n * @private\n * @param {number} index index from start\n */\n __getCursorBoundariesOffsets(index: number) {\n let topOffset = 0,\n leftOffset = 0;\n const { charIndex, lineIndex } = this.get2DCursorLocation(index);\n const { textAlign, direction } = this;\n for (let i = 0; i < lineIndex; i++) {\n topOffset += this.getHeightOfLine(i);\n }\n const lineLeftOffset = this._getLineLeftOffset(lineIndex);\n const bound = this.__charBounds[lineIndex][charIndex];\n bound && (leftOffset = bound.left);\n if (\n this.charSpacing !== 0 &&\n charIndex === this._textLines[lineIndex].length\n ) {\n leftOffset -= this._getWidthOfCharSpacing();\n }\n let left = lineLeftOffset + (leftOffset > 0 ? leftOffset : 0);\n\n if (direction === RTL) {\n if (\n textAlign === RIGHT ||\n textAlign === JUSTIFY ||\n textAlign === JUSTIFY_RIGHT\n ) {\n left *= -1;\n } else if (textAlign === LEFT || textAlign === JUSTIFY_LEFT) {\n left = lineLeftOffset - (leftOffset > 0 ? leftOffset : 0);\n } else if (textAlign === CENTER || textAlign === JUSTIFY_CENTER) {\n left = lineLeftOffset - (leftOffset > 0 ? leftOffset : 0);\n }\n }\n return {\n top: topOffset,\n left,\n };\n }\n\n /**\n * Renders cursor on context Top, outside the animation cycle, on request\n * Used for the drag/drop effect.\n * If contextTop is not available, do nothing.\n */\n renderCursorAt(selectionStart: number) {\n this._renderCursor(\n this.canvas!.contextTop,\n this._getCursorBoundaries(selectionStart, true),\n selectionStart,\n );\n }\n\n /**\n * Renders cursor\n * @param {Object} boundaries\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderCursor(ctx: CanvasRenderingContext2D, boundaries: CursorBoundaries) {\n this._renderCursor(ctx, boundaries, this.selectionStart);\n }\n\n /**\n * Return the data needed to render the cursor for given selection start\n * The left,top are relative to the object, while width and height are prescaled\n * to look think with canvas zoom and object scaling,\n * so they depend on canvas and object scaling\n */\n getCursorRenderingData(\n selectionStart: number = this.selectionStart,\n boundaries: CursorBoundaries = this._getCursorBoundaries(selectionStart),\n ): CursorRenderingData {\n const cursorLocation = this.get2DCursorLocation(selectionStart),\n lineIndex = cursorLocation.lineIndex,\n charIndex =\n cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,\n charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),\n multiplier = this.getObjectScaling().x * this.canvas!.getZoom(),\n cursorWidth = this.cursorWidth / multiplier,\n dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY'),\n topOffset =\n boundaries.topOffset +\n ((1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex)) /\n this.lineHeight -\n charHeight * (1 - this._fontSizeFraction);\n\n return {\n color:\n this.cursorColor ||\n (this.getValueOfPropertyAt(lineIndex, charIndex, 'fill') as string),\n opacity: this._currentCursorOpacity,\n left: boundaries.left + boundaries.leftOffset - cursorWidth / 2,\n top: topOffset + boundaries.top + dy,\n width: cursorWidth,\n height: charHeight,\n };\n }\n\n /**\n * Render the cursor at the given selectionStart.\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n _renderCursor(\n ctx: CanvasRenderingContext2D,\n boundaries: CursorBoundaries,\n selectionStart: number,\n ) {\n const { color, opacity, left, top, width, height } =\n this.getCursorRenderingData(selectionStart, boundaries);\n ctx.fillStyle = color;\n ctx.globalAlpha = opacity;\n ctx.fillRect(left, top, width, height);\n }\n\n /**\n * Renders text selection\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n renderSelection(ctx: CanvasRenderingContext2D, boundaries: CursorBoundaries) {\n const selection = {\n selectionStart: this.inCompositionMode\n ? this.hiddenTextarea!.selectionStart\n : this.selectionStart,\n selectionEnd: this.inCompositionMode\n ? this.hiddenTextarea!.selectionEnd\n : this.selectionEnd,\n };\n this._renderSelection(ctx, selection, boundaries);\n }\n\n /**\n * Renders drag start text selection\n */\n renderDragSourceEffect() {\n const dragStartSelection =\n this.draggableTextDelegate.getDragStartSelection()!;\n this._renderSelection(\n this.canvas!.contextTop,\n dragStartSelection,\n this._getCursorBoundaries(dragStartSelection.selectionStart, true),\n );\n }\n\n renderDropTargetEffect(e: DragEvent) {\n const dragSelection = this.getSelectionStartFromPointer(e);\n this.renderCursorAt(dragSelection);\n }\n\n /**\n * Renders text selection\n * @private\n * @param {{ selectionStart: number, selectionEnd: number }} selection\n * @param {Object} boundaries Object with left/top/leftOffset/topOffset\n * @param {CanvasRenderingContext2D} ctx transformed context to draw on\n */\n _renderSelection(\n ctx: CanvasRenderingContext2D,\n selection: { selectionStart: number; selectionEnd: number },\n boundaries: CursorBoundaries,\n ) {\n const { textAlign, direction } = this;\n const selectionStart = selection.selectionStart,\n selectionEnd = selection.selectionEnd,\n isJustify = textAlign.includes(JUSTIFY),\n start = this.get2DCursorLocation(selectionStart),\n end = this.get2DCursorLocation(selectionEnd),\n startLine = start.lineIndex,\n endLine = end.lineIndex,\n startChar = start.charIndex < 0 ? 0 : start.charIndex,\n endChar = end.charIndex < 0 ? 0 : end.charIndex;\n\n for (let i = startLine; i <= endLine; i++) {\n const lineOffset = this._getLineLeftOffset(i) || 0;\n let lineHeight = this.getHeightOfLine(i),\n realLineHeight = 0,\n boxStart = 0,\n boxEnd = 0;\n\n if (i === startLine) {\n boxStart = this.__charBounds[startLine][startChar].left;\n }\n if (i >= startLine && i < endLine) {\n boxEnd =\n isJustify && !this.isEndOfWrapping(i)\n ? this.width\n : this.getLineWidth(i) || 5; // WTF is this 5?\n } else if (i === endLine) {\n if (endChar === 0) {\n boxEnd = this.__charBounds[endLine][endChar].left;\n } else {\n const charSpacing = this._getWidthOfCharSpacing();\n boxEnd =\n this.__charBounds[endLine][endChar - 1].left +\n this.__charBounds[endLine][endChar - 1].width -\n charSpacing;\n }\n }\n realLineHeight = lineHeight;\n if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {\n lineHeight /= this.lineHeight;\n }\n let drawStart = boundaries.left + lineOffset + boxStart,\n drawHeight = lineHeight,\n extraTop = 0;\n const drawWidth = boxEnd - boxStart;\n if (this.inCompositionMode) {\n ctx.fillStyle = this.compositionColor || 'black';\n drawHeight = 1;\n extraTop = lineHeight;\n } else {\n ctx.fillStyle = this.selectionColor;\n }\n if (direction === RTL) {\n if (\n textAlign === RIGHT ||\n textAlign === JUSTIFY ||\n textAlign === JUSTIFY_RIGHT\n ) {\n drawStart = this.width - drawStart - drawWidth;\n } else if (textAlign === LEFT || textAlign === JUSTIFY_LEFT) {\n drawStart = boundaries.left + lineOffset - boxEnd;\n } else if (textAlign === CENTER || textAlign === JUSTIFY_CENTER) {\n drawStart = boundaries.left + lineOffset - boxEnd;\n }\n }\n ctx.fillRect(\n drawStart,\n boundaries.top + boundaries.topOffset + extraTop,\n drawWidth,\n drawHeight,\n );\n boundaries.topOffset += realLineHeight;\n }\n }\n\n /**\n * High level function to know the height of the cursor.\n * the currentChar is the one that precedes the cursor\n * Returns fontSize of char at the current cursor\n * Unused from the library, is for the end user\n * @return {Number} Character font size\n */\n getCurrentCharFontSize(): number {\n const cp = this._getCurrentCharIndex();\n return this.getValueOfPropertyAt(cp.l, cp.c, 'fontSize');\n }\n\n /**\n * High level function to know the color of the cursor.\n * the currentChar is the one that precedes the cursor\n * Returns color (fill) of char at the current cursor\n * if the text object has a pattern or gradient for filler, it will return that.\n * Unused by the library, is for the end user\n * @return {String | TFiller} Character color (fill)\n */\n getCurrentCharColor(): string | TFiller | null {\n const cp = this._getCurrentCharIndex();\n return this.getValueOfPropertyAt(cp.l, cp.c, FILL);\n }\n\n /**\n * Returns the cursor position for the getCurrent.. functions\n * @private\n */\n _getCurrentCharIndex() {\n const cursorPosition = this.get2DCursorLocation(this.selectionStart, true),\n charIndex =\n cursorPosition.charIndex > 0 ? cursorPosition.charIndex - 1 : 0;\n return { l: cursorPosition.lineIndex, c: charIndex };\n }\n\n dispose() {\n this.exitEditingImpl();\n this.draggableTextDelegate.dispose();\n super.dispose();\n }\n}\n\nclassRegistry.setClass(IText);\n// legacy\nclassRegistry.setClass(IText, 'i-text');\n","import type { TClassProperties, TOptions } from '../typedefs';\nimport { IText } from './IText/IText';\nimport { classRegistry } from '../ClassRegistry';\nimport { createTextboxDefaultControls } from '../controls/commonControls';\nimport { JUSTIFY } from './Text/constants';\nimport type { TextStyleDeclaration } from './Text/StyledText';\nimport type { SerializedITextProps, ITextProps } from './IText/IText';\nimport type { ITextEvents } from './IText/ITextBehavior';\nimport type { TextLinesInfo } from './Text/Text';\nimport type { Control } from '../controls/Control';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const textboxDefaultValues: Partial<TClassProperties<Textbox>> = {\n minWidth: 20,\n dynamicMinWidth: 2,\n lockScalingFlip: true,\n noScaleCache: false,\n _wordJoiners: /[ \\t\\r]/,\n splitByGrapheme: false,\n};\n\nexport type GraphemeData = {\n wordsData: {\n word: string[];\n width: number;\n }[][];\n largestWordWidth: number;\n};\n\nexport type StyleMap = Record<string, { line: number; offset: number }>;\n\n// @TODO this is not complete\ninterface UniqueTextboxProps {\n minWidth: number;\n splitByGrapheme: boolean;\n dynamicMinWidth: number;\n _wordJoiners: RegExp;\n}\n\nexport interface SerializedTextboxProps\n extends SerializedITextProps,\n Pick<UniqueTextboxProps, 'minWidth' | 'splitByGrapheme'> {}\n\nexport interface TextboxProps extends ITextProps, UniqueTextboxProps {}\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 */\nexport class Textbox<\n Props extends TOptions<TextboxProps> = Partial<TextboxProps>,\n SProps extends SerializedTextboxProps = SerializedTextboxProps,\n EventSpec extends ITextEvents = ITextEvents,\n >\n extends IText<Props, SProps, EventSpec>\n implements UniqueTextboxProps\n{\n /**\n * Minimum width of textbox, in pixels.\n * @type Number\n */\n declare minWidth: number;\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 */\n declare dynamicMinWidth: number;\n\n /**\n * Use this boolean property in order to split strings that have no white space concept.\n * this is a cheap way to help with chinese/japanese\n * @type Boolean\n * @since 2.6.0\n */\n declare splitByGrapheme: boolean;\n\n declare _wordJoiners: RegExp;\n\n declare _styleMap: StyleMap;\n\n declare isWrapping: boolean;\n\n static type = 'Textbox';\n\n static textLayoutProperties = [...IText.textLayoutProperties, 'width'];\n\n static ownDefaults = textboxDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...Textbox.ownDefaults,\n };\n }\n\n /**\n * Constructor\n * @param {String} text Text string\n * @param {Object} [options] Options object\n */\n constructor(text: string, options?: Props) {\n super(text, { ...Textbox.ownDefaults, ...options } as Props);\n }\n\n /**\n * Creates the default control object.\n * If you prefer to have on instance of controls shared among all objects\n * make this function return an empty object and add controls to the ownDefaults object\n */\n static createControls(): { controls: Record<string, Control> } {\n return { controls: createTextboxDefaultControls() };\n }\n\n /**\n * Unlike superclass's version of this function, Textbox does not update\n * its width.\n * @private\n * @override\n */\n initDimensions() {\n if (!this.initialized) {\n return;\n }\n this.isEditing && this.initDelayedCursor();\n this._clearCache();\n // clear dynamicMinWidth as it will be different after we re-wrap line\n this.dynamicMinWidth = 0;\n // wrap lines\n this._styleMap = this._generateStyleMap(this._splitText());\n // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n if (this.dynamicMinWidth > this.width) {\n this._set('width', this.dynamicMinWidth);\n }\n if (this.textAlign.includes(JUSTIFY)) {\n // once text is measured we need to make space fatter to make justified text.\n this.enlargeSpaces();\n }\n // clear cache and re-calculate height\n this.height = this.calcTextHeight();\n }\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(textInfo: TextLinesInfo): StyleMap {\n let realLineCount = 0,\n realLineCharCount = 0,\n charCount = 0;\n const map: StyleMap = {};\n\n for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n realLineCharCount = 0;\n charCount++;\n realLineCount++;\n } else if (\n !this.splitByGrapheme &&\n this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n i > 0\n ) {\n // this case deals with space's that are removed from end of lines when wrapping\n realLineCharCount++;\n charCount++;\n }\n\n map[i] = { line: realLineCount, offset: realLineCharCount };\n\n charCount += textInfo.graphemeLines[i].length;\n realLineCharCount += textInfo.graphemeLines[i].length;\n }\n\n return map;\n }\n\n /**\n * Returns true if object has a style property or has it on a specified line\n * @param {Number} lineIndex\n * @return {Boolean}\n */\n styleHas(property: keyof TextStyleDeclaration, lineIndex: number): boolean {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (map) {\n lineIndex = map.line;\n }\n }\n return super.styleHas(property, lineIndex);\n }\n\n /**\n * Returns true if object has no styling or no styling in a line\n * @param {Number} lineIndex , lineIndex is on wrapped lines.\n * @return {Boolean}\n */\n isEmptyStyles(lineIndex: number): boolean {\n if (!this.styles) {\n return true;\n }\n let offset = 0,\n nextLineIndex = lineIndex + 1,\n nextOffset: number,\n shouldLimit = false;\n const map = this._styleMap[lineIndex],\n mapNextLine = this._styleMap[lineIndex + 1];\n if (map) {\n lineIndex = map.line;\n offset = map.offset;\n }\n if (mapNextLine) {\n nextLineIndex = mapNextLine.line;\n shouldLimit = nextLineIndex === lineIndex;\n nextOffset = mapNextLine.offset;\n }\n const obj =\n typeof lineIndex === 'undefined'\n ? this.styles\n : { line: this.styles[lineIndex] };\n for (const p1 in obj) {\n for (const p2 in obj[p1]) {\n const p2Number = parseInt(p2, 10);\n if (p2Number >= offset && (!shouldLimit || p2Number < nextOffset!)) {\n for (const p3 in obj[p1][p2]) {\n return false;\n }\n }\n }\n }\n return true;\n }\n\n /**\n * @protected\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined\n */\n _getStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n ): TextStyleDeclaration {\n if (this._styleMap && !this.isWrapping) {\n const map = this._styleMap[lineIndex];\n if (!map) {\n return {};\n }\n lineIndex = map.line;\n charIndex = map.offset + charIndex;\n }\n return super._getStyleDeclaration(lineIndex, charIndex);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @param {Object} style\n * @private\n */\n protected _setStyleDeclaration(\n lineIndex: number,\n charIndex: number,\n style: object,\n ) {\n const map = this._styleMap[lineIndex];\n super._setStyleDeclaration(map.line, map.offset + charIndex, style);\n }\n\n /**\n * @param {Number} lineIndex\n * @param {Number} charIndex\n * @private\n */\n protected _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n const map = this._styleMap[lineIndex];\n super._deleteStyleDeclaration(map.line, map.offset + charIndex);\n }\n\n /**\n * probably broken need a fix\n * Returns the real style line that correspond to the wrapped lineIndex line\n * Used just to verify if the line does exist or not.\n * @param {Number} lineIndex\n * @returns {Boolean} if the line exists or not\n * @private\n */\n protected _getLineStyle(lineIndex: number): boolean {\n const map = this._styleMap[lineIndex];\n return !!this.styles[map.line];\n }\n\n /**\n * Set the line style to an empty object so that is initialized\n * @param {Number} lineIndex\n * @param {Object} style\n * @private\n */\n protected _setLineStyle(lineIndex: number) {\n const map = this._styleMap[lineIndex];\n super._setLineStyle(map.line);\n }\n\n /**\n * Wraps text using the 'width' property of Textbox. First this function\n * splits text on newlines, so we preserve newlines entered by the user.\n * Then it wraps each line using the width of the Textbox by calling\n * _wrapLine().\n * @param {Array} lines The string array of text that is split into lines\n * @param {Number} desiredWidth width you want to wrap to\n * @returns {Array} Array of lines\n */\n _wrapText(lines: string[], desiredWidth: number): string[][] {\n this.isWrapping = true;\n // extract all thewords and the widths to optimally wrap lines.\n const data = this.getGraphemeDataForRender(lines);\n const wrapped: string[][] = [];\n for (let i = 0; i < data.wordsData.length; i++) {\n wrapped.push(...this._wrapLine(i, desiredWidth, data));\n }\n this.isWrapping = false;\n return wrapped;\n }\n\n /**\n * For each line of text terminated by an hard line stop,\n * measure each word width and extract the largest word from all.\n * The returned words here are the one that at the end will be rendered.\n * @param {string[]} lines the lines we need to measure\n *\n */\n getGraphemeDataForRender(lines: string[]): GraphemeData {\n const splitByGrapheme = this.splitByGrapheme,\n infix = splitByGrapheme ? '' : ' ';\n\n let largestWordWidth = 0;\n\n const data = lines.map((line, lineIndex) => {\n let offset = 0;\n const wordsOrGraphemes = splitByGrapheme\n ? this.graphemeSplit(line)\n : this.wordSplit(line);\n\n if (wordsOrGraphemes.length === 0) {\n return [{ word: [], width: 0 }];\n }\n\n return wordsOrGraphemes.map((word: string) => {\n // if using splitByGrapheme words are already in graphemes.\n const graphemeArray = splitByGrapheme\n ? [word]\n : this.graphemeSplit(word);\n const width = this._measureWord(graphemeArray, lineIndex, offset);\n largestWordWidth = Math.max(width, largestWordWidth);\n offset += graphemeArray.length + infix.length;\n return { word: graphemeArray, width };\n });\n });\n\n return {\n wordsData: data,\n largestWordWidth,\n };\n }\n\n /**\n * Helper function to measure a string of text, given its lineIndex and charIndex offset\n * It gets called when charBounds are not available yet.\n * Override if necessary\n * Use with {@link Textbox#wordSplit}\n *\n * @param {CanvasRenderingContext2D} ctx\n * @param {String} text\n * @param {number} lineIndex\n * @param {number} charOffset\n * @returns {number}\n */\n _measureWord(word: string[], lineIndex: number, charOffset = 0): number {\n let width = 0,\n prevGrapheme;\n const skipLeft = true;\n for (let i = 0, len = word.length; i < len; i++) {\n const box = this._getGraphemeBox(\n word[i],\n lineIndex,\n i + charOffset,\n prevGrapheme,\n skipLeft,\n );\n width += box.kernedWidth;\n prevGrapheme = word[i];\n }\n return width;\n }\n\n /**\n * Override this method to customize word splitting\n * Use with {@link Textbox#_measureWord}\n * @param {string} value\n * @returns {string[]} array of words\n */\n wordSplit(value: string): string[] {\n return value.split(this._wordJoiners);\n }\n\n /**\n * Wraps a line of text using the width of the Textbox as desiredWidth\n * and leveraging the known width o words from GraphemeData\n * @private\n * @param {Number} lineIndex\n * @param {Number} desiredWidth width you want to wrap the line to\n * @param {GraphemeData} graphemeData an object containing all the lines' words width.\n * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n * @returns {Array} Array of line(s) into which the given text is wrapped\n * to.\n */\n _wrapLine(\n lineIndex: number,\n desiredWidth: number,\n { largestWordWidth, wordsData }: GraphemeData,\n reservedSpace = 0,\n ): string[][] {\n const additionalSpace = this._getWidthOfCharSpacing(),\n splitByGrapheme = this.splitByGrapheme,\n graphemeLines = [],\n infix = splitByGrapheme ? '' : ' ';\n\n let lineWidth = 0,\n line: string[] = [],\n // spaces in different languages?\n offset = 0,\n infixWidth = 0,\n lineJustStarted = true;\n\n desiredWidth -= reservedSpace;\n\n const maxWidth = Math.max(\n desiredWidth,\n largestWordWidth,\n this.dynamicMinWidth,\n );\n // layout words\n const data = wordsData[lineIndex];\n offset = 0;\n let i;\n for (i = 0; i < data.length; i++) {\n const { word, width: wordWidth } = data[i];\n offset += word.length;\n\n lineWidth += infixWidth + wordWidth - additionalSpace;\n if (lineWidth > maxWidth && !lineJustStarted) {\n graphemeLines.push(line);\n line = [];\n lineWidth = wordWidth;\n lineJustStarted = true;\n } else {\n lineWidth += additionalSpace;\n }\n\n if (!lineJustStarted && !splitByGrapheme) {\n line.push(infix);\n }\n line = line.concat(word);\n\n infixWidth = splitByGrapheme\n ? 0\n : this._measureWord([infix], lineIndex, offset);\n offset++;\n lineJustStarted = false;\n }\n\n i && graphemeLines.push(line);\n\n // TODO: this code is probably not necessary anymore.\n // it can be moved out of this function since largestWordWidth is now\n // known in advance\n if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n }\n return graphemeLines;\n }\n\n /**\n * Detect if the text line is ended with an hard break\n * text and itext do not have wrapping, return false\n * @param {Number} lineIndex text to split\n * @return {Boolean}\n */\n isEndOfWrapping(lineIndex: number): boolean {\n if (!this._styleMap[lineIndex + 1]) {\n // is last line, return true;\n return true;\n }\n if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n // this is last line before a line break, return true;\n return true;\n }\n return false;\n }\n\n /**\n * Detect if a line has a linebreak and so we need to account for it when moving\n * and counting style.\n * This is important only for splitByGrapheme at the end of wrapping.\n * If we are not wrapping the offset is always 1\n * @return Number\n */\n missingNewlineOffset(lineIndex: number, skipWrapping?: boolean): 0 | 1 {\n if (this.splitByGrapheme && !skipWrapping) {\n return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n }\n return 1;\n }\n\n /**\n * Gets lines of text to render in the Textbox. This function calculates\n * text wrapping on the fly every time it is called.\n * @param {String} text text to split\n * @returns {Array} Array of lines in the Textbox.\n * @override\n */\n _splitTextIntoLines(text: string) {\n const newText = super._splitTextIntoLines(text),\n graphemeLines = this._wrapText(newText.lines, this.width),\n lines = new Array(graphemeLines.length);\n for (let i = 0; i < graphemeLines.length; i++) {\n lines[i] = graphemeLines[i].join('');\n }\n newText.lines = lines;\n newText.graphemeLines = graphemeLines;\n return newText;\n }\n\n getMinWidth() {\n return Math.max(this.minWidth, this.dynamicMinWidth);\n }\n\n _removeExtraneousStyles() {\n const linesToKeep = new Map();\n for (const prop in this._styleMap) {\n const propNumber = parseInt(prop, 10);\n if (this._textLines[propNumber]) {\n const lineIndex = this._styleMap[prop].line;\n linesToKeep.set(`${lineIndex}`, true);\n }\n }\n for (const prop in this.styles) {\n if (!linesToKeep.has(prop)) {\n delete this.styles[prop];\n }\n }\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n return super.toObject<T, K>([\n 'minWidth',\n 'splitByGrapheme',\n ...propertiesToInclude,\n ] as K[]);\n }\n}\n\nclassRegistry.setClass(Textbox);\n","import { Point } from '../../Point';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { makeBoundingBoxFromPoints } from '../../util/misc/boundingBoxFromPoints';\nimport { sendPointToPlane } from '../../util/misc/planeChange';\nimport type { LayoutStrategyResult, StrictLayoutContext } from '../types';\nimport { LayoutStrategy } from './LayoutStrategy';\nimport { getObjectBounds } from './utils';\nimport { classRegistry } from '../../ClassRegistry';\n\n/**\n * Layout will adjust the bounding box to match the clip path bounding box.\n */\nexport class ClipPathLayout extends LayoutStrategy {\n static readonly type = 'clip-path';\n\n shouldPerformLayout(context: StrictLayoutContext): boolean {\n return !!context.target.clipPath && super.shouldPerformLayout(context);\n }\n\n shouldLayoutClipPath() {\n return false;\n }\n\n calcLayoutResult(\n context: StrictLayoutContext,\n objects: FabricObject[],\n ): LayoutStrategyResult | undefined {\n const { target } = context;\n const { clipPath, group } = target;\n if (!clipPath || !this.shouldPerformLayout(context)) {\n return;\n }\n // TODO: remove stroke calculation from this case\n const { width, height } = makeBoundingBoxFromPoints(\n getObjectBounds(target, clipPath as FabricObject),\n );\n const size = new Point(width, height);\n if (clipPath.absolutePositioned) {\n // we want the center point to exist in group's containing plane\n const clipPathCenter = sendPointToPlane(\n clipPath.getRelativeCenterPoint(),\n undefined,\n group ? group.calcTransformMatrix() : undefined,\n );\n return {\n center: clipPathCenter,\n size,\n };\n } else {\n // we want the center point to exist in group's containing plane, so we send it upwards\n const clipPathCenter = clipPath\n .getRelativeCenterPoint()\n .transform(target.calcOwnMatrix(), true);\n if (this.shouldPerformLayout(context)) {\n // the clip path is positioned relative to the group's center which is affected by the bbox\n // so we first calculate the bbox\n const { center = new Point(), correction = new Point() } =\n this.calcBoundingBox(objects, context) || {};\n return {\n center: center.add(clipPathCenter),\n correction: correction.subtract(clipPathCenter),\n size,\n };\n } else {\n return {\n center: target.getRelativeCenterPoint().add(clipPathCenter),\n size,\n };\n }\n }\n }\n}\n\nclassRegistry.setClass(ClipPathLayout);\n","import { Point } from '../../Point';\nimport type {\n InitializationLayoutContext,\n LayoutStrategyResult,\n StrictLayoutContext,\n} from '../types';\nimport { LayoutStrategy } from './LayoutStrategy';\nimport { classRegistry } from '../../ClassRegistry';\n\n/**\n * Layout will keep target's initial size.\n */\nexport class FixedLayout extends LayoutStrategy {\n static readonly type = 'fixed';\n\n /**\n * @override respect target's initial size\n */\n getInitialSize(\n { target }: StrictLayoutContext & InitializationLayoutContext,\n { size }: Pick<LayoutStrategyResult, 'center' | 'size'>,\n ): Point {\n return new Point(target.width || size.x, target.height || size.y);\n }\n}\n\nclassRegistry.setClass(FixedLayout);\n","import { LayoutManager } from './LayoutManager';\nimport type { RegistrationContext, StrictLayoutContext } from './types';\nimport type { Group } from '../shapes/Group';\n\n/**\n * Today the LayoutManager class also takes care of subscribing event handlers\n * to update the group layout when the group is interactive and a transform is applied\n * to a child object.\n * The ActiveSelection is never interactive, but it could contain objects from\n * groups that are.\n * The standard LayoutManager would subscribe the children of the activeSelection to\n * perform layout changes to the active selection itself, what we need instead is that\n * the transformation applied to the active selection will trigger changes to the\n * original group of the children ( the one referenced under the parent property )\n * This subclass of the LayoutManager has a single duty to fill the gap of this difference.`\n */\nexport class ActiveSelectionLayoutManager extends LayoutManager {\n subscribeTargets(\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ): void {\n const activeSelection = context.target;\n const parents = context.targets.reduce((parents, target) => {\n target.parent && parents.add(target.parent);\n return parents;\n }, new Set<Group>());\n parents.forEach((parent) => {\n parent.layoutManager.subscribeTargets({\n target: parent,\n targets: [activeSelection],\n });\n });\n }\n\n /**\n * unsubscribe from parent only if all its children were deselected\n */\n unsubscribeTargets(\n context: RegistrationContext & Partial<StrictLayoutContext>,\n ): void {\n const activeSelection = context.target;\n const selectedObjects = activeSelection.getObjects();\n const parents = context.targets.reduce((parents, target) => {\n target.parent && parents.add(target.parent);\n return parents;\n }, new Set<Group>());\n parents.forEach((parent) => {\n !selectedObjects.some((object) => object.parent === parent) &&\n parent.layoutManager.unsubscribeTargets({\n target: parent,\n targets: [activeSelection],\n });\n });\n }\n}\n","import type { ControlRenderingStyleOverride } from '../controls/controlRendering';\nimport { classRegistry } from '../ClassRegistry';\nimport type { GroupProps } from './Group';\nimport { Group } from './Group';\nimport type { FabricObject } from './Object/FabricObject';\nimport {\n LAYOUT_TYPE_ADDED,\n LAYOUT_TYPE_REMOVED,\n} from '../LayoutManager/constants';\nimport type { TClassProperties } from '../typedefs';\nimport { log } from '../util/internals/console';\nimport { ActiveSelectionLayoutManager } from '../LayoutManager/ActiveSelectionLayoutManager';\n\nexport type MultiSelectionStacking = 'canvas-stacking' | 'selection-order';\n\nexport interface ActiveSelectionOptions extends GroupProps {\n multiSelectionStacking: MultiSelectionStacking;\n}\n\nconst activeSelectionDefaultValues: Partial<TClassProperties<ActiveSelection>> =\n {\n multiSelectionStacking: 'canvas-stacking',\n };\n\n/**\n * Used by Canvas to manage selection.\n *\n * @example\n * class MyActiveSelection extends ActiveSelection {\n * ...\n * }\n *\n * // override the default `ActiveSelection` class\n * classRegistry.setClass(MyActiveSelection)\n */\nexport class ActiveSelection extends Group {\n static type = 'ActiveSelection';\n\n static ownDefaults: Record<string, any> = activeSelectionDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return { ...super.getDefaults(), ...ActiveSelection.ownDefaults };\n }\n\n /**\n * The ActiveSelection needs to use the ActiveSelectionLayoutManager\n * or selections on interactive groups may be broken\n */\n declare layoutManager: ActiveSelectionLayoutManager;\n\n /**\n * controls how selected objects are added during a multiselection event\n * - `canvas-stacking` adds the selected object to the active selection while respecting canvas object stacking order\n * - `selection-order` adds the selected object to the top of the stack,\n * meaning that the stack is ordered by the order in which objects were selected\n * @default `canvas-stacking`\n */\n declare multiSelectionStacking: MultiSelectionStacking;\n\n constructor(\n objects: FabricObject[] = [],\n options: Partial<ActiveSelectionOptions> = {},\n ) {\n super();\n Object.assign(this, ActiveSelection.ownDefaults);\n this.setOptions(options);\n const { left, top, layoutManager } = options;\n this.groupInit(objects, {\n left,\n top,\n layoutManager: layoutManager ?? new ActiveSelectionLayoutManager(),\n });\n }\n\n /**\n * @private\n */\n _shouldSetNestedCoords() {\n return true;\n }\n\n /**\n * @private\n * @override we don't want the selection monitor to be active\n */\n __objectSelectionMonitor() {\n // noop\n }\n\n /**\n * Adds objects with respect to {@link multiSelectionStacking}\n * @param targets object to add to selection\n */\n multiSelectAdd(...targets: FabricObject[]) {\n if (this.multiSelectionStacking === 'selection-order') {\n this.add(...targets);\n } else {\n // respect object stacking as it is on canvas\n // perf enhancement for large ActiveSelection: consider a binary search of `isInFrontOf`\n targets.forEach((target) => {\n const index = this._objects.findIndex((obj) => obj.isInFrontOf(target));\n const insertAt =\n index === -1\n ? // `target` is in front of all other objects\n this.size()\n : index;\n this.insertAt(insertAt, target);\n });\n }\n }\n\n /**\n * @override block ancestors/descendants of selected objects from being selected to prevent a circular object tree\n */\n canEnterGroup(object: FabricObject) {\n if (\n this.getObjects().some(\n (o) => o.isDescendantOf(object) || object.isDescendantOf(o),\n )\n ) {\n // prevent circular object tree\n log(\n 'error',\n 'ActiveSelection: circular object trees are not supported, this call has no effect',\n );\n return false;\n }\n\n return super.canEnterGroup(object);\n }\n\n /**\n * Change an object so that it can be part of an active selection.\n * this method is called by multiselectAdd from canvas code.\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object is in canvas coordinate plane\n */\n enterGroup(object: FabricObject, removeParentTransform?: boolean) {\n // This condition check that the object has currently a group, and the group\n // is also its parent, meaning that is not in an active selection, but is\n // in a normal group.\n if (object.parent && object.parent === object.group) {\n // Disconnect the object from the group functionalities, but keep the ref parent intact\n // for later re-enter\n object.parent._exitGroup(object);\n // in this case the object is probably inside an active selection.\n } else if (object.group && object.parent !== object.group) {\n // in this case group.remove will also clear the old parent reference.\n object.group.remove(object);\n }\n // enter the active selection from a render perspective\n // the object will be in the objects array of both the ActiveSelection and the Group\n // but referenced in the group's _activeObjects so that it won't be rendered twice.\n this._enterGroup(object, removeParentTransform);\n }\n\n /**\n * we want objects to retain their canvas ref when exiting instance\n * @private\n * @param {FabricObject} object\n * @param {boolean} [removeParentTransform] true if object should exit group without applying group's transform to it\n */\n exitGroup(object: FabricObject, removeParentTransform?: boolean) {\n this._exitGroup(object, removeParentTransform);\n // return to parent\n object.parent && object.parent._enterGroup(object, true);\n }\n\n /**\n * @private\n * @param {'added'|'removed'} type\n * @param {FabricObject[]} targets\n */\n _onAfterObjectsChange(type: 'added' | 'removed', targets: FabricObject[]) {\n super._onAfterObjectsChange(type, targets);\n const groups = new Set<Group>();\n targets.forEach((object) => {\n const { parent } = object;\n parent && groups.add(parent);\n });\n if (type === LAYOUT_TYPE_REMOVED) {\n // invalidate groups' layout and mark as dirty\n groups.forEach((group) => {\n group._onAfterObjectsChange(LAYOUT_TYPE_ADDED, targets);\n });\n } else {\n // mark groups as dirty\n groups.forEach((group) => {\n group._set('dirty', true);\n });\n }\n }\n\n /**\n * @override remove all objects\n */\n onDeselect() {\n this.removeAll();\n return false;\n }\n\n /**\n * Returns string representation of a group\n * @return {String}\n */\n toString() {\n return `#<ActiveSelection: (${this.complexity()})>`;\n }\n\n /**\n * Decide if the object should cache or not. The Active selection never caches\n * @return {Boolean}\n */\n shouldCache() {\n return false;\n }\n\n /**\n * Check if this group or its parent group are caching, recursively up\n * @return {Boolean}\n */\n isOnACache() {\n return false;\n }\n\n /**\n * Renders controls and borders for the object\n * @param {CanvasRenderingContext2D} ctx Context to render on\n * @param {Object} [styleOverride] properties to override the object style\n * @param {Object} [childrenOverride] properties to override the children overrides\n */\n _renderControls(\n ctx: CanvasRenderingContext2D,\n styleOverride?: ControlRenderingStyleOverride,\n childrenOverride?: ControlRenderingStyleOverride,\n ) {\n ctx.save();\n ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n const options = {\n hasControls: false,\n ...childrenOverride,\n forActiveSelection: true,\n };\n for (let i = 0; i < this._objects.length; i++) {\n this._objects[i]._renderControls(ctx, options);\n }\n super._renderControls(ctx, styleOverride);\n ctx.restore();\n }\n}\n\nclassRegistry.setClass(ActiveSelection);\nclassRegistry.setClass(ActiveSelection, 'activeSelection');\n","/**\n * Canvas 2D filter backend.\n */\nimport type { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TPipelineResources } from './typedefs';\n\nexport class Canvas2dFilterBackend {\n /**\n * Experimental. This object is a sort of repository of help layers used to avoid\n * of recreating them during frequent filtering. If you are previewing a filter with\n * a slider you probably do not want to create help layers every filter step.\n * in this object there will be appended some canvases, created once, resized sometimes\n * cleared never. Clearing is left to the developer.\n **/\n resources: TPipelineResources = {};\n\n /**\n * Apply a set of filters against a source image and draw the filtered output\n * to the provided destination canvas.\n *\n * @param {EnhancedFilter} filters The filter to apply.\n * @param {HTMLImageElement|HTMLCanvasElement} sourceElement The source to be filtered.\n * @param {Number} sourceWidth The width of the source input.\n * @param {Number} sourceHeight The height of the source input.\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n */\n applyFilters(\n filters: BaseFilter<string, Record<string, any>>[],\n sourceElement: CanvasImageSource,\n sourceWidth: number,\n sourceHeight: number,\n targetCanvas: HTMLCanvasElement,\n ): T2DPipelineState | void {\n const ctx = targetCanvas.getContext('2d', {\n willReadFrequently: true,\n desynchronized: true,\n });\n if (!ctx) {\n return;\n }\n ctx.drawImage(sourceElement, 0, 0, sourceWidth, sourceHeight);\n const imageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n const originalImageData = ctx.getImageData(0, 0, sourceWidth, sourceHeight);\n const pipelineState: T2DPipelineState = {\n sourceWidth,\n sourceHeight,\n imageData,\n originalEl: sourceElement,\n originalImageData,\n canvasEl: targetCanvas,\n ctx,\n filterBackend: this,\n };\n filters.forEach((filter) => {\n filter.applyTo(pipelineState);\n });\n const { imageData: imageDataPostFilter } = pipelineState;\n if (\n imageDataPostFilter.width !== sourceWidth ||\n imageDataPostFilter.height !== sourceHeight\n ) {\n targetCanvas.width = imageDataPostFilter.width;\n targetCanvas.height = imageDataPostFilter.height;\n }\n ctx.putImageData(imageDataPostFilter, 0, 0);\n return pipelineState;\n }\n}\n","import { config } from '../config';\nimport { createCanvasElementFor } from '../util/misc/dom';\nimport type {\n TWebGLPipelineState,\n TProgramCache,\n TTextureCache,\n TPipelineResources,\n} from './typedefs';\nimport type { BaseFilter } from './BaseFilter';\n\nexport class WebGLFilterBackend {\n declare tileSize: number;\n\n /**\n * Define ...\n **/\n aPosition: Float32Array = new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]);\n\n /**\n * If GLPut data is the fastest operation, or if forced, this buffer will be used\n * to transfer the data back in the 2d logic\n **/\n declare imageBuffer?: ArrayBuffer;\n\n declare canvas: HTMLCanvasElement;\n\n /**\n * The Webgl context that will execute the operations for filtering\n **/\n declare gl: WebGLRenderingContext;\n\n /**\n * Keyed map for shader cache\n **/\n declare programCache: TProgramCache;\n\n /**\n * Keyed map for texture cache\n **/\n declare textureCache: TTextureCache;\n\n /**\n * Contains GPU info for debug\n **/\n declare gpuInfo: any;\n\n /**\n * Experimental. This object is a sort of repository of help layers used to avoid\n * of recreating them during frequent filtering. If you are previewing a filter with\n * a slider you probably do not want to create help layers every filter step.\n * in this object there will be appended some canvases, created once, resized sometimes\n * cleared never. Clearing is left to the developer.\n **/\n resources: TPipelineResources = {};\n\n constructor({ tileSize = config.textureSize } = {}) {\n this.tileSize = tileSize;\n this.setupGLContext(tileSize, tileSize);\n this.captureGPUInfo();\n }\n\n /**\n * Setup a WebGL context suitable for filtering, and bind any needed event handlers.\n */\n setupGLContext(width: number, height: number): void {\n this.dispose();\n this.createWebGLCanvas(width, height);\n }\n\n /**\n * Create a canvas element and associated WebGL context and attaches them as\n * class properties to the GLFilterBackend class.\n */\n createWebGLCanvas(width: number, height: number): void {\n const canvas = createCanvasElementFor({ width, height });\n const glOptions = {\n alpha: true,\n premultipliedAlpha: false,\n depth: false,\n stencil: false,\n antialias: false,\n },\n gl = canvas.getContext('webgl', glOptions) as WebGLRenderingContext;\n\n if (!gl) {\n return;\n }\n gl.clearColor(0, 0, 0, 0);\n // this canvas can fire webglcontextlost and webglcontextrestored\n this.canvas = canvas;\n this.gl = gl;\n }\n\n /**\n * Attempts to apply the requested filters to the source provided, drawing the filtered output\n * to the provided target canvas.\n *\n * @param {Array} filters The filters to apply.\n * @param {TexImageSource} source The source to be filtered.\n * @param {Number} width The width of the source input.\n * @param {Number} height The height of the source input.\n * @param {HTMLCanvasElement} targetCanvas The destination for filtered output to be drawn.\n * @param {String|undefined} cacheKey A key used to cache resources related to the source. If\n * omitted, caching will be skipped.\n */\n applyFilters(\n filters: BaseFilter<string, Record<string, any>>[],\n source: TexImageSource,\n width: number,\n height: number,\n targetCanvas: HTMLCanvasElement,\n cacheKey?: string,\n ): TWebGLPipelineState | undefined {\n const gl = this.gl;\n const ctx = targetCanvas.getContext('2d');\n if (!gl || !ctx) {\n return;\n }\n let cachedTexture;\n if (cacheKey) {\n cachedTexture = this.getCachedTexture(cacheKey, source);\n }\n const pipelineState: TWebGLPipelineState = {\n originalWidth:\n (source as HTMLImageElement).width ||\n (source as HTMLImageElement).naturalWidth ||\n 0,\n originalHeight:\n (source as HTMLImageElement).height ||\n (source as HTMLImageElement).naturalHeight ||\n 0,\n sourceWidth: width,\n sourceHeight: height,\n destinationWidth: width,\n destinationHeight: height,\n context: gl,\n sourceTexture: this.createTexture(\n gl,\n width,\n height,\n !cachedTexture ? source : undefined,\n ),\n targetTexture: this.createTexture(gl, width, height),\n originalTexture:\n cachedTexture ||\n this.createTexture(\n gl,\n width,\n height,\n !cachedTexture ? source : undefined,\n ),\n passes: filters.length,\n webgl: true,\n aPosition: this.aPosition,\n programCache: this.programCache,\n pass: 0,\n filterBackend: this,\n targetCanvas: targetCanvas,\n };\n const tempFbo = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, tempFbo);\n filters.forEach((filter: any) => {\n filter && filter.applyTo(pipelineState);\n });\n resizeCanvasIfNeeded(pipelineState);\n this.copyGLTo2D(gl, pipelineState);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.deleteTexture(pipelineState.sourceTexture);\n gl.deleteTexture(pipelineState.targetTexture);\n gl.deleteFramebuffer(tempFbo);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n return pipelineState;\n }\n\n /**\n * Detach event listeners, remove references, and clean up caches.\n */\n dispose() {\n if (this.canvas) {\n // we are disposing, we don't care about the fact\n // that the canvas shouldn't be null.\n // @ts-expect-error disposing\n this.canvas = null;\n // @ts-expect-error disposing\n this.gl = null;\n }\n this.clearWebGLCaches();\n }\n\n /**\n * Wipe out WebGL-related caches.\n */\n clearWebGLCaches() {\n this.programCache = {};\n this.textureCache = {};\n }\n\n /**\n * Create a WebGL texture object.\n *\n * Accepts specific dimensions to initialize the texture to or a source image.\n *\n * @param {WebGLRenderingContext} gl The GL context to use for creating the texture.\n * @param {number} width The width to initialize the texture at.\n * @param {number} height The height to initialize the texture.\n * @param {TexImageSource} textureImageSource A source for the texture data.\n * @param {number} filter gl.NEAREST default or gl.LINEAR filters for the texture.\n * This filter is very useful for LUTs filters. If you need interpolation use gl.LINEAR\n * @returns {WebGLTexture}\n */\n createTexture(\n gl: WebGLRenderingContext,\n width: number,\n height: number,\n textureImageSource?: TexImageSource,\n filter?:\n | WebGLRenderingContextBase['NEAREST']\n | WebGLRenderingContextBase['LINEAR'],\n ): WebGLTexture {\n const {\n NEAREST,\n TEXTURE_2D,\n RGBA,\n UNSIGNED_BYTE,\n CLAMP_TO_EDGE,\n TEXTURE_MAG_FILTER,\n TEXTURE_MIN_FILTER,\n TEXTURE_WRAP_S,\n TEXTURE_WRAP_T,\n } = gl;\n const texture = gl.createTexture();\n gl.bindTexture(TEXTURE_2D, texture);\n gl.texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, filter || NEAREST);\n gl.texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, filter || NEAREST);\n gl.texParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE);\n gl.texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE);\n if (textureImageSource) {\n gl.texImage2D(\n TEXTURE_2D,\n 0,\n RGBA,\n RGBA,\n UNSIGNED_BYTE,\n textureImageSource,\n );\n } else {\n gl.texImage2D(\n TEXTURE_2D,\n 0,\n RGBA,\n width,\n height,\n 0,\n RGBA,\n UNSIGNED_BYTE,\n null,\n );\n }\n // disabled because website and issues with different typescript version\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return texture!;\n }\n\n /**\n * Can be optionally used to get a texture from the cache array\n *\n * If an existing texture is not found, a new texture is created and cached.\n *\n * @param {String} uniqueId A cache key to use to find an existing texture.\n * @param {HTMLImageElement|HTMLCanvasElement} textureImageSource A source to use to create the\n * texture cache entry if one does not already exist.\n */\n getCachedTexture(\n uniqueId: string,\n textureImageSource: TexImageSource,\n filter?:\n | WebGLRenderingContextBase['NEAREST']\n | WebGLRenderingContextBase['LINEAR'],\n ): WebGLTexture | null {\n const { textureCache } = this;\n if (textureCache[uniqueId]) {\n return textureCache[uniqueId];\n } else {\n const texture = this.createTexture(\n this.gl,\n (textureImageSource as HTMLImageElement).width,\n (textureImageSource as HTMLImageElement).height,\n textureImageSource,\n filter,\n );\n if (texture) {\n textureCache[uniqueId] = texture;\n }\n return texture;\n }\n }\n\n /**\n * Clear out cached resources related to a source image that has been\n * filtered previously.\n *\n * @param {String} cacheKey The cache key provided when the source image was filtered.\n */\n evictCachesForKey(cacheKey: string) {\n if (this.textureCache[cacheKey]) {\n this.gl.deleteTexture(this.textureCache[cacheKey]);\n delete this.textureCache[cacheKey];\n }\n }\n\n /**\n * Copy an input WebGL canvas on to an output 2D canvas.\n *\n * The WebGL canvas is assumed to be upside down, with the top-left pixel of the\n * desired output image appearing in the bottom-left corner of the WebGL canvas.\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\n copyGLTo2D(gl: WebGLRenderingContext, pipelineState: TWebGLPipelineState) {\n const glCanvas = gl.canvas,\n targetCanvas = pipelineState.targetCanvas,\n ctx = targetCanvas.getContext('2d');\n if (!ctx) {\n return;\n }\n ctx.translate(0, targetCanvas.height); // move it down again\n ctx.scale(1, -1); // vertical flip\n // where is my image on the big glcanvas?\n const sourceY = glCanvas.height - targetCanvas.height;\n ctx.drawImage(\n glCanvas,\n 0,\n sourceY,\n targetCanvas.width,\n targetCanvas.height,\n 0,\n 0,\n targetCanvas.width,\n targetCanvas.height,\n );\n }\n\n /**\n * Copy an input WebGL canvas on to an output 2D canvas using 2d canvas' putImageData\n * API. Measurably faster than using ctx.drawImage in Firefox (version 54 on OSX Sierra).\n *\n * @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.\n * @param {HTMLCanvasElement} targetCanvas The 2D target canvas to copy on to.\n * @param {Object} pipelineState The 2D target canvas to copy on to.\n */\n copyGLTo2DPutImageData(\n this: Required<WebGLFilterBackend>,\n gl: WebGLRenderingContext,\n pipelineState: TWebGLPipelineState,\n ) {\n const targetCanvas = pipelineState.targetCanvas,\n ctx = targetCanvas.getContext('2d'),\n dWidth = pipelineState.destinationWidth,\n dHeight = pipelineState.destinationHeight,\n numBytes = dWidth * dHeight * 4;\n if (!ctx) {\n return;\n }\n const u8 = new Uint8Array(this.imageBuffer, 0, numBytes);\n const u8Clamped = new Uint8ClampedArray(this.imageBuffer, 0, numBytes);\n\n gl.readPixels(0, 0, dWidth, dHeight, gl.RGBA, gl.UNSIGNED_BYTE, u8);\n const imgData = new ImageData(u8Clamped, dWidth, dHeight);\n ctx.putImageData(imgData, 0, 0);\n }\n\n /**\n * Attempt to extract GPU information strings from a WebGL context.\n *\n * Useful information when debugging or blacklisting specific GPUs.\n *\n * @returns {Object} A GPU info object with renderer and vendor strings.\n */\n captureGPUInfo() {\n if (this.gpuInfo) {\n return this.gpuInfo;\n }\n const gl = this.gl,\n gpuInfo = { renderer: '', vendor: '' };\n if (!gl) {\n return gpuInfo;\n }\n const ext = gl.getExtension('WEBGL_debug_renderer_info');\n if (ext) {\n const renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);\n const vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);\n if (renderer) {\n gpuInfo.renderer = renderer.toLowerCase();\n }\n if (vendor) {\n gpuInfo.vendor = vendor.toLowerCase();\n }\n }\n this.gpuInfo = gpuInfo;\n return gpuInfo;\n }\n}\n\nfunction resizeCanvasIfNeeded(pipelineState: TWebGLPipelineState): void {\n const targetCanvas = pipelineState.targetCanvas,\n width = targetCanvas.width,\n height = targetCanvas.height,\n dWidth = pipelineState.destinationWidth,\n dHeight = pipelineState.destinationHeight;\n\n if (width !== dWidth || height !== dHeight) {\n targetCanvas.width = dWidth;\n targetCanvas.height = dHeight;\n }\n}\n","import { config } from '../config';\nimport { getEnv } from '../env';\nimport { createCanvasElement } from '../util/misc/dom';\nimport { Canvas2dFilterBackend } from './Canvas2dFilterBackend';\nimport { WebGLFilterBackend } from './WebGLFilterBackend';\n\nexport type FilterBackend = WebGLFilterBackend | Canvas2dFilterBackend;\n\nlet filterBackend: FilterBackend;\n\n/**\n * Verifies if it is possible to initialize webgl or fallback on a canvas2d filtering backend\n */\nexport function initFilterBackend(): FilterBackend {\n const { WebGLProbe } = getEnv();\n WebGLProbe.queryWebGL(createCanvasElement());\n if (config.enableGLFiltering && WebGLProbe.isSupported(config.textureSize)) {\n return new WebGLFilterBackend({ tileSize: config.textureSize });\n } else {\n return new Canvas2dFilterBackend();\n }\n}\n\n/**\n * Get the current fabricJS filter backend or initialize one if not available yet\n * @param [strict] pass `true` to create the backend if it wasn't created yet (default behavior),\n * pass `false` to get the backend ref without mutating it\n */\nexport function getFilterBackend(strict = true): FilterBackend {\n if (!filterBackend && strict) {\n filterBackend = initFilterBackend();\n }\n return filterBackend;\n}\n\nexport function setFilterBackend(backend: FilterBackend) {\n filterBackend = backend;\n}\n","import { getFabricDocument, getEnv } from '../env';\nimport type { BaseFilter } from '../filters/BaseFilter';\nimport { getFilterBackend } from '../filters/FilterBackend';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type {\n TClassProperties,\n TCrossOrigin,\n TSize,\n Abortable,\n TOptions,\n} from '../typedefs';\nimport { uid } from '../util/internals/uid';\nimport { createCanvasElementFor } from '../util/misc/dom';\nimport { findScaleToCover, findScaleToFit } from '../util/misc/findScaleTo';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\nimport {\n enlivenObjectEnlivables,\n enlivenObjects,\n loadImage,\n} from '../util/misc/objectEnlive';\nimport { parsePreserveAspectRatioAttribute } from '../util/misc/svgParsing';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport { WebGLFilterBackend } from '../filters/WebGLFilterBackend';\nimport { FILL, NONE } from '../constants';\nimport { getDocumentFromElement } from '../util/dom_misc';\nimport type { CSSRules } from '../parser/typedefs';\nimport type { Resize, ResizeSerializedProps } from '../filters/Resize';\nimport type { TCachedFabricObject } from './Object/Object';\nimport { log } from '../util/internals/console';\n\n// @todo Would be nice to have filtering code not imported directly.\n\nexport type ImageSource =\n | HTMLImageElement\n | HTMLVideoElement\n | HTMLCanvasElement;\n\nexport type ParsedPAROffsets = {\n width: number;\n height: number;\n scaleX: number;\n scaleY: number;\n offsetLeft: number;\n offsetTop: number;\n cropX: number;\n cropY: number;\n};\n\ninterface UniqueImageProps {\n srcFromAttribute: boolean;\n minimumScaleTrigger: number;\n cropX: number;\n cropY: number;\n imageSmoothing: boolean;\n filters: BaseFilter<string, Record<string, any>>[];\n resizeFilter?: Resize;\n}\n\nexport const imageDefaultValues: Partial<TClassProperties<FabricImage>> = {\n strokeWidth: 0,\n srcFromAttribute: false,\n minimumScaleTrigger: 0.5,\n cropX: 0,\n cropY: 0,\n imageSmoothing: true,\n};\n\nexport interface SerializedImageProps extends SerializedObjectProps {\n src: string;\n crossOrigin: TCrossOrigin;\n filters: any[];\n resizeFilter?: ResizeSerializedProps;\n cropX: number;\n cropY: number;\n}\n\nexport interface ImageProps extends FabricObjectProps, UniqueImageProps {}\n\nconst IMAGE_PROPS = ['cropX', 'cropY'] as const;\n\n/**\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-1#images}\n */\nexport class FabricImage<\n Props extends TOptions<ImageProps> = Partial<ImageProps>,\n SProps extends SerializedImageProps = SerializedImageProps,\n EventSpec extends ObjectEvents = ObjectEvents,\n >\n extends FabricObject<Props, SProps, EventSpec>\n implements ImageProps\n{\n /**\n * When calling {@link FabricImage.getSrc}, return value from element src with `element.getAttribute('src')`.\n * This allows for relative urls as image src.\n * @since 2.7.0\n * @type Boolean\n * @default false\n */\n declare srcFromAttribute: boolean;\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 protected _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 protected _lastScaleY = 1;\n\n /**\n * private\n * contains last value of scaling applied by the apply filter chain\n * @type Number\n */\n protected _filterScalingX = 1;\n\n /**\n * private\n * contains last value of scaling applied by the apply filter chain\n * @type Number\n */\n protected _filterScalingY = 1;\n\n /**\n * minimum scale factor under which any resizeFilter is triggered to resize the image\n * 0 will disable the automatic resize. 1 will trigger automatically always.\n * number bigger than 1 are not implemented yet.\n * @type Number\n */\n declare minimumScaleTrigger: number;\n\n /**\n * key used to retrieve the texture representing this image\n * @since 2.0.0\n * @type String\n */\n declare cacheKey: string;\n\n /**\n * Image crop in pixels from original image size.\n * @since 2.0.0\n * @type Number\n */\n declare cropX: number;\n\n /**\n * Image crop in pixels from original image size.\n * @since 2.0.0\n * @type Number\n */\n declare cropY: number;\n\n /**\n * Indicates whether this canvas will use image smoothing when painting this image.\n * Also influence if the cacheCanvas for this image uses imageSmoothing\n * @since 4.0.0-beta.11\n * @type Boolean\n */\n declare imageSmoothing: boolean;\n\n declare preserveAspectRatio: string;\n\n declare protected src: string;\n\n declare filters: BaseFilter<string, Record<string, any>>[];\n declare resizeFilter: Resize;\n\n declare _element: ImageSource;\n declare _filteredEl?: HTMLCanvasElement;\n declare _originalElement: ImageSource;\n\n static type = 'Image';\n\n static cacheProperties = [...cacheProperties, ...IMAGE_PROPS];\n\n static ownDefaults = imageDefaultValues;\n\n static getDefaults(): Record<string, any> {\n return {\n ...super.getDefaults(),\n ...FabricImage.ownDefaults,\n };\n }\n /**\n * Constructor\n * Image can be initialized with any canvas drawable or a string.\n * The string should be a url and will be loaded as an image.\n * Canvas and Image element work out of the box, while videos require extra code to work.\n * Please check video element events for seeking.\n * @param {ImageSource | string} element Image element\n * @param {Object} [options] Options object\n */\n constructor(elementId: string, options?: Props);\n constructor(element: ImageSource, options?: Props);\n constructor(arg0: ImageSource | string, options?: Props) {\n super();\n this.filters = [];\n Object.assign(this, FabricImage.ownDefaults);\n this.setOptions(options);\n this.cacheKey = `texture${uid()}`;\n this.setElement(\n typeof arg0 === 'string'\n ? ((\n (this.canvas && getDocumentFromElement(this.canvas.getElement())) ||\n getFabricDocument()\n ).getElementById(arg0) as ImageSource)\n : arg0,\n options,\n );\n }\n\n /**\n * Returns image element which this instance if based on\n */\n getElement() {\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 {Partial<TSize>} [size] Options object\n */\n setElement(element: ImageSource, size: Partial<TSize> = {}) {\n this.removeTexture(this.cacheKey);\n this.removeTexture(`${this.cacheKey}_filtered`);\n this._element = element;\n this._originalElement = element;\n this._setWidthHeight(size);\n if (this.filters.length !== 0) {\n this.applyFilters();\n }\n // resizeFilters work on the already filtered copy.\n // we need to apply resizeFilters AFTER normal filters.\n // applyResizeFilters is run more often than normal filters\n // and is triggered by user interactions rather than dev code\n if (this.resizeFilter) {\n this.applyResizeFilters();\n }\n }\n\n /**\n * Delete a single texture if in webgl mode\n */\n removeTexture(key: string) {\n const backend = getFilterBackend(false);\n if (backend instanceof WebGLFilterBackend) {\n backend.evictCachesForKey(key);\n }\n }\n\n /**\n * Delete textures, reference to elements and eventually JSDOM cleanup\n */\n dispose() {\n super.dispose();\n this.removeTexture(this.cacheKey);\n this.removeTexture(`${this.cacheKey}_filtered`);\n this._cacheContext = null;\n (\n ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'] as const\n ).forEach((elementKey) => {\n const el = this[elementKey];\n el && getEnv().dispose(el);\n // @ts-expect-error disposing\n this[elementKey] = undefined;\n });\n }\n\n /**\n * Get the crossOrigin value (of the corresponding image element)\n */\n getCrossOrigin(): string | null {\n return (\n this._originalElement &&\n ((this._originalElement as any).crossOrigin || null)\n );\n }\n\n /**\n * Returns original size of an image\n */\n getOriginalSize() {\n const element = this.getElement() as any;\n if (!element) {\n return {\n width: 0,\n height: 0,\n };\n }\n return {\n width: element.naturalWidth || element.width,\n height: element.naturalHeight || element.height,\n };\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _stroke(ctx: CanvasRenderingContext2D) {\n if (!this.stroke || this.strokeWidth === 0) {\n return;\n }\n const w = this.width / 2,\n h = this.height / 2;\n ctx.beginPath();\n ctx.moveTo(-w, -h);\n ctx.lineTo(w, -h);\n ctx.lineTo(w, h);\n ctx.lineTo(-w, h);\n ctx.lineTo(-w, -h);\n ctx.closePath();\n }\n\n /**\n * Returns object representation of an instance\n * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n * @return {Object} Object representation of an instance\n */\n toObject<\n T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n K extends keyof T = never,\n >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n const filters: Record<string, any>[] = [];\n this.filters.forEach((filterObj) => {\n filterObj && filters.push(filterObj.toObject());\n });\n return {\n ...super.toObject([...IMAGE_PROPS, ...propertiesToInclude]),\n src: this.getSrc(),\n crossOrigin: this.getCrossOrigin(),\n filters,\n ...(this.resizeFilter\n ? { resizeFilter: this.resizeFilter.toObject() }\n : {}),\n };\n }\n\n /**\n * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,height.\n * @return {Boolean}\n */\n hasCrop() {\n return (\n !!this.cropX ||\n !!this.cropY ||\n this.width < this._element.width ||\n this.height < this._element.height\n );\n }\n\n /**\n * Returns svg representation of an instance\n * @return {string[]} an array of strings with the specific svg representation\n * of the instance\n */\n _toSVG() {\n const imageMarkup: string[] = [],\n element = this._element,\n x = -this.width / 2,\n y = -this.height / 2;\n let svgString: string[] = [],\n strokeSvg: string[] = [],\n clipPath = '',\n imageRendering = '';\n if (!element) {\n return [];\n }\n if (this.hasCrop()) {\n const clipPathId = uid();\n svgString.push(\n '<clipPath id=\"imageCrop_' + clipPathId + '\">\\n',\n '\\t<rect x=\"' +\n x +\n '\" y=\"' +\n y +\n '\" width=\"' +\n this.width +\n '\" height=\"' +\n this.height +\n '\" />\\n',\n '</clipPath>\\n',\n );\n clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n }\n if (!this.imageSmoothing) {\n imageRendering = ' image-rendering=\"optimizeSpeed\"';\n }\n imageMarkup.push(\n '\\t<image ',\n 'COMMON_PARTS',\n `xlink:href=\"${this.getSvgSrc(true)}\" x=\"${x - this.cropX}\" y=\"${\n y - this.cropY\n // we're essentially moving origin of transformation from top/left corner to the center of the shape\n // by wrapping it in container <g> 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=\"${\n element.width || (element as HTMLImageElement).naturalWidth\n }\" height=\"${\n element.height || (element as HTMLImageElement).naturalHeight\n }\"${imageRendering}${clipPath}></image>\\n`,\n );\n\n if (this.stroke || this.strokeDashArray) {\n const origFill = this.fill;\n this.fill = null;\n strokeSvg = [\n `\\t<rect x=\"${x}\" y=\"${y}\" width=\"${this.width}\" height=\"${\n this.height\n }\" style=\"${this.getSvgStyles()}\" />\\n`,\n ];\n this.fill = origFill;\n }\n if (this.paintFirst !== FILL) {\n svgString = svgString.concat(strokeSvg, imageMarkup);\n } else {\n svgString = svgString.concat(imageMarkup, strokeSvg);\n }\n return svgString;\n }\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(filtered?: boolean): string {\n const element = filtered ? this._element : this._originalElement;\n if (element) {\n if ((element as HTMLCanvasElement).toDataURL) {\n return (element as HTMLCanvasElement).toDataURL();\n }\n\n if (this.srcFromAttribute) {\n return element.getAttribute('src') || '';\n } else {\n return (element as HTMLImageElement).src;\n }\n } else {\n return this.src || '';\n }\n }\n\n /**\n * Alias for getSrc\n * @param filtered\n * @deprecated\n */\n getSvgSrc(filtered?: boolean) {\n return this.getSrc(filtered);\n }\n\n /**\n * Loads and sets source of an image\\\n * **IMPORTANT**: It is recommended to abort loading tasks before calling this method to prevent race conditions and unnecessary networking\n * @param {String} src Source string (URL)\n * @param {LoadImageOptions} [options] Options object\n */\n setSrc(src: string, { crossOrigin, signal }: LoadImageOptions = {}) {\n return loadImage(src, { crossOrigin, signal }).then((img) => {\n typeof crossOrigin !== 'undefined' && this.set({ crossOrigin });\n this.setElement(img);\n });\n }\n\n /**\n * Returns string representation of an instance\n * @return {String} String representation of an instance\n */\n toString() {\n return `#<Image: { src: \"${this.getSrc()}\" }>`;\n }\n\n applyResizeFilters() {\n const filter = this.resizeFilter,\n minimumScale = this.minimumScaleTrigger,\n objectScale = this.getTotalObjectScaling(),\n scaleX = objectScale.x,\n scaleY = objectScale.y,\n elementToFilter = this._filteredEl || this._originalElement;\n if (this.group) {\n this.set('dirty', true);\n }\n if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {\n this._element = elementToFilter;\n this._filterScalingX = 1;\n this._filterScalingY = 1;\n this._lastScaleX = scaleX;\n this._lastScaleY = scaleY;\n return;\n }\n const canvasEl = createCanvasElementFor(elementToFilter),\n { width, height } = elementToFilter;\n this._element = canvasEl;\n this._lastScaleX = filter.scaleX = scaleX;\n this._lastScaleY = filter.scaleY = scaleY;\n getFilterBackend().applyFilters(\n [filter],\n elementToFilter,\n width,\n height,\n this._element,\n );\n this._filterScalingX = canvasEl.width / this._originalElement.width;\n this._filterScalingY = canvasEl.height / this._originalElement.height;\n }\n\n /**\n * Applies filters assigned to this image (from \"filters\" array) or from filter param\n * @param {Array} filters to be applied\n * @param {Boolean} forResizing specify if the filter operation is a resize operation\n */\n applyFilters(\n filters: BaseFilter<string, Record<string, any>>[] = this.filters || [],\n ) {\n filters = filters.filter((filter) => filter && !filter.isNeutralState());\n this.set('dirty', true);\n\n // needs to clear out or WEBGL will not resize correctly\n this.removeTexture(`${this.cacheKey}_filtered`);\n\n if (filters.length === 0) {\n this._element = this._originalElement;\n // this is unsafe and needs to be rethinkend\n this._filteredEl = undefined;\n this._filterScalingX = 1;\n this._filterScalingY = 1;\n return;\n }\n\n const imgElement = this._originalElement,\n sourceWidth =\n (imgElement as HTMLImageElement).naturalWidth || imgElement.width,\n sourceHeight =\n (imgElement as HTMLImageElement).naturalHeight || imgElement.height;\n\n if (this._element === this._originalElement) {\n // if the _element a reference to _originalElement\n // we need to create a new element to host the filtered pixels\n const canvasEl = createCanvasElementFor({\n width: sourceWidth,\n height: sourceHeight,\n });\n this._element = canvasEl;\n this._filteredEl = canvasEl;\n } else if (this._filteredEl) {\n // if the _element is it own element,\n // and we also have a _filteredEl, then we clean up _filteredEl\n // and we assign it to _element.\n // in this way we invalidate the eventual old resize filtered element\n this._element = this._filteredEl;\n this._filteredEl\n .getContext('2d')!\n .clearRect(0, 0, sourceWidth, sourceHeight);\n // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\n this._lastScaleX = 1;\n this._lastScaleY = 1;\n }\n getFilterBackend().applyFilters(\n filters,\n this._originalElement,\n sourceWidth,\n sourceHeight,\n this._element as HTMLCanvasElement,\n this.cacheKey,\n );\n if (\n this._originalElement.width !== this._element.width ||\n this._originalElement.height !== this._element.height\n ) {\n this._filterScalingX = this._element.width / this._originalElement.width;\n this._filterScalingY =\n this._element.height / this._originalElement.height;\n }\n }\n\n /**\n * @private\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n _render(ctx: CanvasRenderingContext2D) {\n ctx.imageSmoothingEnabled = this.imageSmoothing;\n if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\n this.applyResizeFilters();\n }\n this._stroke(ctx);\n this._renderPaintInOrder(ctx);\n }\n\n /**\n * Paint the cached copy of the object on the target context.\n * it will set the imageSmoothing for the draw operation\n * @param {CanvasRenderingContext2D} ctx Context to render on\n */\n drawCacheOnCanvas(\n this: TCachedFabricObject<FabricImage>,\n ctx: CanvasRenderingContext2D,\n ) {\n ctx.imageSmoothingEnabled = this.imageSmoothing;\n super.drawCacheOnCanvas(ctx);\n }\n\n /**\n * Decide if the FabricImage should cache or not. Create its own cache level\n * needsItsOwnCache should be used when the object drawing method requires\n * a cache step.\n * Generally you do not cache objects in groups because the group outside is cached.\n * This is the special Image version where we would like to avoid caching where possible.\n * Essentially images do not benefit from caching. They may require caching, and in that\n * case we do it. Also caching an image usually ends in a loss of details.\n * A full performance audit should be done.\n * @return {Boolean}\n */\n shouldCache() {\n return this.needsItsOwnCache();\n }\n\n _renderFill(ctx: CanvasRenderingContext2D) {\n const elementToDraw = this._element;\n if (!elementToDraw) {\n return;\n }\n const scaleX = this._filterScalingX,\n scaleY = this._filterScalingY,\n w = this.width,\n h = this.height,\n // crop values cannot be lesser than 0.\n cropX = Math.max(this.cropX, 0),\n cropY = Math.max(this.cropY, 0),\n elWidth =\n (elementToDraw as HTMLImageElement).naturalWidth || elementToDraw.width,\n elHeight =\n (elementToDraw as HTMLImageElement).naturalHeight ||\n elementToDraw.height,\n sX = cropX * scaleX,\n sY = cropY * scaleY,\n // the width height cannot exceed element width/height, starting from the crop offset.\n sW = Math.min(w * scaleX, elWidth - sX),\n sH = Math.min(h * scaleY, elHeight - sY),\n x = -w / 2,\n y = -h / 2,\n maxDestW = Math.min(w, elWidth / scaleX - cropX),\n maxDestH = Math.min(h, elHeight / scaleY - cropY);\n\n elementToDraw &&\n ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\n }\n\n /**\n * needed to check if image needs resize\n * @private\n */\n _needsResize() {\n const scale = this.getTotalObjectScaling();\n return scale.x !== this._lastScaleX || scale.y !== this._lastScaleY;\n }\n\n /**\n * @private\n * @deprecated unused\n */\n _resetWidthHeight() {\n this.set(this.getOriginalSize());\n }\n\n /**\n * @private\n * Set the width and the height of the image object, using the element or the\n * options.\n */\n _setWidthHeight({ width, height }: Partial<TSize> = {}) {\n const size = this.getOriginalSize();\n this.width = width || size.width;\n this.height = height || size.height;\n }\n\n /**\n * Calculate offset for center and scale factor for the image in order to respect\n * the preserveAspectRatio attribute\n * @private\n */\n parsePreserveAspectRatioAttribute(): ParsedPAROffsets {\n const pAR = parsePreserveAspectRatioAttribute(\n this.preserveAspectRatio || '',\n ),\n pWidth = this.width,\n pHeight = this.height,\n parsedAttributes = { width: pWidth, height: pHeight };\n let rWidth = this._element.width,\n rHeight = this._element.height,\n scaleX = 1,\n scaleY = 1,\n offsetLeft = 0,\n offsetTop = 0,\n cropX = 0,\n cropY = 0,\n offset;\n\n if (pAR && (pAR.alignX !== NONE || pAR.alignY !== NONE)) {\n if (pAR.meetOrSlice === 'meet') {\n scaleX = scaleY = findScaleToFit(this._element, parsedAttributes);\n offset = (pWidth - rWidth * scaleX) / 2;\n if (pAR.alignX === 'Min') {\n offsetLeft = -offset;\n }\n if (pAR.alignX === 'Max') {\n offsetLeft = offset;\n }\n offset = (pHeight - rHeight * scaleY) / 2;\n if (pAR.alignY === 'Min') {\n offsetTop = -offset;\n }\n if (pAR.alignY === 'Max') {\n offsetTop = offset;\n }\n }\n if (pAR.meetOrSlice === 'slice') {\n scaleX = scaleY = findScaleToCover(this._element, parsedAttributes);\n offset = rWidth - pWidth / scaleX;\n if (pAR.alignX === 'Mid') {\n cropX = offset / 2;\n }\n if (pAR.alignX === 'Max') {\n cropX = offset;\n }\n offset = rHeight - pHeight / scaleY;\n if (pAR.alignY === 'Mid') {\n cropY = offset / 2;\n }\n if (pAR.alignY === 'Max') {\n cropY = offset;\n }\n rWidth = pWidth / scaleX;\n rHeight = pHeight / scaleY;\n }\n } else {\n scaleX = pWidth / rWidth;\n scaleY = pHeight / rHeight;\n }\n return {\n width: rWidth,\n height: rHeight,\n scaleX,\n scaleY,\n offsetLeft,\n offsetTop,\n cropX,\n cropY,\n };\n }\n\n /**\n * List of attribute names to account for when parsing SVG element (used by {@link FabricImage.fromElement})\n * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n */\n static ATTRIBUTE_NAMES = [\n ...SHARED_ATTRIBUTES,\n 'x',\n 'y',\n 'width',\n 'height',\n 'preserveAspectRatio',\n 'xlink:href',\n 'href',\n 'crossOrigin',\n 'image-rendering',\n ];\n\n /**\n * Creates an instance of FabricImage from its object representation\n * @param {Object} object Object to create an instance from\n * @param {object} [options] Options object\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricImage>}\n */\n static fromObject<T extends TOptions<SerializedImageProps>>(\n { filters: f, resizeFilter: rf, src, crossOrigin, type, ...object }: T,\n options?: Abortable,\n ) {\n return Promise.all([\n loadImage(src!, { ...options, crossOrigin }),\n f && enlivenObjects<BaseFilter<string>>(f, options),\n // redundant - handled by enlivenObjectEnlivables, but nicely explicit\n rf ? enlivenObjects<Resize>([rf], options) : [],\n enlivenObjectEnlivables(object, options),\n ]).then(([el, filters = [], [resizeFilter], hydratedProps = {}]) => {\n return new this(el, {\n ...object,\n // TODO: passing src creates a difference between image creation and restoring from JSON\n src,\n filters,\n resizeFilter,\n ...hydratedProps,\n });\n });\n }\n\n /**\n * Creates an instance of Image from an URL string\n * @param {String} url URL to create an image from\n * @param {LoadImageOptions} [options] Options object\n * @returns {Promise<FabricImage>}\n */\n static fromURL<T extends TOptions<ImageProps>>(\n url: string,\n { crossOrigin = null, signal }: LoadImageOptions = {},\n imageOptions?: T,\n ): Promise<FabricImage> {\n return loadImage(url, { crossOrigin, signal }).then(\n (img) => new this(img, imageOptions),\n );\n }\n\n /**\n * Returns {@link FabricImage} instance from an SVG element\n * @param {HTMLElement} element Element to parse\n * @param {Object} [options] Options object\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @param {Function} callback Callback to execute when Image object is created\n */\n static async fromElement(\n element: HTMLElement,\n options: Abortable = {},\n cssRules?: CSSRules,\n ) {\n const parsedAttributes = parseAttributes(\n element,\n this.ATTRIBUTE_NAMES,\n cssRules,\n );\n return this.fromURL(\n parsedAttributes['xlink:href'] || parsedAttributes['href'],\n options,\n parsedAttributes,\n ).catch((err) => {\n log('log', 'Unable to parse Image', err);\n return null;\n });\n }\n}\n\nclassRegistry.setClass(FabricImage);\nclassRegistry.setSVGClass(FabricImage);\n","import { svgNS } from './constants';\nimport {\n parsePreserveAspectRatioAttribute,\n parseUnit,\n} from '../util/misc/svgParsing';\nimport { svgViewBoxElementsRegEx, reViewBoxAttrValue } from './constants';\nimport { NONE } from '../constants';\n\nexport type ParsedViewboxTransform = Partial<{\n width: number;\n height: number;\n minX: number;\n minY: number;\n viewBoxWidth: number;\n viewBoxHeight: number;\n}>;\n\n/**\n * Add a <g> element that envelop all child elements and makes the viewbox transformMatrix descend on all elements\n */\nexport function applyViewboxTransform(\n element: Element,\n): ParsedViewboxTransform {\n if (!svgViewBoxElementsRegEx.test(element.nodeName)) {\n return {};\n }\n const viewBoxAttr: string | null = element.getAttribute('viewBox');\n let scaleX = 1;\n let scaleY = 1;\n let minX = 0;\n let minY = 0;\n let matrix;\n let el;\n const widthAttr = element.getAttribute('width');\n const heightAttr = element.getAttribute('height');\n const x = element.getAttribute('x') || 0;\n const y = element.getAttribute('y') || 0;\n const goodViewbox = viewBoxAttr && reViewBoxAttrValue.test(viewBoxAttr);\n const missingViewBox = !goodViewbox;\n const missingDimAttr =\n !widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%';\n\n let translateMatrix = '';\n let widthDiff = 0;\n let heightDiff = 0;\n\n if (missingViewBox) {\n if (\n (x || y) &&\n element.parentNode &&\n element.parentNode.nodeName !== '#document'\n ) {\n translateMatrix =\n ' translate(' + parseUnit(x || '0') + ' ' + parseUnit(y || '0') + ') ';\n matrix = (element.getAttribute('transform') || '') + translateMatrix;\n element.setAttribute('transform', matrix);\n element.removeAttribute('x');\n element.removeAttribute('y');\n }\n }\n\n if (missingViewBox && missingDimAttr) {\n return {\n width: 0,\n height: 0,\n };\n }\n\n const parsedDim: ParsedViewboxTransform = {\n width: 0,\n height: 0,\n };\n\n if (missingViewBox) {\n parsedDim.width = parseUnit(widthAttr!);\n parsedDim.height = parseUnit(heightAttr!);\n // set a transform for elements that have x y and are inner(only) SVGs\n return parsedDim;\n }\n\n const pasedViewBox = viewBoxAttr.match(reViewBoxAttrValue)!;\n minX = -parseFloat(pasedViewBox[1]);\n minY = -parseFloat(pasedViewBox[2]);\n const viewBoxWidth = parseFloat(pasedViewBox[3]);\n const viewBoxHeight = parseFloat(pasedViewBox[4]);\n parsedDim.minX = minX;\n parsedDim.minY = minY;\n parsedDim.viewBoxWidth = viewBoxWidth;\n parsedDim.viewBoxHeight = viewBoxHeight;\n if (!missingDimAttr) {\n parsedDim.width = parseUnit(widthAttr);\n parsedDim.height = parseUnit(heightAttr);\n scaleX = parsedDim.width / viewBoxWidth;\n scaleY = parsedDim.height / viewBoxHeight;\n } else {\n parsedDim.width = viewBoxWidth;\n parsedDim.height = viewBoxHeight;\n }\n\n // default is to preserve aspect ratio\n const preserveAspectRatio = parsePreserveAspectRatioAttribute(\n element.getAttribute('preserveAspectRatio') || '',\n );\n if (preserveAspectRatio.alignX !== NONE) {\n //translate all container for the effect of Mid, Min, Max\n if (preserveAspectRatio.meetOrSlice === 'meet') {\n scaleY = scaleX = scaleX > scaleY ? scaleY : scaleX;\n // calculate additional translation to move the viewbox\n }\n if (preserveAspectRatio.meetOrSlice === 'slice') {\n scaleY = scaleX = scaleX > scaleY ? scaleX : scaleY;\n // calculate additional translation to move the viewbox\n }\n widthDiff = parsedDim.width - viewBoxWidth * scaleX;\n heightDiff = parsedDim.height - viewBoxHeight * scaleX;\n if (preserveAspectRatio.alignX === 'Mid') {\n widthDiff /= 2;\n }\n if (preserveAspectRatio.alignY === 'Mid') {\n heightDiff /= 2;\n }\n if (preserveAspectRatio.alignX === 'Min') {\n widthDiff = 0;\n }\n if (preserveAspectRatio.alignY === 'Min') {\n heightDiff = 0;\n }\n }\n\n if (\n scaleX === 1 &&\n scaleY === 1 &&\n minX === 0 &&\n minY === 0 &&\n x === 0 &&\n y === 0\n ) {\n return parsedDim;\n }\n if ((x || y) && element.parentNode!.nodeName !== '#document') {\n translateMatrix =\n ' translate(' + parseUnit(x || '0') + ' ' + parseUnit(y || '0') + ') ';\n }\n\n matrix =\n translateMatrix +\n ' matrix(' +\n scaleX +\n ' 0' +\n ' 0 ' +\n scaleY +\n ' ' +\n (minX * scaleX + widthDiff) +\n ' ' +\n (minY * scaleY + heightDiff) +\n ') ';\n // seems unused.\n // parsedDim.viewboxTransform = parseTransformAttribute(matrix);\n if (element.nodeName === 'svg') {\n el = element.ownerDocument.createElementNS(svgNS, 'g');\n // element.firstChild != null\n while (element.firstChild) {\n el.appendChild(element.firstChild);\n }\n element.appendChild(el);\n } else {\n el = element;\n el.removeAttribute('x');\n el.removeAttribute('y');\n matrix = el.getAttribute('transform') + matrix;\n }\n el.setAttribute('transform', matrix);\n return parsedDim;\n}\n","export const getTagName = (node: Element) => node.tagName.replace('svg:', '');\n","import { svgInvalidAncestors } from './constants';\nimport { getSvgRegex } from './getSvgRegex';\nimport { getTagName } from './getTagName';\n\nconst svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);\n\nexport function hasInvalidAncestor(element: Element) {\n let _element: Element | null = element;\n while (_element && (_element = _element.parentElement)) {\n if (\n _element &&\n _element.nodeName &&\n svgInvalidAncestorsRegEx.test(getTagName(_element)) &&\n !_element.getAttribute('instantiated_by_use')\n ) {\n return true;\n }\n }\n return false;\n}\n","export function getMultipleNodes(\n doc: Document,\n nodeNames: string[],\n): Element[] {\n let nodeName,\n nodeArray: Element[] = [],\n nodeList,\n i,\n len;\n for (i = 0, len = nodeNames.length; i < len; i++) {\n nodeName = nodeNames[i];\n nodeList = doc.getElementsByTagNameNS(\n 'http://www.w3.org/2000/svg',\n nodeName,\n );\n nodeArray = nodeArray.concat(Array.from(nodeList));\n }\n return nodeArray;\n}\n","const gradientsAttrs = [\n 'gradientTransform',\n 'x1',\n 'x2',\n 'y1',\n 'y2',\n 'gradientUnits',\n 'cx',\n 'cy',\n 'r',\n 'fx',\n 'fy',\n];\nconst xlinkAttr = 'xlink:href';\n\nexport function recursivelyParseGradientsXlink(\n doc: Document,\n gradient: Element,\n) {\n const xLink = gradient.getAttribute(xlinkAttr)?.slice(1) || '',\n referencedGradient = doc.getElementById(xLink);\n if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {\n recursivelyParseGradientsXlink(doc, referencedGradient as Element);\n }\n if (referencedGradient) {\n gradientsAttrs.forEach((attr) => {\n const value = referencedGradient.getAttribute(attr);\n if (!gradient.hasAttribute(attr) && value) {\n gradient.setAttribute(attr, value);\n }\n });\n if (!gradient.children.length) {\n const referenceClone = referencedGradient.cloneNode(true);\n while (referenceClone.firstChild) {\n gradient.appendChild(referenceClone.firstChild);\n }\n }\n }\n gradient.removeAttribute(xlinkAttr);\n}\n","import { getMultipleNodes } from './getMultipleNodes';\nimport { recursivelyParseGradientsXlink } from './recursivelyParseGradientsXlink';\n\nconst tagArray = [\n 'linearGradient',\n 'radialGradient',\n 'svg:linearGradient',\n 'svg:radialGradient',\n];\n\n/**\n * Parses an SVG document, returning all of the gradient declarations found in it\n * @param {SVGDocument} doc SVG document to parse\n * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element\n */\nexport function getGradientDefs(\n doc: Document,\n): Record<string, SVGGradientElement> {\n const elList = getMultipleNodes(doc, tagArray);\n const gradientDefs: Record<string, SVGGradientElement> = {};\n let j = elList.length;\n while (j--) {\n const el = elList[j];\n if (el.getAttribute('xlink:href')) {\n recursivelyParseGradientsXlink(doc, el);\n }\n const id = el.getAttribute('id');\n if (id) {\n gradientDefs[id] = el as SVGGradientElement;\n }\n }\n return gradientDefs;\n}\n","import { Gradient } from '../gradient/Gradient';\nimport { Group } from '../shapes/Group';\nimport { FabricImage } from '../shapes/Image';\nimport { classRegistry } from '../ClassRegistry';\nimport {\n invertTransform,\n multiplyTransformMatrices,\n qrDecompose,\n} from '../util/misc/matrix';\nimport { removeTransformMatrixForSvgParsing } from '../util/transform_matrix_removal';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport { Point } from '../Point';\nimport { CENTER, FILL, STROKE } from '../constants';\nimport { getGradientDefs } from './getGradientDefs';\nimport { getCSSRules } from './getCSSRules';\nimport type { LoadImageOptions } from '../util';\nimport type { CSSRules, TSvgReviverCallback } from './typedefs';\nimport type { ParsedViewboxTransform } from './applyViewboxTransform';\nimport type { SVGOptions } from '../gradient';\nimport { getTagName } from './getTagName';\nimport { parseTransformAttribute } from './parseTransformAttribute';\n\nconst findTag = (el: Element) =>\n classRegistry.getSVGClass(getTagName(el).toLowerCase());\n\ntype StorageType = {\n fill: SVGGradientElement;\n stroke: SVGGradientElement;\n clipPath: Element[];\n};\n\ntype NotParsedFabricObject = FabricObject & {\n fill: string;\n stroke: string;\n clipPath?: string;\n clipRule?: CanvasFillRule;\n};\n\nexport class ElementsParser {\n declare elements: Element[];\n declare options: LoadImageOptions & ParsedViewboxTransform;\n declare reviver?: TSvgReviverCallback;\n declare regexUrl: RegExp;\n declare doc: Document;\n declare clipPaths: Record<string, Element[]>;\n declare gradientDefs: Record<string, SVGGradientElement>;\n declare cssRules: CSSRules;\n\n constructor(\n elements: Element[],\n options: LoadImageOptions & ParsedViewboxTransform,\n reviver: TSvgReviverCallback | undefined,\n doc: Document,\n clipPaths: Record<string, Element[]>,\n ) {\n this.elements = elements;\n this.options = options;\n this.reviver = reviver;\n this.regexUrl = /^url\\(['\"]?#([^'\"]+)['\"]?\\)/g;\n this.doc = doc;\n this.clipPaths = clipPaths;\n this.gradientDefs = getGradientDefs(doc);\n this.cssRules = getCSSRules(doc);\n }\n\n parse(): Promise<Array<FabricObject | null>> {\n return Promise.all(\n this.elements.map((element) => this.createObject(element)),\n );\n }\n\n async createObject(el: Element): Promise<FabricObject | null> {\n const klass = findTag(el);\n if (klass) {\n const obj: NotParsedFabricObject = await klass.fromElement(\n el,\n this.options,\n this.cssRules,\n );\n this.resolveGradient(obj, el, FILL);\n this.resolveGradient(obj, el, STROKE);\n if (obj instanceof FabricImage && obj._originalElement) {\n removeTransformMatrixForSvgParsing(\n obj,\n obj.parsePreserveAspectRatioAttribute(),\n );\n } else {\n removeTransformMatrixForSvgParsing(obj);\n }\n await this.resolveClipPath(obj, el);\n this.reviver && this.reviver(el, obj);\n return obj;\n }\n return null;\n }\n\n extractPropertyDefinition(\n obj: NotParsedFabricObject,\n property: 'fill' | 'stroke' | 'clipPath',\n storage: Record<string, StorageType[typeof property]>,\n ): StorageType[typeof property] | undefined {\n const value = obj[property]!,\n regex = this.regexUrl;\n if (!regex.test(value)) {\n return undefined;\n }\n // verify: can we remove the 'g' flag? and remove lastIndex changes?\n regex.lastIndex = 0;\n // we passed the regex test, so we know is not null;\n const id = regex.exec(value)![1];\n regex.lastIndex = 0;\n // @todo fix this\n return storage[id];\n }\n\n resolveGradient(\n obj: NotParsedFabricObject,\n el: Element,\n property: 'fill' | 'stroke',\n ) {\n const gradientDef = this.extractPropertyDefinition(\n obj,\n property,\n this.gradientDefs,\n ) as SVGGradientElement;\n if (gradientDef) {\n const opacityAttr = el.getAttribute(property + '-opacity');\n const gradient = Gradient.fromElement(gradientDef, obj, {\n ...this.options,\n opacity: opacityAttr,\n } as SVGOptions);\n obj.set(property, gradient);\n }\n }\n\n // TODO: resolveClipPath could be run once per clippath with minor work per object.\n // is a refactor that i m not sure is worth on this code\n async resolveClipPath(\n obj: NotParsedFabricObject,\n usingElement: Element,\n exactOwner?: Element,\n ) {\n const clipPathElements = this.extractPropertyDefinition(\n obj,\n 'clipPath',\n this.clipPaths,\n ) as Element[];\n if (clipPathElements) {\n const objTransformInv = invertTransform(obj.calcTransformMatrix());\n const clipPathTag = clipPathElements[0].parentElement!;\n let clipPathOwner = usingElement;\n while (\n !exactOwner &&\n clipPathOwner.parentElement &&\n clipPathOwner.getAttribute('clip-path') !== obj.clipPath\n ) {\n clipPathOwner = clipPathOwner.parentElement;\n }\n // move the clipPath tag as sibling to the real element that is using it\n clipPathOwner.parentElement!.appendChild(clipPathTag);\n\n // this multiplication order could be opposite.\n // but i don't have an svg to test it\n // at the first SVG that has a transform on both places and is misplaced\n // try to invert this multiplication order\n const finalTransform = parseTransformAttribute(\n `${clipPathOwner.getAttribute('transform') || ''} ${\n clipPathTag.getAttribute('originalTransform') || ''\n }`,\n );\n\n clipPathTag.setAttribute(\n 'transform',\n `matrix(${finalTransform.join(',')})`,\n );\n\n const container = await Promise.all(\n clipPathElements.map((clipPathElement) => {\n return findTag(clipPathElement)\n .fromElement(clipPathElement, this.options, this.cssRules)\n .then((enlivedClippath: NotParsedFabricObject) => {\n removeTransformMatrixForSvgParsing(enlivedClippath);\n enlivedClippath.fillRule = enlivedClippath.clipRule!;\n delete enlivedClippath.clipRule;\n return enlivedClippath;\n });\n }),\n );\n const clipPath =\n container.length === 1 ? container[0] : new Group(container);\n const gTransform = multiplyTransformMatrices(\n objTransformInv,\n clipPath.calcTransformMatrix(),\n );\n if (clipPath.clipPath) {\n await this.resolveClipPath(\n clipPath,\n clipPathOwner,\n // this is tricky.\n // it tries to differentiate from when clipPaths are inherited by outside groups\n // or when are really clipPaths referencing other clipPaths\n clipPathTag.getAttribute('clip-path') ? clipPathOwner : undefined,\n );\n }\n const { scaleX, scaleY, angle, skewX, translateX, translateY } =\n qrDecompose(gTransform);\n clipPath.set({\n flipX: false,\n flipY: false,\n });\n clipPath.set({\n scaleX,\n scaleY,\n angle,\n skewX,\n skewY: 0,\n });\n clipPath.setPositionByOrigin(\n new Point(translateX, translateY),\n CENTER,\n CENTER,\n );\n obj.clipPath = clipPath;\n } else {\n // if clip-path does not resolve to any element, delete the property.\n delete obj.clipPath;\n return;\n }\n }\n}\n","import type { CSSRules } from './typedefs';\n\n/**\n * Returns CSS rules for a given SVG document\n * @param {HTMLElement} doc SVG document to parse\n * @return {Object} CSS rules of this document\n */\nexport function getCSSRules(doc: Document) {\n const styles = doc.getElementsByTagName('style');\n const allRules: CSSRules = {};\n\n // very crude parsing of style contents\n for (let i = 0; i < styles.length; i++) {\n const styleContents = (styles[i].textContent || '').replace(\n // remove comments\n /\\/\\*[\\s\\S]*?\\*\\//g,\n '',\n );\n\n if (styleContents.trim() === '') {\n continue;\n }\n // recovers all the rule in this form `body { style code... }`\n // rules = styleContents.match(/[^{]*\\{[\\s\\S]*?\\}/g);\n styleContents\n .split('}')\n // remove empty rules and remove everything if we didn't split in at least 2 pieces\n .filter((rule, index, array) => array.length > 1 && rule.trim())\n // at this point we have hopefully an array of rules `body { style code... `\n .forEach((rule) => {\n // if there is more than one opening bracket and the rule starts with '@', it is likely\n // a nested at-rule like @media, @supports, @scope, etc. Ignore these as the code below\n // can not handle it.\n if (\n (rule.match(/{/g) || []).length > 1 &&\n rule.trim().startsWith('@')\n ) {\n return;\n }\n\n const match = rule.split('{'),\n ruleObj: Record<string, string> = {},\n declaration = match[1].trim(),\n propertyValuePairs = declaration.split(';').filter(function (pair) {\n return pair.trim();\n });\n\n for (let j = 0; j < propertyValuePairs.length; j++) {\n const pair = propertyValuePairs[j].split(':'),\n property = pair[0].trim(),\n value = pair[1].trim();\n ruleObj[property] = value;\n }\n rule = match[0].trim();\n rule.split(',').forEach((_rule) => {\n _rule = _rule.replace(/^svg/i, '').trim();\n if (_rule === '') {\n return;\n }\n allRules[_rule] = {\n ...(allRules[_rule] || {}),\n ...ruleObj,\n };\n });\n });\n }\n return allRules;\n}\n","import { applyViewboxTransform } from './applyViewboxTransform';\nimport { svgValidTagNamesRegEx } from './constants';\nimport { hasInvalidAncestor } from './hasInvalidAncestor';\nimport { parseUseDirectives } from './parseUseDirectives';\nimport type { SVGParsingOutput, TSvgReviverCallback } from './typedefs';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\nimport { ElementsParser } from './elements_parser';\nimport { log, SignalAbortedError } from '../util/internals/console';\nimport { getTagName } from './getTagName';\n\nconst isValidSvgTag = (el: Element) =>\n svgValidTagNamesRegEx.test(getTagName(el));\n\nexport const createEmptyResponse = (): SVGParsingOutput => ({\n objects: [],\n elements: [],\n options: {},\n allElements: [],\n});\n\n/**\n * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback\n * @param {HTMLElement} doc SVG document to parse\n * @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes.\n * @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created.\n * Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric,\n * or extra custom manipulation\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin setting to use for external resources\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @return {SVGParsingOutput}\n * {@link SVGParsingOutput} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document.\n * You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added )\n */\nexport async function parseSVGDocument(\n doc: Document,\n reviver?: TSvgReviverCallback,\n { crossOrigin, signal }: LoadImageOptions = {},\n): Promise<SVGParsingOutput> {\n if (signal && signal.aborted) {\n log('log', new SignalAbortedError('parseSVGDocument'));\n // this is an unhappy path, we dont care about speed\n return createEmptyResponse();\n }\n const documentElement = doc.documentElement;\n parseUseDirectives(doc);\n\n const descendants = Array.from(documentElement.getElementsByTagName('*')),\n options = {\n ...applyViewboxTransform(documentElement),\n crossOrigin,\n signal,\n };\n const elements = descendants.filter((el) => {\n applyViewboxTransform(el);\n return isValidSvgTag(el) && !hasInvalidAncestor(el); // http://www.w3.org/TR/SVG/struct.html#DefsElement\n });\n if (!elements || (elements && !elements.length)) {\n return {\n ...createEmptyResponse(),\n options,\n allElements: descendants,\n };\n }\n const localClipPaths: Record<string, Element[]> = {};\n descendants\n .filter((el) => getTagName(el) === 'clipPath')\n .forEach((el) => {\n el.setAttribute('originalTransform', el.getAttribute('transform') || '');\n const id = el.getAttribute('id')!;\n localClipPaths[id] = Array.from(el.getElementsByTagName('*')).filter(\n (el) => isValidSvgTag(el),\n );\n });\n\n // Precedence of rules: style > class > attribute\n const elementParser = new ElementsParser(\n elements,\n options,\n reviver,\n doc,\n localClipPaths,\n );\n\n const instances = await elementParser.parse();\n\n return {\n objects: instances,\n elements,\n options,\n allElements: descendants,\n };\n}\n","import { svgNS } from './constants';\nimport { getMultipleNodes } from './getMultipleNodes';\nimport { applyViewboxTransform } from './applyViewboxTransform';\nimport { parseStyleString } from './parseStyleString';\n\nexport function parseUseDirectives(doc: Document) {\n const nodelist = getMultipleNodes(doc, ['use', 'svg:use']);\n const skipAttributes = ['x', 'y', 'xlink:href', 'href', 'transform'];\n\n for (const useElement of nodelist) {\n const useAttributes: NamedNodeMap = useElement.attributes;\n\n const useAttrMap: Record<string, string> = {};\n for (const attr of useAttributes) {\n attr.value && (useAttrMap[attr.name] = attr.value);\n }\n\n const xlink = (useAttrMap['xlink:href'] || useAttrMap.href || '').slice(1);\n\n if (xlink === '') {\n return;\n }\n const referencedElement = doc.getElementById(xlink);\n if (referencedElement === null) {\n // if we can't find the target of the xlink, consider this use tag bad, similar to no xlink\n return;\n }\n let clonedOriginal = referencedElement.cloneNode(true) as Element;\n\n const originalAttributes: NamedNodeMap = clonedOriginal.attributes;\n\n const originalAttrMap: Record<string, string> = {};\n for (const attr of originalAttributes) {\n attr.value && (originalAttrMap[attr.name] = attr.value);\n }\n\n // Transform attribute needs to be merged in a particular way\n const { x = 0, y = 0, transform = '' } = useAttrMap;\n const currentTrans = `${transform} ${\n originalAttrMap.transform || ''\n } translate(${x}, ${y})`;\n\n applyViewboxTransform(clonedOriginal);\n\n if (/^svg$/i.test(clonedOriginal.nodeName)) {\n // if is an SVG, create a group and apply all the attributes on top of it\n const el3 = clonedOriginal.ownerDocument.createElementNS(svgNS, 'g');\n Object.entries(originalAttrMap).forEach(([name, value]) =>\n el3.setAttributeNS(svgNS, name, value),\n );\n el3.append(...clonedOriginal.childNodes);\n clonedOriginal = el3;\n }\n\n for (const attr of useAttributes) {\n if (!attr) {\n continue;\n }\n const { name, value } = attr;\n if (skipAttributes.includes(name)) {\n continue;\n }\n\n if (name === 'style') {\n // when use has a style, merge the two styles, with the ref being priority (not use)\n // priority is by feature. an attribute for fill on the original element\n // will overwrite the fill in style or attribute for tha use\n const styleRecord: Record<string, any> = {};\n parseStyleString(value, styleRecord);\n // cleanup styleRecord from attributes of original\n Object.entries(originalAttrMap).forEach(([name, value]) => {\n styleRecord[name] = value;\n });\n // now we can put in the style of the original that will overwrite the original attributes\n parseStyleString(originalAttrMap.style || '', styleRecord);\n const mergedStyles = Object.entries(styleRecord)\n .map((entry) => entry.join(':'))\n .join(';');\n clonedOriginal.setAttribute(name, mergedStyles);\n } else {\n // set the attribute from use element only if the original does not have it already\n !originalAttrMap[name] && clonedOriginal.setAttribute(name, value);\n }\n }\n\n clonedOriginal.setAttribute('transform', currentTrans);\n clonedOriginal.setAttribute('instantiated_by_use', '1');\n clonedOriginal.removeAttribute('id');\n useElement.parentNode!.replaceChild(clonedOriginal, useElement);\n }\n}\n","import { getFabricWindow } from '../env';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\nimport { parseSVGDocument } from './parseSVGDocument';\nimport type { SVGParsingOutput, TSvgReviverCallback } from './typedefs';\n\n/**\n * Takes string corresponding to an SVG document, and parses it into a set of fabric objects\n * @param {String} string representing the svg\n * @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes.\n * {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document.\n * You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added )\n * @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created.\n * Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric,\n * or extra custom manipulation\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin setting to use for external resources\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n */\nexport function loadSVGFromString(\n string: string,\n reviver?: TSvgReviverCallback,\n options?: LoadImageOptions,\n): Promise<SVGParsingOutput> {\n const parser = new (getFabricWindow().DOMParser)(),\n // should we use `image/svg+xml` here?\n doc = parser.parseFromString(string.trim(), 'text/xml');\n return parseSVGDocument(doc, reviver, options);\n}\n","import { createEmptyResponse } from './parseSVGDocument';\nimport { loadSVGFromString } from './loadSVGFromString';\nimport type { SVGParsingOutput, TSvgReviverCallback } from './typedefs';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\nimport { FabricError } from '../util/internals/console';\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 fetch API, so it needs to conform to SOP (Same Origin Policy)\n * @param {string} url where the SVG is\n * @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes.\n * {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document.\n * You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added )\n * @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created.\n * Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric,\n * or extra custom manipulation\n * @param {Object} [options] Object containing options for parsing\n * @param {String} [options.crossOrigin] crossOrigin setting to use for external resources\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n */\nexport function loadSVGFromURL(\n url: string,\n reviver?: TSvgReviverCallback,\n options: LoadImageOptions = {},\n): Promise<SVGParsingOutput> {\n return fetch(url.replace(/^\\n\\s*/, '').trim(), {\n signal: options.signal,\n })\n .then((response) => {\n if (!response.ok) {\n throw new FabricError(`HTTP error! status: ${response.status}`);\n }\n return response.text();\n })\n .then((svgText) => {\n return loadSVGFromString(svgText, reviver, options);\n })\n .catch(() => {\n // this is an unhappy path, we dont care about speed\n return createEmptyResponse();\n });\n}\n","import { getFabricWindow } from '../env';\nimport { createCanvasElement, createCanvasElementFor } from '../util/misc/dom';\nimport { WebGLFilterBackend } from './WebGLFilterBackend';\nimport type { TWebGLPipelineState, T2DPipelineState } from './typedefs';\n\nexport const isWebGLPipelineState = (\n options: TWebGLPipelineState | T2DPipelineState,\n): options is TWebGLPipelineState => {\n return (options as TWebGLPipelineState).webgl !== undefined;\n};\n\n/**\n * Pick a method to copy data from GL context to 2d canvas. In some browsers using\n * drawImage should be faster, but is also bugged for a small combination of old hardware\n * and drivers.\n * putImageData is faster than drawImage for that specific operation.\n */\nexport const isPutImageFaster = (width: number, height: number): boolean => {\n const targetCanvas = createCanvasElementFor({ width, height });\n const sourceCanvas = createCanvasElement();\n const gl = sourceCanvas.getContext('webgl')!;\n // eslint-disable-next-line no-undef\n const imageBuffer = new ArrayBuffer(width * height * 4);\n\n const testContext = {\n imageBuffer: imageBuffer,\n } as unknown as Required<WebGLFilterBackend>;\n const testPipelineState = {\n destinationWidth: width,\n destinationHeight: height,\n targetCanvas: targetCanvas,\n } as unknown as TWebGLPipelineState;\n let startTime;\n\n startTime = getFabricWindow().performance.now();\n WebGLFilterBackend.prototype.copyGLTo2D.call(\n testContext,\n gl,\n testPipelineState,\n );\n const drawImageTime = getFabricWindow().performance.now() - startTime;\n\n startTime = getFabricWindow().performance.now();\n WebGLFilterBackend.prototype.copyGLTo2DPutImageData.call(\n testContext,\n gl,\n testPipelineState,\n );\n const putImageDataTime = getFabricWindow().performance.now() - startTime;\n\n return drawImageTime > putImageDataTime;\n};\n","export const highPsourceCode = `precision highp float`;\n\nexport const identityFragmentShader = `\n ${highPsourceCode};\n varying vec2 vTexCoord;\n uniform sampler2D uTexture;\n void main() {\n gl_FragColor = texture2D(uTexture, vTexCoord);\n }`;\n\nexport const vertexSource = `\n attribute vec2 aPosition;\n varying vec2 vTexCoord;\n void main() {\n vTexCoord = aPosition;\n gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n }`;\n","import { getEnv } from '../env';\nimport type {\n T2DPipelineState,\n TWebGLAttributeLocationMap,\n TWebGLPipelineState,\n TWebGLProgramCacheItem,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport {\n highPsourceCode,\n identityFragmentShader,\n vertexSource,\n} from './shaders/baseFilter';\nimport type { Abortable } from '../typedefs';\nimport { FabricError } from '../util/internals/console';\nimport { createCanvasElementFor } from '../util/misc/dom';\n\nconst regex = new RegExp(highPsourceCode, 'g');\n\nexport class BaseFilter<\n Name extends string,\n OwnProps extends Record<string, any> = object,\n SerializedProps extends Record<string, any> = OwnProps,\n> {\n /**\n * Filter type\n */\n get type(): Name {\n return (this.constructor as typeof BaseFilter).type as Name;\n }\n\n /**\n * The class type. Used to identify which class this is.\n * This is used for serialization purposes and internally it can be used\n * to identify classes. As a developer you could use `instance of Class`\n * but to avoid importing all the code and blocking tree shaking we try\n * to avoid doing that.\n */\n static type = 'BaseFilter';\n\n /**\n * Contains the uniform locations for the fragment shader.\n * uStepW and uStepH are handled by the BaseFilter, each filter class\n * needs to specify all the one that are needed\n */\n static uniformLocations: string[] = [];\n\n declare static defaults: Record<string, unknown>;\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor({\n type,\n ...options\n }: { type?: never } & Partial<OwnProps> & Record<string, any> = {}) {\n Object.assign(\n this,\n (this.constructor as typeof BaseFilter).defaults,\n options,\n );\n }\n\n protected getFragmentSource(): string {\n return identityFragmentShader;\n }\n\n getVertexSource(): string {\n return vertexSource;\n }\n\n /**\n * Compile this filter's shader program.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\n * @param {String} fragmentSource fragmentShader source for compilation\n * @param {String} vertexSource vertexShader source for compilation\n */\n createProgram(\n gl: WebGLRenderingContext,\n fragmentSource: string = this.getFragmentSource(),\n vertexSource: string = this.getVertexSource(),\n ) {\n const {\n WebGLProbe: { GLPrecision = 'highp' },\n } = getEnv();\n if (GLPrecision !== 'highp') {\n fragmentSource = fragmentSource.replace(\n regex,\n highPsourceCode.replace('highp', GLPrecision),\n );\n }\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n const program = gl.createProgram();\n\n if (!vertexShader || !fragmentShader || !program) {\n throw new FabricError(\n 'Vertex, fragment shader or program creation error',\n );\n }\n gl.shaderSource(vertexShader, vertexSource);\n gl.compileShader(vertexShader);\n if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n throw new FabricError(\n `Vertex shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n vertexShader,\n )}`,\n );\n }\n\n gl.shaderSource(fragmentShader, fragmentSource);\n gl.compileShader(fragmentShader);\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n throw new FabricError(\n `Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n fragmentShader,\n )}`,\n );\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new FabricError(\n `Shader link error for \"${this.type}\" ${gl.getProgramInfoLog(program)}`,\n );\n }\n\n const uniformLocations = this.getUniformLocations(gl, program) || {};\n uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\n\n return {\n program,\n attributeLocations: this.getAttributeLocations(gl, program),\n uniformLocations,\n };\n }\n\n /**\n * Return a map of attribute names to WebGLAttributeLocation objects.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\n * @returns {Object} A map of attribute names to attribute locations.\n */\n getAttributeLocations(\n gl: WebGLRenderingContext,\n program: WebGLProgram,\n ): TWebGLAttributeLocationMap {\n return {\n aPosition: gl.getAttribLocation(program, 'aPosition'),\n };\n }\n\n /**\n * Return a map of uniform names to WebGLUniformLocation objects.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\n * @returns {Object} A map of uniform names to uniform locations.\n */\n getUniformLocations(\n gl: WebGLRenderingContext,\n program: WebGLProgram,\n ): TWebGLUniformLocationMap {\n const locations = (this.constructor as unknown as typeof BaseFilter<string>)\n .uniformLocations;\n\n const uniformLocations: Record<string, WebGLUniformLocation | null> = {};\n for (let i = 0; i < locations.length; i++) {\n uniformLocations[locations[i]] = gl.getUniformLocation(\n program,\n locations[i],\n );\n }\n return uniformLocations;\n }\n\n /**\n * Send attribute data from this filter to its shader program on the GPU.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {Object} attributeLocations A map of shader attribute names to their locations.\n */\n sendAttributeData(\n gl: WebGLRenderingContext,\n attributeLocations: Record<string, number>,\n aPositionData: Float32Array,\n ) {\n const attributeLocation = attributeLocations.aPosition;\n const buffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.enableVertexAttribArray(attributeLocation);\n gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\n gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\n }\n\n _setupFrameBuffer(options: TWebGLPipelineState) {\n const gl = options.context;\n if (options.passes > 1) {\n const width = options.destinationWidth;\n const height = options.destinationHeight;\n if (options.sourceWidth !== width || options.sourceHeight !== height) {\n gl.deleteTexture(options.targetTexture);\n options.targetTexture = options.filterBackend.createTexture(\n gl,\n width,\n height,\n );\n }\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n options.targetTexture,\n 0,\n );\n } else {\n // draw last filter on canvas and not to framebuffer.\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.finish();\n }\n }\n\n _swapTextures(options: TWebGLPipelineState) {\n options.passes--;\n options.pass++;\n const temp = options.targetTexture;\n options.targetTexture = options.sourceTexture;\n options.sourceTexture = temp;\n }\n\n /**\n * Generic isNeutral implementation for one parameter based filters.\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * Other filters may need their own version ( ColorMatrix, HueRotation, gamma, ComposedFilter )\n * @param {Object} options\n **/\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n isNeutralState(options?: any): boolean {\n return false;\n }\n\n /**\n * Apply this filter to the input image data provided.\n *\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n this._setupFrameBuffer(options);\n this.applyToWebGL(options);\n this._swapTextures(options);\n } else {\n this.applyTo2d(options);\n }\n }\n\n applyTo2d(_options: T2DPipelineState): void {\n // override by subclass\n }\n\n /**\n * Returns a string that represent the current selected shader code for the filter.\n * Used to force recompilation when parameters change or to retrieve the shader from cache\n * @type string\n **/\n getCacheKey(): string {\n return this.type;\n }\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n * @return {WebGLProgram} the compiled program shader\n */\n retrieveShader(options: TWebGLPipelineState): TWebGLProgramCacheItem {\n const key = this.getCacheKey();\n if (!options.programCache[key]) {\n options.programCache[key] = this.createProgram(options.context);\n }\n return options.programCache[key];\n }\n\n /**\n * Apply this filter using webgl.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.originalTexture The texture of the original input image.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyToWebGL(options: TWebGLPipelineState) {\n const gl = options.context;\n const shader = this.retrieveShader(options);\n if (options.pass === 0 && options.originalTexture) {\n gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\n } else {\n gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\n }\n gl.useProgram(shader.program);\n this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\n\n gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\n gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\n\n this.sendUniformData(gl, shader.uniformLocations);\n gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n bindAdditionalTexture(\n gl: WebGLRenderingContext,\n texture: WebGLTexture,\n textureUnit: number,\n ) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n // reset active texture to 0 as usual\n gl.activeTexture(gl.TEXTURE0);\n }\n\n unbindAdditionalTexture(gl: WebGLRenderingContext, textureUnit: number) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.activeTexture(gl.TEXTURE0);\n }\n\n /**\n * Send uniform data from this filter to its shader program on the GPU.\n *\n * Intended to be overridden by subclasses.\n *\n * @param {WebGLRenderingContext} _gl The canvas context used to compile the shader program.\n * @param {Object} _uniformLocations A map of shader uniform names to their locations.\n */\n sendUniformData(\n _gl: WebGLRenderingContext,\n _uniformLocations: TWebGLUniformLocationMap,\n ): void {\n // override by subclass\n }\n\n /**\n * If needed by a 2d filter, this functions can create an helper canvas to be used\n * remember that options.targetCanvas is available for use till end of chain.\n */\n createHelpLayer(options: T2DPipelineState) {\n if (!options.helpLayer) {\n const { sourceWidth, sourceHeight } = options;\n const helpLayer = createCanvasElementFor({\n width: sourceWidth,\n height: sourceHeight,\n });\n options.helpLayer = helpLayer;\n }\n }\n\n /**\n * Returns object representation of an instance\n * It will automatically export the default values of a filter,\n * stored in the static defaults property.\n * @return {Object} Object representation of an instance\n */\n toObject(): { type: Name } & SerializedProps {\n const defaultKeys = Object.keys(\n (this.constructor as typeof BaseFilter).defaults || {},\n ) as (keyof SerializedProps)[];\n\n return {\n type: this.type,\n ...defaultKeys.reduce<SerializedProps>((acc, key) => {\n acc[key] = this[\n key as keyof this\n ] as unknown as (typeof acc)[typeof key];\n return acc;\n }, {} as SerializedProps),\n };\n }\n\n /**\n * Returns a JSON representation of an instance\n * @return {Object} JSON\n */\n toJSON() {\n // delegate, not alias\n return this.toObject();\n }\n\n static async fromObject(\n { type, ...filterOptions }: Record<string, any>,\n _options?: Abortable,\n ): Promise<BaseFilter<string>> {\n return new this(filterOptions);\n }\n}\n","export const blendColorFragmentSource = {\n multiply: 'gl_FragColor.rgb *= uColor.rgb;\\n',\n screen:\n 'gl_FragColor.rgb = 1.0 - (1.0 - gl_FragColor.rgb) * (1.0 - uColor.rgb);\\n',\n add: 'gl_FragColor.rgb += uColor.rgb;\\n',\n difference: 'gl_FragColor.rgb = abs(gl_FragColor.rgb - uColor.rgb);\\n',\n subtract: 'gl_FragColor.rgb -= uColor.rgb;\\n',\n lighten: 'gl_FragColor.rgb = max(gl_FragColor.rgb, uColor.rgb);\\n',\n darken: 'gl_FragColor.rgb = min(gl_FragColor.rgb, uColor.rgb);\\n',\n exclusion:\n 'gl_FragColor.rgb += uColor.rgb - 2.0 * (uColor.rgb * gl_FragColor.rgb);\\n',\n overlay: `\n if (uColor.r < 0.5) {\n gl_FragColor.r *= 2.0 * uColor.r;\n } else {\n gl_FragColor.r = 1.0 - 2.0 * (1.0 - gl_FragColor.r) * (1.0 - uColor.r);\n }\n if (uColor.g < 0.5) {\n gl_FragColor.g *= 2.0 * uColor.g;\n } else {\n gl_FragColor.g = 1.0 - 2.0 * (1.0 - gl_FragColor.g) * (1.0 - uColor.g);\n }\n if (uColor.b < 0.5) {\n gl_FragColor.b *= 2.0 * uColor.b;\n } else {\n gl_FragColor.b = 1.0 - 2.0 * (1.0 - gl_FragColor.b) * (1.0 - uColor.b);\n }\n `,\n tint: `\n gl_FragColor.rgb *= (1.0 - uColor.a);\n gl_FragColor.rgb += uColor.rgb;\n `,\n} as const;\n","import { Color } from '../color/Color';\nimport { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { blendColorFragmentSource } from './shaders/blendColor';\n\nexport type TBlendMode =\n | 'multiply'\n | 'add'\n | 'difference'\n | 'screen'\n | 'subtract'\n | 'darken'\n | 'lighten'\n | 'overlay'\n | 'exclusion'\n | 'tint';\n\ntype BlendColorOwnProps = {\n color: string;\n mode: TBlendMode;\n alpha: number;\n};\n\nexport const blendColorDefaultValues: BlendColorOwnProps = {\n color: '#F95C63',\n mode: 'multiply',\n alpha: 1,\n};\n\n/**\n * Color Blend filter class\n * @example\n * const filter = new BlendColor({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * const filter = new BlendImage({\n * image: fabricImageObject,\n * mode: 'multiply'\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class BlendColor extends BaseFilter<'BlendColor', BlendColorOwnProps> {\n /**\n * Color to make the blend operation with. default to a reddish color since black or white\n * gives always strong result.\n * @type String\n **/\n declare color: BlendColorOwnProps['color'];\n\n /**\n * Blend mode for the filter: one of multiply, add, difference, screen, subtract,\n * darken, lighten, overlay, exclusion, tint.\n * @type String\n **/\n declare mode: BlendColorOwnProps['mode'];\n /**\n * alpha value. represent the strength of the blend color operation.\n * @type Number\n **/\n declare alpha: BlendColorOwnProps['alpha'];\n\n static defaults = blendColorDefaultValues;\n\n static type = 'BlendColor';\n\n static uniformLocations = ['uColor'];\n\n getCacheKey() {\n return `${this.type}_${this.mode}`;\n }\n\n protected getFragmentSource(): string {\n return `\n precision highp float;\n uniform sampler2D uTexture;\n uniform vec4 uColor;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n gl_FragColor = color;\n if (color.a > 0.0) {\n ${blendColorFragmentSource[this.mode]}\n }\n }\n `;\n }\n\n /**\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const source = new Color(this.color).getSource();\n const alpha = this.alpha;\n const tr = source[0] * alpha;\n const tg = source[1] * alpha;\n const tb = source[2] * alpha;\n const alpha1 = 1 - alpha;\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n let oR, oG, oB;\n switch (this.mode) {\n case 'multiply':\n oR = (r * tr) / 255;\n oG = (g * tg) / 255;\n oB = (b * tb) / 255;\n break;\n case 'screen':\n oR = 255 - ((255 - r) * (255 - tr)) / 255;\n oG = 255 - ((255 - g) * (255 - tg)) / 255;\n oB = 255 - ((255 - b) * (255 - tb)) / 255;\n break;\n case 'add':\n oR = r + tr;\n oG = g + tg;\n oB = b + tb;\n break;\n case 'difference':\n oR = Math.abs(r - tr);\n oG = Math.abs(g - tg);\n oB = Math.abs(b - tb);\n break;\n case 'subtract':\n oR = r - tr;\n oG = g - tg;\n oB = b - tb;\n break;\n case 'darken':\n oR = Math.min(r, tr);\n oG = Math.min(g, tg);\n oB = Math.min(b, tb);\n break;\n case 'lighten':\n oR = Math.max(r, tr);\n oG = Math.max(g, tg);\n oB = Math.max(b, tb);\n break;\n case 'overlay':\n oR =\n tr < 128\n ? (2 * r * tr) / 255\n : 255 - (2 * (255 - r) * (255 - tr)) / 255;\n oG =\n tg < 128\n ? (2 * g * tg) / 255\n : 255 - (2 * (255 - g) * (255 - tg)) / 255;\n oB =\n tb < 128\n ? (2 * b * tb) / 255\n : 255 - (2 * (255 - b) * (255 - tb)) / 255;\n break;\n case 'exclusion':\n oR = tr + r - (2 * tr * r) / 255;\n oG = tg + g - (2 * tg * g) / 255;\n oB = tb + b - (2 * tb * b) / 255;\n break;\n case 'tint':\n oR = tr + r * alpha1;\n oG = tg + g * alpha1;\n oB = tb + b * alpha1;\n }\n data[i] = oR;\n data[i + 1] = oG;\n data[i + 2] = oB;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const source = new Color(this.color).getSource();\n source[0] = (this.alpha * source[0]) / 255;\n source[1] = (this.alpha * source[1]) / 255;\n source[2] = (this.alpha * source[2]) / 255;\n source[3] = this.alpha;\n gl.uniform4fv(uniformLocations.uColor, source);\n }\n}\n\nclassRegistry.setClass(BlendColor);\n","import type { TBlendImageMode } from '../BlendImage';\n\nexport const fragmentSource: Record<TBlendImageMode, string> = {\n multiply: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform sampler2D uImage;\n uniform vec4 uColor;\n varying vec2 vTexCoord;\n varying vec2 vTexCoord2;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n vec4 color2 = texture2D(uImage, vTexCoord2);\n color.rgba *= color2.rgba;\n gl_FragColor = color;\n }\n `,\n mask: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform sampler2D uImage;\n uniform vec4 uColor;\n varying vec2 vTexCoord;\n varying vec2 vTexCoord2;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n vec4 color2 = texture2D(uImage, vTexCoord2);\n color.a = color2.a;\n gl_FragColor = color;\n }\n `,\n} as const;\n\nexport const vertexSource = `\n attribute vec2 aPosition;\n varying vec2 vTexCoord;\n varying vec2 vTexCoord2;\n uniform mat3 uTransformMatrix;\n void main() {\n vTexCoord = aPosition;\n vTexCoord2 = (uTransformMatrix * vec3(aPosition, 1.0)).xy;\n gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n }\n ` as const;\n","import { FabricImage } from '../shapes/Image';\nimport { createCanvasElement } from '../util/misc/dom';\nimport { BaseFilter } from './BaseFilter';\nimport type {\n T2DPipelineState,\n TWebGLPipelineState,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport type { WebGLFilterBackend } from './WebGLFilterBackend';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource, vertexSource } from './shaders/blendImage';\n\nexport type TBlendImageMode = 'multiply' | 'mask';\n\ntype BlendImageOwnProps = {\n mode: TBlendImageMode;\n alpha: number;\n};\n\nexport const blendImageDefaultValues: BlendImageOwnProps = {\n mode: 'multiply',\n alpha: 1,\n};\n\n/**\n * Image Blend filter class\n * @example\n * const filter = new filters.BlendColor({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * const filter = new BlendImage({\n * image: fabricImageObject,\n * mode: 'multiply'\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class BlendImage extends BaseFilter<'BlendImage', BlendImageOwnProps> {\n /**\n * Image to make the blend operation with.\n **/\n declare image: FabricImage;\n\n /**\n * Blend mode for the filter: either 'multiply' or 'mask'. 'multiply' will\n * multiply the values of each channel (R, G, B, and A) of the filter image by\n * their corresponding values in the base image. 'mask' will only look at the\n * alpha channel of the filter image, and apply those values to the base\n * image's alpha channel.\n * @type String\n **/\n declare mode: BlendImageOwnProps['mode'];\n\n /**\n * alpha value. represent the strength of the blend image operation.\n * not implemented.\n **/\n declare alpha: BlendImageOwnProps['alpha'];\n\n static type = 'BlendImage';\n\n static defaults = blendImageDefaultValues;\n\n static uniformLocations = ['uTransformMatrix', 'uImage'];\n\n getCacheKey() {\n return `${this.type}_${this.mode}`;\n }\n\n getFragmentSource(): string {\n return fragmentSource[this.mode];\n }\n\n getVertexSource(): string {\n return vertexSource;\n }\n\n applyToWebGL(options: TWebGLPipelineState) {\n const gl = options.context,\n texture = this.createTexture(options.filterBackend, this.image);\n this.bindAdditionalTexture(gl, texture!, gl.TEXTURE1);\n super.applyToWebGL(options);\n this.unbindAdditionalTexture(gl, gl.TEXTURE1);\n }\n\n createTexture(backend: WebGLFilterBackend, image: FabricImage) {\n return backend.getCachedTexture(image.cacheKey, image.getElement());\n }\n\n /**\n * Calculate a transformMatrix to adapt the image to blend over\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n calculateMatrix() {\n const image = this.image,\n { width, height } = image.getElement();\n return [\n 1 / image.scaleX,\n 0,\n 0,\n 0,\n 1 / image.scaleY,\n 0,\n -image.left / width,\n -image.top / height,\n 1,\n ];\n }\n\n /**\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({\n imageData: { data, width, height },\n filterBackend: { resources },\n }: T2DPipelineState) {\n const image = this.image;\n if (!resources.blendImage) {\n resources.blendImage = createCanvasElement();\n }\n const canvas1 = resources.blendImage;\n const context = canvas1.getContext('2d')!;\n if (canvas1.width !== width || canvas1.height !== height) {\n canvas1.width = width;\n canvas1.height = height;\n } else {\n context.clearRect(0, 0, width, height);\n }\n context.setTransform(\n image.scaleX,\n 0,\n 0,\n image.scaleY,\n image.left,\n image.top,\n );\n context.drawImage(image.getElement(), 0, 0, width, height);\n const blendData = context.getImageData(0, 0, width, height).data;\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const a = data[i + 3];\n\n const tr = blendData[i];\n const tg = blendData[i + 1];\n const tb = blendData[i + 2];\n const ta = blendData[i + 3];\n\n switch (this.mode) {\n case 'multiply':\n data[i] = (r * tr) / 255;\n data[i + 1] = (g * tg) / 255;\n data[i + 2] = (b * tb) / 255;\n data[i + 3] = (a * ta) / 255;\n break;\n case 'mask':\n data[i + 3] = ta;\n break;\n }\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const matrix = this.calculateMatrix();\n gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\n gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\n }\n\n /**\n * Returns object representation of an instance\n * TODO: Handle the possibility of missing image better.\n * As of now a BlendImage filter without image can't be used with fromObject\n * @return {Object} Object representation of an instance\n */\n toObject(): {\n type: 'BlendImage';\n image: ReturnType<FabricImage['toObject']>;\n } & BlendImageOwnProps {\n return {\n ...super.toObject(),\n image: this.image && this.image.toObject(),\n };\n }\n\n /**\n * Create filter instance from an object representation\n * @param {object} object Object to create an instance from\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting image loading, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<BlendImage>}\n */\n static async fromObject(\n { type, image, ...filterOptions }: Record<string, any>,\n options: { signal: AbortSignal },\n ): Promise<BaseFilter<'BlendImage', BlendImageOwnProps>> {\n return FabricImage.fromObject(image, options).then(\n (enlivedImage) => new this({ ...filterOptions, image: enlivedImage }),\n );\n }\n}\n\nclassRegistry.setClass(BlendImage);\n","import { BaseFilter } from './BaseFilter';\nimport type {\n TWebGLPipelineState,\n T2DPipelineState,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/blur';\n\ntype BlurOwnProps = {\n blur: number;\n};\n\nexport const blurDefaultValues: BlurOwnProps = {\n blur: 0,\n};\n\n/**\n * Blur filter class\n * @example\n * const filter = new Blur({\n * blur: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class Blur extends BaseFilter<'Blur', BlurOwnProps> {\n /**\n * blur value, in percentage of image dimensions.\n * specific to keep the image blur constant at different resolutions\n * range between 0 and 1.\n * @type Number\n */\n declare blur: BlurOwnProps['blur'];\n\n declare horizontal: boolean;\n declare aspectRatio: number;\n\n static type = 'Blur';\n\n static defaults = blurDefaultValues;\n\n static uniformLocations = ['uDelta'];\n\n getFragmentSource(): string {\n return fragmentSource;\n }\n\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n // this aspectRatio is used to give the same blur to vertical and horizontal\n this.aspectRatio = options.sourceWidth / options.sourceHeight;\n options.passes++;\n this._setupFrameBuffer(options);\n this.horizontal = true;\n this.applyToWebGL(options);\n this._swapTextures(options);\n this._setupFrameBuffer(options);\n this.horizontal = false;\n this.applyToWebGL(options);\n this._swapTextures(options);\n } else {\n this.applyTo2d(options);\n }\n }\n\n applyTo2d({ imageData: { data, width, height } }: T2DPipelineState) {\n // this code mimic the shader for output consistency\n // it samples 31 pixels across the image over a distance that depends from the blur value.\n this.aspectRatio = width / height;\n this.horizontal = true;\n let blurValue = this.getBlurValue() * width;\n const imageData = new Uint8ClampedArray(data);\n const samples = 15;\n const bytesInRow = 4 * width;\n for (let i = 0; i < data.length; i += 4) {\n let r = 0.0,\n g = 0.0,\n b = 0.0,\n a = 0.0,\n totalA = 0;\n const minIRow = i - (i % bytesInRow);\n const maxIRow = minIRow + bytesInRow;\n // for now let's keep noise out of the way\n // let pixelOffset = 0;\n // const offset = Math.random() * 3;\n // if (offset > 2) {\n // pixelOffset = 4;\n // } else if (offset < 1) {\n // pixelOffset = -4;\n // }\n for (let j = -samples + 1; j < samples; j++) {\n const percent = j / samples;\n const distance = Math.floor(blurValue * percent) * 4;\n const weight = 1 - Math.abs(percent);\n let sampledPixel = i + distance; // + pixelOffset;\n // try to implement edge mirroring\n if (sampledPixel < minIRow) {\n sampledPixel = minIRow;\n } else if (sampledPixel > maxIRow) {\n sampledPixel = maxIRow;\n }\n const localAlpha = data[sampledPixel + 3] * weight;\n r += data[sampledPixel] * localAlpha;\n g += data[sampledPixel + 1] * localAlpha;\n b += data[sampledPixel + 2] * localAlpha;\n a += localAlpha;\n totalA += weight;\n }\n imageData[i] = r / a;\n imageData[i + 1] = g / a;\n imageData[i + 2] = b / a;\n imageData[i + 3] = a / totalA;\n }\n this.horizontal = false;\n blurValue = this.getBlurValue() * height;\n for (let i = 0; i < imageData.length; i += 4) {\n let r = 0.0,\n g = 0.0,\n b = 0.0,\n a = 0.0,\n totalA = 0;\n const minIRow = i % bytesInRow;\n const maxIRow = imageData.length - bytesInRow + minIRow;\n // for now let's keep noise out of the way\n // let pixelOffset = 0;\n // const offset = Math.random() * 3;\n // if (offset > 2) {\n // pixelOffset = bytesInRow;\n // } else if (offset < 1) {\n // pixelOffset = -bytesInRow;\n // }\n for (let j = -samples + 1; j < samples; j++) {\n const percent = j / samples;\n const distance = Math.floor(blurValue * percent) * bytesInRow;\n const weight = 1 - Math.abs(percent);\n let sampledPixel = i + distance; // + pixelOffset;\n // try to implement edge mirroring\n if (sampledPixel < minIRow) {\n sampledPixel = minIRow;\n } else if (sampledPixel > maxIRow) {\n sampledPixel = maxIRow;\n }\n const localAlpha = imageData[sampledPixel + 3] * weight;\n r += imageData[sampledPixel] * localAlpha;\n g += imageData[sampledPixel + 1] * localAlpha;\n b += imageData[sampledPixel + 2] * localAlpha;\n a += localAlpha;\n totalA += weight;\n }\n data[i] = r / a;\n data[i + 1] = g / a;\n data[i + 2] = b / a;\n data[i + 3] = a / totalA;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const delta = this.chooseRightDelta();\n gl.uniform2fv(uniformLocations.uDelta, delta);\n }\n\n isNeutralState() {\n return this.blur === 0;\n }\n\n getBlurValue(): number {\n let blurScale = 1;\n const { horizontal, aspectRatio } = this;\n if (horizontal) {\n if (aspectRatio > 1) {\n // image is wide, i want to shrink radius horizontal\n blurScale = 1 / aspectRatio;\n }\n } else {\n if (aspectRatio < 1) {\n // image is tall, i want to shrink radius vertical\n blurScale = aspectRatio;\n }\n }\n return blurScale * this.blur * 0.12;\n }\n\n /**\n * choose right value of image percentage to blur with\n * @returns {Array} a numeric array with delta values\n */\n chooseRightDelta() {\n const blur = this.getBlurValue();\n return this.horizontal ? [blur, 0] : [0, blur];\n }\n}\n\nclassRegistry.setClass(Blur);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform vec2 uDelta;\n varying vec2 vTexCoord;\n const float nSamples = 15.0;\n vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\n float random(vec3 scale) {\n /* use the fragment position for a different seed per-pixel */\n return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\n }\n void main() {\n vec4 color = vec4(0.0);\n float totalC = 0.0;\n float totalA = 0.0;\n float offset = random(v3offset);\n for (float t = -nSamples; t <= nSamples; t++) {\n float percent = (t + offset - 0.5) / nSamples;\n vec4 sample = texture2D(uTexture, vTexCoord + uDelta * percent);\n float weight = 1.0 - abs(percent);\n float alpha = weight * sample.a;\n color.rgb += sample.rgb * alpha;\n color.a += alpha;\n totalA += weight;\n totalC += alpha;\n }\n gl_FragColor.rgb = color.rgb / totalC;\n gl_FragColor.a = color.a / totalA;\n }\n ` as const;\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/brightness';\n\ntype BrightnessOwnProps = {\n brightness: number;\n};\n\nexport const brightnessDefaultValues: BrightnessOwnProps = {\n brightness: 0,\n};\n\n/**\n * Brightness filter class\n * @example\n * const filter = new Brightness({\n * brightness: 0.05\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Brightness extends BaseFilter<'Brightness', BrightnessOwnProps> {\n /**\n * Brightness value, from -1 to 1.\n * translated to -255 to 255 for 2d\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n * @param {Number} brightness\n */\n declare brightness: BrightnessOwnProps['brightness'];\n\n static type = 'Brightness';\n\n static defaults = brightnessDefaultValues;\n\n static uniformLocations = ['uBrightness'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const brightness = Math.round(this.brightness * 255);\n for (let i = 0; i < data.length; i += 4) {\n data[i] += brightness;\n data[i + 1] += brightness;\n data[i + 2] += brightness;\n }\n }\n\n isNeutralState() {\n return this.brightness === 0;\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uBrightness, this.brightness);\n }\n}\n\nclassRegistry.setClass(Brightness);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uBrightness;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n color.rgb += uBrightness;\n gl_FragColor = color;\n }\n`;\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n varying vec2 vTexCoord;\n uniform mat4 uColorMatrix;\n uniform vec4 uConstants;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n color *= uColorMatrix;\n color += uConstants;\n gl_FragColor = color;\n }`;\n","import { BaseFilter } from './BaseFilter';\nimport type {\n T2DPipelineState,\n TMatColorMatrix,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/colorMatrix';\n\nexport type ColorMatrixOwnProps = {\n matrix: TMatColorMatrix;\n colorsOnly: boolean;\n};\n\nexport const colorMatrixDefaultValues: ColorMatrixOwnProps = {\n matrix: [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],\n colorsOnly: true,\n};\n\n/**\n * Color Matrix filter class\n * @see {@link http://fabric5.fabricjs.com/image-filters|ImageFilters demo}\n * @see {@link http://phoboslab.org/log/2013/11/fast-image-filters-with-webgl demo}\n * @example <caption>Kodachrome filter</caption>\n * const filter = new ColorMatrix({\n * matrix: [\n 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502,\n -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203,\n -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946,\n 0, 0, 0, 1, 0\n ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class ColorMatrix<\n Name extends string = 'ColorMatrix',\n OwnProps extends object = ColorMatrixOwnProps,\n SerializedProps extends object = ColorMatrixOwnProps,\n> extends BaseFilter<Name, OwnProps, SerializedProps> {\n /**\n * Colormatrix for pixels.\n * array of 20 floats. Numbers in positions 4, 9, 14, 19 loose meaning\n * outside the -1, 1 range.\n * 0.0039215686 is the part of 1 that get translated to 1 in 2d\n * @param {Array} matrix array of 20 numbers.\n */\n declare matrix: ColorMatrixOwnProps['matrix'];\n\n /**\n * Lock the colormatrix on the color part, skipping alpha, mainly for non webgl scenario\n * to save some calculation\n * @type Boolean\n * @default true\n */\n declare colorsOnly: ColorMatrixOwnProps['colorsOnly'];\n\n static type = 'ColorMatrix';\n\n static defaults = colorMatrixDefaultValues;\n\n static uniformLocations = ['uColorMatrix', 'uConstants'];\n\n getFragmentSource(): string {\n return fragmentSource;\n }\n\n /**\n * Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d(options: T2DPipelineState) {\n const imageData = options.imageData,\n data = imageData.data,\n m = this.matrix,\n colorsOnly = this.colorsOnly;\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n\n data[i] = r * m[0] + g * m[1] + b * m[2] + m[4] * 255;\n data[i + 1] = r * m[5] + g * m[6] + b * m[7] + m[9] * 255;\n data[i + 2] = r * m[10] + g * m[11] + b * m[12] + m[14] * 255;\n if (!colorsOnly) {\n const a = data[i + 3];\n data[i] += a * m[3];\n data[i + 1] += a * m[8];\n data[i + 2] += a * m[13];\n data[i + 3] =\n r * m[15] + g * m[16] + b * m[17] + a * m[18] + m[19] * 255;\n }\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const m = this.matrix,\n matrix = [\n m[0],\n m[1],\n m[2],\n m[3],\n m[5],\n m[6],\n m[7],\n m[8],\n m[10],\n m[11],\n m[12],\n m[13],\n m[15],\n m[16],\n m[17],\n m[18],\n ],\n constants = [m[4], m[9], m[14], m[19]];\n gl.uniformMatrix4fv(uniformLocations.uColorMatrix, false, matrix);\n gl.uniform4fv(uniformLocations.uConstants, constants);\n }\n\n toObject(): { type: Name } & SerializedProps {\n return {\n ...super.toObject(),\n matrix: [...this.matrix] as TMatColorMatrix,\n };\n }\n}\n\nclassRegistry.setClass(ColorMatrix);\n","import { ColorMatrix } from './ColorMatrix';\nimport { classRegistry } from '../ClassRegistry';\nimport type { TMatColorMatrix } from './typedefs';\n\ntype FixedFiltersOwnProps = {\n colorsOnly: boolean;\n};\n\nexport function createColorMatrixFilter(key: string, matrix: TMatColorMatrix) {\n const newClass = class extends ColorMatrix<\n typeof key,\n FixedFiltersOwnProps,\n FixedFiltersOwnProps\n > {\n static type = key;\n\n static defaults = {\n colorsOnly: false,\n matrix,\n };\n\n toObject(): { type: string } & FixedFiltersOwnProps {\n return { type: this.type, colorsOnly: this.colorsOnly };\n }\n };\n classRegistry.setClass(newClass, key);\n return newClass as typeof ColorMatrix<typeof key, FixedFiltersOwnProps>;\n}\n\nexport const Brownie = createColorMatrixFilter(\n 'Brownie',\n [\n 0.5997, 0.34553, -0.27082, 0, 0.186, -0.0377, 0.86095, 0.15059, 0, -0.1449,\n 0.24113, -0.07441, 0.44972, 0, -0.02965, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const Vintage = createColorMatrixFilter(\n 'Vintage',\n [\n 0.62793, 0.32021, -0.03965, 0, 0.03784, 0.02578, 0.64411, 0.03259, 0,\n 0.02926, 0.0466, -0.08512, 0.52416, 0, 0.02023, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const Kodachrome = createColorMatrixFilter(\n 'Kodachrome',\n [\n 1.12855, -0.39673, -0.03992, 0, 0.24991, -0.16404, 1.08352, -0.05498, 0,\n 0.09698, -0.16786, -0.56034, 1.60148, 0, 0.13972, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const Technicolor = createColorMatrixFilter(\n 'Technicolor',\n [\n 1.91252, -0.85453, -0.09155, 0, 0.04624, -0.30878, 1.76589, -0.10601, 0,\n -0.27589, -0.2311, -0.75018, 1.84759, 0, 0.12137, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const Polaroid = createColorMatrixFilter(\n 'Polaroid',\n [\n 1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016,\n 1.483, 0, 0, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const Sepia = createColorMatrixFilter(\n 'Sepia',\n [\n 0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131,\n 0, 0, 0, 0, 0, 1, 0,\n ],\n);\n\nexport const BlackWhite = createColorMatrixFilter(\n 'BlackWhite',\n [\n 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 1.5, 1.5, 1.5, 0, -1, 0, 0, 0,\n 1, 0,\n ],\n);\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLPipelineState } from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport { classRegistry } from '../ClassRegistry';\n\ntype ComposedOwnProps = {\n subFilters: BaseFilter<string, object, object>[];\n};\n\ntype ComposedSerializedProps = {\n subFilters: Record<string, unknown>[];\n};\n\n/**\n * A container class that knows how to apply a sequence of filters to an input image.\n */\nexport class Composed extends BaseFilter<\n 'Composed',\n ComposedOwnProps,\n ComposedSerializedProps\n> {\n /**\n * A non sparse array of filters to apply\n */\n declare subFilters: ComposedOwnProps['subFilters'];\n\n static type = 'Composed';\n\n constructor(\n options: { subFilters?: BaseFilter<string>[] } & Record<string, any> = {},\n ) {\n super(options);\n this.subFilters = options.subFilters || [];\n }\n\n /**\n * Apply this container's filters to the input image provided.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be applied.\n */\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n options.passes += this.subFilters.length - 1;\n }\n this.subFilters.forEach((filter) => {\n filter.applyTo(options);\n });\n }\n\n /**\n * Serialize this filter into JSON.\n * @returns {Object} A JSON representation of this filter.\n */\n toObject() {\n return {\n type: this.type,\n subFilters: this.subFilters.map((filter) => filter.toObject()),\n };\n }\n\n isNeutralState() {\n return !this.subFilters.some((filter) => !filter.isNeutralState());\n }\n\n /**\n * Deserialize a JSON definition of a ComposedFilter into a concrete instance.\n * @param {oject} object Object to create an instance from\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting `BlendImage` filter loading, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Composed>}\n */\n static fromObject(\n object: Record<string, any>,\n options?: { signal: AbortSignal },\n ): Promise<Composed> {\n return Promise.all(\n ((object.subFilters || []) as BaseFilter<string>[]).map((filter) =>\n classRegistry\n .getClass<typeof BaseFilter>(filter.type)\n .fromObject(filter, options),\n ),\n ).then((enlivedFilters) => new this({ subFilters: enlivedFilters }));\n }\n}\n\nclassRegistry.setClass(Composed);\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/constrast';\n\ntype ContrastOwnProps = {\n contrast: number;\n};\n\nexport const contrastDefaultValues: ContrastOwnProps = {\n contrast: 0,\n};\n\n/**\n * Contrast filter class\n * @example\n * const filter = new Contrast({\n * contrast: 0.25\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Contrast extends BaseFilter<'Contrast', ContrastOwnProps> {\n /**\n * contrast value, range from -1 to 1.\n * @param {Number} contrast\n * @default 0\n */\n declare contrast: ContrastOwnProps['contrast'];\n\n static type = 'Contrast';\n\n static defaults = contrastDefaultValues;\n\n static uniformLocations = ['uContrast'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n isNeutralState() {\n return this.contrast === 0;\n }\n\n /**\n * Apply the Contrast operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const contrast = Math.floor(this.contrast * 255),\n contrastF = (259 * (contrast + 255)) / (255 * (259 - contrast));\n\n for (let i = 0; i < data.length; i += 4) {\n data[i] = contrastF * (data[i] - 128) + 128;\n data[i + 1] = contrastF * (data[i + 1] - 128) + 128;\n data[i + 2] = contrastF * (data[i + 2] - 128) + 128;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uContrast, this.contrast);\n }\n}\n\nclassRegistry.setClass(Contrast);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uContrast;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float contrastF = 1.015 * (uContrast + 1.0) / (1.0 * (1.015 - uContrast));\n color.rgb = contrastF * (color.rgb - 0.5) + 0.5;\n gl_FragColor = color;\n }`;\n","export const fragmentSource = {\n Convolute_3_1: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[9];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 0);\n for (float h = 0.0; h < 3.0; h+=1.0) {\n for (float w = 0.0; w < 3.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 1), uStepH * (h - 1));\n color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 3.0 + w)];\n }\n }\n gl_FragColor = color;\n }\n `,\n Convolute_3_0: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[9];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 1);\n for (float h = 0.0; h < 3.0; h+=1.0) {\n for (float w = 0.0; w < 3.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 1.0), uStepH * (h - 1.0));\n color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 3.0 + w)];\n }\n }\n float alpha = texture2D(uTexture, vTexCoord).a;\n gl_FragColor = color;\n gl_FragColor.a = alpha;\n }\n `,\n Convolute_5_1: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[25];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 0);\n for (float h = 0.0; h < 5.0; h+=1.0) {\n for (float w = 0.0; w < 5.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\n color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 5.0 + w)];\n }\n }\n gl_FragColor = color;\n }\n `,\n Convolute_5_0: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[25];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 1);\n for (float h = 0.0; h < 5.0; h+=1.0) {\n for (float w = 0.0; w < 5.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 2.0), uStepH * (h - 2.0));\n color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 5.0 + w)];\n }\n }\n float alpha = texture2D(uTexture, vTexCoord).a;\n gl_FragColor = color;\n gl_FragColor.a = alpha;\n }\n `,\n Convolute_7_1: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[49];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 0);\n for (float h = 0.0; h < 7.0; h+=1.0) {\n for (float w = 0.0; w < 7.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\n color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 7.0 + w)];\n }\n }\n gl_FragColor = color;\n }\n `,\n Convolute_7_0: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[49];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 1);\n for (float h = 0.0; h < 7.0; h+=1.0) {\n for (float w = 0.0; w < 7.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 3.0), uStepH * (h - 3.0));\n color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 7.0 + w)];\n }\n }\n float alpha = texture2D(uTexture, vTexCoord).a;\n gl_FragColor = color;\n gl_FragColor.a = alpha;\n }\n `,\n Convolute_9_1: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[81];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 0);\n for (float h = 0.0; h < 9.0; h+=1.0) {\n for (float w = 0.0; w < 9.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\n color += texture2D(uTexture, vTexCoord + matrixPos) * uMatrix[int(h * 9.0 + w)];\n }\n }\n gl_FragColor = color;\n }\n `,\n Convolute_9_0: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uMatrix[81];\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = vec4(0, 0, 0, 1);\n for (float h = 0.0; h < 9.0; h+=1.0) {\n for (float w = 0.0; w < 9.0; w+=1.0) {\n vec2 matrixPos = vec2(uStepW * (w - 4.0), uStepH * (h - 4.0));\n color.rgb += texture2D(uTexture, vTexCoord + matrixPos).rgb * uMatrix[int(h * 9.0 + w)];\n }\n }\n float alpha = texture2D(uTexture, vTexCoord).a;\n gl_FragColor = color;\n gl_FragColor.a = alpha;\n }\n `,\n};\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/convolute';\n\nexport type ConvoluteOwnProps = {\n opaque: boolean;\n matrix: number[];\n};\n\nexport const convoluteDefaultValues: ConvoluteOwnProps = {\n opaque: false,\n matrix: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n};\n\n/**\n * Adapted from <a href=\"http://www.html5rocks.com/en/tutorials/canvas/imagefilters/\">html5rocks article</a>\n * @example <caption>Sharpen filter</caption>\n * const filter = new Convolute({\n * matrix: [ 0, -1, 0,\n * -1, 5, -1,\n * 0, -1, 0 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example <caption>Blur filter</caption>\n * const filter = new Convolute({\n * matrix: [ 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9,\n * 1/9, 1/9, 1/9 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example <caption>Emboss filter</caption>\n * const filter = new Convolute({\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n * @example <caption>Emboss filter with opaqueness</caption>\n * const filter = new Convolute({\n * opaque: true,\n * matrix: [ 1, 1, 1,\n * 1, 0.7, -1,\n * -1, -1, -1 ]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class Convolute extends BaseFilter<'Convolute', ConvoluteOwnProps> {\n /*\n * Opaque value (true/false)\n */\n declare opaque: ConvoluteOwnProps['opaque'];\n\n /*\n * matrix for the filter, max 9x9\n */\n declare matrix: ConvoluteOwnProps['matrix'];\n\n static type = 'Convolute';\n\n static defaults = convoluteDefaultValues;\n\n static uniformLocations = ['uMatrix', 'uOpaque', 'uHalfSize', 'uSize'];\n\n getCacheKey() {\n return `${this.type}_${Math.sqrt(this.matrix.length)}_${\n this.opaque ? 1 : 0\n }` as keyof typeof fragmentSource;\n }\n\n getFragmentSource() {\n return fragmentSource[this.getCacheKey()];\n }\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d(options: T2DPipelineState) {\n const imageData = options.imageData,\n data = imageData.data,\n weights = this.matrix,\n side = Math.round(Math.sqrt(weights.length)),\n halfSide = Math.floor(side / 2),\n sw = imageData.width,\n sh = imageData.height,\n output = options.ctx.createImageData(sw, sh),\n dst = output.data,\n // go through the destination image pixels\n alphaFac = this.opaque ? 1 : 0;\n let r, g, b, a, dstOff, scx, scy, srcOff, wt, x, y, cx, cy;\n\n for (y = 0; y < sh; y++) {\n for (x = 0; x < sw; x++) {\n dstOff = (y * sw + x) * 4;\n // calculate the weighed sum of the source image pixels that\n // fall under the convolution matrix\n r = 0;\n g = 0;\n b = 0;\n a = 0;\n\n for (cy = 0; cy < side; cy++) {\n for (cx = 0; cx < side; cx++) {\n scy = y + cy - halfSide;\n scx = x + cx - halfSide;\n\n // eslint-disable-next-line max-depth\n if (scy < 0 || scy >= sh || scx < 0 || scx >= sw) {\n continue;\n }\n\n srcOff = (scy * sw + scx) * 4;\n wt = weights[cy * side + cx];\n\n r += data[srcOff] * wt;\n g += data[srcOff + 1] * wt;\n b += data[srcOff + 2] * wt;\n // eslint-disable-next-line max-depth\n if (!alphaFac) {\n a += data[srcOff + 3] * wt;\n }\n }\n }\n dst[dstOff] = r;\n dst[dstOff + 1] = g;\n dst[dstOff + 2] = b;\n if (!alphaFac) {\n dst[dstOff + 3] = a;\n } else {\n dst[dstOff + 3] = data[dstOff + 3];\n }\n }\n }\n options.imageData = output;\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1fv(uniformLocations.uMatrix, this.matrix);\n }\n\n /**\n * Returns object representation of an instance\n * @return {Object} Object representation of an instance\n */\n toObject() {\n return {\n ...super.toObject(),\n opaque: this.opaque,\n matrix: [...this.matrix],\n };\n }\n}\n\nclassRegistry.setClass(Convolute);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform vec3 uGamma;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n vec3 correction = (1.0 / uGamma);\n color.r = pow(color.r, correction.r);\n color.g = pow(color.g, correction.g);\n color.b = pow(color.b, correction.b);\n gl_FragColor = color;\n gl_FragColor.rgb *= color.a;\n }\n`;\n","import { BaseFilter } from './BaseFilter';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/gamma';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\n\nconst GAMMA = 'Gamma' as const;\n\nexport type GammaInput = [number, number, number];\n\nexport type GammaOwnProps = {\n gamma: GammaInput;\n};\n\nexport const gammaDefaultValues: GammaOwnProps = {\n gamma: [1, 1, 1],\n};\n\n/**\n * Gamma filter class\n * @example\n * const filter = new Gamma({\n * gamma: [1, 0.5, 2.1]\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Gamma extends BaseFilter<typeof GAMMA, GammaOwnProps> {\n /**\n * Gamma array value, from 0.01 to 2.2.\n * @param {Array} gamma\n */\n declare gamma: GammaOwnProps['gamma'];\n declare rgbValues?: {\n r: Uint8Array;\n g: Uint8Array;\n b: Uint8Array;\n };\n\n static type = GAMMA;\n\n static defaults = gammaDefaultValues;\n\n static uniformLocations = ['uGamma'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n constructor(options: { gamma?: GammaInput } = {}) {\n super(options);\n this.gamma =\n options.gamma ||\n ((\n this.constructor as typeof Gamma\n ).defaults.gamma.concat() as GammaInput);\n }\n\n /**\n * Apply the Gamma operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const gamma = this.gamma,\n rInv = 1 / gamma[0],\n gInv = 1 / gamma[1],\n bInv = 1 / gamma[2];\n\n if (!this.rgbValues) {\n this.rgbValues = {\n r: new Uint8Array(256),\n g: new Uint8Array(256),\n b: new Uint8Array(256),\n };\n }\n\n // This is an optimization - pre-compute a look-up table for each color channel\n // instead of performing these pow calls for each pixel in the image.\n const rgb = this.rgbValues;\n for (let i = 0; i < 256; i++) {\n rgb.r[i] = Math.pow(i / 255, rInv) * 255;\n rgb.g[i] = Math.pow(i / 255, gInv) * 255;\n rgb.b[i] = Math.pow(i / 255, bInv) * 255;\n }\n for (let i = 0; i < data.length; i += 4) {\n data[i] = rgb.r[data[i]];\n data[i + 1] = rgb.g[data[i + 1]];\n data[i + 2] = rgb.b[data[i + 2]];\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform3fv(uniformLocations.uGamma, this.gamma);\n }\n\n isNeutralState() {\n const { gamma } = this;\n return gamma[0] === 1 && gamma[1] === 1 && gamma[2] === 1;\n }\n\n toObject(): { type: typeof GAMMA; gamma: GammaInput } {\n return {\n type: GAMMA,\n gamma: this.gamma.concat() as GammaInput,\n };\n }\n}\n\nclassRegistry.setClass(Gamma);\n","import type { TGrayscaleMode } from '../Grayscale';\n\nexport const fragmentSource: Record<TGrayscaleMode, string> = {\n average: `\n precision highp float;\n uniform sampler2D uTexture;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float average = (color.r + color.b + color.g) / 3.0;\n gl_FragColor = vec4(average, average, average, color.a);\n }\n `,\n lightness: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform int uMode;\n varying vec2 vTexCoord;\n void main() {\n vec4 col = texture2D(uTexture, vTexCoord);\n float average = (max(max(col.r, col.g),col.b) + min(min(col.r, col.g),col.b)) / 2.0;\n gl_FragColor = vec4(average, average, average, col.a);\n }\n `,\n luminosity: `\n precision highp float;\n uniform sampler2D uTexture;\n uniform int uMode;\n varying vec2 vTexCoord;\n void main() {\n vec4 col = texture2D(uTexture, vTexCoord);\n float average = 0.21 * col.r + 0.72 * col.g + 0.07 * col.b;\n gl_FragColor = vec4(average, average, average, col.a);\n }\n `,\n};\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/grayscale';\n\nexport type TGrayscaleMode = 'average' | 'lightness' | 'luminosity';\n\ntype GrayscaleOwnProps = {\n mode: TGrayscaleMode;\n};\n\nexport const grayscaleDefaultValues: GrayscaleOwnProps = {\n mode: 'average',\n};\n\n/**\n * Grayscale image filter class\n * @example\n * const filter = new Grayscale();\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Grayscale extends BaseFilter<'Grayscale', GrayscaleOwnProps> {\n declare mode: TGrayscaleMode;\n\n static type = 'Grayscale';\n\n static defaults = grayscaleDefaultValues;\n\n static uniformLocations = ['uMode'];\n\n /**\n * Apply the Grayscale operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n for (let i = 0, value: number; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n switch (this.mode) {\n case 'average':\n value = (r + g + b) / 3;\n break;\n case 'lightness':\n value = (Math.min(r, g, b) + Math.max(r, g, b)) / 2;\n break;\n case 'luminosity':\n value = 0.21 * r + 0.72 * g + 0.07 * b;\n break;\n }\n\n data[i + 2] = data[i + 1] = data[i] = value;\n }\n }\n\n getCacheKey() {\n return `${this.type}_${this.mode}`;\n }\n\n getFragmentSource() {\n return fragmentSource[this.mode];\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const mode = 1;\n gl.uniform1i(uniformLocations.uMode, mode);\n }\n\n /**\n * Grayscale filter isNeutralState implementation\n * The filter is never neutral\n * on the image\n **/\n isNeutralState() {\n return false;\n }\n}\n\nclassRegistry.setClass(Grayscale);\n","import { cos } from '../util/misc/cos';\nimport { sin } from '../util/misc/sin';\nimport {\n ColorMatrix,\n type ColorMatrixOwnProps,\n colorMatrixDefaultValues,\n} from './ColorMatrix';\nimport type { TWebGLPipelineState, T2DPipelineState } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\n\nexport type HueRotationOwnProps = ColorMatrixOwnProps & {\n rotation: number;\n};\n\nexport type HueRotationSerializedProps = {\n rotation: number;\n};\n\nexport const hueRotationDefaultValues: HueRotationOwnProps = {\n ...colorMatrixDefaultValues,\n rotation: 0,\n};\n\n/**\n * HueRotation filter class\n * @example\n * const filter = new HueRotation({\n * rotation: -0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class HueRotation extends ColorMatrix<\n 'HueRotation',\n HueRotationOwnProps,\n HueRotationSerializedProps\n> {\n /**\n * HueRotation value, from -1 to 1.\n */\n declare rotation: HueRotationOwnProps['rotation'];\n\n static type = 'HueRotation';\n\n static defaults = hueRotationDefaultValues;\n\n calculateMatrix() {\n const rad = this.rotation * Math.PI,\n cosine = cos(rad),\n sine = sin(rad),\n aThird = 1 / 3,\n aThirdSqtSin = Math.sqrt(aThird) * sine,\n OneMinusCos = 1 - cosine;\n this.matrix = [\n cosine + OneMinusCos / 3,\n aThird * OneMinusCos - aThirdSqtSin,\n aThird * OneMinusCos + aThirdSqtSin,\n 0,\n 0,\n aThird * OneMinusCos + aThirdSqtSin,\n cosine + aThird * OneMinusCos,\n aThird * OneMinusCos - aThirdSqtSin,\n 0,\n 0,\n aThird * OneMinusCos - aThirdSqtSin,\n aThird * OneMinusCos + aThirdSqtSin,\n cosine + aThird * OneMinusCos,\n 0,\n 0,\n 0,\n 0,\n 0,\n 1,\n 0,\n ];\n }\n\n isNeutralState() {\n return this.rotation === 0;\n }\n\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n this.calculateMatrix();\n super.applyTo(options);\n }\n\n toObject() {\n return {\n type: this.type,\n rotation: this.rotation,\n };\n }\n}\n\nclassRegistry.setClass(HueRotation);\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/invert';\n\nexport type InvertOwnProps = {\n alpha: boolean;\n invert: boolean;\n};\n\nexport const invertDefaultValues: InvertOwnProps = {\n alpha: false,\n invert: true,\n};\n\n/**\n * @example\n * const filter = new Invert();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\nexport class Invert extends BaseFilter<'Invert', InvertOwnProps> {\n /**\n * Invert also alpha.\n * @param {Boolean} alpha\n **/\n declare alpha: InvertOwnProps['alpha'];\n\n /**\n * Filter invert. if false, does nothing\n * @param {Boolean} invert\n */\n declare invert: InvertOwnProps['invert'];\n\n static type = 'Invert';\n\n static defaults = invertDefaultValues;\n\n static uniformLocations = ['uInvert', 'uAlpha'];\n\n /**\n * Apply the Invert operation to a Uint8Array representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8Array to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n for (let i = 0; i < data.length; 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 if (this.alpha) {\n data[i + 3] = 255 - data[i + 3];\n }\n }\n }\n\n protected getFragmentSource(): string {\n return fragmentSource;\n }\n\n /**\n * Invert filter isNeutralState implementation\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * @param {Object} options\n **/\n isNeutralState() {\n return !this.invert;\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1i(uniformLocations.uInvert, Number(this.invert));\n gl.uniform1i(uniformLocations.uAlpha, Number(this.alpha));\n }\n}\n\nclassRegistry.setClass(Invert);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform int uInvert;\n uniform int uAlpha;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n if (uInvert == 1) {\n if (uAlpha == 1) {\n gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,1.0 -color.a);\n } else {\n gl_FragColor = vec4(1.0 - color.r,1.0 -color.g,1.0 -color.b,color.a);\n }\n } else {\n gl_FragColor = color;\n }\n }\n`;\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/noise';\n\nexport type NoiseOwnProps = {\n noise: number;\n};\n\nexport const noiseDefaultValues: NoiseOwnProps = {\n noise: 0,\n};\n\n/**\n * Noise filter class\n * @example\n * const filter = new Noise({\n * noise: 700\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class Noise extends BaseFilter<'Noise', NoiseOwnProps> {\n /**\n * Noise value, from\n * @param {Number} noise\n */\n declare noise: NoiseOwnProps['noise'];\n\n static type = 'Noise';\n\n static defaults = noiseDefaultValues;\n\n static uniformLocations = ['uNoise', 'uSeed'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n /**\n * Apply the Brightness operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const noise = this.noise;\n for (let i = 0; i < data.length; i += 4) {\n const rand = (0.5 - Math.random()) * noise;\n data[i] += rand;\n data[i + 1] += rand;\n data[i + 2] += rand;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uNoise, this.noise / 255);\n gl.uniform1f(uniformLocations.uSeed, Math.random());\n }\n\n isNeutralState() {\n return this.noise === 0;\n }\n}\n\nclassRegistry.setClass(Noise);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uStepH;\n uniform float uNoise;\n uniform float uSeed;\n varying vec2 vTexCoord;\n float rand(vec2 co, float seed, float vScale) {\n return fract(sin(dot(co.xy * vScale ,vec2(12.9898 , 78.233))) * 43758.5453 * (seed + 0.01) / 2.0);\n }\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n color.rgb += (0.5 - rand(vTexCoord, uSeed, 0.1 / uStepH)) * uNoise;\n gl_FragColor = color;\n }\n`;\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/pixelate';\n\nexport type PixelateOwnProps = {\n blocksize: number;\n};\n\nexport const pixelateDefaultValues: PixelateOwnProps = {\n blocksize: 4,\n};\n\n/**\n * Pixelate filter class\n * @example\n * const filter = new Pixelate({\n * blocksize: 8\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Pixelate extends BaseFilter<'Pixelate', PixelateOwnProps> {\n declare blocksize: PixelateOwnProps['blocksize'];\n\n static type = 'Pixelate';\n\n static defaults = pixelateDefaultValues;\n\n static uniformLocations = ['uBlocksize'];\n\n /**\n * Apply the Pixelate operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data, width, height } }: T2DPipelineState) {\n for (let i = 0; i < height; i += this.blocksize) {\n for (let j = 0; j < width; j += this.blocksize) {\n const index = i * 4 * width + j * 4;\n const r = data[index];\n const g = data[index + 1];\n const b = data[index + 2];\n const a = data[index + 3];\n\n for (let _i = i; _i < Math.min(i + this.blocksize, height); _i++) {\n for (let _j = j; _j < Math.min(j + this.blocksize, width); _j++) {\n const index = _i * 4 * width + _j * 4;\n data[index] = r;\n data[index + 1] = g;\n data[index + 2] = b;\n data[index + 3] = a;\n }\n }\n }\n }\n }\n\n /**\n * Indicate when the filter is not gonna apply changes to the image\n **/\n isNeutralState() {\n return this.blocksize === 1;\n }\n\n protected getFragmentSource(): string {\n return fragmentSource;\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uBlocksize, this.blocksize);\n }\n}\n\nclassRegistry.setClass(Pixelate);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uBlocksize;\n uniform float uStepW;\n uniform float uStepH;\n varying vec2 vTexCoord;\n void main() {\n float blockW = uBlocksize * uStepW;\n float blockH = uBlocksize * uStepH;\n int posX = int(vTexCoord.x / blockW);\n int posY = int(vTexCoord.y / blockH);\n float fposX = float(posX);\n float fposY = float(posY);\n vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\n vec4 color = texture2D(uTexture, squareCoords);\n gl_FragColor = color;\n }\n`;\n","import { classRegistry } from '../ClassRegistry';\nimport { Color } from '../color/Color';\nimport { BaseFilter } from './BaseFilter';\nimport { fragmentShader } from './shaders/removeColor';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\n\nexport type RemoveColorOwnProps = {\n color: string;\n distance: number;\n useAlpha: boolean;\n};\n\nexport const removeColorDefaultValues: RemoveColorOwnProps = {\n color: '#FFFFFF',\n distance: 0.02,\n useAlpha: false,\n};\n\n/**\n * Remove white filter class\n * @example\n * const filter = new RemoveColor({\n * threshold: 0.2,\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class RemoveColor extends BaseFilter<\n 'RemoveColor',\n RemoveColorOwnProps\n> {\n /**\n * Color to remove, in any format understood by {@link Color}.\n */\n declare color: RemoveColorOwnProps['color'];\n\n /**\n * distance to actual color, as value up or down from each r,g,b\n * between 0 and 1\n **/\n declare distance: RemoveColorOwnProps['distance'];\n\n /**\n * For color to remove inside distance, use alpha channel for a smoother deletion\n * NOT IMPLEMENTED YET\n **/\n declare useAlpha: RemoveColorOwnProps['useAlpha'];\n\n static type = 'RemoveColor';\n\n static defaults = removeColorDefaultValues;\n\n static uniformLocations = ['uLow', 'uHigh'];\n\n getFragmentSource() {\n return fragmentShader;\n }\n\n /**\n * Applies filter to canvas element\n * @param {Object} canvasEl Canvas element to apply filter to\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const distance = this.distance * 255,\n source = new Color(this.color).getSource(),\n lowC = [source[0] - distance, source[1] - distance, source[2] - distance],\n highC = [\n source[0] + distance,\n source[1] + distance,\n source[2] + distance,\n ];\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n\n if (\n r > lowC[0] &&\n g > lowC[1] &&\n b > lowC[2] &&\n r < highC[0] &&\n g < highC[1] &&\n b < highC[2]\n ) {\n data[i + 3] = 0;\n }\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n const source = new Color(this.color).getSource(),\n distance = this.distance,\n lowC = [\n 0 + source[0] / 255 - distance,\n 0 + source[1] / 255 - distance,\n 0 + source[2] / 255 - distance,\n 1,\n ],\n highC = [\n source[0] / 255 + distance,\n source[1] / 255 + distance,\n source[2] / 255 + distance,\n 1,\n ];\n gl.uniform4fv(uniformLocations.uLow, lowC);\n gl.uniform4fv(uniformLocations.uHigh, highC);\n }\n}\n\nclassRegistry.setClass(RemoveColor);\n","export const fragmentShader = `\nprecision highp float;\nuniform sampler2D uTexture;\nuniform vec4 uLow;\nuniform vec4 uHigh;\nvarying vec2 vTexCoord;\nvoid main() {\n gl_FragColor = texture2D(uTexture, vTexCoord);\n if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\n gl_FragColor.a = 0.0;\n }\n}\n`;\n","import { BaseFilter } from './BaseFilter';\nimport type {\n T2DPipelineState,\n TWebGLPipelineState,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport { classRegistry } from '../ClassRegistry';\nimport { createCanvasElement } from '../util/misc/dom';\nimport type { XY } from '../Point';\n\nexport type TResizeType = 'bilinear' | 'hermite' | 'sliceHack' | 'lanczos';\n\nexport type ResizeOwnProps = {\n resizeType: TResizeType;\n scaleX: number;\n scaleY: number;\n lanczosLobes: number;\n};\n\nexport type ResizeSerializedProps = ResizeOwnProps;\n\nexport const resizeDefaultValues: ResizeOwnProps = {\n resizeType: 'hermite',\n scaleX: 1,\n scaleY: 1,\n lanczosLobes: 3,\n};\n\ntype ResizeDuring2DResize = Resize & {\n rcpScaleX: number;\n rcpScaleY: number;\n};\n\ntype ResizeDuringWEBGLResize = Resize & {\n rcpScaleX: number;\n rcpScaleY: number;\n horizontal: boolean;\n width: number;\n height: number;\n taps: number[];\n tempScale: number;\n dH: number;\n dW: number;\n};\n\n/**\n * Resize image filter class\n * @example\n * const filter = new Resize();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\nexport class Resize extends BaseFilter<'Resize', ResizeOwnProps> {\n /**\n * Resize type\n * for webgl resizeType is just lanczos, for canvas2d can be:\n * bilinear, hermite, sliceHack, lanczos.\n */\n declare resizeType: ResizeOwnProps['resizeType'];\n\n /**\n * Scale factor for resizing, x axis\n * @param {Number} scaleX\n */\n declare scaleX: ResizeOwnProps['scaleX'];\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n */\n declare scaleY: ResizeOwnProps['scaleY'];\n\n /**\n * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n * @param {Number} lanczosLobes\n */\n declare lanczosLobes: ResizeOwnProps['lanczosLobes'];\n\n static type = 'Resize';\n\n static defaults = resizeDefaultValues;\n\n static uniformLocations = ['uDelta', 'uTaps'];\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n this: ResizeDuringWEBGLResize,\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform2fv(\n uniformLocations.uDelta,\n this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height],\n );\n gl.uniform1fv(uniformLocations.uTaps, this.taps);\n }\n\n getFilterWindow(this: ResizeDuringWEBGLResize) {\n const scale = this.tempScale;\n return Math.ceil(this.lanczosLobes / scale);\n }\n\n getCacheKey(this: ResizeDuringWEBGLResize): string {\n const filterWindow = this.getFilterWindow();\n return `${this.type}_${filterWindow}`;\n }\n\n getFragmentSource(this: ResizeDuringWEBGLResize): string {\n const filterWindow = this.getFilterWindow();\n return this.generateShader(filterWindow);\n }\n\n getTaps(this: ResizeDuringWEBGLResize) {\n const lobeFunction = this.lanczosCreate(this.lanczosLobes),\n scale = this.tempScale,\n filterWindow = this.getFilterWindow(),\n taps = new Array(filterWindow);\n for (let i = 1; i <= filterWindow; i++) {\n taps[i - 1] = lobeFunction(i * scale);\n }\n return taps;\n }\n\n /**\n * Generate vertex and shader sources from the necessary steps numbers\n * @param {Number} filterWindow\n */\n generateShader(filterWindow: number) {\n const offsets = new Array(filterWindow);\n for (let i = 1; i <= filterWindow; i++) {\n offsets[i - 1] = `${i}.0 * uDelta`;\n }\n return `\n precision highp float;\n uniform sampler2D uTexture;\n uniform vec2 uDelta;\n varying vec2 vTexCoord;\n uniform float uTaps[${filterWindow}];\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float sum = 1.0;\n ${offsets\n .map(\n (offset, i) => `\n color += texture2D(uTexture, vTexCoord + ${offset}) * uTaps[${i}] + texture2D(uTexture, vTexCoord - ${offset}) * uTaps[${i}];\n sum += 2.0 * uTaps[${i}];\n `,\n )\n .join('\\n')}\n gl_FragColor = color / sum;\n }\n `;\n }\n\n applyToForWebgl(this: ResizeDuringWEBGLResize, options: TWebGLPipelineState) {\n options.passes++;\n this.width = options.sourceWidth;\n this.horizontal = true;\n this.dW = Math.round(this.width * this.scaleX);\n this.dH = options.sourceHeight;\n this.tempScale = this.dW / this.width;\n this.taps = this.getTaps();\n options.destinationWidth = this.dW;\n super.applyTo(options);\n options.sourceWidth = options.destinationWidth;\n\n this.height = options.sourceHeight;\n this.horizontal = false;\n this.dH = Math.round(this.height * this.scaleY);\n this.tempScale = this.dH / this.height;\n this.taps = this.getTaps();\n options.destinationHeight = this.dH;\n super.applyTo(options);\n options.sourceHeight = options.destinationHeight;\n }\n\n /**\n * Apply the resize filter to the image\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n (this as unknown as ResizeDuringWEBGLResize).applyToForWebgl(options);\n } else {\n (this as unknown as ResizeDuring2DResize).applyTo2d(options);\n }\n }\n\n isNeutralState() {\n return this.scaleX === 1 && this.scaleY === 1;\n }\n\n lanczosCreate(lobes: number) {\n return (x: number) => {\n if (x >= lobes || x <= -lobes) {\n return 0.0;\n }\n if (x < 1.1920929e-7 && x > -1.1920929e-7) {\n return 1.0;\n }\n x *= Math.PI;\n const xx = x / lobes;\n return ((Math.sin(x) / x) * Math.sin(xx)) / xx;\n };\n }\n\n applyTo2d(this: ResizeDuring2DResize, options: T2DPipelineState) {\n const imageData = options.imageData,\n scaleX = this.scaleX,\n scaleY = this.scaleY;\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n const oW = imageData.width;\n const oH = imageData.height;\n const dW = Math.round(oW * scaleX);\n const dH = Math.round(oH * scaleY);\n let newData: ImageData;\n\n if (this.resizeType === 'sliceHack') {\n newData = this.sliceByTwo(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'hermite') {\n newData = this.hermiteFastResize(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'bilinear') {\n newData = this.bilinearFiltering(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'lanczos') {\n newData = this.lanczosResize(options, oW, oH, dW, dH);\n } else {\n // this should never trigger, is here just for safety net.\n newData = new ImageData(dW, dH);\n }\n options.imageData = newData;\n }\n\n /**\n * Filter sliceByTwo\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n sliceByTwo(\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n const imageData = options.imageData;\n const mult = 0.5;\n let doneW = false;\n let doneH = false;\n let stepW = oW * mult;\n let stepH = oH * mult;\n const resources = options.filterBackend.resources;\n let sX = 0;\n let sY = 0;\n const dX = oW;\n let dY = 0;\n if (!resources.sliceByTwo) {\n resources.sliceByTwo = createCanvasElement();\n }\n const tmpCanvas = resources.sliceByTwo;\n if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\n tmpCanvas.width = oW * 1.5;\n tmpCanvas.height = oH;\n }\n const ctx = tmpCanvas.getContext('2d')!;\n ctx.clearRect(0, 0, oW * 1.5, oH);\n ctx.putImageData(imageData, 0, 0);\n\n dW = Math.floor(dW);\n dH = Math.floor(dH);\n\n while (!doneW || !doneH) {\n oW = stepW;\n oH = stepH;\n if (dW < Math.floor(stepW * mult)) {\n stepW = Math.floor(stepW * mult);\n } else {\n stepW = dW;\n doneW = true;\n }\n if (dH < Math.floor(stepH * mult)) {\n stepH = Math.floor(stepH * mult);\n } else {\n stepH = dH;\n doneH = true;\n }\n ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\n sX = dX;\n sY = dY;\n dY += stepH;\n }\n return ctx.getImageData(sX, sY, dW, dH);\n }\n\n /**\n * Filter lanczosResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n lanczosResize(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ): ImageData {\n function process(u: number): ImageData {\n let v, i, weight, idx, a, red, green, blue, alpha, fX, fY;\n center.x = (u + 0.5) * ratioX;\n icenter.x = Math.floor(center.x);\n for (v = 0; v < dH; v++) {\n center.y = (v + 0.5) * ratioY;\n icenter.y = Math.floor(center.y);\n a = 0;\n red = 0;\n green = 0;\n blue = 0;\n alpha = 0;\n for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n if (i < 0 || i >= oW) {\n continue;\n }\n fX = Math.floor(1000 * Math.abs(i - center.x));\n if (!cacheLanc[fX]) {\n cacheLanc[fX] = {};\n }\n for (let j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n if (j < 0 || j >= oH) {\n continue;\n }\n fY = Math.floor(1000 * Math.abs(j - center.y));\n if (!cacheLanc[fX][fY]) {\n cacheLanc[fX][fY] = lanczos(\n Math.sqrt(\n Math.pow(fX * rcpRatioX, 2) + Math.pow(fY * rcpRatioY, 2),\n ) / 1000,\n );\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 } else {\n return destImg;\n }\n }\n\n const srcData = options.imageData.data,\n destImg = options.ctx.createImageData(dW, dH),\n destData = destImg.data,\n lanczos = this.lanczosCreate(this.lanczosLobes),\n ratioX = this.rcpScaleX,\n ratioY = this.rcpScaleY,\n rcpRatioX = 2 / this.rcpScaleX,\n rcpRatioY = 2 / this.rcpScaleY,\n range2X = Math.ceil((ratioX * this.lanczosLobes) / 2),\n range2Y = Math.ceil((ratioY * this.lanczosLobes) / 2),\n cacheLanc: Record<number, Record<number, number>> = {},\n center: XY = { x: 0, y: 0 },\n icenter: XY = { x: 0, y: 0 };\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(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n let a;\n let b;\n let c;\n let d;\n let x;\n let y;\n let i;\n let j;\n let xDiff;\n let yDiff;\n let chnl;\n let color;\n let offset = 0;\n let origPix;\n const ratioX = this.rcpScaleX;\n const ratioY = this.rcpScaleY;\n const w4 = 4 * (oW - 1);\n const img = options.imageData;\n const pixels = img.data;\n const destImage = options.ctx.createImageData(dW, dH);\n const destPixels = destImage.data;\n for (i = 0; i < dH; i++) {\n for (j = 0; j < dW; j++) {\n x = Math.floor(ratioX * j);\n y = Math.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 =\n a * (1 - xDiff) * (1 - yDiff) +\n b * xDiff * (1 - yDiff) +\n c * yDiff * (1 - xDiff) +\n 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(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n const ratioW = this.rcpScaleX,\n ratioH = this.rcpScaleY,\n ratioWHalf = Math.ceil(ratioW / 2),\n ratioHHalf = Math.ceil(ratioH / 2),\n img = options.imageData,\n data = img.data,\n img2 = options.ctx.createImageData(dW, dH),\n data2 = img2.data;\n for (let j = 0; j < dH; j++) {\n for (let i = 0; i < dW; i++) {\n const x2 = (i + j * dW) * 4;\n let weight = 0;\n let weights = 0;\n let weightsAlpha = 0;\n let gxR = 0;\n let gxG = 0;\n let gxB = 0;\n let gxA = 0;\n const centerY = (j + 0.5) * ratioH;\n for (let yy = Math.floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n const dy = Math.abs(centerY - (yy + 0.5)) / ratioHHalf,\n centerX = (i + 0.5) * ratioW,\n w0 = dy * dy;\n for (let xx = Math.floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n let dx = Math.abs(centerX - (xx + 0.5)) / ratioWHalf;\n const w = Math.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\nclassRegistry.setClass(Resize);\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/saturation';\n\nexport type SaturationOwnProps = {\n saturation: number;\n};\n\nexport const saturationDefaultValues: SaturationOwnProps = {\n saturation: 0,\n};\n\n/**\n * Saturate filter class\n * @example\n * const filter = new Saturation({\n * saturation: 1\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Saturation extends BaseFilter<'Saturation', SaturationOwnProps> {\n /**\n * Saturation value, from -1 to 1.\n * Increases/decreases the color saturation.\n * A value of 0 has no effect.\n *\n * @param {Number} saturation\n */\n declare saturation: SaturationOwnProps['saturation'];\n\n static type = 'Saturation';\n\n static defaults = saturationDefaultValues;\n\n static uniformLocations = ['uSaturation'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n /**\n * Apply the Saturation operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const adjust = -this.saturation;\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const max = Math.max(r, g, b);\n data[i] += max !== r ? (max - r) * adjust : 0;\n data[i + 1] += max !== g ? (max - g) * adjust : 0;\n data[i + 2] += max !== b ? (max - b) * adjust : 0;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uSaturation, -this.saturation);\n }\n\n isNeutralState() {\n return this.saturation === 0;\n }\n}\n\nclassRegistry.setClass(Saturation);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uSaturation;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float rgMax = max(color.r, color.g);\n float rgbMax = max(rgMax, color.b);\n color.r += rgbMax != color.r ? (rgbMax - color.r) * uSaturation : 0.00;\n color.g += rgbMax != color.g ? (rgbMax - color.g) * uSaturation : 0.00;\n color.b += rgbMax != color.b ? (rgbMax - color.b) * uSaturation : 0.00;\n gl_FragColor = color;\n }\n`;\n","import { BaseFilter } from './BaseFilter';\nimport type { T2DPipelineState, TWebGLUniformLocationMap } from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/vibrance';\n\nexport type VibranceOwnProps = {\n vibrance: number;\n};\n\nexport const vibranceDefaultValues: VibranceOwnProps = {\n vibrance: 0,\n};\n\n/**\n * Vibrance filter class\n * @example\n * const filter = new Vibrance({\n * vibrance: 1\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n */\nexport class Vibrance extends BaseFilter<'Vibrance', VibranceOwnProps> {\n /**\n * Vibrance value, from -1 to 1.\n * Increases/decreases the saturation of more muted colors with less effect on saturated colors.\n * A value of 0 has no effect.\n *\n * @param {Number} vibrance\n */\n declare vibrance: VibranceOwnProps['vibrance'];\n\n static type = 'Vibrance';\n\n static defaults = vibranceDefaultValues;\n\n static uniformLocations = ['uVibrance'];\n\n getFragmentSource() {\n return fragmentSource;\n }\n\n /**\n * Apply the Vibrance operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({ imageData: { data } }: T2DPipelineState) {\n const adjust = -this.vibrance;\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const max = Math.max(r, g, b);\n const avg = (r + g + b) / 3;\n const amt = ((Math.abs(max - avg) * 2) / 255) * adjust;\n data[i] += max !== r ? (max - r) * amt : 0;\n data[i + 1] += max !== g ? (max - g) * amt : 0;\n data[i + 2] += max !== b ? (max - b) * amt : 0;\n }\n }\n\n /**\n * Send data from this filter to its shader program's uniforms.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n * @param {TWebGLUniformLocationMap} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n */\n sendUniformData(\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform1f(uniformLocations.uVibrance, -this.vibrance);\n }\n\n isNeutralState() {\n return this.vibrance === 0;\n }\n}\n\nclassRegistry.setClass(Vibrance);\n","export const fragmentSource = `\n precision highp float;\n uniform sampler2D uTexture;\n uniform float uVibrance;\n varying vec2 vTexCoord;\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float max = max(color.r, max(color.g, color.b));\n float avg = (color.r + color.g + color.b) / 3.0;\n float amt = (abs(max - avg) * 2.0) * uVibrance;\n color.r += max != color.r ? (max - color.r) * amt : 0.00;\n color.g += max != color.g ? (max - color.g) * amt : 0.00;\n color.b += max != color.b ? (max - color.b) * amt : 0.00;\n gl_FragColor = color;\n }\n`;\n"],"names":["BaseConfiguration","constructor","_defineProperty","this","window","devicePixelRatio","config","super","configure","arguments","length","undefined","Object","assign","addFonts","paths","fontPaths","removeFonts","forEach","fontFamily","clearFonts","restoreDefaults","keys","defaults","reduce","acc","key","log","severity","_len","optionalParams","Array","_key","console","FabricError","Error","message","options","SignalAbortedError","context","GLProbe","WebGLProbe","testPrecision","gl","precision","fragmentSource","fragmentShader","createShader","FRAGMENT_SHADER","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","queryWebGL","canvas","getContext","maxTextureSize","getParameter","MAX_TEXTURE_SIZE","GLPrecision","find","getExtension","loseContext","isSupported","textureSize","copyPasteData","env","setEnv","value","getEnv","document","isTouchSupported","navigator","maxTouchPoints","dispose","getFabricDocument","getFabricWindow","getDevicePixelRatio","_config$devicePixelRa","Math","max","cache","charWidthsCache","Map","getFontCache","_ref","fontStyle","fontWeight","toLowerCase","has","set","fontCache","get","cacheKey","clearFontCache","delete","limitDimsByArea","ar","perfLimitSizeTotal","roughWidth","sqrt","floor","VERSION","noop","halfPI","PI","quarterPI","twoMathPi","PiBy180","iMatrix","freeze","DEFAULT_SVG_FONT_SIZE","kRect","CENTER","LEFT","TOP","BOTTOM","RIGHT","NONE","reNewline","MOVING","SCALING","ROTATING","ROTATE","SKEWING","RESIZING","MODIFY_POLY","MODIFY_PATH","CHANGED","SCALE","SCALE_X","SCALE_Y","SKEW_X","SKEW_Y","FILL","STROKE","MODIFIED","LTR","RTL","NORMAL","JSON","SVG","classRegistry","classType","getClass","setClass","classConstructor","type","getSVGClass","SVGTagName","setSVGClass","runningAnimations","remove","index","indexOf","splice","cancelAll","animations","animation","abort","cancelByCanvas","filter","_animation$target","target","cancelByTarget","Observable","on","arg0","handler","__eventListeners","entries","eventName","off","push","once","disposers","_ref2","d","disposer","args","call","_removeEventListener","eventListener","_ref3","fire","_this$__eventListener","listenersForEvent","concat","i","removeFromArray","array","idx","cos","angle","abs","sin","angleSlice","sign","Point","y","x","add","that","addEquals","scalarAdd","scalar","scalarAddEquals","subtract","subtractEquals","scalarSubtract","scalarSubtractEquals","multiply","scalarMultiply","scalarMultiplyEquals","divide","scalarDivide","scalarDivideEquals","eq","lt","lte","gt","gte","lerp","t","min","distanceFrom","dx","dy","midPointFrom","toString","setXY","setX","setY","setFromPoint","swap","clone","rotate","radians","origin","ZERO","sinus","cosinus","p","transform","ignoreOffset","isCollection","fabricObject","isArray","_objects","createCollectionMixin","Base","Collection","_onObjectAdded","object","_onObjectRemoved","_onStackOrderChanged","objects","size","insertAt","_len2","_key2","removed","_len3","_key3","forEachObject","callback","getObjects","_len4","types","_key4","o","isType","item","isEmpty","contains","deep","includes","some","obj","complexity","memo","current","sendObjectToBack","unshift","bringObjectToFront","sendObjectBackwards","intersecting","newIdx","findNewLowerIndex","bringObjectForward","findNewUpperIndex","moveObjectTo","isOverlapping","collectObjects","left","top","width","height","includeIntersecting","tl","br","selectable","visible","intersectsWithRect","isContainedWithinRect","containsPoint","CommonMethods","_setOptions","prop","_setObject","_set","toggle","property","requestAnimFrame","requestAnimationFrame","cancelAnimFrame","handle","cancelAnimationFrame","id","uid","createCanvasElement","element","createElement","createImage","createCanvasElementFor","newCanvas","toDataURL","canvasEl","format","quality","toBlob","Promise","resolve","_","degreesToRadians","degrees","radiansToDegrees","isIdentityMatrix","mat","every","transformPoint","invertTransform","a","r","multiplyTransformMatrices","b","is2x2","multiplyTransformMatrixArray","matrices","reduceRight","product","curr","calcPlaneRotation","atan2","qrDecompose","denom","pow","scaleX","scaleY","skewX","skewY","translateX","translateY","createTranslateMatrix","createRotateMatrix","angleRadiant","cosValue","sinValue","createScaleMatrix","angleToSkew","tan","createSkewXMatrix","skewValue","createSkewYMatrix","calcDimensionsMatrix","flipX","flipY","matrix","composeMatrix","scaleMatrix","loadImage","url","signal","crossOrigin","reject","aborted","img","err","src","addEventListener","done","onload","onerror","removeEventListener","enlivenObjects","reviver","instances","all","map","fromObject","then","fabricInstance","catch","error","instance","finally","enlivenObjectEnlivables","serializedObject","promises","values","enlived","pick","source","pickBy","predicate","toFixed","number","fractionDigits","parseFloat","Number","matrixToSVG","NUM_FRACTION_DIGITS","join","isFiller","filler","toLive","isSerializableFiller","toObject","isPattern","offsetX","isActiveSelection","getScrollLeftTop","doc","getDocumentFromElement","elementLoop","docElement","documentElement","body","scrollLeft","scrollTop","parentNode","host","nodeType","style","position","el","ownerDocument","getWindowFromElement","_el$ownerDocument","defaultView","setCanvasDimensions","ctx","retinaScaling","setAttribute","scale","setCSSDimensions","makeElementUnselectable","onselectstart","userSelect","StaticCanvasDOMManager","createLowerCanvas","lower","getElementById","hasAttribute","_originalCanvasStyle","cssText","classList","cleanupDOM","removeAttribute","setDimensions","calcOffset","_getWindowFromElement","offset","elemStyle","getComputedStyle","parseInt","borderLeftWidth","borderTopWidth","paddingLeft","paddingTop","box","docElem","getBoundingClientRect","scrollLeftTop","clientLeft","clientTop","getElementOffset","staticCanvasDefaults","backgroundVpt","backgroundColor","overlayVpt","overlayColor","includeDefaultValues","svgViewportTransformation","renderOnAddRemove","skipOffscreen","enableRetinaScaling","imageSmoothingEnabled","controlsAboveOverlay","allowTouchScrolling","viewportTransform","patternQuality","StaticCanvas","lowerCanvasEl","_this$elements$lower","elements","contextContainer","_this$elements$lower2","getDefaults","ownDefaults","initElements","_setDimensionsImpl","skipControlsDrawing","calcViewportBoundaries","requestRenderAll","setCoords","getRetinaScaling","_offset","getWidth","getHeight","dimensions","cssOnly","backstoreOnly","hasLostContext","getZoom","setViewportTransform","vpt","zoomToPoint","point","before","newPoint","after","setZoom","absolutePan","relativePan","getElement","clearContext","clearRect","clear","backgroundImage","overlayImage","renderAll","cancelRequestedRender","destroyed","renderCanvas","renderAndReset","nextRenderHandle","disposed","iVpt","vptCoords","tr","bl","drawControls","_ctx","v","path","clipPath","_renderBackground","save","_renderObjects","restore","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","__cleanupTask","globalCompositeOperation","zoomX","zoomY","drawImage","_cacheCanvas","cacheTranslationX","cacheTranslationY","len","render","_renderBackgroundOrOverlay","fill","needsVpt","isAFiller","beginPath","moveTo","lineTo","closePath","fillStyle","offsetY","m","gradientTransform","patternTransform","getCenterPoint","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","center","toDatalessJSON","propertiesToInclude","toDatalessObject","_toObjectMethod","toJSON","methodName","clipPathData","excludeFromExport","_toObject","version","__serializeBgOverlay","originalValue","data","bgImage","bgColor","background","overlay","toSVG","markup","_setSVGPreamble","_setSVGHeader","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","suppressPreamble","encoding","optViewBox","viewBox","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","toClipPathSVG","shouldTransform","additionalTransform","fontList","_renderText","styles","styleRow","fontListMarkup","_setSVGObject","bgOrOverlay","repeat","finalWidth","finalHeight","loadFromJSON","json","serialized","parse","enlivedMap","properties","cloneWithoutData","multiplier","finalMultiplier","toCanvasElement","scaledWidth","scaledHeight","zoom","originalWidth","originalHeight","originalSkipControlsDrawing","newZoom","vp","newVp","originalRetina","objectsToRender","task","destroy","kill","touchEvents","getPointer","event","scroll","_evt","touchProp","changedTouches","getTouchInfo","clientX","clientY","isTouchEvent","pointerType","stopEvent","e","preventDefault","stopPropagation","makeBoundingBoxFromPoints","points","addTransformToObject","applyTransformToObject","calcOwnMatrix","otherOptions","setPositionByOrigin","resetObjectTransform","saveObjectTransform","sizeAfterTransform","dimX","dimY","bbox","calcPlaneChangeMatrix","from","sendPointToPlane","to","sendVectorToPlane","sendObjectToPlane","originOffset","bottom","right","resolveOrigin","originValue","unitVectorX","zero","rotateVector","vector","createVector","magnitude","calcAngleBetweenVectors","crossProduct","dotProduct","calcVectorRotation","getUnitVector","getOrthonormalVector","counterClockwise","isBetweenVectors","AxB","AxT","BxT","NOT_ALLOWED_CURSOR","isTransformCentered","originX","originY","invertOrigin","isLocked","lockingKey","commonEventInfo","eventData","pointer","findCornerQuadrant","control","coord","round","getLocalPoint","_target$canvas","corner","controls","padding","localPoint","getRelativeCenterPoint","translateToGivenOrigin","normalizePoint","normalizeWs","replace","ColorNameMap","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgrey","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","hue2rgb","q","rgb2Hsl","g","maxValue","minValue","h","s","l","fromAlphaToFloat","endsWith","hexify","toUpperCase","padStart","greyAverage","avg","Color","color","setSource","_source","_tryParsingColor","sourceFromHex","sourceFromRgb","sourceFromHsl","isUnrecognised","getSource","toRgb","toRgba","toHsl","toHsla","toHex","toHexa","slice","getAlpha","setAlpha","alpha","toGrayscale","toBlackWhite","threshold","average","bOrW","overlayWith","otherColor","otherSource","R","G","B","fromRgb","fromRgba","match","parsedValue","fromHsl","fromHsla","parseAngletoDegrees","fromHex","expandedValue","split","hex","hexCouple","lowercase","numeric","parseUnit","fontSize","unit","exec","dpi","DPI","parsePreserveAspectRatioAttribute","attribute","firstPart","secondPart","trim","alignX","alignY","align","meetOrSlice","colorPropToSVG","colorValue","opacityValue","inlineStyle","opacity","FabricObjectSVGExportMixin","getSvgStyles","skipShadow","fillRule","strokeWidth","strokeDashArray","strokeDashOffset","strokeLineCap","strokeLineJoin","strokeMiterLimit","visibility","getSvgFilter","stroke","shadow","getSvgCommons","getSvgTransform","full","calcTransformMatrix","_toSVG","_reviver","_createBaseSVGMarkup","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","noStyle","withShadow","styleInfo","shadowInfo","vectorEffect","strokeUniform","absoluteClipPath","absolutePositioned","clipPathMarkup","addPaintOrder","paintFirst","getSvgRegex","arr","RegExp","TEXT_DECORATION_THICKNESS","fontProperties","textDecorationProperties","textLayoutProperties","additionalProps","styleProperties","textDefaultValues","_reNewline","_reSpacesAndTabs","_reSpaceAndTab","_reWords","underline","overline","linethrough","textAlign","lineHeight","textBackgroundColor","pathStartOffset","pathSide","pathAlign","charSpacing","deltaY","direction","CACHE_FONT_SIZE","MIN_TEXT_WIDTH","superscript","baseline","subscript","_fontSizeFraction","offsets","_fontSizeMult","JUSTIFY","JUSTIFY_LEFT","JUSTIFY_RIGHT","JUSTIFY_CENTER","reNum","String","raw","viewportSeparator","svgNS","reFontDeclaration","attributesMap","cx","cy","display","fSize","cPath","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgValidParentsRegEx","reViewBoxAttrValue","shadowOffsetRegex","reOffsetsAndBlur","Shadow","parseShadow","shadowStr","blur","fBoxX","fBoxY","affectStroke","nonScaling","capValue","stateProperties","cacheProperties","fabricObjectDefaultValues","minScaleLimit","objectCaching","inverted","centeredRotation","centeredScaling","dirty","normalize","c","asin","elastic","defaultEasing","easeOutBounce","easeInBounce","easeInCirc","easeInCubic","easeInElastic","normA","normS","normP","easeInExpo","easeInOutBounce","easeInOutCirc","easeInOutCubic","easeInOutElastic","normC","easeInOutExpo","easeInOutQuad","easeInOutQuart","easeInOutQuint","easeInOutSine","easeInQuad","easeInQuart","easeInQuint","easeInSine","easeOutCirc","easeOutCubic","easeOutElastic","easeOutExpo","easeOutQuad","easeOutQuart","easeOutQuint","easeOutSine","defaultAbort","AnimationBase","startValue","byValue","duration","delay","easing","onStart","onChange","onComplete","tick","bind","_onStart","_onChange","_onComplete","_abort","endValue","calculate","state","_state","isDone","start","firstTick","timestamp","startTime","Date","register","setTimeout","durationMs","boundDurationMs","durationProgress","valueProgress","unregister","ValueAnimation","timeElapsed","ArrayAnimation","defaultColorEasing","wrapColorCallback","rgba","ColorAnimation","startColor","endColor","animate","isArrayAnimation","animateColor","Intersection","status","append","isPointContained","T","A","infinite","AB","isPointInPolygon","other","hits","inter","intersectSegmentSegment","intersectLineLine","a1","a2","b1","b2","aInfinite","bInfinite","a2xa1x","a2ya1y","b2xb1x","b2yb1y","a1xb1x","a1yb1y","uaT","ubT","uB","ua","ub","segmentsCoincide","intersectSegmentLine","s1","s2","l1","l2","intersectLinePolygon","result","intersectSegmentPolygon","intersectPolygonPolygon","points1","points2","coincidences","intersectPolygonRectangle","r1","r2","topRight","bottomLeft","ObjectGeometry","getX","getXY","getY","getRelativeX","setRelativeX","getRelativeY","setRelativeY","relativePosition","getRelativeXY","group","setRelativeXY","isStrokeAccountedForInDimensions","getCoords","aCoords","calcACoords","coords","intersectsWithObject","intersection","isContainedWithinObject","getBoundingRect","isOnScreen","isPartiallyOnScreen","getScaledWidth","_getTransformedDimensions","getScaledHeight","scaleToWidth","boundingRectFactor","scaleToHeight","getCanvasRetinaScaling","_this$canvas","getTotalAngle","getViewportTransform","_this$canvas2","rotateMatrix","tMatrix","finalMatrix","dim","w","transformMatrixKey","skipGroup","prefix","matrixCache","ownMatrixCache","_getNonTransformedDimensions","_calculateCurrentDimensions","dimOptions","preScalingStrokeValue","postScalingStrokeValue","finalDimensions","fromOriginX","fromOriginY","toOriginX","toOriginY","translateToCenterPoint","translateToOriginPoint","relCenter","getPointByOrigin","getPositionByOrigin","pos","_getLeftTopCoords","positionByLeftTop","FabricObject","name","setOptions","_createCacheCanvas","_cacheContext","_updateCacheCanvas","_limitCacheSize","dims","maxCacheSideLimit","minCacheSideLimit","limX","limY","capped","_getCacheCanvasDimensions","objectScale","getTotalObjectScaling","neededX","neededY","ceil","dimensionsChanged","zoomChanged","setTransform","drawingWidth","drawingHeight","translate","needFullTransform","contextTop","getObjectScaling","retina","getObjectOpacity","_constrainScale","isChanged","parent","isNotVisible","_setupCompositeOperation","drawSelectionBackground","_setOpacity","_setShadow","drawCacheOnCanvas","_removeCacheCanvas","drawObject","isCacheDirty","parentClipPaths","hasStroke","hasFill","needsItsOwnCache","ownCaching","isOnACache","willDrawShadow","drawClipPathOnCache","canvasWithClipPath","originalFill","originalStroke","_setClippingProperties","_render","_drawClipPath","createClipPathLayer","prevClipPath","skipCanvas","fillRect","_removeShadow","globalAlpha","_setStrokeStyles","decl","lineWidth","lineCap","lineDashOffset","lineJoin","miterLimit","gradientUnits","_applyPatternForTransformedGradient","strokeStyle","_applyPatternGradientTransform","_setFillStyles","_setLineDash","dashArray","setLineDash","sx","sy","multX","multY","scaling","shadowColor","shadowBlur","browserShadowBlurConstant","shadowOffsetX","shadowOffsetY","_renderPaintInOrder","_renderStroke","_renderFill","_pCtx$createPattern","pCanvas","pCtx","createPattern","_findCenterFromElement","objectForm","cloneAsImage","origParams","originalGroup","originalShadow","canvasProvider","withoutTransform","withoutShadow","boundingRect","shadowOffset","originalCanvas","setOnGroup","animatable","_animate","propIsColor","colorProperties","animationOptions","isDescendantOf","getAncestors","ancestors","findCommonAncestors","fork","otherFork","common","otherAncestors","ancestor","j","hasCommonAncestors","commonAncestors","isInFrontOf","ancestorData","firstCommonAncestor","headOfFork","pop","headOfOtherFork","thisIndex","otherIndex","propertiesToSerialize","customProperties","toFixedBound","val","_removeDefaultValues","baseValues","getPrototypeOf","baseValue","_fromObject","serializedObjectOptions","extraParam","enlivedObjectOptions","fireEvent","wrapWithFireEvent","actionHandler","extraEventInfo","actionPerformed","wrapWithFixedAnchor","constraint","changeObjectDimensionGen","dimension","xorY","localPointValue","strokePadding","oldWidth","newWidth","changeObjectWidth","changeObjectHeight","changeWidth","changeHeight","renderCircleControl","styleOverride","xSize","ySize","opName","commonRenderProps","arc","renderSquareControl","xSizeBy2","ySizeBy2","strokeRect","Control","shouldActivate","controlKey","_fabricObject$canvas","getActiveObject","isControlVisible","getActionHandler","getMouseDownHandler","mouseDownHandler","getMouseUpHandler","mouseUpHandler","cursorStyleHandler","cursorStyle","getActionName","actionName","getVisibility","_fabricObject$_contro","_fabricObject$_contro2","_controlsVisibility","setVisibility","positionHandler","currentControl","calcCornerCoords","objectCornerSize","centerX","centerY","isTouch","touchSizeX","sizeX","touchSizeY","sizeY","cornerSize","cornerColor","transparentCorners","cornerStrokeColor","sizeFromProps","transparent","strokeColor","cornerStyle","rotationStyleHandler","lockRotation","rotationWithSnapping","rotateObjectWithSnapping","ex","ey","theta","pivotPoint","lastAngle","curAngle","snapAngle","snapThreshold","rightAngleLocked","leftAngleLocked","hasRotated","scaleIsProportional","uniformIsToggled","uniScaleKey","uniformScaling","scalingIsForbidden","by","scaleProportionally","lockX","lockY","scaleMap","scaleCursorStyleHandler","n","scaleObject","signX","signY","gestureScale","distance","original","oldScaleX","oldScaleY","scalingEqually","scaleObjectFromCorner","scalingX","scaleObjectX","scalingY","scaleObjectY","AXIS_KEYS","counterAxis","skew","lockSkewing","flip","skewMap","skewCursorStyleHandler","skewHandler","axis","originKey","lockSkewingKey","skewKey","flipKey","counterOriginKey","counterFlipKey","counterOriginFactor","skewingSide","finalHandler","skewingBefore","skewingStart","shearingStart","shearing","skewing","atan","changed","dimBefore","dimAfter","compensationFactor","skewObject","skewHandlerX","skewHandlerY","isAltAction","altActionKey","scaleOrSkewActionName","isAlternative","scaleSkewCursorStyleHandler","scalingXOrSkewingY","scalingYOrSkewingX","createObjectDefaultControls","ml","mr","mb","mt","mtr","withConnection","createResizeControls","createTextboxDefaultControls","InteractiveFabricObject","createControls","targetCanvas","noScaleCache","_currentTransform","action","startsWith","getActiveControl","__corner","oCoords","findControl","forTouch","hasControls","cornerEntries","touchCorner","calcOCoords","rMatrix","positionMatrix","startMatrix","transformOptions","forEachControl","_calcCornerCoords","touchCornerSize","fn","selectionBackgroundColor","_activeObject","wh","strokeBorders","_drawBorders","borderColor","borderDashArray","drawControlsConnectingLines","_renderControls","hasBorders","styleOptions","shouldDrawBorders","shouldDrawControls","borderScaleFactor","isMoving","borderOpacityWhenMoving","drawBorders","forActiveSelection","shouldStroke","cornerDashArray","setControlVisible","setControlsVisibility","clearContextTop","restoreManually","onDeselect","_options","onSelect","shouldStartDragging","_e","onDragStart","canDrop","renderDragSourceEffect","renderDropTargetEffect","applyMixins","derivedCtor","constructors","baseCtor","getOwnPropertyNames","prototype","defineProperty","getOwnPropertyDescriptor","create","lockMovementX","lockMovementY","lockScalingX","lockScalingY","lockSkewingX","lockSkewingY","lockScalingFlip","evented","perPixelTargetFind","activeOn","hoverCursor","moveCursor","isTransparent","tolerance","getImageData","StrokeProjectionsBase","strokeProjectionMagnitude","strokeUniformScalar","createSideVector","projectOrthogonally","applySkew","calcOrthogonalProjection","isSkewed","scaleUnitVector","unitVector","zeroVector","StrokeLineJoinProjections","getOrthogonalRotationFactor","vector1","vector2","C","AC","bisector","orthogonalProjection","correctSide","projectBevel","projections","projectMiter","hypotUnitScalar","miterVector","projectRoundNoSkew","startCircle","endCircle","projectRoundWithSkew","circleRadius","newY","furthestY","newX","furthestX","projectRound","isStraightLine","newOrigin","proj0","proj1","comparisonVector","isProj0Start","projectPoints","project","originPoint","projectedPoint","StrokeLineCapProjections","projectButt","projection","projectSquare","strokePointingOut","projectedA","projectStrokeOnPoints","openPath","reduced","findIndexRight","cloneStyles","newObj","keyInner","escapeXml","string","segmenter","graphemeSplit","textstring","Intl","Segmenter","granularity","segments","segment","graphemeSplitImpl","graphemes","chr","getWholeChar","str","code","charCodeAt","isNaN","charAt","next","prev","firstLetterOnly","hasStyleChanged","prevStyle","thisStyle","forTextSpans","textDecorationThickness","stylesToArray","text","textLines","stylesArray","charIndex","chars","end","stylesFromArray","stylesObject","styleIndex","SHARED_ATTRIBUTES","selectorMatches","selector","nodeName","classNames","getAttribute","azAz","matcher","splitClassNames","elementMatchesRule","selectors","parentMatching","firstMatching","parentElement","doesSomeParentMatch","getGlobalStylesForElement","cssRules","rule","normalizeAttr","attr","_attributesMap","regex","transforms","transformList","reTransformList","reTransform","reTransformAll","parseTransformAttribute","attributeValue","cleanupSvgAttribute","test","matchAll","transformMatch","matchedParams","operation","rawArgs","arg1","arg2","arg3","arg4","arg5","arg","normalizeValue","parentAttributes","parsed","ouputValue","transformMatrix","fillIndex","strokeIndex","parseStyleString","oStyle","chunk","parseStyleAttribute","parseStyleObject","colorAttributesMap","parseAttributes","attributes","parentFontSize","ownAttributes","normalizedStyle","normalizedAttr","normalizedValue","font","parseFontDeclaration","mergedAttrs","colorAttr","setStrokeFillOpacity","RECT_PROPS","Rect","_initRxRy","rx","ry","isRounded","bezierCurveTo","fromElement","restOfparsedAttributes","ATTRIBUTE_NAMES","Boolean","LAYOUT_TYPE_INITIALIZATION","LAYOUT_TYPE_ADDED","LAYOUT_TYPE_REMOVED","LAYOUT_TYPE_IMPERATIVE","getObjectBounds","destinationGroup","currentGroup","objectCenter","accountForStroke","strokeUniformVector","scalingStrokeWidth","sizeVector","LayoutStrategy","calcLayoutResult","shouldPerformLayout","calcBoundingBox","prevStrategy","strategy","shouldLayoutClipPath","getInitialSize","overrides","bboxSize","bboxCenter","actualSize","relativeCorrection","FitContentLayout","LAYOUT_MANAGER","LayoutManager","_subscriptions","performLayout","strictContext","bubbles","_prevLayoutStrategy","onBeforeLayout","layoutResult","getLayoutResult","commitLayout","onAfterLayout","attachHandlers","trigger","subscribe","unsubscribe","_context","unsubscribeTargets","targets","subscribeTargets","tricklingContext","layoutManager","prevCenter","nextCenter","correction","_context$x","_context$y","layoutObjects","layoutObject","bubblingContext","NoopLayoutManager","Group","groupInit","_options$layoutManage","__objectSelectionTracker","__objectSelectionMonitor","__objectSelectionDisposer","enterGroup","canEnterGroup","_filterObjectsBeforeEnteringGroup","allowedObjects","_onAfterObjectsChange","removeParentTransform","exitGroup","_shouldSetNestedCoords","subTargetCheck","removeAll","_activeObjects","selected","activeObjects","_watchObject","watch","_enterGroup","activeObject","_exitGroup","ownCache","preserveObjectStacking","triggerLayout","__serializeObjects","method","_includeDefaultValues","originalDefaults","_createSVGBgRect","fillStroke","commons","svgString","bg","abortable","hydratedOptions","layoutClass","strategyClass","interactive","findScaleToFit","destination","findScaleToCover","commaWsp","reArcCommandPoints","repeatedCommands","M","segmentToBezier","theta1","theta2","cosTh","sinTh","cx1","cy1","mT","fromX","fromY","costh1","sinth1","costh2","sinth2","toX","toY","calcVectorAngle","ux","uy","vx","vy","ta","tb","getBoundsOfCurve","begx","begy","cp1x","cp1y","cp2x","cp2y","endx","endy","argsString","cachesBoundsOfCurve","boundsOfCurveCache","tvalues","bounds","b2ac","sqrtb2ac","t1","t2","jlen","iterator","getPointOnCubicBezierIterator","fromArcToBeziers","fx","fy","rot","large","sweep","tx","ty","segsNorm","arcToSegments","rotateX","root","sinTheta","px","py","rx2","ry2","py2","px2","pl","_rx","_ry","mTheta","dtheta","mDelta","th3","makePathSimpler","x1","y1","destinationPath","previous","controlX","controlY","parsedCommand","converted","calcLineLength","x2","y2","pct","c1","c2","CB2","c3","CB3","c4","CB4","QB1","QB2","QB3","getTangentCubicIterator","p1x","p1y","p2x","p2y","p3x","p3y","p4x","p4y","qb1","qb2","qb3","tangentX","tangentY","getPointOnQuadraticBezierIterator","getTangentQuadraticIterator","invT","pathIterator","tempP","tmpLen","perc","findPercentageForDistance","segInfo","nextLen","nextStep","lastPerc","angleFinder","getPathSegmentsInfo","tempInfo","totalLength","info","basicInfo","command","destX","destY","getPointOnPath","infos","segPercent","rePathCmdAll","regExpArcCommandPoints","reMyNum","commandLengths","parsePath","pathString","_pathString$match","chain","matchStr","commandLetter","commandLength","paramArr","lastIndex","out","newCommand","transformedCommand","getSmoothPathFromPoints","p1","p2","multSignX","multSignY","manyPoints","midPoint","joinPath","pathData","getRandomInt","random","removeTransformMatrixForSvgParsing","preserveAspectRatioOptions","_assignTransformMatrixProps","cropX","cropY","offsetLeft","offsetTop","_newCanvas$getContext","getRegularPolygonPath","numVertexes","radius","interiorAngle","rotationAdjustment","rad","commonAttributes","groupSVGElements","mergeClipPaths","_b$group","removeTransformFromObject","finalTransform","transformPath","pathOffset","pathSegment","newSegment","setStyle","elementStyle","setProperty","CanvasDOMManager","containerClass","upperCanvasEl","createUpperCanvas","upper","applyCanvasStyle","container","createContainerElement","replaceChild","className","removeChild","dragHandler","newLeft","newTop","moveX","moveY","ACTION_NAME","createPolyPositionHandler","pointIndex","polyObject","polyActionHandler","poly","mouseLocalPosition","factoryPolyActionHandler","anchorPoint","anchorPointInParentPlane","diff","createPolyActionHandler","calcPathPointPosition","pathObject","commandIndex","pathPositionHandler","pathActionHandler","movePathPoint","anchorCommand","PathPointControl","controlFill","controlStroke","PathControlPointControl","connectToCommandIndex","connectToPointIndex","connectionDashArray","commandType","point2","createControl","commandIndexPos","pointIndexPos","isControlPoint","controlPointStyle","pointStyle","previousCommandType","indexFromPrevCommand","SelectableCanvas","_this$elements$upper","_this$elements$upper2","wrapperEl","_objectsToRender","deselected","_discardActiveObject","_hoveredTarget","_hoveredTargets","_chooseObjectsToRender","contextTopDirty","_groupSelector","isDrawingMode","renderTopLayer","_isCurrentlyDrawing","freeDrawingBrush","selection","_drawSelection","renderTop","setTargetFindTolerance","targetFindTolerance","pixelFindCanvasEl","pixelFindContext","isTargetTransparent","selectionBgc","enhancedTolerance","_isSelectionKeyPressed","sKey","selectionKey","_shouldClearSelection","getActiveObjects","_shouldCenterTransform","modifierKeyPressed","centerTransform","_getOriginFromCorner","controlName","_setupCurrentTransform","alreadySelected","_control$getActionHan","getScenePoint","getActionFromCorner","altKey","centeredKey","lastX","lastY","shiftKey","setCursor","cursor","deltaX","extent","strokeOffset","selectionLineWidth","minX","minY","maxX","maxY","selectionColor","selectionBorderColor","selectionDashArray","findTarget","_targetInfo","skipTargetFind","subTargets","currentSubTargets","aObjects","targetInfo","searchPossibleTargets","currentContainer","currentTarget","fullTargetInfo","activeObjectTargetInfo","getViewportPoint","altSelectionKey","_pointIsInObjectSelectionArea","viewportZoom","angleRadians","cosP","sinP","cosPSinP","cosPMinusSinP","_checkTarget","isEditing","viewportPoint","_searchPossibleTargets","subTarget","_viewportPoint","_getPointerImpl","_scenePoint","fromViewport","boundsWidth","boundsHeight","cssScale","_resetTransformEventData","_setBrushStyles","willReadFrequently","getTopContext","getSelectionContext","getSelectionElement","active","_fireSelectionEvents","oldObjects","somethingChanged","invalidate","added","setActiveObject","currentActives","_setActiveObject","prevActiveObject","endCurrentTransform","discardActiveObject","discarded","_finalizeCurrentTransform","_scaling","originalProperties","_realizeGroupTransformOnObject","originalValues","selectionFullyContained","defaultCursor","freeDrawingCursor","notAllowedCursor","stopContextMenu","fireRightClick","fireMiddleClick","enablePointerEvents","TextEditingManager","cb","hiddenTextarea","focus","__disposer","exitTextEditing","exitEditing","onMouseMove","_this$target","updateSelectionOnMouseMove","addEventOptions","passive","getEventPoints","scenePoint","addListener","removeListener","syntheticEventConfig","mouse","in","targetIn","targetOut","canvasIn","canvasOut","drag","Canvas","eventHandler","addOrRemove","_getEventPrefix","functor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onClick","_onDragStart","_onDragEnd","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","removeListeners","_onMouseUp","_onTouchEnd","clearTimeout","_willAddMouseDown","_cacheTransformEventData","_handleEvent","shared","nestedTarget","_isClick","_dragSource","_onDragProgress","_renderDragEffects","dropTarget","_dropTarget","didDrop","dataTransfer","dropEffect","dragSource","_draggedoverTarget","eventType","_fireEnterLeaveEvents","_basicEventHandler","clicks","detail","fireEventFromPointerEvent","secondaryName","extraData","getPointerId","evt","identifier","pointerId","_isMainEvent","isPrimary","touches","mainTouchId","shouldPreventScrolling","currentActiveObject","__onMouseDown","__onMouseUp","__onMouseMove","_shouldRender","_this$_activeObject","isClick","button","_onMouseUpInDrawingMode","shouldRender","targetWasActive","handleSelection","found","originalControl","originalMouseUpHandler","_setCursorFromEvent","_onMouseDownInDrawingMode","onMouseDown","_onMouseMoveInDrawingMode","onMouseUp","grouped","handleMultiSelection","groupSelector","_transformObject","_fireOverOutEvents","textEditingManager","fireSyntheticInOutEvents","oldTarget","fireCanvas","draggedoverTarget","targetChanged","outOpt","nextTarget","inOpt","previousTarget","localPointer","_performTransformAction","activeSelection","reverse","_target","isAS","prevActiveObjects","multiSelectAdd","newActiveSelection","point1","collectedObjects","klass","htmlElement","linearDefaultCoords","radialDefaultCoords","ifNaN","valueIfNaN","isPercent","isFinite","parsePercent","NaN","RE_KEY_VALUE_PAIRS","RE_KEY_VALUE","parseColorStop","opacityMultiplier","keyValuePairs","parseColorStops","opacityAttr","colorStops","colorStopEls","getElementsByTagName","parseType","parseGradientUnits","getValue","parseCoords","valuesToConvert","finalValue","propValue","isString","convertPercentUnitsToValues","parseLinearCoords","parseRadialCoords","Gradient","addColorStop","colorStop","preTransform","sort","_renderPathCommands","needsSwap","minRadius","percentageShift","gradient","createLinearGradient","createRadialGradient","svgOptions","viewBoxWidth","viewBoxHeight","Pattern","isImageSource","isCanvasSource","sourceToString","complete","naturalWidth","naturalHeight","patternSource","patternOffsetX","patternOffsetY","BaseBrush","_saveAndTransform","needsFullRender","_resetShadow","_isOutSideCanvas","Path","_setPath","adjustPosition","setBoundingBox","_calcBoundsFromPath","quadraticCurveTo","pathCmd","sourcePath","_getOffsetTransform","digits","_calcDimensions","subpathStartX","subpathStartY","parsedAttributes","PencilBrush","_points","_hasStraightLine","drawSegment","drawStraightLine","straightLineKey","_prepareForDrawing","_addPoint","limitedToCanvasSize","oldEnd","_finalizeAndAddPath","_reset","convertPointsToSVGPath","createPath","decimatePoints","cDistance","lastPoint","adjustedDistance","newPoints","decimate","isEmptySVGPath","CIRCLE_PROPS","Circle","setRadius","startAngle","endAngle","getRadiusX","getRadiusY","startX","startY","endX","endY","otherParsedAttributes","CircleBrush","drawDot","addPoint","dot","originalRenderOnAddRemove","circles","circle","pointerPoint","SprayBrush","sprayChunks","sprayChunk","addSprayChunk","renderChunck","rects","chunck","rect","optimizeOverlapping","uniqueRects","uniqueRectsArray","getUniqueRects","sprayChunck","density","dotWidthVariance","dotWidth","randomOpacity","PatternBrush","getPatternSrc","patternCanvas","patternCtx","getPattern","pattern","topLeft","coordProps","Line","_setWidthHeight","calcLinePoints","origStrokeStyle","_this$stroke","_x1","_x2","_y1","_y2","xMult","yMult","Triangle","widthBy2","heightBy2","ELLIPSE_PROPS","Ellipse","getRx","getRy","polylineDefaultValues","exactBoundingBox","Polyline","initialized","isOpen","_projectStrokeOnPoints","strokeDiff","bboxNoStroke","layoutProperties","_options$width","_options$height","_options$width2","_options$height2","output","diffX","diffY","pointsSplit","parsedPoints","parsePointsAttribute","Polygon","StyledText","isEmptyStyles","lineIndex","line","p3","styleHas","cleanStyle","letterCount","stylePropertyValue","stylesCount","allStyleObjectPropertiesMatch","graphemeCount","styleObject","_textLines","removeStyle","lineNum","charNum","_extendStyles","get2DCursorLocation","_getLineStyle","_setLineStyle","newStyle","_getStyleDeclaration","_setStyleDeclaration","getSelectionStyles","startIndex","endIndex","getStyleAtPosition","getCompleteStyleDeclaration","setSelectionStyles","_forceClearCache","_lineStyle$charIndex","lineStyle","_styleProperties","_deleteStyleDeclaration","_deleteLineStyle","multipleSpacesRegex","dblQuoteRegex","createSVGInlineRect","svgColor","createSVGRect","measuringContext","FabricText","setPathInfo","initDimensions","segmentsInfo","_splitText","newLines","_splitTextIntoLines","lines","graphemeLines","_unwrappedTextLines","_unwrappedLines","_text","graphemeText","_clearCache","calcTextWidth","cursorWidth","calcTextHeight","enlargeSpaces","diffSpace","currentLineWidth","numberOfSpaces","accumulatedSpace","charBound","spaces","isEndOfWrapping","getLineWidth","__charBounds","kernedWidth","missingNewlineOffset","_lineIndex","selectionStart","skipWrapping","_setTextStyles","_renderTextLinesBackground","_renderTextDecoration","_renderTextStroke","_renderTextFill","charStyle","forMeasuring","textBaseline","_getFontDeclaration","maxWidth","_renderTextLine","_renderChars","leftOffset","_getLeftOffset","lineTopOffset","_getTopOffset","heightOfLine","getHeightOfLine","lineLeftOffset","_getLineLeftOffset","drawStart","currentColor","boxWidth","boxStart","lastColor","getValueOfPropertyAt","bgHeight","getHeightOfLineImpl","charBox","renderLeft","_measureChar","_char","previousChar","prevCharStyle","fontDeclaration","couple","stylesAreEqual","fontMultiplier","coupleWidth","previousWidth","getMeasuringContext","measureText","getHeightOfChar","measureLine","lineInfo","_measureLine","_getWidthOfCharSpacing","prevGrapheme","graphemeInfo","llength","lineBounds","grapheme","_getGraphemeBox","positionInPath","totalPathLength","_setGraphemeOnPath","numOfSpaces","centerPosition","skipLeft","previousBox","lh","__lineHeights","maxHeight","_renderTextCommon","lineHeights","isJustify","shortCut","isLtr","currentDirection","actualStyle","nextStyle","timeToRender","drawingLeft","charsToRender","_renderChar","_applyPatternGradientTransformText","handleFiller","fullDecl","shouldFill","fillOffsets","fillText","strokeOffsets","strokeText","setSuperscript","_setScript","setSubscript","schema","loc","lineDiff","__lineWidths","_charStyle$property","topOffset","offsetAligner","lastDecoration","lastFill","lastTickness","currentDecoration","currentFill","currentTickness","currentSize","currentDy","finalTickness","parsedFontFamily","genericFonts","newLine","newText","needsDims","isAddingPath","textAnchor","textDecoration","restOfOptions","textContent","textHeightScaleFactor","scaledDiff","textHeight","offX","_getSVGLeftTopOffsets","textAndBg","_getSVGTextAndBg","textTop","textLeft","_wrapSVGTextAndBg","textSvg","lineTop","textBgRects","textSpans","getSvgTextDecoration","textTopOffset","textLeftOffset","lineOffset","_setSVGTextLineBg","_setSVGTextLineText","_createTextCharSpan","char","styleDecl","numFractionDigit","styleProps","getSvgSpanStyles","fillStyles","dySpan","angleAttr","wBy2","renderPoint","useWhiteSpace","thickness","decoration","DraggableTextDelegate","dragEnterHandler","dragOverHandler","dragLeaveHandler","dragEndHandler","dropHandler","_dispose","isPointerOverSelection","newSelection","getSelectionStartFromPointer","selectionEnd","__mouseDownInPlace","isActive","__dragStartFired","setCursorByClick","initDelayedCursor","__isDraggingOver","getDragStartSelection","__dragStartSelection","setDragImage","_e$dataTransfer","flipFactor","boundaries","_getCursorBoundaries","bgc","dragImage","border","__dragImageDisposer","appendChild","setData","stringify","effectAllowed","abortCursorAnimation","editable","defaultPrevented","dragStartSelection","targetCanDrop","ev","_e$dataTransfer2","insert","getData","trailing","selectionStartOffset","removeChars","trimEnd","insertChars","enterEditing","_updateTextarea","_e$dataTransfer3","reNonWord","ITextBehavior","initBehavior","_tick","_onTickComplete","_animateCursor","toValue","_currentCursorOpacity","renderCursorOrSelection","_currentTickState","cursorDuration","_this$_currentTickCom","_currentTickCompleteState","restart","cursorDelay","shouldClear","cursorAnimation","restartCursorIfNeeded","selectAll","_fireSelectionChanged","cmdAll","getSelectedText","findWordBoundaryLeft","startFrom","_reSpace","findWordBoundaryRight","findLineBoundaryLeft","findLineBoundaryRight","searchWordBoundary","selectWord","newSelectionStart","newSelectionEnd","selectLine","enterEditingImpl","initHiddenTextarea","_saveEditingProps","_setEditingProps","_textBeforeEdit","activeElement","currentStart","currentEnd","__selectionStartOnMouseDown","editingBorderColor","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","fromGraphemeToStringSelection","cursorOffsetCache","inCompositionMode","updateTextareaPosition","updateFromTextArea","anchorX","originalPosition","_calcTextareaPosition","desiredPosition","compositionStart","cursorLocation","charHeight","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","exitEditingImpl","isTextChanged","_removeExtraneousStyles","removeStyleFromTo","lineStart","charStart","lineEnd","charEnd","styleObj","shiftLineStyles","numericChar","clonedStyles","numericLine","insertNewlineStyleObject","qty","copiedStyle","newLineStyles","originalLineLength","isEndOfLine","someStyleIsCarryingOver","currentCharStyle","numIndex","styleCarriedOver","insertCharStyleObject","quantity","currentLineStyles","currentLineStylesCloned","numericIndex","insertNewStyleBlock","insertedText","cursorLoc","addedLines","linesLength","setSelectionStartEndWithShift","_selectionDirection","ITextKeyBehavior","textarea","autocapitalize","autocorrect","autocomplete","spellcheck","wrap","hiddenTextareaContainer","keydown","keyup","input","copy","cut","paste","compositionstart","compositionupdate","compositionend","onKeyDown","keyMap","keysMapRtl","keysMap","keyCode","ctrlKeysMapDown","ctrlKey","metaKey","stopImmediatePropagation","onKeyUp","_copyDone","ctrlKeysMapUp","onInput","fromPaste","updateAndFire","nextText","charCount","nextCharCount","_selectionStart","_selectionEnd","removedText","removeFrom","removeTo","charDiff","textareaSelection","backDelete","copiedText","disableStyleCopyPaste","copiedTextStyle","onCompositionStart","onCompositionEnd","onCompositionUpdate","compositionEnd","_getWidthBeforeCursor","bound","widthBeforeCursor","getDownCursorOffset","isRight","selectionProp","_getSelectionForOffset","indexOnOtherLine","_getIndexOnLine","getUpCursorOffset","textBeforeCursor","charWidth","foundMatch","widthOfCharsOnLine","indexOnLine","leftEdge","rightEdge","offsetFromLeftEdge","moveCursorDown","_moveCursorUpOrDown","moveCursorUp","moveCursorWithShift","moveCursorWithoutShift","moveCursorLeft","_moveCursorLeftOrRight","_move","newValue","_moveLeft","_moveRight","moveCursorLeftWithoutShift","change","moveCursorLeftWithShift","moveCursorRight","moveCursorRightWithShift","moveCursorRightWithoutShift","notALeftClick","ITextClickBehavior","_mouseDownHandler","doubleClickHandler","tripleClickHandler","draggableTextDelegate","didDrag","mouseOffset","charLength","widthAfter","MOVE_CURSOR_UP","MOVE_CURSOR_DOWN","MOVE_CURSOR_LEFT","MOVE_CURSOR_RIGHT","EXIT_EDITING","applyCanvasTransform","iTextDefaultValues","cursorColor","caching","IText","setSelectionStart","_updateAndFire","setSelectionEnd","findAncestorsWithClipPath","hasAncestorsWithClipping","drawingCanvas","drawingCtx","renderSelection","renderCursor","clippingCanvas","clippingCtx","clipPathAncestors","skipCaching","_getCursorBoundariesOffsets","__getCursorBoundariesOffsets","renderCursorAt","_renderCursor","getCursorRenderingData","_renderSelection","dragSelection","startLine","endLine","startChar","endChar","realLineHeight","boxEnd","drawHeight","extraTop","drawWidth","compositionColor","getCurrentCharFontSize","cp","_getCurrentCharIndex","getCurrentCharColor","cursorPosition","Textbox","dynamicMinWidth","_styleMap","_generateStyleMap","textInfo","realLineCount","realLineCharCount","splitByGrapheme","isWrapping","nextOffset","nextLineIndex","shouldLimit","mapNextLine","p2Number","_wrapText","desiredWidth","getGraphemeDataForRender","wrapped","wordsData","_wrapLine","infix","largestWordWidth","wordsOrGraphemes","wordSplit","word","graphemeArray","_measureWord","charOffset","_wordJoiners","reservedSpace","additionalSpace","infixWidth","lineJustStarted","wordWidth","getMinWidth","minWidth","linesToKeep","propNumber","ClipPathLayout","clipPathCenter","FixedLayout","ActiveSelectionLayoutManager","parents","Set","selectedObjects","ActiveSelection","multiSelectionStacking","findIndex","groups","childrenOverride","Canvas2dFilterBackend","applyFilters","filters","sourceElement","sourceWidth","sourceHeight","desynchronized","pipelineState","imageData","originalEl","originalImageData","filterBackend","applyTo","imageDataPostFilter","putImageData","WebGLFilterBackend","tileSize","Float32Array","setupGLContext","captureGPUInfo","createWebGLCanvas","premultipliedAlpha","depth","stencil","antialias","clearColor","cachedTexture","getCachedTexture","destinationWidth","destinationHeight","sourceTexture","createTexture","targetTexture","originalTexture","passes","webgl","aPosition","programCache","pass","tempFbo","createFramebuffer","bindFramebuffer","FRAMEBUFFER","dWidth","dHeight","resizeCanvasIfNeeded","copyGLTo2D","bindTexture","TEXTURE_2D","deleteTexture","deleteFramebuffer","clearWebGLCaches","textureCache","textureImageSource","NEAREST","RGBA","UNSIGNED_BYTE","CLAMP_TO_EDGE","TEXTURE_MAG_FILTER","TEXTURE_MIN_FILTER","TEXTURE_WRAP_S","TEXTURE_WRAP_T","texture","texParameteri","texImage2D","uniqueId","evictCachesForKey","glCanvas","sourceY","copyGLTo2DPutImageData","numBytes","u8","Uint8Array","imageBuffer","u8Clamped","Uint8ClampedArray","readPixels","imgData","ImageData","gpuInfo","renderer","vendor","ext","UNMASKED_RENDERER_WEBGL","UNMASKED_VENDOR_WEBGL","initFilterBackend","enableGLFiltering","getFilterBackend","setFilterBackend","backend","IMAGE_PROPS","FabricImage","setElement","_element","removeTexture","_originalElement","resizeFilter","applyResizeFilters","elementKey","getCrossOrigin","getOriginalSize","_stroke","filterObj","getSrc","hasCrop","imageMarkup","strokeSvg","imageRendering","imageSmoothing","getSvgSrc","origFill","filtered","srcFromAttribute","setSrc","minimumScale","minimumScaleTrigger","elementToFilter","_filteredEl","_filterScalingX","_filterScalingY","_lastScaleX","_lastScaleY","isNeutralState","imgElement","_needsResize","elementToDraw","elWidth","elHeight","sX","sY","sW","sH","maxDestW","maxDestH","_resetWidthHeight","pAR","preserveAspectRatio","pWidth","pHeight","rWidth","rHeight","f","rf","hydratedProps","fromURL","imageOptions","applyViewboxTransform","viewBoxAttr","widthAttr","heightAttr","missingViewBox","missingDimAttr","translateMatrix","widthDiff","heightDiff","parsedDim","pasedViewBox","createElementNS","firstChild","getTagName","node","tagName","svgInvalidAncestorsRegEx","getMultipleNodes","nodeNames","nodeList","nodeArray","getElementsByTagNameNS","gradientsAttrs","xlinkAttr","recursivelyParseGradientsXlink","_gradient$getAttribut","xLink","referencedGradient","children","referenceClone","cloneNode","tagArray","findTag","ElementsParser","clipPaths","regexUrl","gradientDefs","elList","getGradientDefs","allRules","styleContents","ruleObj","propertyValuePairs","pair","_rule","getCSSRules","createObject","resolveGradient","resolveClipPath","extractPropertyDefinition","storage","gradientDef","usingElement","exactOwner","clipPathElements","objTransformInv","clipPathTag","clipPathOwner","clipPathElement","enlivedClippath","clipRule","gTransform","isValidSvgTag","async","parseSVGDocument","createEmptyResponse","allElements","nodelist","skipAttributes","useElement","useAttributes","useAttrMap","xlink","href","referencedElement","clonedOriginal","originalAttributes","originalAttrMap","currentTrans","el3","setAttributeNS","childNodes","styleRecord","mergedStyles","entry","parseUseDirectives","descendants","hasInvalidAncestor","localClipPaths","elementParser","loadSVGFromString","parseFromString","loadSVGFromURL","fetch","response","ok","svgText","isWebGLPipelineState","isPutImageFaster","testContext","ArrayBuffer","testPipelineState","performance","now","drawImageTime","highPsourceCode","identityFragmentShader","BaseFilter","getFragmentSource","getVertexSource","createProgram","vertexSource","vertexShader","VERTEX_SHADER","program","getShaderInfoLog","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","attributeLocations","getAttributeLocations","getAttribLocation","locations","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","framebufferTexture2D","COLOR_ATTACHMENT0","finish","_swapTextures","temp","applyToWebGL","applyTo2d","getCacheKey","retrieveShader","shader","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","_gl","_uniformLocations","createHelpLayer","helpLayer","defaultKeys","filterOptions","blendColorFragmentSource","screen","difference","lighten","darken","exclusion","tint","BlendColor","mode","tg","alpha1","oR","oG","oB","uniform4fv","uColor","mask","BlendImage","image","TEXTURE1","calculateMatrix","resources","blendImage","canvas1","blendData","uniform1i","uImage","uniformMatrix3fv","uTransformMatrix","enlivedImage","Blur","aspectRatio","horizontal","blurValue","getBlurValue","samples","bytesInRow","totalA","minIRow","maxIRow","percent","weight","sampledPixel","localAlpha","delta","chooseRightDelta","uniform2fv","uDelta","blurScale","Brightness","brightness","uBrightness","colorMatrixDefaultValues","colorsOnly","ColorMatrix","constants","uniformMatrix4fv","uColorMatrix","uConstants","createColorMatrixFilter","_Class","newClass","Brownie","Vintage","Kodachrome","Technicolor","Polaroid","Sepia","BlackWhite","Composed","subFilters","enlivedFilters","Contrast","contrast","contrastF","uContrast","Convolute_3_1","Convolute_3_0","Convolute_5_1","Convolute_5_0","Convolute_7_1","Convolute_7_0","Convolute_9_1","Convolute_9_0","Convolute","opaque","weights","side","halfSide","sw","sh","createImageData","dst","alphaFac","dstOff","scx","scy","srcOff","wt","uniform1fv","uMatrix","GAMMA","Gamma","gamma","rInv","gInv","bInv","rgbValues","rgb","uniform3fv","uGamma","lightness","luminosity","Grayscale","uMode","hueRotationDefaultValues","rotation","HueRotation","cosine","sine","aThird","aThirdSqtSin","OneMinusCos","Invert","invert","uInvert","uAlpha","Noise","noise","rand","uNoise","uSeed","Pixelate","blocksize","_i","_j","uBlocksize","RemoveColor","lowC","highC","uLow","uHigh","useAlpha","Resize","uTaps","taps","getFilterWindow","tempScale","lanczosLobes","filterWindow","generateShader","getTaps","lobeFunction","lanczosCreate","applyToForWebgl","dW","dH","lobes","xx","rcpScaleX","rcpScaleY","oW","oH","newData","resizeType","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","mult","doneW","doneH","stepW","stepH","dX","dY","tmpCanvas","srcData","destImg","destData","lanczos","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","icenter","process","u","fX","fY","xDiff","yDiff","chnl","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","weightsAlpha","gxR","gxG","gxB","gxA","yy","w0","Saturation","adjust","saturation","uSaturation","Vibrance","vibrance","amt","uVibrance"],"mappings":"kbAEA,MAAMA,EAAkBC,WAAAA,GACtBC,mCAc4B,GAE5BA,aAGM,IAENA,EAAAC,KAAA,mBAKoB,oBAAXC,OAAyBA,OAAOC,iBAAmB,GAE5DH,4BAKqB,SAErBA,2BAKoB,MAEpBA,2BAKoB,KAEpBA,gCAOwB,GAExBA,4BAOoB,GAEpBA,qBASc,MAEdA,8BAOsB,GAEtBA,8BAQsB,GAEtBA,EAAAC,KAAA,YAIwE,IAExED,6BAKsB,EAAC,QA8CZI,EAAS,IA3Cf,cAA4BN,EACjCC,WAAAA,CAAYK,GACVC,QACAJ,KAAKK,UAAUF,EACjB,CAEAE,SAAAA,GAAuC,IAA7BF,EAAsBG,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACjCG,OAAOC,OAAOV,KAAMG,EACtB,CAKAQ,QAAAA,GAEE,IADAC,EAAiEN,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEpEN,KAAKa,UAAY,IACZb,KAAKa,aACLD,EAEP,CAEAE,WAAAA,IAAiCR,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,IACtBS,QAASC,WACZhB,KAAKa,UAAUG,IAE1B,CAEAC,UAAAA,GACEjB,KAAKa,UAAY,CAAA,CACnB,CAEAK,eAAAA,CAA6CC,GAC3C,MAAMC,EAAW,IAAIvB,EACfM,GACJgB,aAAI,EAAJA,EAAME,OAAO,CAACC,EAAKC,KACjBD,EAAIC,GAAOH,EAASG,GACbD,GACN,CAAA,KAAYF,EACjBpB,KAAKK,UAAUF,EACjB,GC1JWqB,EAAM,SACjBC,GAAkC,IAAA,IAAAC,EAAApB,UAAAC,OAC/BoB,MAAcC,MAAAF,EAAA,EAAAA,OAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAdF,EAAcE,EAAA,GAAAvB,UAAAuB,GAAA,OAGjBC,QAAQL,GAAU,YAAaE,EAAe,EAEzC,MAAMI,UAAoBC,MAC/BlC,WAAAA,CAAYmC,EAAkBC,GAC5B9B,MAAM,WAAW6B,IAAWC,EAC9B,EAGK,MAAMC,UAA2BJ,EACtCjC,WAAAA,CAAYsC,GACVhC,MAAM,GAAGgC,2CACX,ECdK,MAAeC,GCKf,MAAMC,UAAmBD,EAStBE,aAAAA,CACNC,EACAC,GAEA,MAAMC,EAAiB,aAAaD,0BAC9BE,EAAiBH,EAAGI,aAAaJ,EAAGK,iBAC1C,QAAKF,IAGLH,EAAGM,aAAaH,EAAgBD,GAChCF,EAAGO,cAAcJ,KACRH,EAAGQ,mBAAmBL,EAAgBH,EAAGS,gBACpD,CAKAC,UAAAA,CAAWC,GACT,MAAMX,EAAKW,EAAOC,WAAW,SACzBZ,IACFxC,KAAKqD,eAAiBb,EAAGc,aAAad,EAAGe,kBACzCvD,KAAKwD,YAAe,CAAC,QAAS,UAAW,QAAkBC,KACxDhB,GAAczC,KAAKuC,cAAcC,EAAIC,IAExCD,EAAGkB,aAAa,sBAAuBC,cACvCnC,EAAI,MAAO,2BAA2BxB,KAAKqD,kBAE/C,CAEAO,WAAAA,CAAYC,GACV,QAAS7D,KAAKqD,gBAAkBrD,KAAKqD,gBAAkBQ,CACzD,EC3CF,MAAMC,EAAgC,CAAA,ECStC,IAAIC,EAeG,MAAMC,EAAUC,IACrBF,EAAME,GAMKC,EAASA,IAAMH,IAAQA,ED5B3B,CACLI,kBACAlE,cACAmE,iBACE,iBAAkBnE,QAClB,iBAAkBkE,UACjBlE,QAAUA,OAAOoE,WAAapE,OAAOoE,UAAUC,eAAiB,EACnEhC,WAAY,IAAIA,EAChBiC,OAAAA,GACE,EAEFT,kBCmBSU,EAAoBA,IAAgBN,IAASC,SAE7CM,EAAkBA,IAC7BP,IAASjE,OAKEyE,EAAsBA,KAAA,IAAAC,EAAA,OACjCC,KAAKC,IAA2B,QAAxBF,EAACxE,EAAOD,wBAAgB,IAAAyE,EAAAA,EAAIF,IAAkBvE,iBAAkB,UC6C7D4E,EAAQ,IApFd,MAMLhF,WAAAA,GAmEAC,EAAAC,KAAA,qBAQkD,IA1EhDA,KAAK+E,gBAAkB,IAAIC,GAC7B,CAKAC,YAAAA,CAAYC,GAQS,IARRlE,WACXA,EAAUmE,UACVA,EAASC,WACTA,GAKDF,EACClE,EAAaA,EAAWqE,cACxB,MAAMP,EAAQ9E,KAAK+E,gBACdD,EAAMQ,IAAItE,IACb8D,EAAMS,IAAIvE,EAAY,IAAIgE,KAE5B,MAAMQ,EAAYV,EAAMW,IAAIzE,GACtB0E,EAAW,GAAGP,EAAUE,kBAC5BD,EAAa,IACbC,gBAIF,OAHKG,EAAUF,IAAII,IACjBF,EAAUD,IAAIG,EAAU,IAAIV,KAEvBQ,EAAUC,IAAIC,EACvB,CAaAC,cAAAA,CAAe3E,GACRA,EAGHhB,KAAK+E,gBAAgBa,QAAQ5E,GAAc,IAAIqE,eAF/CrF,KAAK+E,gBAAkB,IAAIC,GAI/B,CAQAa,eAAAA,CAAgBC,GACd,MAAMC,mBAAEA,GAAuB5F,EACzB6F,EAAapB,KAAKqB,KAAKF,EAAqBD,GAGlD,MAAO,CACLlB,KAAKsB,MAAMF,GACXpB,KAAKsB,MAAMH,EAAqBC,GAEpC,GC1EK,MAAMG,UAEN,SAASC,IAAQ,CAEjB,MAAMC,EAASzB,KAAK0B,GAAK,EACnBC,EAAY3B,KAAK0B,GAAK,EACtBE,EAAsB,EAAV5B,KAAK0B,GACjBG,EAAU7B,KAAK0B,GAAK,IAEpBI,EAAUjG,OAAOkG,OAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,IACxCC,EAAwB,GAIxBC,EAAQ,YAERC,EAAS,SACTC,EAAO,OACPC,EAAM,MACNC,EAAS,SACTC,EAAQ,QACRC,EAAO,OAGPC,EAAY,QAEZC,EAAS,SACTC,EAAU,UACVC,EAAW,WACXC,EAAS,SACTC,EAAU,UACVC,EAAW,WACXC,EAAc,aACdC,EAAc,aACdC,EAAU,UACVC,EAAQ,QACRC,EAAU,SACVC,EAAU,SACVC,EAAS,QACTC,EAAS,QACTC,EAAO,OACPC,EAAS,SACTC,EAAW,WAEXC,EAAM,MACNC,EAAM,MAENC,EAAS,SCrCTC,EAAO,OACPC,EAAM,YA8CNC,GAAgB,IA5CtB,MAIL7I,WAAAA,GACEE,KAAKyI,GAAQ,IAAIzD,IACjBhF,KAAK0I,GAAO,IAAI1D,GAClB,CAEAM,GAAAA,CAAIsD,GACF,OAAO5I,KAAKyI,GAAMnD,IAAIsD,EACxB,CAEAC,QAAAA,CAAYD,GACV,MAAM9I,EAAcE,KAAKyI,GAAMhD,IAAImD,GACnC,IAAK9I,EACH,MAAM,IAAIiC,EAAY,2BAA2B6G,KAEnD,OAAO9I,CACT,CAEAgJ,QAAAA,CAASC,EAAuBH,GAC1BA,EACF5I,KAAKyI,GAAMlD,IAAIqD,EAAWG,IAE1B/I,KAAKyI,GAAMlD,IAAIwD,EAAiBC,KAAMD,GAGtC/I,KAAKyI,GAAMlD,IAAIwD,EAAiBC,KAAK3D,cAAe0D,GAExD,CAEAE,WAAAA,CAAYC,GACV,OAAOlJ,KAAK0I,GAAKjD,IAAIyD,EACvB,CAEAC,WAAAA,CAAYJ,EAAuBG,GACjClJ,KAAK0I,GAAKnD,IACR2D,QAAAA,EAAcH,EAAiBC,KAAK3D,cACpC0D,EAEJ,SCAWK,GAAoB,IAnDjC,cAAgCxH,MAK9ByH,MAAAA,CAAOjH,GACL,MAAMkH,EAAQtJ,KAAKuJ,QAAQnH,GAC3BkH,GAAQ,GAAMtJ,KAAKwJ,OAAOF,EAAO,EACnC,CAKAG,SAAAA,GACE,MAAMC,EAAa1J,KAAKwJ,OAAO,GAE/B,OADAE,EAAW3I,QAAS4I,GAAcA,EAAUC,SACrCF,CACT,CAMAG,cAAAA,CAAe1G,GACb,IAAKA,EACH,MAAO,GAET,MAAMuG,EAAa1J,KAAK8J,OACrBH,IAAS,IAAAI,EAAA,OACRJ,EAAUK,SAAW7G,GACQ,iBAArBwG,EAAUK,SACC,QAAjBD,EAACJ,EAAUK,cAAM,IAAAD,OAAA,EAAjBA,EAAoC5G,UAAWA,IAGrD,OADAuG,EAAW3I,QAAS4I,GAAcA,EAAUC,SACrCF,CACT,CAMAO,cAAAA,CAAeD,GACb,IAAKA,EACH,MAAO,GAET,MAAMN,EAAa1J,KAAK8J,OAAQH,GAAcA,EAAUK,SAAWA,GAEnE,OADAN,EAAW3I,QAAS4I,GAAcA,EAAUC,SACrCF,CACT,GC7CK,MAAMQ,GAAsBpK,WAAAA,GAAAC,EAAAC,KAAA,mBAE/B,GAAE,CAeJmK,EAAAA,CACEC,EACAC,GAKA,GAHKrK,KAAKsK,mBACRtK,KAAKsK,iBAAmB,CAAA,GAEN,iBAATF,EAKT,OAHA3J,OAAO8J,QAAQH,GAAMrJ,QAAQmE,IAA0B,IAAxBsF,EAAWH,GAAQnF,EAChDlF,KAAKmK,GAAGK,EAAgBH,KAEnB,IAAMrK,KAAKyK,IAAIL,GACjB,GAAIC,EAAS,CAClB,MAAMG,EAAYJ,EAKlB,OAJKpK,KAAKsK,iBAAiBE,KACzBxK,KAAKsK,iBAAiBE,GAAa,IAErCxK,KAAKsK,iBAAiBE,GAAWE,KAAKL,GAC/B,IAAMrK,KAAKyK,IAAID,EAAWH,EACnC,CAEE,MAAO,KAAM,CAEjB,CAeAM,IAAAA,CACEP,EACAC,GAEA,GAAoB,iBAATD,EAAmB,CAE5B,MAAMQ,EAA4B,GAIlC,OAHAnK,OAAO8J,QAAQH,GAAMrJ,QAAQ8J,IAA0B,IAAxBL,EAAWH,GAAQQ,EAChDD,EAAUF,KAAK1K,KAAK2K,KAAKH,EAAgBH,MAEpC,IAAMO,EAAU7J,QAAS+J,GAAMA,IACxC,CAAO,GAAIT,EAAS,CAClB,MAAMU,EAAW/K,KAAKmK,GACpBC,EACA,WAA2D,IAAA,IAAA1I,EAAApB,UAAAC,OAANyK,EAAI,IAAApJ,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAJmJ,EAAInJ,GAAAvB,UAAAuB,GACvDwI,EAAQY,KAAKjL,QAASgL,GACtBD,GACF,GAEF,OAAOA,CACT,CAEE,MAAO,KAAM,CAEjB,CAOQG,oBAAAA,CACNV,EACAH,GAEA,GAAKrK,KAAKsK,iBAAiBE,GAI3B,GAAIH,EAAS,CACX,MAAMc,EAAgBnL,KAAKsK,iBAAiBE,GACtClB,EAAQ6B,EAAc5B,QAAQc,GACpCf,GAAQ,GAAM6B,EAAc3B,OAAOF,EAAO,EAC5C,MACEtJ,KAAKsK,iBAAiBE,GAAa,EAEvC,CAyBAC,GAAAA,CACEL,EACAC,GAEA,GAAKrK,KAAKsK,iBAKV,QAAoB,IAATF,EACT,IAAK,MAAMI,KAAaxK,KAAKsK,iBAC3BtK,KAAKkL,qBAAqBV,OAIL,iBAATJ,EACd3J,OAAO8J,QAAQH,GAAMrJ,QAAQqK,IAA0B,IAAxBZ,EAAWH,GAAQe,EAChDpL,KAAKkL,qBAAqBV,EAAgBH,KAG5CrK,KAAKkL,qBAAqBd,EAAMC,EAEpC,CAOAgB,IAAAA,CAAgCb,EAActI,GAAwB,IAAAoJ,EACpE,IAAKtL,KAAKsK,iBACR,OAGF,MAAMiB,UAAiBD,EAAGtL,KAAKsK,iBAAiBE,UAAU,IAAAc,OAAA,EAAhCA,EAAkCE,SAC5D,GAAID,EACF,IAAK,IAAIE,EAAI,EAAGA,EAAIF,EAAkBhL,OAAQkL,IAC5CF,EAAkBE,GAAGR,KAAKjL,KAAMkC,GAAW,CAAA,EAGjD,EC1KK,MAAMwJ,GAAkBA,CAAIC,EAAY1H,KAC7C,MAAM2H,EAAMD,EAAMpC,QAAQtF,GAI1B,OAHY,IAAR2H,GACFD,EAAMnC,OAAOoC,EAAK,GAEbD,GCFIE,GAAOC,IAClB,GAAc,IAAVA,EACF,OAAO,EAGT,OADmBlH,KAAKmH,IAAID,GAASzF,GAEnC,KAAK,EACL,KAAK,EACH,OAAO,EACT,KAAK,EACH,OAAO,EAEX,OAAOzB,KAAKiH,IAAIC,ICZLE,GAAOF,IAClB,GAAc,IAAVA,EACF,OAAO,EAET,MAAMG,EAAaH,EAAQzF,EACrBpC,EAAQW,KAAKsH,KAAKJ,GACxB,OAAQG,GACN,KAAK,EACH,OAAOhI,EACT,KAAK,EACH,OAAO,EACT,KAAK,EACH,OAAQA,EAEZ,OAAOW,KAAKoH,IAAIF,ICZX,MAAMK,GAQXrM,WAAAA,GAA0C,IAA9BsK,EAAiB9J,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EAAG8L,EAAC9L,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EACjB,iBAAT8J,GACTpK,KAAKqM,EAAIjC,EAAKiC,EACdrM,KAAKoM,EAAIhC,EAAKgC,IAEdpM,KAAKqM,EAAIjC,EACTpK,KAAKoM,EAAIA,EAEb,CAOAE,GAAAA,CAAIC,GACF,OAAO,IAAIJ,GAAMnM,KAAKqM,EAAIE,EAAKF,EAAGrM,KAAKoM,EAAIG,EAAKH,EAClD,CAQAI,SAAAA,CAAUD,GAGR,OAFAvM,KAAKqM,GAAKE,EAAKF,EACfrM,KAAKoM,GAAKG,EAAKH,EACRpM,IACT,CAOAyM,SAAAA,CAAUC,GACR,OAAO,IAAIP,GAAMnM,KAAKqM,EAAIK,EAAQ1M,KAAKoM,EAAIM,EAC7C,CAQAC,eAAAA,CAAgBD,GAGd,OAFA1M,KAAKqM,GAAKK,EACV1M,KAAKoM,GAAKM,EACH1M,IACT,CAOA4M,QAAAA,CAASL,GACP,OAAO,IAAIJ,GAAMnM,KAAKqM,EAAIE,EAAKF,EAAGrM,KAAKoM,EAAIG,EAAKH,EAClD,CAQAS,cAAAA,CAAeN,GAGb,OAFAvM,KAAKqM,GAAKE,EAAKF,EACfrM,KAAKoM,GAAKG,EAAKH,EACRpM,IACT,CAOA8M,cAAAA,CAAeJ,GACb,OAAO,IAAIP,GAAMnM,KAAKqM,EAAIK,EAAQ1M,KAAKoM,EAAIM,EAC7C,CAQAK,oBAAAA,CAAqBL,GAGnB,OAFA1M,KAAKqM,GAAKK,EACV1M,KAAKoM,GAAKM,EACH1M,IACT,CAOAgN,QAAAA,CAAST,GACP,OAAO,IAAIJ,GAAMnM,KAAKqM,EAAIE,EAAKF,EAAGrM,KAAKoM,EAAIG,EAAKH,EAClD,CAOAa,cAAAA,CAAeP,GACb,OAAO,IAAIP,GAAMnM,KAAKqM,EAAIK,EAAQ1M,KAAKoM,EAAIM,EAC7C,CAQAQ,oBAAAA,CAAqBR,GAGnB,OAFA1M,KAAKqM,GAAKK,EACV1M,KAAKoM,GAAKM,EACH1M,IACT,CAOAmN,MAAAA,CAAOZ,GACL,OAAO,IAAIJ,GAAMnM,KAAKqM,EAAIE,EAAKF,EAAGrM,KAAKoM,EAAIG,EAAKH,EAClD,CAOAgB,YAAAA,CAAaV,GACX,OAAO,IAAIP,GAAMnM,KAAKqM,EAAIK,EAAQ1M,KAAKoM,EAAIM,EAC7C,CAQAW,kBAAAA,CAAmBX,GAGjB,OAFA1M,KAAKqM,GAAKK,EACV1M,KAAKoM,GAAKM,EACH1M,IACT,CAOAsN,EAAAA,CAAGf,GACD,OAAOvM,KAAKqM,IAAME,EAAKF,GAAKrM,KAAKoM,IAAMG,EAAKH,CAC9C,CAOAmB,EAAAA,CAAGhB,GACD,OAAOvM,KAAKqM,EAAIE,EAAKF,GAAKrM,KAAKoM,EAAIG,EAAKH,CAC1C,CAOAoB,GAAAA,CAAIjB,GACF,OAAOvM,KAAKqM,GAAKE,EAAKF,GAAKrM,KAAKoM,GAAKG,EAAKH,CAC5C,CAQAqB,EAAAA,CAAGlB,GACD,OAAOvM,KAAKqM,EAAIE,EAAKF,GAAKrM,KAAKoM,EAAIG,EAAKH,CAC1C,CAOAsB,GAAAA,CAAInB,GACF,OAAOvM,KAAKqM,GAAKE,EAAKF,GAAKrM,KAAKoM,GAAKG,EAAKH,CAC5C,CAQAuB,IAAAA,CAAKpB,GAA0B,IAAhBqB,EAACtN,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAEjB,OADAsN,EAAIhJ,KAAKC,IAAID,KAAKiJ,IAAI,EAAGD,GAAI,GACtB,IAAIzB,GACTnM,KAAKqM,GAAKE,EAAKF,EAAIrM,KAAKqM,GAAKuB,EAC7B5N,KAAKoM,GAAKG,EAAKH,EAAIpM,KAAKoM,GAAKwB,EAEjC,CAOAE,YAAAA,CAAavB,GACX,MAAMwB,EAAK/N,KAAKqM,EAAIE,EAAKF,EACvB2B,EAAKhO,KAAKoM,EAAIG,EAAKH,EACrB,OAAOxH,KAAKqB,KAAK8H,EAAKA,EAAKC,EAAKA,EAClC,CAOAC,YAAAA,CAAa1B,GACX,OAAOvM,KAAK2N,KAAKpB,EACnB,CAOAsB,GAAAA,CAAItB,GACF,OAAO,IAAIJ,GAAMvH,KAAKiJ,IAAI7N,KAAKqM,EAAGE,EAAKF,GAAIzH,KAAKiJ,IAAI7N,KAAKoM,EAAGG,EAAKH,GACnE,CAOAvH,GAAAA,CAAI0H,GACF,OAAO,IAAIJ,GAAMvH,KAAKC,IAAI7E,KAAKqM,EAAGE,EAAKF,GAAIzH,KAAKC,IAAI7E,KAAKoM,EAAGG,EAAKH,GACnE,CAMA8B,QAAAA,GACE,MAAO,GAAGlO,KAAKqM,KAAKrM,KAAKoM,GAC3B,CAOA+B,KAAAA,CAAM9B,EAAWD,GAGf,OAFApM,KAAKqM,EAAIA,EACTrM,KAAKoM,EAAIA,EACFpM,IACT,CAMAoO,IAAAA,CAAK/B,GAEH,OADArM,KAAKqM,EAAIA,EACFrM,IACT,CAMAqO,IAAAA,CAAKjC,GAEH,OADApM,KAAKoM,EAAIA,EACFpM,IACT,CAMAsO,YAAAA,CAAa/B,GAGX,OAFAvM,KAAKqM,EAAIE,EAAKF,EACdrM,KAAKoM,EAAIG,EAAKH,EACPpM,IACT,CAMAuO,IAAAA,CAAKhC,GACH,MAAMF,EAAIrM,KAAKqM,EACbD,EAAIpM,KAAKoM,EACXpM,KAAKqM,EAAIE,EAAKF,EACdrM,KAAKoM,EAAIG,EAAKH,EACdG,EAAKF,EAAIA,EACTE,EAAKH,EAAIA,CACX,CAMAoC,KAAAA,GACE,OAAO,IAAIrC,GAAMnM,KAAKqM,EAAGrM,KAAKoM,EAChC,CAQAqC,MAAAA,CAAOC,GAA4C,IAA1BC,EAAUrO,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGsO,GAGpC,MAAMC,EAAQ7C,GAAI0C,GAChBI,EAAUjD,GAAI6C,GACVK,EAAI/O,KAAK4M,SAAS+B,GAKxB,OAJgB,IAAIxC,GAClB4C,EAAE1C,EAAIyC,EAAUC,EAAE3C,EAAIyC,EACtBE,EAAE1C,EAAIwC,EAAQE,EAAE3C,EAAI0C,GAEPxC,IAAIqC,EACrB,CAQAK,SAAAA,CAAUpB,GAAwC,IAA7BqB,EAAY3O,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAC/B,OAAO,IAAI6L,GACTyB,EAAE,GAAK5N,KAAKqM,EAAIuB,EAAE,GAAK5N,KAAKoM,GAAK6C,EAAe,EAAIrB,EAAE,IACtDA,EAAE,GAAK5N,KAAKqM,EAAIuB,EAAE,GAAK5N,KAAKoM,GAAK6C,EAAe,EAAIrB,EAAE,IAE1D,EAGK,MAAMgB,GAAO,IAAIzC,GAAM,EAAG,GC7WpB+C,GACXC,KAESA,GAAgBvN,MAAMwN,QAASD,EAAuBE,UAG1D,SAASC,GAAiDC,GAC/D,MAAMC,UAAmBD,EAAKzP,WAAAA,GAAAM,SAAAE,WAC5BP,kBAI2B,GAAE,CAG7B0P,cAAAA,CAAeC,GACb,CAIFC,gBAAAA,CAAiBD,GACf,CAIFE,oBAAAA,CAAqBF,GACnB,CASFpD,GAAAA,GAAwC,IAAA,IAAA5K,EAAApB,UAAAC,OAAjCsP,EAAO,IAAAjO,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAPgO,EAAOhO,GAAAvB,UAAAuB,GACZ,MAAMiO,EAAO9P,KAAKqP,SAAS3E,QAAQmF,GAEnC,OADAA,EAAQ9O,QAAS2O,GAAW1P,KAAKyP,eAAeC,IACzCI,CACT,CAQAC,QAAAA,CAASzG,GAA2C,IAAA,IAAA0G,EAAA1P,UAAAC,OAAzBsP,MAAOjO,MAAAoO,EAAA,EAAAA,OAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAPJ,EAAOI,EAAA,GAAA3P,UAAA2P,GAGhC,OAFAjQ,KAAKqP,SAAS7F,OAAOF,EAAO,KAAMuG,GAClCA,EAAQ9O,QAAS2O,GAAW1P,KAAKyP,eAAeC,IACzC1P,KAAKqP,SAAS9O,MACvB,CAQA8I,MAAAA,GACE,MAAMsC,EAAQ3L,KAAKqP,SACjBa,EAA0B,GAAG,IAAA,IAAAC,EAAA7P,UAAAC,OAFvBsP,EAAO,IAAAjO,MAAAuO,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAPP,EAAOO,GAAA9P,UAAA8P,GAYf,OATAP,EAAQ9O,QAAS2O,IACf,MAAMpG,EAAQqC,EAAMpC,QAAQmG,IAEd,IAAVpG,IACFqC,EAAMnC,OAAOF,EAAO,GACpB4G,EAAQxF,KAAKgF,GACb1P,KAAK2P,iBAAiBD,MAGnBQ,CACT,CAUAG,aAAAA,CACEC,GAMAtQ,KAAKuQ,aAAaxP,QAAQ,CAAC2O,EAAQpG,EAAOuG,IACxCS,EAASZ,EAAQpG,EAAOuG,GAE5B,CAOAU,UAAAA,GAA+B,IAAA,IAAAC,EAAAlQ,UAAAC,OAAjBkQ,EAAK,IAAA7O,MAAA4O,GAAAE,EAAA,EAAAA,EAAAF,EAAAE,IAALD,EAAKC,GAAApQ,UAAAoQ,GACjB,OAAqB,IAAjBD,EAAMlQ,OACD,IAAIP,KAAKqP,UAEXrP,KAAKqP,SAASvF,OAAQ6G,GAAMA,EAAEC,UAAUH,GACjD,CAOAI,IAAAA,CAAKvH,GACH,OAAOtJ,KAAKqP,SAAS/F,EACvB,CAMAwH,OAAAA,GACE,OAAgC,IAAzB9Q,KAAKqP,SAAS9O,MACvB,CAMAuP,IAAAA,GACE,OAAO9P,KAAKqP,SAAS9O,MACvB,CAUAwQ,QAAAA,CAASrB,EAAsBsB,GAC7B,QAAIhR,KAAKqP,SAAS4B,SAASvB,MAEhBsB,GACFhR,KAAKqP,SAAS6B,KAClBC,GACCA,aAAe3B,GACd2B,EAA8BJ,SAASrB,GAAQ,GAIxD,CAMA0B,UAAAA,GACE,OAAOpR,KAAKqP,SAAShO,OAAO,CAACgQ,EAAMC,IACjCD,GAAQC,EAAQF,WAAaE,EAAQF,aAAe,EAEnD,EACL,CAQAG,gBAAAA,CAAiB7B,GACf,SAAKA,GAAUA,IAAW1P,KAAKqP,SAAS,MAGxC3D,GAAgB1L,KAAKqP,SAAUK,GAC/B1P,KAAKqP,SAASmC,QAAQ9B,GACtB1P,KAAK4P,qBAAqBF,IACnB,EACT,CAQA+B,kBAAAA,CAAmB/B,GACjB,SAAKA,GAAUA,IAAW1P,KAAKqP,SAASrP,KAAKqP,SAAS9O,OAAS,MAG/DmL,GAAgB1L,KAAKqP,SAAUK,GAC/B1P,KAAKqP,SAAS3E,KAAKgF,GACnB1P,KAAK4P,qBAAqBF,IACnB,EACT,CAYAgC,mBAAAA,CAAoBhC,EAAsBiC,GACxC,IAAKjC,EACH,OAAO,EAET,MAAM9D,EAAM5L,KAAKqP,SAAS9F,QAAQmG,GAClC,GAAY,IAAR9D,EAAW,CAEb,MAAMgG,EAAS5R,KAAK6R,kBAAkBnC,EAAQ9D,EAAK+F,GAInD,OAHAjG,GAAgB1L,KAAKqP,SAAUK,GAC/B1P,KAAKqP,SAAS7F,OAAOoI,EAAQ,EAAGlC,GAChC1P,KAAK4P,qBAAqBF,IACnB,CACT,CACA,OAAO,CACT,CAYAoC,kBAAAA,CAAmBpC,EAAsBiC,GACvC,IAAKjC,EACH,OAAO,EAET,MAAM9D,EAAM5L,KAAKqP,SAAS9F,QAAQmG,GAClC,GAAI9D,IAAQ5L,KAAKqP,SAAS9O,OAAS,EAAG,CAEpC,MAAMqR,EAAS5R,KAAK+R,kBAAkBrC,EAAQ9D,EAAK+F,GAInD,OAHAjG,GAAgB1L,KAAKqP,SAAUK,GAC/B1P,KAAKqP,SAAS7F,OAAOoI,EAAQ,EAAGlC,GAChC1P,KAAK4P,qBAAqBF,IACnB,CACT,CACA,OAAO,CACT,CAQAsC,YAAAA,CAAatC,EAAsBpG,GACjC,OAAIoG,IAAW1P,KAAKqP,SAAS/F,KAG7BoC,GAAgB1L,KAAKqP,SAAUK,GAC/B1P,KAAKqP,SAAS7F,OAAOF,EAAO,EAAGoG,GAC/B1P,KAAK4P,qBAAqBF,IACnB,EACT,CAEAmC,iBAAAA,CACEnC,EACA9D,EACA+F,GAEA,IAAIC,EAEJ,GAAID,EAAc,CAChBC,EAAShG,EAET,IAAK,IAAIH,EAAIG,EAAM,EAAGH,GAAK,IAAKA,EAC9B,GAAIiE,EAAOuC,cAAcjS,KAAKqP,SAAS5D,IAAK,CAC1CmG,EAASnG,EACT,KACF,CAEJ,MACEmG,EAAShG,EAAM,EAGjB,OAAOgG,CACT,CAEAG,iBAAAA,CACErC,EACA9D,EACA+F,GAEA,IAAIC,EAEJ,GAAID,EAAc,CAChBC,EAAShG,EAET,IAAK,IAAIH,EAAIG,EAAM,EAAGH,EAAIzL,KAAKqP,SAAS9O,SAAUkL,EAChD,GAAIiE,EAAOuC,cAAcjS,KAAKqP,SAAS5D,IAAK,CAC1CmG,EAASnG,EACT,KACF,CAEJ,MACEmG,EAAShG,EAAM,EAGjB,OAAOgG,CACT,CAUAM,cAAAA,CAAchN,GAGZ,IAFAiN,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GAAepN,GACnCqN,oBAAEA,GAAsB,GAAyCjS,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEpE,MAAMuP,EAAqC,GACzC2C,EAAK,IAAIrG,GAAMgG,EAAMC,GACrBK,EAAKD,EAAGlG,IAAI,IAAIH,GAAMkG,EAAOC,IAG/B,IAAK,IAAI7G,EAAIzL,KAAKqP,SAAS9O,OAAS,EAAGkL,GAAK,EAAGA,IAAK,CAClD,MAAMiE,EAAS1P,KAAKqP,SAAS5D,GAE3BiE,EAAOgD,YACPhD,EAAOiD,UACLJ,GAAuB7C,EAAOkD,mBAAmBJ,EAAIC,IACrD/C,EAAOmD,sBAAsBL,EAAIC,IAChCF,GAAuB7C,EAAOoD,cAAcN,IAC5CD,GAAuB7C,EAAOoD,cAAcL,KAE/C5C,EAAQnF,KAAKgF,EAEjB,CAEA,OAAOG,CACT,EAIF,OAAOL,CACT,CChWO,MAAMuD,WAAiC7I,GAMlC8I,WAAAA,GAA+B,IAAnB9Q,EAAY5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACnC,IAAK,MAAM2S,KAAQ/Q,EACjBlC,KAAKuF,IAAI0N,EAAM/Q,EAAQ+Q,GAE3B,CAKAC,UAAAA,CAAW/B,GACT,IAAK,MAAM8B,KAAQ9B,EACjBnR,KAAKmT,KAAKF,EAAM9B,EAAI8B,GAExB,CAOA1N,GAAAA,CAAIhE,EAAmC0C,GAMrC,MALmB,iBAAR1C,EACTvB,KAAKkT,WAAW3R,GAEhBvB,KAAKmT,KAAK5R,EAAK0C,GAEVjE,IACT,CAEAmT,IAAAA,CAAK5R,EAAa0C,GAChBjE,KAAKuB,GAAqB0C,CAC5B,CAMAmP,MAAAA,CAAOC,GACL,MAAMpP,EAAQjE,KAAKyF,IAAI4N,GAIvB,MAHqB,kBAAVpP,GACTjE,KAAKuF,IAAI8N,GAAWpP,GAEfjE,IACT,CAOAyF,GAAAA,CAAI4N,GACF,OAAOrT,KAAKqT,EACd,EC1DK,SAASC,GAAiBhD,GAC/B,OAAO7L,IAAkB8O,sBAAsBjD,EACjD,CAEO,SAASkD,GAAgBC,GAC9B,OAAOhP,IAAkBiP,qBAAqBD,EAChD,CCRA,IAAIE,GAAK,EAEF,MAAMC,GAAMA,IAAMD,KCKZE,GAAsBA,KACjC,MAAMC,EAAUtP,IAAoBuP,cAAc,UAClD,IAAKD,QAAyC,IAAvBA,EAAQ1Q,WAC7B,MAAM,IAAIrB,EAAY,qCAExB,OAAO+R,GAOIE,GAAcA,IACzBxP,IAAoBuP,cAAc,OAoBvBE,GACX9Q,IAEA,MAAM+Q,EAAYL,KAGlB,OAFAK,EAAU7B,MAAQlP,EAAOkP,MACzB6B,EAAU5B,OAASnP,EAAOmP,OACnB4B,GAWIC,GAAYA,CACvBC,EACAC,EACAC,IACGF,EAASD,UAAU,SAASE,IAAUC,GAQ9BC,GAASA,CACpBH,EACAC,EACAC,IAEA,IAAIE,QAAQ,CAACC,EAASC,KACpBN,EAASG,OAAOE,EAAS,SAASJ,IAAUC,KCnEnCK,GAAoBC,GAC9BA,EAAUnO,EAOAoO,GAAoBnG,GAC9BA,EAAUjI,ECiBAqO,GAAoBC,GAC/BA,EAAIC,MAAM,CAAC/Q,EAAOqF,IAAUrF,IAAUyC,EAAQ4C,IAUnC2L,GAAiBA,CAC5BlG,EACAnB,EACAqB,IACU,IAAI9C,GAAM4C,GAAGC,UAAUpB,EAAGqB,GAOzBiG,GAAmBtH,IAC9B,MAAMuH,EAAI,GAAKvH,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAE,IACpCwH,EAAI,CAACD,EAAIvH,EAAE,IAAKuH,EAAIvH,EAAE,IAAKuH,EAAIvH,EAAE,GAAIuH,EAAIvH,EAAE,GAAI,EAAG,IAClDvB,EAAEA,EAACD,EAAEA,GAAM,IAAID,GAAMyB,EAAE,GAAIA,EAAE,IAAIoB,UAAUoG,GAAG,GAGhD,OAFAA,EAAE,IAAM/I,EACR+I,EAAE,IAAMhJ,EACDgJ,GAUIC,GAA4BA,CACvCF,EACAG,EACAC,IAEA,CACEJ,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GACvBH,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GACvBH,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GACvBH,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GACvBC,EAAQ,EAAIJ,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAC1CI,EAAQ,EAAIJ,EAAE,GAAKG,EAAE,GAAKH,EAAE,GAAKG,EAAE,GAAKH,EAAE,IAYjCK,GAA+BA,CAC1CC,EACAF,IAEAE,EAASC,YACP,CAACC,EAAiBC,IAChBA,GAAQD,EACJN,GAA0BO,EAAMD,EAASJ,GACzCK,GAAQD,OACdnV,IACGkG,EAAQ8E,SAEFqK,GAAoB3Q,IAAA,IAAEiQ,EAAGG,GAAUpQ,EAAA,OAC9CN,KAAKkR,MAAMR,EAAGH,IAOHY,GAAeZ,IAC1B,MAAMrJ,EAAQ+J,GAAkBV,GAC9Ba,EAAQpR,KAAKqR,IAAId,EAAE,GAAI,GAAKvQ,KAAKqR,IAAId,EAAE,GAAI,GAC3Ce,EAAStR,KAAKqB,KAAK+P,GACnBG,GAAUhB,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAE,IAAMe,EACvCE,EAAQxR,KAAKkR,MAAMX,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAKA,EAAE,GAAIa,GAChD,MAAO,CACLlK,MAAO+I,GAAiB/I,GACxBoK,SACAC,SACAC,MAAOvB,GAAiBuB,GACxBC,MAAO,EACPC,WAAYnB,EAAE,IAAM,EACpBoB,WAAYpB,EAAE,IAAM,IAkBXqB,GAAwB,SAACnK,GAAgB,MAAa,CACjE,EACA,EACA,EACA,EACAA,EALgD/L,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EAOpD,EAeM,SAASmW,KAGN,IAFR3K,MAAEA,EAAQ,GAAsBxL,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,GACnC+L,EAAEA,EAAI,EAACD,EAAEA,EAAI,GAAgB9L,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEhC,MAAMoW,EAAe/B,GAAiB7I,GACpC6K,EAAW9K,GAAI6K,GACfE,EAAW5K,GAAI0K,GACjB,MAAO,CACLC,EACAC,GACCA,EACDD,EACAtK,EAAIA,GAAKsK,EAAWtK,EAAIuK,EAAWxK,GAAK,EACxCA,EAAIA,GAAKwK,EAAWvK,EAAIsK,EAAWvK,GAAK,EAE5C,CAgBO,MAAMyK,GAAoB,SAACxK,GAAwB,MAAa,CACrEA,EACA,EACA,EAHoD/L,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG+L,EAKvD,EACA,EACD,EAEYyK,GAAehL,GAC1BlH,KAAKmS,IAAIpC,GAAiB7I,IAkBfkL,GAAqBC,GAA+B,CAC/D,EACA,EACAH,GAAYG,GACZ,EACA,EACA,GAgBWC,GAAqBD,GAA+B,CAC/D,EACAH,GAAYG,GACZ,EACA,EACA,EACA,GAkBWE,GAAuBtM,IAOZ,IAPaqL,OACnCA,EAAS,EAACC,OACVA,EAAS,EAACiB,MACVA,GAAQ,EAAKC,MACbA,GAAQ,EAAKjB,MACbA,EAAQ,EAAYC,MACpBA,EAAQ,GACSxL,EACbyM,EAAST,GACXO,GAASlB,EAASA,EAClBmB,GAASlB,EAASA,GAQpB,OANIC,IACFkB,EAASjC,GAA0BiC,EAAQN,GAAkBZ,IAAQ,IAEnEC,IACFiB,EAASjC,GAA0BiC,EAAQJ,GAAkBb,IAAQ,IAEhEiB,GAoBIC,GAAiBrV,IAC5B,MAAMoU,WAAEA,EAAa,EAACC,WAAEA,EAAa,EAACzK,MAAEA,EAAQ,GAAiB5J,EACjE,IAAIoV,EAASd,GAAsBF,EAAYC,GAC3CzK,IACFwL,EAASjC,GAA0BiC,EAAQb,GAAmB,CAAE3K,YAElE,MAAM0L,EAAcL,GAAqBjV,GAIzC,OAHK4S,GAAiB0C,KACpBF,EAASjC,GAA0BiC,EAAQE,IAEtCF,GCrSIG,GAAY,SACvBC,GAAW,IACXC,OAAEA,EAAMC,YAAEA,EAAc,MAAwBtX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAAE,OAErD,IAAIkU,QAA0B,SAAUC,EAASoD,GAC/C,GAAIF,GAAUA,EAAOG,QACnB,OAAOD,EAAO,IAAI1V,EAAmB,cAEvC,MAAM4V,EAAM/D,KACZ,IAAIpK,EACA+N,IACF/N,EAAQ,SAAUoO,GAChBD,EAAIE,IAAM,GACVJ,EAAOG,EACT,EACAL,EAAOO,iBAAiB,QAAStO,EAAO,CAAEe,MAAM,KAElD,MAAMwN,EAAO,WACXJ,EAAIK,OAASL,EAAIM,QAAU,KAC3BzO,IAAS+N,SAAAA,EAAQW,oBAAoB,QAAS1O,IAC9C6K,EAAQsD,EACV,EACKL,GAILK,EAAIK,OAASD,EACbJ,EAAIM,QAAU,WACZzO,IAAS+N,SAAAA,EAAQW,oBAAoB,QAAS1O,IAC9CiO,EAAO,IAAI9V,EAAY,iBAAiBgW,EAAIE,OAC9C,EACAL,IAAgBG,EAAIH,YAAcA,GAClCG,EAAIE,IAAMP,GATRS,GAUJ,EAAE,EA8BSI,GAAiB,SAQ5B1I,GAAc,IACd8H,OAAEA,EAAMa,QAAEA,EAAUpS,GAA4B9F,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAAE,OAErD,IAAIkU,QAAa,CAACC,EAASoD,KACzB,MAAMY,EAAiB,GACvBd,GAAUA,EAAOO,iBAAiB,QAASL,EAAQ,CAAElN,MAAM,IAC3D6J,QAAQkE,IACN7I,EAAQ8I,IAAKxH,GACXxI,GACGE,SAICsI,EAAInI,MACL4P,WAAWzH,EAAK,CAAEwG,WAClBkB,KAAMC,IACLN,EAAQrH,EAAK2H,GACbL,EAAU/N,KAAKoO,GACRA,MAIZD,KAAKpE,GACLsE,MAAOC,IAENP,EAAU1X,QAASkY,IAChBA,EAA0B1U,SACxB0U,EAA0B1U,YAE/BsT,EAAOmB,KAERE,QAAQ,KACPvB,GAAUA,EAAOW,oBAAoB,QAAST,MAElD,EASSsB,GAA0B,SAGrCC,GAAqB,IACrBzB,OAAEA,GAAmBrX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAAE,OAE1B,IAAIkU,QAAW,CAACC,EAASoD,KACvB,MAAMY,EAAiD,GACvDd,GAAUA,EAAOO,iBAAiB,QAASL,EAAQ,CAAElN,MAAM,IAE3D,MAAM0O,EAAW5Y,OAAO6Y,OAAOF,GAAkBT,IAAK1U,GAC/CA,GASDA,EAAM+E,MAAQL,GAAcrD,IAAIrB,EAAM+E,MACjCuP,GAAgD,CAACtU,GAAQ,CAC9D0T,WACCkB,KAAK3T,IAAe,IAAbqU,GAAQrU,EAEhB,OADAuT,EAAU/N,KAAK6O,GACRA,IAbFtV,GAkBL9C,EAAOV,OAAOU,KAAKiY,GACzB5E,QAAQkE,IAAIW,GACTR,KAAMU,GACEA,EAAQlY,OAAO,CAACC,EAAK2X,EAAU3P,KACpChI,EAAIH,EAAKmI,IAAU2P,EACZ3X,GACN,CAAA,IAEJuX,KAAKpE,GACLsE,MAAOC,IAENP,EAAU1X,QAASkY,IACjBA,EAAS1U,SAAW0U,EAAS1U,YAE/BsT,EAAOmB,KAERE,QAAQ,KACPvB,GAAUA,EAAOW,oBAAoB,QAAST,MAElD,ECzLS2B,GAAO,SAClBC,GAGA,OAFiBnZ,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,IAERe,OAAO,CAACsP,EAAGpP,KACjBA,KAAOkY,IACT9I,EAAEpP,GAAOkY,EAAOlY,IAEXoP,GACN,CAAA,EACL,EAEa+I,GAASA,CACpBD,EACAE,IAEQlZ,OAAOU,KAAKsY,GAAwBpY,OAAO,CAACsP,EAAGpP,KACjDoY,EAAUF,EAAOlY,GAAMA,EAAKkY,KAC9B9I,EAAEpP,GAAOkY,EAAOlY,IAEXoP,GACN,CAAA,GCrBQiJ,GAAUA,CAACC,EAAyBC,IAC/CC,WAAWC,OAAOH,GAAQD,QAAQE,ICEvBG,GAAejL,GAC1B,UACAA,EACG2J,IAAK1U,GAAU2V,GAAQ3V,EAAO9D,EAAO+Z,sBACrCC,KAAK,KACR,ICPWC,GACXC,KAESA,QAAyC7Z,IAA9B6Z,EAAmBC,OAG5BC,GACXF,KAESA,GAAkD,mBAAhCA,EAAmBG,SAGnCC,GAAaJ,KAEpBA,QAA0C7Z,IAA/B6Z,EAAmBK,SAAyB,WAAYL,EAsB5DM,GACXxL,KAEEA,GAAgB,2BAA4BA,ECzCzC,SAASyL,GAAiB9G,GAC/B,MAAM+G,EAAM/G,GAAWgH,GAAuBhH,GAC9C,IAAI3B,EAAO,EACTC,EAAM,EACR,IAAK0B,IAAY+G,EACf,MAAO,CAAE1I,OAAMC,OAEjB,IAAI2I,EAAmDjH,EACvD,MAAMkH,EAAaH,EAAII,gBACrBC,EAAOL,EAAIK,MAAQ,CACjBC,WAAY,EACZC,UAAW,GAMf,KACEL,IACCA,EAAYM,YAAeN,EAAsCO,QAElEP,EAAeA,EAAYM,YACxBN,EAAsCO,KAIrCP,IAAgBF,GAClB1I,EAAO+I,EAAKC,YAAcH,EAAWG,YAAc,EACnD/I,EAAM8I,EAAKE,WAAaJ,EAAWI,WAAa,IAEhDjJ,GAAS4I,EAA4BI,YAAc,EACnD/I,GAAQ2I,EAA4BK,WAAa,GAIxB,IAAzBL,EAAYQ,UACoC,UAA/CR,EAA4BS,MAAMC,YAMvC,MAAO,CAAEtJ,OAAMC,MACjB,CAEO,MAAM0I,GAA0BY,GACrCA,EAAGC,eAAiB,KAETC,GAAwBF,IAAe,IAAAG,EAAA,OAClC,QAAhBA,EAAAH,EAAGC,qBAAa,IAAAE,OAAA,EAAhBA,EAAkBC,cAAe,MC9CtBC,GAAsB,SACjCL,EACAM,EAA6B9W,GAG1B,IAFHmN,MAAEA,EAAKC,OAAEA,GAAepN,EACxB+W,EAAa3b,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EAEhBob,EAAGrJ,MAAQA,EACXqJ,EAAGpJ,OAASA,EACR2J,EAAgB,IAClBP,EAAGQ,aAAa,SAAU7J,EAAQ4J,GAAe/N,YACjDwN,EAAGQ,aAAa,UAAW5J,EAAS2J,GAAe/N,YACnD8N,EAAIG,MAAMF,EAAeA,GAE7B,EAOaG,GAAmBA,CAC9BV,EAAe7Q,KAEZ,IADHwH,MAAEA,EAAKC,OAAEA,GAAgCzH,EAEzCwH,IAAUqJ,EAAGF,MAAMnJ,MAAyB,iBAAVA,EAAqB,GAAGA,MAAYA,GACtEC,IACGoJ,EAAGF,MAAMlJ,OAA2B,iBAAXA,EAAsB,GAAGA,MAAaA,IA4C7D,SAAS+J,GAAwBvI,GAKtC,YAJqC,IAA1BA,EAAQwI,gBACjBxI,EAAQwI,cAAgB,KAAM,GAEhCxI,EAAQ0H,MAAMe,WAAapV,EACpB2M,CACT,CCvEO,MAAM0I,GAUX1c,WAAAA,CAAYsK,GATZrK,EAAAC,KAAA,4BAAA,GAAAD,EAAAC,KAAA,aAAA,GAUE,MAAM0b,EAAK1b,KAAKyc,kBAAkBrS,GAClCpK,KAAK0c,MAAQ,CAAEhB,KAAIM,IAAKN,EAAGtY,WAAW,MACxC,CAEUqZ,iBAAAA,CAAkBrS,GAE1B,MAAMsR,GVkCRvY,EUlC0BiH,SVoCsC5J,IAA5C2C,EAA6BC,WUnC3CgH,EACCA,GACE5F,IAAoBmY,eAAevS,IACtCyJ,KV8BN1Q,MU7BE,GAAIuY,EAAGkB,aAAa,eAClB,MAAM,IAAI7a,EACR,0GAMJ,OAHA/B,KAAK6c,qBAAuBnB,EAAGF,MAAMsB,QACrCpB,EAAGQ,aAAa,cAAe,QAC/BR,EAAGqB,UAAUzQ,IAAI,gBACVoP,CACT,CAEAsB,UAAAA,CAAU9X,GAA2B,IAA1BmN,MAAEA,EAAKC,OAAEA,GAAepN,EACjC,MAAMwW,GAAEA,GAAO1b,KAAK0c,MAEpBhB,EAAGqB,UAAU1T,OAAO,gBACpBqS,EAAGuB,gBAAgB,eAEnBvB,EAAGQ,aAAa,QAAS,GAAG7J,KAC5BqJ,EAAGQ,aAAa,SAAU,GAAG5J,KAC7BoJ,EAAGF,MAAMsB,QAAU9c,KAAK6c,sBAAwB,GAChD7c,KAAK6c,0BAAuBrc,CAC9B,CAEA0c,aAAAA,CAAcpN,EAAamM,GACzB,MAAMP,GAAEA,EAAEM,IAAEA,GAAQhc,KAAK0c,MACzBX,GAAoBL,EAAIM,EAAKlM,EAAMmM,EACrC,CAEAG,gBAAAA,CAAiBtM,GACfsM,GAAiBpc,KAAK0c,MAAMhB,GAAI5L,EAClC,CAKAqN,UAAAA,GACE,OD7BG,SAA0BrJ,GAAsB,IAAAsJ,EACrD,MAAMvC,EAAM/G,GAAWgH,GAAuBhH,GAC5CuJ,EAAS,CAAElL,KAAM,EAAGC,IAAK,GAE3B,IAAKyI,EACH,OAAOwC,EAET,MAAMC,GACyB,QAA7BF,EAAAxB,GAAqB9H,cAAQsJ,SAA7BA,EAA+BG,iBAAiBzJ,EAAS,QACxD,CAAA,EACHuJ,EAAOlL,MAAQqL,SAASF,EAAUG,gBAAiB,KAAO,EAC1DJ,EAAOjL,KAAOoL,SAASF,EAAUI,eAAgB,KAAO,EACxDL,EAAOlL,MAAQqL,SAASF,EAAUK,YAAa,KAAO,EACtDN,EAAOjL,KAAOoL,SAASF,EAAUM,WAAY,KAAO,EAEpD,IAAIC,EAAM,CAAE1L,KAAM,EAAGC,IAAK,GAE1B,MAAM0L,EAAUjD,EAAII,qBACyB,IAAlCnH,EAAQiK,wBACjBF,EAAM/J,EAAQiK,yBAGhB,MAAMC,EAAgBpD,GAAiB9G,GAEvC,MAAO,CACL3B,KACE0L,EAAI1L,KAAO6L,EAAc7L,MAAQ2L,EAAQG,YAAc,GAAKZ,EAAOlL,KACrEC,IAAKyL,EAAIzL,IAAM4L,EAAc5L,KAAO0L,EAAQI,WAAa,GAAKb,EAAOjL,IAEzE,CCAW+L,CAAiBne,KAAK0c,MAAMhB,GACrC,CAEAnX,OAAAA,GACEL,IAASK,QAAQvE,KAAK0c,MAAMhB,WAErB1b,KAAK0c,KACd,ECoFK,MAAM0B,GAAsD,CACjEC,eAAe,EACfC,gBAAiB,GACjBC,YAAY,EACZC,aAAc,GAEdC,sBAAsB,EACtBC,2BAA2B,EAE3BC,mBAAmB,EACnBC,eAAe,EACfC,qBAAqB,EACrBC,uBAAuB,EAKvBC,sBAAsB,EAItBC,qBAAqB,EAErBC,kBAAmB,IAAIvY,GACvBwY,eAAgB,QCnGX,MAAMC,WAIH7P,GAAsByD,KA+C9B,iBAAIqM,GAAgB,IAAAC,EAClB,OAA0B,QAA1BA,EAAOrf,KAAKsf,SAAS5C,aAAK,IAAA2C,OAAA,EAAnBA,EAAqB3D,EAC9B,CAEA,oBAAI6D,GAAmB,IAAAC,EACrB,OAA0B,QAA1BA,EAAOxf,KAAKsf,SAAS5C,aAAK,IAAA8C,OAAA,EAAnBA,EAAqBxD,GAC9B,CA6CA,kBAAOyD,GACL,OAAON,GAAaO,WACtB,CAEA5f,WAAAA,CACE4b,GAEA,IADAxZ,EAAsC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEzCF,QACAK,OAAOC,OACLV,KACCA,KAAKF,YAAoC2f,eAE5Czf,KAAKuF,IAAIrD,GACTlC,KAAK2f,aAAajE,GAClB1b,KAAK4f,mBAAmB,CACtBvN,MAAOrS,KAAKqS,OAASrS,KAAKsf,SAAS5C,MAAMhB,GAAGrJ,OAAS,EACrDC,OAAQtS,KAAKsS,QAAUtS,KAAKsf,SAAS5C,MAAMhB,GAAGpJ,QAAU,IAE1DtS,KAAK6f,qBAAsB,EAC3B7f,KAAKif,kBAAoB,IAAIjf,KAAKif,mBAClCjf,KAAK8f,wBACP,CAEUH,YAAAA,CAAajE,GACrB1b,KAAKsf,SAAW,IAAI9C,GAAuBd,EAC7C,CAEApP,GAAAA,GACE,MAAMwD,EAAO1P,MAAMkM,OAAIhM,WAEvB,OADAA,UAAQC,OAAS,GAAKP,KAAK2e,mBAAqB3e,KAAK+f,mBAC9CjQ,CACT,CAEAC,QAAAA,CAASzG,GAA2C,IAAA,IAAA5H,EAAApB,UAAAC,OAAzBsP,MAAOjO,MAAAF,EAAA,EAAAA,OAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAPgO,EAAOhO,EAAA,GAAAvB,UAAAuB,GAChC,MAAMiO,EAAO1P,MAAM2P,SAASzG,KAAUuG,GAEtC,OADAA,EAAQtP,OAAS,GAAKP,KAAK2e,mBAAqB3e,KAAK+f,mBAC9CjQ,CACT,CAEAzG,MAAAA,GACE,MAAM6G,EAAU9P,MAAMiJ,UAAO/I,WAE7B,OADA4P,EAAQ3P,OAAS,GAAKP,KAAK2e,mBAAqB3e,KAAK+f,mBAC9C7P,CACT,CAEAT,cAAAA,CAAe0B,GACTA,EAAIhO,QAAWgO,EAAIhO,SAA4BnD,OACjDwB,EACE,OACA,uKAGF2P,EAAIhO,OAAOkG,OAAO8H,IAEpBA,EAAIgC,KAAK,SAAUnT,MACnBmR,EAAI6O,YACJhgB,KAAKqL,KAAK,eAAgB,CAAErB,OAAQmH,IACpCA,EAAI9F,KAAK,QAAS,CAAErB,OAAQhK,MAC9B,CAEA2P,gBAAAA,CAAiBwB,GACfA,EAAIgC,KAAK,cAAU3S,GACnBR,KAAKqL,KAAK,iBAAkB,CAAErB,OAAQmH,IACtCA,EAAI9F,KAAK,UAAW,CAAErB,OAAQhK,MAChC,CAEA4P,oBAAAA,GACE5P,KAAK2e,mBAAqB3e,KAAK+f,kBACjC,CAOAE,gBAAAA,GACE,OAAOjgB,KAAK6e,oBAAsBna,IAAwB,CAC5D,CAMAyY,UAAAA,GACE,OAAQnd,KAAKkgB,QAAUlgB,KAAKsf,SAASnC,YACvC,CAMAgD,QAAAA,GACE,OAAOngB,KAAKqS,KACd,CAMA+N,SAAAA,GACE,OAAOpgB,KAAKsS,MACd,CAMUsN,kBAAAA,CACRS,GAEA,IADAC,QAAEA,GAAU,EAAKC,cAAEA,GAAgB,GAA2BjgB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEjE,IAAKggB,EAAS,CACZ,MAAMxQ,EAAO,CACXuC,MAAOrS,KAAKqS,MACZC,OAAQtS,KAAKsS,UACT+N,GAENrgB,KAAKsf,SAASpC,cAAcpN,EAAM9P,KAAKigB,oBACvCjgB,KAAKwgB,gBAAiB,EACtBxgB,KAAKqS,MAAQvC,EAAKuC,MAClBrS,KAAKsS,OAASxC,EAAKwC,MACrB,CACKiO,GACHvgB,KAAKsf,SAASlD,iBAAiBiE,GAGjCrgB,KAAKmd,YACP,CAoBAD,aAAAA,CACEmD,EACAne,GAEAlC,KAAK4f,mBAAmBS,EAAYne,GAC/BA,GAAYA,EAAQoe,SACvBtgB,KAAK+f,kBAET,CAMAU,OAAAA,GACE,OAAOzgB,KAAKif,kBAAkB,EAChC,CAMAyB,oBAAAA,CAAqBC,GACnB3gB,KAAKif,kBAAoB0B,EACzB3gB,KAAK8f,yBACL9f,KAAK2e,mBAAqB3e,KAAK+f,kBACjC,CAUAa,WAAAA,CAAYC,EAAc5c,GAExB,MAAM6c,EAASD,EACbF,EAAc,IAAI3gB,KAAKif,mBACnB8B,EAAW9L,GAAe4L,EAAO3L,GAAgByL,IACvDA,EAAI,GAAK1c,EACT0c,EAAI,GAAK1c,EACT,MAAM+c,EAAQ/L,GAAe8L,EAAUJ,GACvCA,EAAI,IAAMG,EAAOzU,EAAI2U,EAAM3U,EAC3BsU,EAAI,IAAMG,EAAO1U,EAAI4U,EAAM5U,EAC3BpM,KAAK0gB,qBAAqBC,EAC5B,CAMAM,OAAAA,CAAQhd,GACNjE,KAAK4gB,YAAY,IAAIzU,GAAM,EAAG,GAAIlI,EACpC,CAMAid,WAAAA,CAAYL,GACV,MAAMF,EAAc,IAAI3gB,KAAKif,mBAG7B,OAFA0B,EAAI,IAAME,EAAMxU,EAChBsU,EAAI,IAAME,EAAMzU,EACTpM,KAAK0gB,qBAAqBC,EACnC,CAMAQ,WAAAA,CAAYN,GACV,OAAO7gB,KAAKkhB,YACV,IAAI/U,IACD0U,EAAMxU,EAAIrM,KAAKif,kBAAkB,IACjC4B,EAAMzU,EAAIpM,KAAKif,kBAAkB,IAGxC,CAMAmC,UAAAA,GACE,OAAOphB,KAAKsf,SAAS5C,MAAMhB,EAC7B,CAMA2F,YAAAA,CAAarF,GACXA,EAAIsF,UAAU,EAAG,EAAGthB,KAAKqS,MAAOrS,KAAKsS,OACvC,CAMAlP,UAAAA,GACE,OAAOpD,KAAKsf,SAAS5C,MAAMV,GAC7B,CAKAuF,KAAAA,GACEvhB,KAAKqJ,UAAUrJ,KAAKuQ,cACpBvQ,KAAKwhB,qBAAkBhhB,EACvBR,KAAKyhB,kBAAejhB,EACpBR,KAAKse,gBAAkB,GACvBte,KAAKwe,aAAe,GACpBxe,KAAKqhB,aAAarhB,KAAKoD,cACvBpD,KAAKqL,KAAK,kBACVrL,KAAK2e,mBAAqB3e,KAAK+f,kBACjC,CAKA2B,SAAAA,GACE1hB,KAAK2hB,wBACD3hB,KAAK4hB,WAGT5hB,KAAK6hB,aAAa7hB,KAAKoD,aAAcpD,KAAKqP,SAC5C,CAUAyS,cAAAA,GACE9hB,KAAK+hB,iBAAmB,EACxB/hB,KAAK0hB,WACP,CAOA3B,gBAAAA,GACO/f,KAAK+hB,kBAAqB/hB,KAAKgiB,UAAahiB,KAAK4hB,YACpD5hB,KAAK+hB,iBAAmBzO,GAAiB,IAAMtT,KAAK8hB,kBAExD,CAMAhC,sBAAAA,GACE,MAAMzN,EAAQrS,KAAKqS,MACjBC,EAAStS,KAAKsS,OACd2P,EAAO/M,GAAgBlV,KAAKif,mBAC5B9J,EAAIF,GAAe,CAAE5I,EAAG,EAAGD,EAAG,GAAK6V,GACnC3M,EAAIL,GAAe,CAAE5I,EAAGgG,EAAOjG,EAAGkG,GAAU2P,GAG5CpU,EAAMsH,EAAEtH,IAAIyH,GACZzQ,EAAMsQ,EAAEtQ,IAAIyQ,GACd,OAAQtV,KAAKkiB,UAAY,CACvB1P,GAAI3E,EACJsU,GAAI,IAAIhW,GAAMtH,EAAIwH,EAAGwB,EAAIzB,GACzBgW,GAAI,IAAIjW,GAAM0B,EAAIxB,EAAGxH,EAAIuH,GACzBqG,GAAI5N,EAER,CAEA8c,qBAAAA,GACM3hB,KAAK+hB,mBACPvO,GAAgBxT,KAAK+hB,kBACrB/hB,KAAK+hB,iBAAmB,EAE5B,CAEAM,YAAAA,CAAaC,GACX,CAQFT,YAAAA,CAAa7F,EAA+BnM,GAC1C,GAAI7P,KAAK4hB,UACP,OAGF,MAAMW,EAAIviB,KAAKif,kBACbuD,EAAOxiB,KAAKyiB,SACdziB,KAAK8f,yBACL9f,KAAKqhB,aAAarF,GAClBA,EAAI8C,sBAAwB9e,KAAK8e,sBAEjC9C,EAAIkD,eAAiBlf,KAAKkf,eAC1Blf,KAAKqL,KAAK,gBAAiB,CAAE2Q,QAC7Bhc,KAAK0iB,kBAAkB1G,GAEvBA,EAAI2G,OAEJ3G,EAAIhN,UAAUuT,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAC9CviB,KAAK4iB,eAAe5G,EAAKnM,GACzBmM,EAAI6G,UACC7iB,KAAK+e,sBAAyB/e,KAAK6f,qBACtC7f,KAAKqiB,aAAarG,GAEhBwG,IACFA,EAAKrP,KAAK,SAAUnT,MAGpBwiB,EAAKM,cACLN,EAAKO,gBAAiB,EACrBP,EAA6BQ,YAAY,CAAEC,aAAa,IACzDjjB,KAAKkjB,qBAAqBlH,EAAKwG,IAEjCxiB,KAAKmjB,eAAenH,GAChBhc,KAAK+e,uBAAyB/e,KAAK6f,qBACrC7f,KAAKqiB,aAAarG,GAEpBhc,KAAKqL,KAAK,eAAgB,CAAE2Q,QAExBhc,KAAKojB,gBACPpjB,KAAKojB,gBACLpjB,KAAKojB,mBAAgB5iB,EAEzB,CAMA0iB,oBAAAA,CACElH,EACAyG,GAEA,MAAMF,EAAIviB,KAAKif,kBACfjD,EAAI2G,OACJ3G,EAAIhN,aAAauT,GAGjBvG,EAAIqH,yBAA2B,iBAC/BZ,EAASzT,UAAUgN,GACnBA,EAAIG,MAAM,EAAIsG,EAASa,MAAO,EAAIb,EAASc,OAC3CvH,EAAIwH,UACFf,EAASgB,cACRhB,EAASiB,mBACTjB,EAASkB,mBAEZ3H,EAAI6G,SACN,CAOAD,cAAAA,CAAe5G,EAA+BnM,GAC5C,IAAK,IAAIpE,EAAI,EAAGmY,EAAM/T,EAAQtP,OAAQkL,EAAImY,IAAOnY,EAC/CoE,EAAQpE,IAAMoE,EAAQpE,GAAGoY,OAAO7H,EAEpC,CAOA8H,0BAAAA,CACE9H,EACA3I,GAEA,MAAM0Q,EAAO/jB,KAAK,GAAGqT,UACnB3D,EAAS1P,KAAK,GAAGqT,UACjBkP,EAAIviB,KAAKif,kBACT+E,EAAWhkB,KAAK,GAAGqT,QACrB,IAAK0Q,IAASrU,EACZ,OAEF,MAAMuU,EAAY7J,GAAS2J,GAC3B,GAAIA,EAAM,CAYR,GAXA/H,EAAI2G,OACJ3G,EAAIkI,YACJlI,EAAImI,OAAO,EAAG,GACdnI,EAAIoI,OAAOpkB,KAAKqS,MAAO,GACvB2J,EAAIoI,OAAOpkB,KAAKqS,MAAOrS,KAAKsS,QAC5B0J,EAAIoI,OAAO,EAAGpkB,KAAKsS,QACnB0J,EAAIqI,YACJrI,EAAIsI,UAAYL,EAAYF,EAAKzJ,OAAO0B,GAAmB+H,EACvDC,GACFhI,EAAIhN,aAAauT,GAEf0B,EAAW,CACbjI,EAAIhN,UAAU,EAAG,EAAG,EAAG,EAAG+U,EAAKrJ,SAAW,EAAGqJ,EAAKQ,SAAW,GAC7D,MAAMC,EAAMT,EAA4BU,mBACrCV,EAAiBW,iBACpBF,GAAKxI,EAAIhN,aAAawV,EACxB,CACAxI,EAAI+H,OACJ/H,EAAI6G,SACN,CACA,GAAInT,EAAQ,CACVsM,EAAI2G,OACJ,MAAM/D,cAAEA,GAAkB5e,KAG1BA,KAAK4e,cAAgBoF,EACjBA,GACFhI,EAAIhN,aAAauT,GAEnB7S,EAAOmU,OAAO7H,GACdhc,KAAK4e,cAAgBA,EACrB5C,EAAI6G,SACN,CACF,CAMAH,iBAAAA,CAAkB1G,GAChBhc,KAAK8jB,2BAA2B9H,EAAK,aACvC,CAMAmH,cAAAA,CAAenH,GACbhc,KAAK8jB,2BAA2B9H,EAAK,UACvC,CAMA2I,cAAAA,GACE,OAAO,IAAIxY,GAAMnM,KAAKqS,MAAQ,EAAGrS,KAAKsS,OAAS,EACjD,CAKAsS,aAAAA,CAAclV,GACZ,OAAO1P,KAAK6kB,cACVnV,EACA,IAAIvD,GAAMnM,KAAK2kB,iBAAiBtY,EAAGqD,EAAOiV,iBAAiBvY,GAE/D,CAMA0Y,aAAAA,CAAcpV,GACZ,OAAO1P,KAAK6kB,cACVnV,EACA,IAAIvD,GAAMuD,EAAOiV,iBAAiBtY,EAAGrM,KAAK2kB,iBAAiBvY,GAE/D,CAMA2Y,YAAAA,CAAarV,GACX,OAAO1P,KAAK6kB,cAAcnV,EAAQ1P,KAAK2kB,iBACzC,CAMAK,oBAAAA,CAAqBtV,GACnB,OAAO1P,KAAK6kB,cAAcnV,EAAQ1P,KAAKilB,cACzC,CAMAC,qBAAAA,CAAsBxV,GACpB,OAAO1P,KAAK6kB,cACVnV,EACA,IAAIvD,GAAMnM,KAAKilB,cAAc5Y,EAAGqD,EAAOiV,iBAAiBvY,GAE5D,CAMA+Y,qBAAAA,CAAsBzV,GACpB,OAAO1P,KAAK6kB,cACVnV,EACA,IAAIvD,GAAMuD,EAAOiV,iBAAiBtY,EAAGrM,KAAKilB,cAAc7Y,GAE5D,CAMA6Y,WAAAA,GACE,OAAOhQ,GACLjV,KAAK2kB,iBACLzP,GAAgBlV,KAAKif,mBAEzB,CAOA4F,aAAAA,CAAcnV,EAAsB0V,GAClC1V,EAAOvB,MAAMiX,EAAQte,EAAQA,GAC7B4I,EAAOsQ,YACPhgB,KAAK2e,mBAAqB3e,KAAK+f,kBACjC,CAOAsF,cAAAA,CAAeC,GACb,OAAOtlB,KAAKulB,iBAAiBD,EAC/B,CAOA9K,QAAAA,CAAS8K,GACP,OAAOtlB,KAAKwlB,gBAAgB,WAAYF,EAC1C,CAgBAG,MAAAA,GACE,OAAOzlB,KAAKwa,UACd,CAOA+K,gBAAAA,CAAiBD,GACf,OAAOtlB,KAAKwlB,gBAAgB,mBAAoBF,EAClD,CAKAE,eAAAA,CACEE,EACAJ,GAEA,MAAM7C,EAAWziB,KAAKyiB,SAChBkD,EACJlD,IAAaA,EAASmD,kBAClB5lB,KAAK6lB,UAAUpD,EAAUiD,EAAYJ,GACrC,KACN,MAAO,CACLQ,QAAS3f,KACNqT,GAAKxZ,KAAMslB,GACdzV,QAAS7P,KAAKqP,SACXvF,OAAQ4F,IAAYA,EAAOkW,mBAC3BjN,IAAKM,GACJjZ,KAAK6lB,UAAU5M,EAAUyM,EAAYJ,OAEtCtlB,KAAK+lB,qBAAqBL,EAAYJ,MACrCK,EAAe,CAAElD,SAAUkD,GAAiB,KAEpD,CAKUE,SAAAA,CACR5M,EACAyM,EACAJ,GAEA,IAAIU,EAEChmB,KAAKye,uBACRuH,EAAgB/M,EAASwF,qBACzBxF,EAASwF,sBAAuB,GAGlC,MAAM/O,EAASuJ,EAASyM,GAAYJ,GAIpC,OAHKtlB,KAAKye,uBACRxF,EAASwF,uBAAyBuH,GAE7BtW,CACT,CAKAqW,oBAAAA,CACEL,EACAJ,GAEA,MAAMW,EAAY,CAAA,EAChBC,EAAUlmB,KAAKwhB,gBACfC,EAAezhB,KAAKyhB,aACpB0E,EAAUnmB,KAAKse,gBACfE,EAAexe,KAAKwe,aAiCtB,OA/BIpE,GAAS+L,GACNA,EAAQP,oBACXK,EAAKG,WAAaD,EAAQ3L,SAAS8K,IAE5Ba,IACTF,EAAKG,WAAaD,GAGhB/L,GAASoE,GACNA,EAAaoH,oBAChBK,EAAKI,QAAU7H,EAAahE,SAAS8K,IAE9B9G,IACTyH,EAAKI,QAAU7H,GAGb0H,IAAYA,EAAQN,oBACtBK,EAAKzE,gBAAkBxhB,KAAK6lB,UAC1BK,EACAR,EACAJ,IAGA7D,IAAiBA,EAAamE,oBAChCK,EAAKxE,aAAezhB,KAAK6lB,UACvBpE,EACAiE,EACAJ,IAIGW,CACT,CA0CAK,KAAAA,GAA8D,IAAxDpkB,EAA0B5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAAIkY,EAAqBlY,UAAAC,OAAA,EAAAD,kBAAAE,EAC1D0B,EAAQsW,QAAUA,EAClB,MAAM+N,EAAmB,GAkBzB,OAhBAvmB,KAAKwmB,gBAAgBD,EAAQrkB,GAC7BlC,KAAKymB,cAAcF,EAAQrkB,GACvBlC,KAAKyiB,UACP8D,EAAO7b,KAAK,sBAAsB1K,KAAKyiB,SAASiE,oBAElD1mB,KAAK2mB,sBAAsBJ,EAAQ,cACnCvmB,KAAK4mB,sBAAsBL,EAAQ,kBAAmB/N,GACtDxY,KAAK6mB,eAAeN,EAAQ/N,GACxBxY,KAAKyiB,UACP8D,EAAO7b,KAAK,UAEd1K,KAAK2mB,sBAAsBJ,EAAQ,WACnCvmB,KAAK4mB,sBAAsBL,EAAQ,eAAgB/N,GAEnD+N,EAAO7b,KAAK,UAEL6b,EAAOpM,KAAK,GACrB,CAKAqM,eAAAA,CAAgBD,EAAkBrkB,GAC5BA,EAAQ4kB,kBAGZP,EAAO7b,KACL,iCACAxI,EAAQ6kB,UAAY,QACpB,yBACA,kDACA,wDAEJ,CAKAN,aAAAA,CAAcF,EAAkBrkB,GAC9B,MAAMmQ,EAAQnQ,EAAQmQ,OAAS,GAAGrS,KAAKqS,QACrCC,EAASpQ,EAAQoQ,QAAU,GAAGtS,KAAKsS,SACnC4H,EAAsB/Z,EAAO+Z,oBAC7B8M,EAAa9kB,EAAQ+kB,QACvB,IAAIA,EACJ,GAAID,EACFC,EAAU,YAAYD,EAAW3a,KAAK2a,EAAW5a,KAAK4a,EAAW3U,SAAS2U,EAAW1U,gBAChF,GAAItS,KAAK0e,0BAA2B,CACzC,MAAMiC,EAAM3gB,KAAKif,kBACjBgI,EAAU,YAAYrN,IACnB+G,EAAI,GAAKA,EAAI,GACdzG,MACGN,IAAS+G,EAAI,GAAKA,EAAI,GAAIzG,MAAwBN,GACrD5Z,KAAKqS,MAAQsO,EAAI,GACjBzG,MACGN,GAAQ5Z,KAAKsS,OAASqO,EAAI,GAAIzG,MACrC,MACE+M,EAAU,gBAAgBjnB,KAAKqS,SAASrS,KAAKsS,WAG/CiU,EAAO7b,KACL,QACA,sCACA,8CACA,iBACA,UACA2H,EACA,KACA,WACAC,EACA,KACA2U,EACA,0BACA,gCACA9gB,EACA,YACA,WACAnG,KAAKknB,2BACLlnB,KAAKmnB,6BACLnnB,KAAKonB,wBAAwBllB,GAC7B,YAEJ,CAEAklB,uBAAAA,CAAwBllB,GACtB,MAAMugB,EAAWziB,KAAKyiB,SACtB,OAAIA,GACFA,EAASiE,WAAa,YAAY9S,OAC3B,iBAAiB6O,EAASiE,kBAAkBjE,EAAS4E,cAC1DnlB,EAAQsW,yBAGL,EACT,CAMA2O,0BAAAA,GACE,MAAQ,CAAC,aAAc,WACpBxO,IAAK1F,IACJ,MAAM8Q,EAAO/jB,KAAK,GAAGiT,UACrB,GAAImH,GAAS2J,GAAO,CAClB,MAAMuD,EAAkBtnB,KAAK,GAAGiT,QAC9B0N,EAAM3gB,KAAKif,kBACXvP,EAAS,CAEPkB,OAAQA,KAAM,EACdyB,MAAOrS,KAAKqS,OAASiV,EAAkB3G,EAAI,GAAK,GAChDrO,OAAQtS,KAAKsS,QAAUgV,EAAkB3G,EAAI,GAAK,IAEtD,OAAOoD,EAAKuC,MAAM5W,EAAwB,CACxC6X,oBAAqBD,EAAkBrN,GAAY0G,GAAO,IAE9D,IAEDxG,KAAK,GACV,CASA+M,wBAAAA,GACE,MAAMrX,EAA0B,GAC9B2X,EAAoC,CAAA,EACpC3mB,EAAYV,EAAOU,UAErBb,KAAKqP,SAAStO,QAAQ,SAASuL,EAAIoD,GACjCG,EAAQnF,KAAKgF,GACTR,GAAaQ,IACfA,EAAOL,SAAStO,QAAQuL,EAE5B,GAEAuD,EAAQ9O,QAASoQ,IACf,KLtiCJhC,EKsiCsBgC,ILliCgC,mBAA5ChC,EAA4BsY,YKmiChC,OLviCNtY,MKyiCI,MAAMuY,OAAEA,EAAM1mB,WAAEA,GAAemQ,GAC3BqW,EAASxmB,IAAgBH,EAAUG,KAGvCwmB,EAASxmB,IAAc,EAClB0mB,GAGLjnB,OAAO6Y,OAAOoO,GAAQ3mB,QAAS4mB,IAC7BlnB,OAAO6Y,OAAOqO,GAAU5mB,QAAQmE,IAAyB,IAAxBlE,WAAEA,EAAa,IAAIkE,GAC7CsiB,EAASxmB,IAAeH,EAAUG,KACrCwmB,EAASxmB,IAAc,UAM/B,MAAM4mB,EAAiBnnB,OAAOU,KAAKqmB,GAChC7O,IACE3X,GACC,yCAAyCA,wBAAiCH,EAAUG,kBAEvFmZ,KAAK,IAER,OAAIyN,EACK,uCAAuCA,iBAEzC,EACT,CAKAf,cAAAA,CAAeN,EAAkB/N,GAC/BxY,KAAKqQ,cAAelB,IACdA,EAAayW,mBAGjB5lB,KAAK6nB,cAActB,EAAQpX,EAAcqJ,IAE7C,CAMAqP,aAAAA,CACEtB,EACAtN,EACAT,GAEA+N,EAAO7b,KAAKuO,EAASqN,MAAM9N,GAC7B,CAKAoO,qBAAAA,CACEL,EACAlT,EACAmF,GAEA,MAAMsP,EAAc9nB,KAAKqT,GACrByU,IAAgBA,EAAYlC,mBAAqBkC,EAAYxB,OAC/DC,EAAO7b,KAAKod,EAAYxB,MAAM9N,GAElC,CAMAmO,qBAAAA,CAAsBJ,EAAkBlT,GACtC,MAAMgH,EAASra,KAAK,GAAGqT,UACvB,GAAKgH,EAGL,GAAID,GAASC,GAAS,CACpB,MAAM0N,EAAU1N,EAAmB0N,QAAU,GAC3CC,EAAahoB,KAAKqS,MAClB4V,EAAcjoB,KAAKsS,OAEnBiV,EADevnB,KAAK,GAAGqT,QAEnB4G,GAAY/E,GAAgBlV,KAAKif,oBACjC,GACNsH,EAAO7b,KACL,oBAAoB6c,eAAiCS,EAAa,KAChEC,EAAc,UACP5N,EAAOK,QAAUsN,EAAa,SACrC3N,EAAOkK,QAAU0D,EAAc,aAEnB,aAAXF,GAAoC,cAAXA,IAA2BtN,GAAUJ,GAE3D2N,EADC3N,EAAOZ,OAA4BpH,kBAG5B,aAAX0V,GAAoC,cAAXA,IAA2BtN,GAAUJ,GAE3D4N,EADC5N,EAAOZ,OAA4BnH,4BAEpB+H,EAAO1G,iBAEjC,MACE4S,EAAO7b,KACL,gDACA,SACA2P,EACA,IACA,aAGN,CA4BA6N,YAAAA,CACEC,EACA3P,GAEe,IADfb,OAAEA,GAAmBrX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAExB,IAAK6nB,EACH,OAAO3T,QAAQqD,OAAO,IAAI9V,EAAY,wBAIxC,MAAM8N,QAAEA,EAAU,MAAOuY,GACP,iBAATD,EAAoB1f,KAAK4f,MAAMF,GAAQA,GAC1C3G,gBAAEA,EAAe4E,WAAEA,EAAU3E,aAAEA,EAAY4E,QAAEA,EAAO5D,SAAEA,GAC1D2F,EACIzJ,EAAoB3e,KAAK2e,kBAG/B,OAFA3e,KAAK2e,mBAAoB,EAElBnK,QAAQkE,IAAI,CACjBH,GAA6B1I,EAAS,CACpC2I,UACAb,WAEFwB,GACE,CACEqI,kBACAlD,gBAAiB8H,EACjB3E,eACAjD,aAAc6H,EACd5D,YAEF,CAAE9K,aAEHkB,KAAKhO,IAA2B,IAAzB0O,EAAS+O,GAAWzd,EAM5B,OALA7K,KAAKuhB,QACLvhB,KAAKsM,OAAOiN,GACZvZ,KAAKuF,IAAI6iB,GACTpoB,KAAKuF,IAAI+iB,GACTtoB,KAAK2e,kBAAoBA,EAClB3e,MAEX,CAMAwO,KAAAA,CAAM+Z,GACJ,MAAMtC,EAAOjmB,KAAKwa,SAAS+N,GAE3B,OADevoB,KAAKwoB,mBACNN,aAAajC,EAC7B,CAMAuC,gBAAAA,GACE,MAAM9M,EAAKzH,GAAuBjU,MAClC,OAAO,IAAKA,KAAKF,YAAkC4b,EACrD,CAwCAvH,SAAAA,GAAmD,IAAzCjS,EAAO5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAClB,MAAM+T,OACJA,EAAS,MAAKC,QACdA,EAAU,EAACmU,WACXA,EAAa,EAAC5J,oBACdA,GAAsB,GACpB3c,EACEwmB,EACJD,GAAc5J,EAAsB7e,KAAKigB,mBAAqB,GAEhE,OAAO9L,GACLnU,KAAK2oB,gBAAgBD,EAAiBxmB,GACtCmS,EACAC,EAEJ,CACAC,MAAAA,GAA8D,IAAvDrS,EAAO5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACf,MAAM+T,OACJA,EAAS,MAAKC,QACdA,EAAU,EAACmU,WACXA,EAAa,EAAC5J,oBACdA,GAAsB,GACpB3c,EACEwmB,EACJD,GAAc5J,EAAsB7e,KAAKigB,mBAAqB,GAEhE,OAAO1L,GACLvU,KAAK2oB,gBAAgBD,EAAiBxmB,GACtCmS,EACAC,EAEJ,CAgBAqU,eAAAA,GAGqB,IAFnBF,EAAUnoB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GACb+R,MAAEA,EAAKC,OAAEA,EAAMH,KAAEA,EAAIC,IAAEA,EAAGtI,OAAEA,GAAQxJ,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEvC,MAAMsoB,GAAevW,GAASrS,KAAKqS,OAASoW,EAC1CI,GAAgBvW,GAAUtS,KAAKsS,QAAUmW,EACzCK,EAAO9oB,KAAKygB,UACZsI,EAAgB/oB,KAAKqS,MACrB2W,EAAiBhpB,KAAKsS,OACtB2W,EAA8BjpB,KAAK6f,oBACnCqJ,EAAUJ,EAAOL,EACjBU,EAAKnpB,KAAKif,kBAGVmK,EAAQ,CAACF,EAAS,EAAG,EAAGA,GAFVC,EAAG,IAAMhX,GAAQ,IAAMsW,GACvBU,EAAG,IAAM/W,GAAO,IAAMqW,GAEpCY,EAAiBrpB,KAAK6e,oBACtBzK,EAAWH,GAAuB,CAChC5B,MAAOuW,EACPtW,OAAQuW,IAEVS,EAAkBxf,EACd9J,KAAKqP,SAASvF,OAAQqH,GAAQrH,EAAOqH,IACrCnR,KAAKqP,SAcX,OAbArP,KAAK6e,qBAAsB,EAC3B7e,KAAKif,kBAAoBmK,EACzBppB,KAAKqS,MAAQuW,EACb5oB,KAAKsS,OAASuW,EACd7oB,KAAK6f,qBAAsB,EAC3B7f,KAAK8f,yBACL9f,KAAK6hB,aAAazN,EAAShR,WAAW,MAAQkmB,GAC9CtpB,KAAKif,kBAAoBkK,EACzBnpB,KAAKqS,MAAQ0W,EACb/oB,KAAKsS,OAAS0W,EACdhpB,KAAK8f,yBACL9f,KAAK6e,oBAAsBwK,EAC3BrpB,KAAK6f,oBAAsBoJ,EACpB7U,CACT,CAOA7P,OAAAA,GAKE,OAJCvE,KAAKgiB,UACJhiB,KAAKsf,SAAStC,WAAW,CAAE3K,MAAOrS,KAAKqS,MAAOC,OAAQtS,KAAKsS,SAC7DlJ,GAAkBS,eAAe7J,MACjCA,KAAKgiB,UAAW,EACT,IAAIxN,QAAiB,CAACC,EAASoD,KACpC,MAAM0R,EAAOA,KACXvpB,KAAKwpB,UACL/U,GAAQ,IAEV8U,EAAKE,KAAO5R,EACR7X,KAAKojB,eACPpjB,KAAKojB,cAAcqG,KAAK,WAGtBzpB,KAAK4hB,UACPnN,GAAQ,GACCzU,KAAK+hB,iBACd/hB,KAAKojB,cAAgBmG,EAErBA,KAGN,CAgBAC,OAAAA,GACExpB,KAAK4hB,WAAY,EACjB5hB,KAAK2hB,wBACL3hB,KAAKqQ,cAAeX,GAAWA,EAAOnL,WACtCvE,KAAKqP,SAAW,GACZrP,KAAKwhB,iBACPxhB,KAAKwhB,gBAAgBjd,UAEvBvE,KAAKwhB,qBAAkBhhB,EACnBR,KAAKyhB,cACPzhB,KAAKyhB,aAAald,UAEpBvE,KAAKyhB,kBAAejhB,EACpBR,KAAKsf,SAAS/a,SAChB,CAMA2J,QAAAA,GACE,MAAO,aAAalO,KAAKoR,6BACvBpR,KAAKqP,SAAS9O,WAElB,EACDR,EAn3CYof,GAAY,cA8FFf,ICjLvB,MAAMsL,GAAc,CAAC,aAAc,YAAa,YAUzC,MAAMC,GAAcC,IACzB,MACEC,EAASjP,GADKgP,EAAM5f,QAEpB8f,EAXJ,SAAsBF,GACpB,MAAMG,EAAaH,EAAqBI,eACxC,OAAID,GAAaA,EAAU,GAClBA,EAAU,GAEZH,CACT,CAKWK,CAAaL,GACtB,OAAO,IAAIzd,GAAM2d,EAAKI,QAAUL,EAAO1X,KAAM2X,EAAKK,QAAUN,EAAOzX,MAGxDgY,GAAgBR,GAC3BF,GAAYzY,SAAS2Y,EAAM5gB,OACa,UAAvC4gB,EAAuBS,YAEbC,GAAaC,IACxBA,EAAEC,iBACFD,EAAEE,mBCnBSC,GAA6BC,IACxC,IAAIxY,EAAO,EACTC,EAAM,EACNC,EAAQ,EACRC,EAAS,EAEX,IAAK,IAAI7G,EAAI,EAAGmY,EAAM+G,EAAOpqB,OAAQkL,EAAImY,EAAKnY,IAAK,CACjD,MAAMY,EAAEA,EAACD,EAAEA,GAAMue,EAAOlf,IACpBY,EAAIgG,IAAU5G,KAAG4G,EAAQhG,IACzBA,EAAI8F,IAAS1G,KAAG0G,EAAO9F,IACvBD,EAAIkG,IAAW7G,KAAG6G,EAASlG,IAC3BA,EAAIgG,IAAQ3G,KAAG2G,EAAMhG,EAC3B,CAEA,MAAO,CACL+F,OACAC,MACAC,MAAOA,EAAQF,EACfG,OAAQA,EAASF,ICgBRwY,GAAuBA,CAAClb,EAAsBV,IACzD6b,GACEnb,EACA2F,GAA0BrG,EAAWU,EAAOob,kBAQnCD,GAAyBA,CACpCnb,EACAV,KAEA,MAAMsH,WAAEA,EAAUC,WAAEA,EAAUL,OAAEA,EAAMC,OAAEA,KAAW4U,GAC/ChV,GAAY/G,GACdoW,EAAS,IAAIjZ,GAAMmK,EAAYC,GACjC7G,EAAO0H,OAAQ,EACf1H,EAAO2H,OAAQ,EACf5W,OAAOC,OAAOgP,EAAQqb,GACtBrb,EAAOnK,IAAI,CAAE2Q,SAAQC,WACrBzG,EAAOsb,oBAAoB5F,EAAQte,EAAQA,IAMhCmkB,GAAwBjhB,IACnCA,EAAOkM,OAAS,EAChBlM,EAAOmM,OAAS,EAChBnM,EAAOoM,MAAQ,EACfpM,EAAOqM,MAAQ,EACfrM,EAAOoN,OAAQ,EACfpN,EAAOqN,OAAQ,EACfrN,EAAOyE,OAAO,IAQHyc,GAAuBlhB,IAAoB,CACtDkM,OAAQlM,EAAOkM,OACfC,OAAQnM,EAAOmM,OACfC,MAAOpM,EAAOoM,MACdC,MAAOrM,EAAOqM,MACdvK,MAAO9B,EAAO8B,MACdqG,KAAMnI,EAAOmI,KACbiF,MAAOpN,EAAOoN,MACdC,MAAOrN,EAAOqN,MACdjF,IAAKpI,EAAOoI,MAYD+Y,GAAqBA,CAChC9Y,EACAC,EACA1E,KAEA,MAAMwd,EAAO/Y,EAAQ,EACnBgZ,EAAO/Y,EAAS,EAChBqY,EAAS,CACP,IAAIxe,IAAOif,GAAOC,GAClB,IAAIlf,GAAMif,GAAOC,GACjB,IAAIlf,IAAOif,EAAMC,GACjB,IAAIlf,GAAMif,EAAMC,IAChB1S,IAAK5J,GAAMA,EAAEC,UAAUpB,IACzB0d,EAAOZ,GAA0BC,GACnC,OAAO,IAAIxe,GAAMmf,EAAKjZ,MAAOiZ,EAAKhZ,SC1GvBiZ,GAAwB,WAAA,IACnCC,EAAYlrB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,EACK,OACjB2O,GAA0BH,GADnB5U,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,GACqC8kB,EAAK,EAkB5CC,GAAmB,SAC9B5K,GAAY,IACZ2K,EAAYlrB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,EACfglB,EAAUprB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,EAAO,OACVma,EAAM7R,UAAUuc,GAAsBC,EAAME,GAAI,EAK/CC,GAAoB,SAC/B9K,GAAY,IACZ2K,EAAYlrB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,EACfglB,EAAUprB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGoG,EAAO,OACVma,EAAM7R,UAAUuc,GAAsBC,EAAME,IAAK,EAAK,EAgCrDE,GAAoBA,CAC/Blc,EACA8b,EACAE,KAEA,MAAM9d,EAAI2d,GAAsBC,EAAME,GAKtC,OAJAb,GACEnb,EACA2F,GAA0BzH,EAAG8B,EAAOob,kBAE/Bld,GCxFHie,GAAe,CACnB1Z,MAAM,GACNC,KAAK,GACLgT,OAAQ,EACR0G,OAAQ,GACRC,MAAO,IASIC,GACXC,GAEuB,iBAAhBA,EACHJ,GAAaI,GACbA,EAAc,GCjBdC,GAAc,IAAI/f,GAAM,EAAG,GAC3BggB,GAAO,IAAIhgB,GAQJigB,GAAeA,CAACC,EAAe3d,IAC1C2d,EAAO5d,OAAOC,GASH4d,GAAeA,CAACd,EAAUE,IACrC,IAAIvf,GAAMuf,GAAI9e,SAAS4e,GAMZe,GAAa1L,GAAiBA,EAAM/S,aAAaqe,IAQjDK,GAA0BA,CAACrX,EAAUG,IAChD1Q,KAAKkR,MAAM2W,GAAatX,EAAGG,GAAIoX,GAAWvX,EAAGG,IAOlCqX,GAAsBpK,GACjCiK,GAAwBN,GAAa3J,GAM1BqK,GAAiBrK,GAC5BA,EAAEjV,GAAG6e,IAAQ5J,EAAIA,EAAEnV,aAAamf,GAAUhK,IAO/BsK,GAAuB,SAClCtK,GAAQ,IACRuK,IAAgBxsB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAAO,OAEvBssB,GAAc,IAAIzgB,IAAOoW,EAAEnW,EAAGmW,EAAElW,GAAGY,eAAe6f,EAAmB,GAAI,GAAI,EAQlEL,GAAeA,CAACtX,EAAUG,IACrCH,EAAE9I,EAAIiJ,EAAElJ,EAAI+I,EAAE/I,EAAIkJ,EAAEjJ,EAQTqgB,GAAaA,CAACvX,EAAUG,IAAqBH,EAAE9I,EAAIiJ,EAAEjJ,EAAI8I,EAAE/I,EAAIkJ,EAAElJ,EAWjE2gB,GAAmBA,CAACnf,EAAUuH,EAAUG,KACnD,GAAI1H,EAAEN,GAAG6H,IAAMvH,EAAEN,GAAGgI,GAAI,OAAO,EAC/B,MAAM0X,EAAMP,GAAatX,EAAGG,GAC1B2X,EAAMR,GAAatX,EAAGvH,GACtBsf,EAAMT,GAAanX,EAAG1H,GACxB,OAAOof,GAAO,EAAIC,GAAO,GAAKC,GAAO,IAAMD,GAAO,GAAKC,GAAO,ICjFnDC,GAAqB,cA0B3B,SAASC,GAAoBpe,GAClC,OACEgd,GAAchd,EAAUqe,WAAarB,GAAcllB,IACnDklB,GAAchd,EAAUse,WAAatB,GAAcllB,EAEvD,CAEO,SAASymB,GAAa5e,GAC3B,MAAgC,GAAxBqd,GAAcrd,EACxB,CAEO,MAAM6e,GAAWA,CACtBxjB,EACAyjB,IASGzjB,EAAOyjB,GAECC,GAGTA,CAACC,EAAW3e,EAAW3C,EAAGD,KACrB,CACLme,EAAGoD,EACH3e,YACA4e,QAAS,IAAIzhB,GAAME,EAAGD,KAWnB,SAASyhB,GACd1e,EACA2e,EACAC,GAEA,MAAM/jB,EAAS+jB,EACT3I,EAASqG,GACbtc,EAAawV,iBACbxV,EAAahM,OAAQ8b,uBACrBze,GAEIsL,EAAQ6gB,GAAmBL,GAAalH,EAAQpb,IAAWxD,EACjE,OAAO5B,KAAKopB,MAAOliB,EAAQtF,EAAaD,EAC1C,CAqCO,SAAS0nB,GAAa/oB,EAE3BmoB,EACAC,EACAjhB,EACAD,GACA,IAAA8hB,EAAA,IALAlkB,OAAEA,EAAMmkB,OAAEA,GAAmBjpB,EAM7B,MAAM4oB,EAAU9jB,EAAOokB,SAASD,GAC9BrF,GAAoB,QAAboF,EAAAlkB,EAAO7G,cAAM,IAAA+qB,OAAA,EAAbA,EAAezN,YAAa,EACnC4N,EAAUrkB,EAAOqkB,QAAUvF,EAC3BwF,EA1CJ,SACEtkB,EACA6W,EACAwM,EACAC,GAEA,MAAMlI,EAASpb,EAAOukB,yBACpBxf,OACqB,IAAZse,QAA8C,IAAZC,EACrCtjB,EAAOwkB,uBACLpJ,EACAte,EACAA,EACAumB,EACAC,GAEF,IAAInhB,GAAMnC,EAAOmI,KAAMnI,EAAOoI,KAItC,OAHOpI,EAAO8B,MACR+U,EAAMpS,QAAQkG,GAAiB3K,EAAO8B,OAAQsZ,GAC9CvE,GACIjU,SAASmC,EACrB,CAqBiB0f,CAAezkB,EAAQ,IAAImC,GAAME,EAAGD,GAAIihB,EAASC,GAehE,OAdIgB,EAAWjiB,GAAKgiB,IAClBC,EAAWjiB,GAAKgiB,GAEdC,EAAWjiB,IAAMgiB,IACnBC,EAAWjiB,GAAKgiB,GAEdC,EAAWliB,GAAKiiB,IAClBC,EAAWliB,GAAKiiB,GAEdC,EAAWliB,GAAKiiB,IAClBC,EAAWliB,GAAKiiB,GAElBC,EAAWjiB,GAAKyhB,EAAQpT,QACxB4T,EAAWliB,GAAK0hB,EAAQvJ,QACjB+J,CACT,CCjKO,MAAMI,GAAezqB,GAAkBA,EAAM0qB,QAAQ,OAAQ,KCIvDC,GAAe,CAC1BC,UAAW,UACXC,aAAc,UACdC,KAAM,OACNC,WAAY,UACZC,MAAO,UACPC,MAAO,UACPC,OAAQ,UACRC,MAAO,OACPC,eAAgB,UAChBC,KAAM,OACNC,WAAY,UACZC,MAAO,UACPC,UAAW,UACXC,UAAW,UACXC,WAAY,UACZC,UAAW,UACXC,MAAO,UACPC,eAAgB,UAChBC,SAAU,UACVC,QAAS,UACTC,KAAM,OACNC,SAAU,UACVC,SAAU,UACVC,cAAe,UACfC,SAAU,UACVC,SAAU,UACVC,UAAW,UACXC,UAAW,UACXC,YAAa,UACbC,eAAgB,UAChBC,WAAY,UACZC,WAAY,UACZC,QAAS,UACTC,WAAY,UACZC,aAAc,UACdC,cAAe,UACfC,cAAe,UACfC,cAAe,UACfC,cAAe,UACfC,WAAY,UACZC,SAAU,UACVC,YAAa,UACbC,QAAS,UACTC,QAAS,UACTC,WAAY,UACZC,UAAW,UACXC,YAAa,UACbC,YAAa,UACbC,QAAS,OACTC,UAAW,UACXC,WAAY,UACZC,KAAM,UACNC,UAAW,UACXC,KAAM,UACNC,KAAM,UACNC,MAAO,UACPC,YAAa,UACbC,SAAU,UACVC,QAAS,UACTC,UAAW,UACXC,OAAQ,UACRC,MAAO,UACPC,MAAO,UACPC,SAAU,UACVC,cAAe,UACfC,UAAW,UACXC,aAAc,UACdC,UAAW,UACXC,WAAY,UACZC,UAAW,UACXC,qBAAsB,UACtBC,UAAW,UACXC,UAAW,UACXC,WAAY,UACZC,UAAW,UACXC,YAAa,UACbC,cAAe,UACfC,aAAc,UACdC,eAAgB,OAChBC,eAAgB,OAChBC,eAAgB,UAChBC,YAAa,UACbC,KAAM,OACNC,UAAW,UACXC,MAAO,UACPC,QAAS,OACTC,OAAQ,UACRC,iBAAkB,UAClBC,WAAY,UACZC,aAAc,UACdC,aAAc,UACdC,eAAgB,UAChBC,gBAAiB,UACjBC,kBAAmB,UACnBC,gBAAiB,UACjBC,gBAAiB,UACjBC,aAAc,UACdC,UAAW,UACXC,UAAW,UACXC,SAAU,UACVC,YAAa,UACbC,KAAM,UACNC,QAAS,UACTC,MAAO,UACPC,UAAW,UACXC,OAAQ,UACRC,UAAW,UACXC,OAAQ,UACRC,cAAe,UACfC,UAAW,UACXC,cAAe,UACfC,cAAe,UACfC,WAAY,UACZC,UAAW,UACXC,KAAM,UACNC,KAAM,UACNC,KAAM,UACNC,WAAY,UACZC,OAAQ,UACRC,cAAe,OACfC,IAAK,OACLC,UAAW,UACXC,UAAW,UACXC,YAAa,UACbC,OAAQ,UACRC,WAAY,UACZC,SAAU,UACVC,SAAU,UACVC,OAAQ,UACRC,OAAQ,UACRC,QAAS,UACTC,UAAW,UACXC,UAAW,UACXC,UAAW,UACXC,KAAM,UACNC,YAAa,UACbC,UAAW,UACXtgB,IAAK,UACLugB,KAAM,UACNC,QAAS,UACTC,OAAQ,UACRC,UAAW,UACXC,OAAQ,UACRC,MAAO,UACPC,MAAO,OACPC,WAAY,UACZC,OAAQ,OACRC,YAAa,WChJFC,GAAUA,CAACjpB,EAAWkpB,EAAWrqB,KACxCA,EAAI,IACNA,GAAK,GAEHA,EAAI,IACNA,GAAK,GAEHA,EAAI,EAAI,EACHmB,EAAc,GAATkpB,EAAIlpB,GAASnB,EAEvBA,EAAI,GACCqqB,EAELrqB,EAAI,EAAI,EACHmB,GAAKkpB,EAAIlpB,IAAM,EAAI,EAAInB,GAAK,EAE9BmB,GAWImpB,GAAUA,CACrB9iB,EACA+iB,EACA7iB,EACAH,KAEAC,GAAK,IACL+iB,GAAK,IACL7iB,GAAK,IACL,MAAM8iB,EAAWxzB,KAAKC,IAAIuQ,EAAG+iB,EAAG7iB,GAC9B+iB,EAAWzzB,KAAKiJ,IAAIuH,EAAG+iB,EAAG7iB,GAE5B,IAAIgjB,EAAYC,EAChB,MAAMC,GAAKJ,EAAWC,GAAY,EAElC,GAAID,IAAaC,EACfC,EAAIC,EAAI,MACH,CACL,MAAMztB,EAAIstB,EAAWC,EAErB,OADAE,EAAIC,EAAI,GAAM1tB,GAAK,EAAIstB,EAAWC,GAAYvtB,GAAKstB,EAAWC,GACtDD,GACN,KAAKhjB,EACHkjB,GAAKH,EAAI7iB,GAAKxK,GAAKqtB,EAAI7iB,EAAI,EAAI,GAC/B,MACF,KAAK6iB,EACHG,GAAKhjB,EAAIF,GAAKtK,EAAI,EAClB,MACF,KAAKwK,EACHgjB,GAAKljB,EAAI+iB,GAAKrtB,EAAI,EAGtBwtB,GAAK,CACP,CAEA,MAAO,CAAC1zB,KAAKopB,MAAU,IAAJsK,GAAU1zB,KAAKopB,MAAU,IAAJuK,GAAU3zB,KAAKopB,MAAU,IAAJwK,GAAUrjB,IAG5DsjB,GAAmB,WAAA,IAACx0B,EAAK3D,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,IAAG,OAC1CyZ,WAAW9V,IAAUA,EAAMy0B,SAAS,KAAO,IAAM,EAAE,EAKxCC,GAAU10B,GACrBW,KAAKiJ,IAAIjJ,KAAKopB,MAAM/pB,GAAQ,KAAKiK,SAAS,IAAI0qB,cAAcC,SAAS,EAAG,KAK7DC,GAAc5zB,IAKe,IAJxCkQ,EACA+iB,EACA7iB,EACAH,EAAI,GACajQ,EACjB,MAAM6zB,EAAMn0B,KAAKopB,MAAU,GAAJ5Y,EAAc,IAAJ+iB,EAAe,IAAJ7iB,GAC5C,MAAO,CAACyjB,EAAKA,EAAKA,EAAK5jB,IC1ElB,MAAM6jB,GAQXl5B,WAAAA,CAAYm5B,GACV,GAD6Bl5B,yBANd,GAOVk5B,EAGE,GAAIA,aAAiBD,GAC1Bh5B,KAAKk5B,UAAU,IAAID,EAAME,eACpB,GAAIv3B,MAAMwN,QAAQ6pB,GAAQ,CAC/B,MAAO7jB,EAAG+iB,EAAG7iB,EAAGH,EAAI,GAAK8jB,EACzBj5B,KAAKk5B,UAAU,CAAC9jB,EAAG+iB,EAAG7iB,EAAGH,GAC3B,MACEnV,KAAKk5B,UAAUl5B,KAAKo5B,iBAAiBH,SAPrCj5B,KAAKk5B,UAAU,CAAC,EAAG,EAAG,EAAG,GAS7B,CAOUE,gBAAAA,CAAiBH,GAKzB,OAJAA,EAAQA,EAAM5zB,iBACDupB,KACXqK,EAAQrK,GAAaqK,IAEN,gBAAVA,EACF,CAAC,IAAK,IAAK,IAAK,GACjBD,GAAMK,cAAcJ,IAClBD,GAAMM,cAAcL,IACpBD,GAAMO,cAAcN,KAIlBj5B,KAAKw5B,gBAAiB,IAAU,CAAC,EAAG,EAAG,EAAG,EACpD,CAMAC,SAAAA,GACE,OAAOz5B,KAAKm5B,OACd,CAMAD,SAAAA,CAAUzf,GACRzZ,KAAKm5B,QAAU1f,CACjB,CAMAigB,KAAAA,GACE,MAAOtkB,EAAG+iB,EAAG7iB,GAAKtV,KAAKy5B,YACvB,MAAO,OAAOrkB,KAAK+iB,KAAK7iB,IAC1B,CAMAqkB,MAAAA,GACE,MAAO,QAAQ35B,KAAKy5B,YAAYtf,KAAK,OACvC,CAMAyf,KAAAA,GACE,MAAOtB,EAAGC,EAAGC,GAAKN,MAAWl4B,KAAKy5B,aAClC,MAAO,OAAOnB,KAAKC,MAAMC,KAC3B,CAMAqB,MAAAA,GACE,MAAOvB,EAAGC,EAAGC,EAAGrjB,GAAK+iB,MAAWl4B,KAAKy5B,aACrC,MAAO,QAAQnB,KAAKC,MAAMC,MAAMrjB,IAClC,CAMA2kB,KAAAA,GAEE,OADgB95B,KAAK+5B,SACNC,MAAM,EAAG,EAC1B,CAMAD,MAAAA,GACE,MAAO3kB,EAAG+iB,EAAG7iB,EAAGH,GAAKnV,KAAKy5B,YAC1B,MAAO,GAAGd,GAAOvjB,KAAKujB,GAAOR,KAAKQ,GAAOrjB,KAAKqjB,GAAO/zB,KAAKopB,MAAU,IAAJ7Y,KAClE,CAMA8kB,QAAAA,GACE,OAAOj6B,KAAKy5B,YAAY,EAC1B,CAOAS,QAAAA,CAASC,GAEP,OADAn6B,KAAKm5B,QAAQ,GAAKgB,EACXn6B,IACT,CAMAo6B,WAAAA,GAEE,OADAp6B,KAAKk5B,UAAUJ,GAAY94B,KAAKy5B,cACzBz5B,IACT,CAOAq6B,YAAAA,CAAaC,GACX,MAAOC,EAAO,CAAA,CAAMplB,GAAK2jB,GAAY94B,KAAKy5B,aACxCe,EAAOD,GAAWD,GAAa,KAAO,EAAI,IAE5C,OADAt6B,KAAKk5B,UAAU,CAACsB,EAAMA,EAAMA,EAAMrlB,IAC3BnV,IACT,CAOAy6B,WAAAA,CAAYC,GACJA,aAAsB1B,KAC1B0B,EAAa,IAAI1B,GAAM0B,IAGzB,MAAMjhB,EAASzZ,KAAKy5B,YAElBkB,EAAcD,EAAWjB,aACxBmB,EAAGC,EAAGC,GAAKrhB,EAAOd,IAAI,CAAC1U,EAAOqF,IAC7B1E,KAAKopB,MAAW,GAAL/pB,EAHA,GAG2B02B,EAAYrxB,KAItD,OADAtJ,KAAKk5B,UAAU,CAAC0B,EAAGC,EAAGC,EAAGrhB,EAAO,KACzBzZ,IACT,CAOA,cAAO+6B,CAAQ9B,GACb,OAAOD,GAAMgC,SAAS/B,EACxB,CAOA,eAAO+B,CAAS/B,GACd,OAAO,IAAID,GAAMA,GAAMM,cAAcL,GACvC,CAOA,oBAAOK,CAAcL,GACnB,MAAMgC,EAAQvM,GAAYuK,GAAOgC,MC3JnC,oJD4JE,GAAIA,EAAO,CACT,MAAO7lB,EAAG+iB,EAAG7iB,GAAK2lB,EAAMjB,MAAM,EAAG,GAAGrhB,IAAK1U,IACvC,MAAMi3B,EAAcnhB,WAAW9V,GAC/B,OAAOA,EAAMy0B,SAAS,KAClB9zB,KAAKopB,MAAoB,KAAdkN,GACXA,IAEN,MAAO,CAAC9lB,EAAG+iB,EAAG7iB,EAAGmjB,GAAiBwC,EAAM,IAC1C,CACF,CAOA,cAAOE,CAAQlC,GACb,OAAOD,GAAMoC,SAASnC,EACxB,CAOA,eAAOmC,CAASnC,GACd,OAAO,IAAID,GAAMA,GAAMO,cAAcN,GACvC,CASA,oBAAOM,CAAcN,GACnB,MAAMgC,EAAQvM,GAAYuK,GAAOgC,MCzInC,oKD0IE,IAAKA,EACH,OAEF,MAEM3C,GAFgBU,GAAMqC,oBAAoBJ,EAAM,IAEzB,IAAO,KAAO,IAAO,IAChD1C,EAAIxe,WAAWkhB,EAAM,IAAM,IAC3BzC,EAAIze,WAAWkhB,EAAM,IAAM,IAC7B,IAAI7lB,EAAW+iB,EAAW7iB,EAE1B,GAAU,IAANijB,EACFnjB,EAAI+iB,EAAI7iB,EAAIkjB,MACP,CACL,MAAMP,EAAIO,GAAK,GAAMA,GAAKD,EAAI,GAAKC,EAAID,EAAIC,EAAID,EAC7CxpB,EAAQ,EAAJypB,EAAQP,EAEd7iB,EAAI4iB,GAAQjpB,EAAGkpB,EAAGK,EAAI,EAAI,GAC1BH,EAAIH,GAAQjpB,EAAGkpB,EAAGK,GAClBhjB,EAAI0iB,GAAQjpB,EAAGkpB,EAAGK,EAAI,EAAI,EAC5B,CAEA,MAAO,CACL1zB,KAAKopB,MAAU,IAAJ5Y,GACXxQ,KAAKopB,MAAU,IAAJmK,GACXvzB,KAAKopB,MAAU,IAAJ1Y,GACXmjB,GAAiBwC,EAAM,IAE3B,CAOA,cAAOK,CAAQrC,GACb,OAAO,IAAID,GAAMA,GAAMK,cAAcJ,GACvC,CAOA,oBAAOI,CAAcJ,GACnB,GAAIA,EAAMgC,MCjLa,6CDiLG,CACxB,MAAMh3B,EAAQg1B,EAAMe,MAAMf,EAAM1vB,QAAQ,KAAO,GAE/C,IAAIgyB,EAEFA,EAHkBt3B,EAAM1D,QAAU,EAGlB0D,EAAMu3B,MAAM,IAAI7iB,IAAK8iB,GAAQA,EAAMA,GAEnCx3B,EAAMg3B,MAAM,SAE9B,MAAO7lB,EAAG+iB,EAAG7iB,EAAGH,EAAI,KAAOomB,EAAc5iB,IAAK+iB,GAC5Cle,SAASke,EAAW,KAEtB,MAAO,CAACtmB,EAAG+iB,EAAG7iB,EAAGH,EAAI,IACvB,CACF,CAQA,0BAAOkmB,CAAoBp3B,GACzB,MAAM03B,EAAY13B,EAAMoB,cAClBu2B,EAAU7hB,WAAW4hB,GAE3B,OAAIA,EAAU1qB,SAAS,OACd4D,GAAiB+mB,GAGtBD,EAAU1qB,SAAS,QACJ,IAAV2qB,EAIFA,CACT,EEjUK,MAoCMC,GAAY,SAAC53B,GAAoD,IAArC63B,EAAQx7B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGsG,EAClD,MAAMm1B,EAAO,WAAWC,KAAK/3B,GAC3B4V,EAASE,WAAW9V,GAChBg4B,EAAM97B,EAAO+7B,IACnB,OAAQH,eAAAA,EAAO,IACb,IAAK,KACH,OAAQliB,EAASoiB,EAAO,KAE1B,IAAK,KACH,OAAQpiB,EAASoiB,EAAO,KAE1B,IAAK,KACH,OAAOpiB,EAASoiB,EAElB,IAAK,KACH,OAAQpiB,EAASoiB,EAAO,GAE1B,IAAK,KACH,OAASpiB,EAASoiB,EAAO,GAAM,GAEjC,IAAK,KACH,OAAOpiB,EAASiiB,EAElB,QACE,OAAOjiB,EAEb,EA6BasiB,GACXC,IAEA,MAAOC,EAAWC,GAAcF,EAAUG,OAAOf,MAAM,MAIhDgB,EAAQC,IAvBGC,EAuBkBL,IArBvBK,IAAUv1B,EACd,CAACu1B,EAAM1C,MAAM,EAAG,GAAiB0C,EAAM1C,MAAM,EAAG,IAC9C0C,IAAUv1B,EACZ,CAACu1B,EAAOA,GAEV,CAAC,MAAO,OAPGA,MAwBlB,MAAO,CACLC,YAAaL,GAAc,OAC3BE,SACAC,WAYSG,GAAiB,SAC5B3pB,EACAhP,GAEG,IACC44B,EACAC,EAHJC,IAAWz8B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAIX,GAAK2D,EAEE,GAAIA,EAAMqW,OACfuiB,EAAa,cAAc54B,EAAM0P,UAC5B,CACL,MAAMslB,EAAQ,IAAID,GAAM/0B,GACtB+4B,EAAU/D,EAAMgB,WAElB4C,EAAa5D,EAAMS,QACH,IAAZsD,IACFF,EAAeE,EAAQ9uB,WAE3B,MAXE2uB,EAAa,OAYf,OAAIE,EACK,GAAG9pB,MAAS4pB,MACjBC,EAAe,GAAG7pB,cAAiB6pB,MAAmB,KAGjD,GAAG7pB,MAAS4pB,MACjBC,EAAe,GAAG7pB,cAAiB6pB,MAAmB,IAG5D,EClJO,MAAMG,GAaXC,YAAAA,CAEEC,GAEA,MAAMC,EAAWp9B,KAAKo9B,SAAWp9B,KAAKo9B,SAAW,UAC/CC,EAAcr9B,KAAKq9B,YAAcr9B,KAAKq9B,YAAc,IACpDC,EAAkBt9B,KAAKs9B,gBACnBt9B,KAAKs9B,gBAAgBnjB,KAAK,KAC1BhT,EACJo2B,EAAmBv9B,KAAKu9B,iBAAmBv9B,KAAKu9B,iBAAmB,IACnEC,EAAgBx9B,KAAKw9B,cAAgBx9B,KAAKw9B,cAAgB,OAC1DC,EAAiBz9B,KAAKy9B,eAAiBz9B,KAAKy9B,eAAiB,QAC7DC,EAAmB19B,KAAK09B,iBAAmB19B,KAAK09B,iBAAmB,IACnEV,OAAkC,IAAjBh9B,KAAKg9B,QAA0Bh9B,KAAKg9B,QAAU,IAC/DW,EAAa39B,KAAK2S,QAAU,GAAK,uBACjC7I,EAASqzB,EAAa,GAAKn9B,KAAK49B,eAChC7Z,EAAO6Y,GAAez0B,EAAMnI,KAAK+jB,MAGnC,MAAO,CAFI6Y,GAAex0B,EAAQpI,KAAK69B,QAIrC,iBACAR,EACA,KACA,qBACAC,EACA,KACA,mBACAE,EACA,KACA,sBACAD,EACA,KACA,oBACAE,EACA,KACA,sBACAC,EACA,KACA3Z,EACA,cACAqZ,EACA,KACA,YACAJ,EACA,IACAlzB,EACA6zB,GACAxjB,KAAK,GACT,CAMAyjB,YAAAA,GACE,OAAO59B,KAAK89B,OAAS,sBAAsB99B,KAAK89B,OAAOnqB,OAAS,EAClE,CAMAoqB,aAAAA,GAGE,MAAO,CACL/9B,KAAK2T,GAAK,OAAO3T,KAAK2T,OAAS,GAC/B3T,KAAKyiB,SACD,mBACGziB,KAAKyiB,SACHiE,gBAEL,IACJvM,KAAK,GACT,CAOA6jB,eAAAA,CAEEC,GAEA,IADA1W,EAAmBjnB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAEtB,MAAM0O,EAAYivB,EAAOj+B,KAAKk+B,sBAAwBl+B,KAAK8qB,gBAE3D,MAAO,GADU,cAAc7Q,GAAYjL,OAClBuY,KAC3B,CASA4W,MAAAA,CAAOC,GACL,MAAO,CAAC,GACV,CAOA9X,KAAAA,CAEE9N,GAEA,OAAOxY,KAAKq+B,qBAAqBr+B,KAAKm+B,OAAO3lB,GAAU,CACrDA,WAEJ,CAOA6O,aAAAA,CAEE7O,GAEA,MACE,KACAxY,KAAKs+B,6BAA6Bt+B,KAAKm+B,OAAO3lB,GAAU,CACtDA,WAGN,CAKA8lB,4BAAAA,CAEEC,GAKA,IAJA/lB,QACEA,EAAO+O,oBACPA,EAAsB,IACkCjnB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE7D,MAAMk+B,EAAe,CACjBx+B,KAAKg+B,iBAAgB,EAAMzW,GAC3BvnB,KAAK+9B,iBACL5jB,KAAK,IAEP7Q,EAAQi1B,EAAah1B,QAAQ,gBAE/B,OADAg1B,EAAaj1B,GAASk1B,EACfhmB,EAAUA,EAAQ+lB,EAAapkB,KAAK,KAAOokB,EAAapkB,KAAK,GACtE,CAKAkkB,oBAAAA,CAEEE,GAYQ,IAXRE,QACEA,EAAOjmB,QACPA,EAAOkmB,WACPA,EAAUnX,oBACVA,GAMDjnB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEJ,MAAMq+B,EAAYF,EAAU,GAAK,UAAUz+B,KAAKk9B,mBAC9C0B,EAAaF,EAAa,UAAU1+B,KAAK49B,mBAAqB,GAC9Dnb,EAAWziB,KAAKyiB,SAChBoc,EAAe7+B,KAAK8+B,cAChB,sCACA,GACJC,EAAmBtc,GAAYA,EAASuc,mBACxCnB,EAAS79B,KAAK69B,OACd9Z,EAAO/jB,KAAK+jB,KACZ+Z,EAAS99B,KAAK89B,OACdvX,EAAS,GAETjd,EAAQi1B,EAAah1B,QAAQ,gBAC/B,IAAI01B,EACAxc,IACFA,EAASiE,WAAa,YAAY9S,OAClCqrB,EAAiB,iBACfxc,EAASiE,kBACHjE,EAAS4E,cAAc7O,mBAE7BumB,GACFxY,EAAO7b,KAAK,MAAOk0B,EAAY5+B,KAAK+9B,gBAAiB,QAEvDxX,EAAO7b,KACL,MACA1K,KAAKg+B,iBAAgB,GACpBe,EAAuD,GAApCH,EAAa5+B,KAAK+9B,gBACtC,QAEF,MAAMS,EAAe,CACnBG,EACAE,EACAJ,EAAU,GAAKz+B,KAAKk/B,gBACpB,IACA3X,EAAsB,cAAcA,MAA0B,IAC9DpN,KAAK,IAiBP,OAhBAokB,EAAaj1B,GAASk1B,EAClBpkB,GAAS2J,IACXwC,EAAO7b,KAAKqZ,EAAKuC,MAAMtmB,OAErBoa,GAASyjB,IACXtX,EAAO7b,KAAKmzB,EAAOvX,MAAMtmB,OAEvB89B,GACFvX,EAAO7b,KAAKozB,EAAOxX,MAAMtmB,OAEvByiB,GACF8D,EAAO7b,KAAKu0B,GAEd1Y,EAAO7b,KAAK6zB,EAAapkB,KAAK,KAC9BoM,EAAO7b,KAAK,UACZq0B,GAAoBxY,EAAO7b,KAAK,UACzB8N,EAAUA,EAAQ+N,EAAOpM,KAAK,KAAOoM,EAAOpM,KAAK,GAC1D,CAEA+kB,aAAAA,GACE,OAAOl/B,KAAKm/B,aAAeh3B,EAAO,iBAAiBnI,KAAKm/B,eAAiB,EAC3E,EC3PK,SAASC,GAAYC,GAC1B,OAAO,IAAIC,OAAO,KAAOD,EAAIllB,KAAK,KAAO,OAAQ,IACnD,CCEO,MAAMolB,GAA4B,0BAEnCC,GAAiB,CACrB,WACA,aACA,aACA,aAGWC,GAA2B,CACtC,YACA,WACA,eAGWC,GAAiC,IACzCF,GACH,aACA,OACA,cACA,YACA,SACA,OACA,kBACA,WACA,aAGWG,GAAkB,IAC1BD,MACAD,GACH,sBACA,YACAF,IAkBWK,GAAmD,IAC3DJ,MACAC,GACHr3B,EACA,cACAD,EACA,SACA,sBACAo3B,IAMWM,GAA2D,CACtEC,WAAY14B,EACZ24B,iBAAkB,WAClBC,eAAgB,UAChBC,SAAU,OACVnE,SAAU,GACV12B,WAAYoD,EACZxH,WAAY,kBACZk/B,WAAW,EACXC,UAAU,EACVC,aAAa,EACbC,UAAWt5B,EACX5B,UAAWqD,EACX83B,WAAY,KACZC,oBAAqB,GACrB1C,OAAQ,KACRC,OAAQ,KACRtb,UAAMhiB,EACNggC,gBAAiB,EACjBC,SAAU15B,EACV25B,UAAW,WACXC,YAAa,EACbC,OAAQ,EACRC,UAAWv4B,EACXw4B,gBAAiB,IACjBC,eAAgB,EAEhBC,YAAa,CACXlxB,KAAM,GACNmxB,UAAU,KAEZC,UAAW,CACTpxB,KAAM,GACNmxB,SAAU,KAEZE,kBAAmB,KACnBC,QAAS,CACPlB,UAAW,GACXE,aAAa,OACbD,UAAU,QAEZkB,cAAe,KACf9B,CAACA,IAA4B,QAGlB+B,GAAU,UACVC,GAAe,eACfC,GAAgB,gBAChBC,GAAiB,iBChHjBC,GAAQC,OAAOC,GAAG,4CAClBC,GAAoBF,OAAOC,GAAG,uBAE9BE,GAAQ,6BAERC,GAAoB,IAAIzC,OACnC,qHAEEoC,GACA,2CACAA,GACA,eAyBFM,GAAgB,CACdC,GAAIl7B,EACJsF,EAAGtF,EACHqO,EAAG,SACH8sB,GAAIl7B,EACJoF,EAAGpF,EACHm7B,QAAS,UACTxE,WAAY,UACZ3uB,UAAW,kBACX,eAAgB,cAChB,YAAa,WACb,cAAe,aACf,YAAa,WACb,aAAc,YACd,cAAe,aACf,iBAAkB,cAClB,cAAe,aACf,mBAAoB,kBACpB,oBAAqB,mBACrB,iBAAkB,gBAClB,kBAAmB,iBACnB,oBAAqB,mBACrB,iBAAkB,gBAClB,eAAgB,cAChB,kBAAmB,iBACnB,cAAe,aACfguB,QAAS,UACT,YAAa,WACb,YAAa,WACb,gBAAiB,gBACjB,kBAAmB,iBACnB,4BAA6BuC,IAE/B6C,GAAQ,YACRC,GAAQ,YAEGC,GAAwBlD,GA1DL,CAC5B,OACA,SACA,UACA,WACA,UACA,OACA,OACA,QACA,SAmDSmD,GAA0BnD,GAjDhB,CAAC,SAAU,QAAS,SAAU,UAAW,OAAQ,QAmD3DoD,GAAuBpD,GAzChB,CAAC,SAAU,IAAK,IAAK,MAAO,WAAY,SA6C/CqD,GAAqB,IAAInD,OACpCqC,OAAOC,GAAG,QAAQF,MAASG,MAAqBH,MAASG,MAAqBH,MAASG,MAAqBH,WCvDxGgB,GAAoB,yCAEpBC,GAAmB,IAAIrD,OAC3B,YACEoD,GACAA,GACA,IACAhB,GACA,iCAuBG,MAAMkB,GAyDX9iC,WAAAA,GAAmE,IAAvDsK,EAAgD9J,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC7D,MAAM4B,EACY,iBAATkI,EAAoBw4B,GAAOC,YAAYz4B,GAAQA,EACxD3J,OAAOC,OAAOV,KAAM4iC,GAAOljB,YAAaxd,GACxClC,KAAK2T,GAAKC,IACZ,CAMA,kBAAOivB,CAAY5+B,GACjB,MAAM6+B,EAAY7+B,EAAMs4B,QACtB,CAAG7hB,EAAU,EAAG6J,EAAU,EAAGwe,EAAO,IAClCJ,GAAiB3G,KAAK8G,IAAc,IACpCnqB,IAAK1U,GAAU8V,WAAW9V,IAAU,GAGxC,MAAO,CACLg1B,OAHS6J,EAAUnU,QAAQgU,GAAkB,KAAO,cAAcpG,OAIlE7hB,UACA6J,UACAwe,OAEJ,CAOA70B,QAAAA,GACE,MAAO,CAAClO,KAAK0a,QAAS1a,KAAKukB,QAASvkB,KAAK+iC,KAAM/iC,KAAKi5B,OAAO9e,KAAK,MAClE,CAOAmM,KAAAA,CAAM5W,GACJ,MAAM2N,EAAS+O,GACX,IAAIjgB,GAAMnM,KAAK0a,QAAS1a,KAAKukB,SAC7B5P,IAAkBjF,EAAO5D,QAG3BmtB,EAAQ,IAAID,GAAMh5B,KAAKi5B,OACzB,IAAI+J,EAAQ,GACVC,EAAQ,GA2BV,OAzBIvzB,EAAO2C,OAAS3C,EAAO4C,SAGzB0wB,EAKI,IAJFppB,IACGhV,KAAKmH,IAAIsR,EAAOhR,GAAKrM,KAAK+iC,MAAQrzB,EAAO2C,MAC1ClS,EAAO+Z,qBAXA,GAeX+oB,EAKI,IAJFrpB,IACGhV,KAAKmH,IAAIsR,EAAOjR,GAAKpM,KAAK+iC,MAAQrzB,EAAO4C,OAC1CnS,EAAO+Z,qBAlBA,IAuBTxK,EAAO0H,QACTiG,EAAOhR,IAAK,GAEVqD,EAAO2H,QACTgG,EAAOjR,IAAK,GAGP,qBAAqBpM,KAAK2T,WAAWsvB,eAC1C,IAAM,EAAIA,WACFD,cACR,IAAM,EAAIA,2DAC8CppB,GACxD5Z,KAAK+iC,KAAO/iC,KAAK+iC,KAAO,EAAI,EAC5B5iC,EAAO+Z,4DACgCN,GACvCyD,EAAOhR,EACPlM,EAAO+Z,6BACCN,GACRyD,EAAOjR,EACPjM,EAAO+Z,8EACkD+e,EAAMS,2BAA2BT,EAAMgB,yLACpG,CAMAzf,QAAAA,GACE,MAAMyL,EAAgC,CACpCgT,MAAOj5B,KAAKi5B,MACZ8J,KAAM/iC,KAAK+iC,KACXroB,QAAS1a,KAAK0a,QACd6J,QAASvkB,KAAKukB,QACd2e,aAAcljC,KAAKkjC,aACnBC,WAAYnjC,KAAKmjC,WACjBn6B,KAAOhJ,KAAKF,YAA8BkJ,MAEtC5H,EAAWwhC,GAAOljB,YACxB,OAAQ1f,KAAKye,qBAETwH,EADAvM,GAAOuM,EAAM,CAAChiB,EAAO1C,IAAQ0C,IAAU7C,EAASG,GAEtD,CAEA,uBAAaqX,CAAW1W,GACtB,OAAO,IAAIlC,KAAKkC,EAClB,EArIAnC,EArCW6iC,GAAM,cApBmD,CACpE3J,MAAO,aACP8J,KAAM,EACNroB,QAAS,EACT6J,QAAS,EACT2e,cAAc,EACdzkB,sBAAsB,EACtB0kB,YAAY,IA4D4BpjC,EA/C7B6iC,GAAM,OAiDH,UA4HhBj6B,GAAcG,SAAS85B,GAAQ,UC3OxB,MAAMQ,GAAWA,CAACv1B,EAAa5J,EAAeY,IACnDD,KAAKC,IAAIgJ,EAAKjJ,KAAKiJ,IAAI5J,EAAOY,ICcnBw+B,GAAkB,CAC7Br8B,EACAD,EACAgB,EACAC,EACA,QACA,QACA,UACA,UACA,QACA,UACA,2BACA,SACA,UACAC,EACAC,GAGWo7B,GAAkB,CAC7Bn7B,EACAC,EACA,cACA,kBACA,QACA,SACA,aACA,gBACA,gBACA,mBACA,iBACA,mBACA,kBACA,YAGWm7B,GAET,CAEFnxB,IAAK,EACLD,KAAM,EACNE,MAAO,EACPC,OAAQ,EACRxG,MAAO,EACPsL,OAAO,EACPC,OAAO,EACPnB,OAAQ,EACRC,OAAQ,EACRqtB,cAAe,EACfptB,MAAO,EACPC,MAAO,EACPgX,QAASvmB,EACTwmB,QAASxmB,EACTu2B,YAAa,EACbyB,eAAe,EACfzQ,QAAS,EACT2O,QAAS,EACTmC,WAAYh3B,EACZ4b,KAAM,aACNqZ,SAAU,UACVS,OAAQ,KACRP,gBAAiB,KACjBC,iBAAkB,EAClBC,cAAe,OACfC,eAAgB,QAChBC,iBAAkB,EAClBra,yBAA0B,cAC1B/E,gBAAiB,GACjBwf,OAAQ,KACRnrB,SAAS,EACT8L,sBAAsB,EACtBmH,mBAAmB,EACnB6d,eAAe,EACfhhB,cAAUjiB,EACVkjC,UAAU,EACV1E,oBAAoB,EACpB2E,kBAAkB,EAClBC,iBAAiB,EACjBC,OAAO,GCrFHC,GAAYA,CAAC3uB,EAAW4uB,EAAWh1B,EAAWwpB,KAC9CpjB,EAAIvQ,KAAKmH,IAAIg4B,IACf5uB,EAAI4uB,EACJxL,EAAIxpB,EAAI,GAINwpB,EADQ,IAANwL,GAAiB,IAAN5uB,EACRpG,EAAIvI,EAAa5B,KAAKo/B,KAAK,GAE3Bj1B,EAAIvI,EAAa5B,KAAKo/B,KAAKD,EAAI5uB,GAGjC,CAAEA,IAAG4uB,IAAGh1B,IAAGwpB,MAGd0L,GAAUA,CACd9uB,EACAojB,EACAxpB,EACAnB,EACA9C,IAEAqK,EAAIvQ,KAAKqR,IAAI,EAAG,IAAMrI,GAAK,IAAMhJ,KAAKoH,KAAM4B,EAAI9C,EAAIytB,GAAK/xB,EAAauI,GAK3Dm1B,GAAiCA,CAACt2B,EAAG0H,EAAGyuB,EAAGj5B,KACrDi5B,EAAIn/B,KAAKiH,IAAK+B,EAAI9C,EAAKzE,GAAU09B,EAAIzuB,EAoP3B6uB,GAAiCA,CAACv2B,EAAG0H,EAAGyuB,EAAGj5B,KACjD8C,GAAK9C,GAAK,EAAI,KACVi5B,GAAK,OAASn2B,EAAIA,GAAK0H,EACrB1H,EAAI,EAAI,KACVm2B,GAAK,QAAUn2B,GAAK,IAAM,MAAQA,EAAI,KAAQ0H,EAC5C1H,EAAI,IAAM,KACZm2B,GAAK,QAAUn2B,GAAK,KAAO,MAAQA,EAAI,OAAU0H,EAEjDyuB,GAAK,QAAUn2B,GAAK,MAAQ,MAAQA,EAAI,SAAY0H,EAOlD8uB,GAAgCA,CAACx2B,EAAG0H,EAAGyuB,EAAGj5B,IACrDi5B,EAAII,GAAcr5B,EAAI8C,EAAG,EAAGm2B,EAAGj5B,GAAKwK,mEAvCK,SAAC1H,EAAG0H,EAAGyuB,EAAGj5B,GAAC,IAAEytB,EAACj4B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,QAAO,OACjEyjC,GAAKn2B,GAAK9C,GAAK8C,IAAM2qB,EAAI,GAAK3qB,EAAI2qB,GAAKjjB,CAAC,6BArGC+uB,CAACz2B,EAAG0H,EAAGyuB,EAAGj5B,KAClDi5B,GAAKn/B,KAAKqB,KAAK,GAAK2H,GAAK9C,GAAK8C,GAAK,GAAK0H,cArHCgvB,CAAC12B,EAAG0H,EAAGyuB,EAAGj5B,IACpDi5B,GAAKn2B,EAAI9C,IAAM,EAAIwK,gBA0IyBivB,CAAC32B,EAAG0H,EAAGyuB,EAAGj5B,KACtD,MACEqK,EAAI4uB,EACN,IAAIh1B,EAAI,EACR,GAAU,IAANnB,EACF,OAAO0H,EAGT,GAAU,KADV1H,GAAK9C,GAEH,OAAOwK,EAAIyuB,EAERh1B,IACHA,EAAQ,GAAJjE,GAEN,MAAQqK,EAAGqvB,EAAOjM,EAAGkM,EAAO11B,EAAG21B,GAAUZ,GAAU3uB,EAAG4uB,EAAGh1B,EAb/C,SAcV,OAAQk1B,GAAQO,EAAOC,EAAOC,EAAO92B,EAAG9C,GAAKwK,cAnEJqvB,CAAC/2B,EAAG0H,EAAGyuB,EAAGj5B,IAC7C,IAAN8C,EAAU0H,EAAIyuB,EAAI,IAAM,IAAMn2B,EAAI9C,EAAI,IAAMwK,gBA4IA,SAAC1H,EAAG0H,EAAGyuB,EAAGj5B,GAAmB,IAAhBytB,EAACj4B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,QAE7D,OADAsN,GAAK9C,EAAI,GACD,EACEi5B,EAAI,GAAMn2B,EAAIA,IAAqB,GAAd2qB,GAAK,QAAc3qB,EAAI2qB,IAAMjjB,EAEpDyuB,EAAI,IAAOn2B,GAAK,GAAKA,IAAqB,GAAd2qB,GAAK,QAAc3qB,EAAI2qB,GAAK,GAAKjjB,CACvE,kBA0BgDsvB,CAACh3B,EAAG0H,EAAGyuB,EAAGj5B,IACxD8C,EAAI9C,EAAI,EAC2B,GAA/Bs5B,GAAiB,EAAJx2B,EAAO,EAAGm2B,EAAGj5B,GAAWwK,EACD,GAApC6uB,GAAkB,EAAJv2B,EAAQ9C,EAAG,EAAGi5B,EAAGj5B,GAAe,GAAJi5B,EAAUzuB,gBAvIZuvB,CAACj3B,EAAG0H,EAAGyuB,EAAGj5B,KACtD8C,GAAK9C,EAAI,GACD,GACGi5B,EAAI,GAAMn/B,KAAKqB,KAAK,EAAI2H,GAAK,GAAK,GAAK0H,EAE1CyuB,EAAI,GAAMn/B,KAAKqB,KAAK,GAAK2H,GAAK,GAAKA,GAAK,GAAK0H,iBAzHRwvB,CAACl3B,EAAG0H,EAAGyuB,EAAGj5B,KACvD8C,GAAK9C,EAAI,GACD,EACEi5B,EAAI,EAAKn2B,GAAK,EAAI0H,EAEpByuB,EAAI,IAAOn2B,EAAI,IAAM,EAAI,GAAK0H,mBAwKSyvB,CAACn3B,EAAG0H,EAAGyuB,EAAGj5B,KACzD,MACEqK,EAAI4uB,EACN,IAAIh1B,EAAI,EACR,GAAU,IAANnB,EACF,OAAO0H,EAGT,GAAU,KADV1H,GAAK9C,EAAI,GAEP,OAAOwK,EAAIyuB,EAERh1B,IACHA,EAAIjE,GAAK,GAAM,MAEjB,MAAQqK,EAAGqvB,EAAOjM,EAAGkM,EAAO11B,EAAG21B,EAAOX,EAAGiB,GAAUlB,GAAU3uB,EAAG4uB,EAAGh1B,EAbzD,SAcV,OAAInB,EAAI,GACC,GAAOq2B,GAAQO,EAAOC,EAAOC,EAAO92B,EAAG9C,GAAKwK,EAGnDkvB,EACE5/B,KAAKqR,IAAI,GAAG,IAAOrI,GAAK,IACxBhJ,KAAKoH,KAAM4B,EAAI9C,EAAI25B,GAASj+B,EAAak+B,GACzC,GACFM,EACA1vB,iBA9G0C2vB,CAACr3B,EAAG0H,EAAGyuB,EAAGj5B,IAC5C,IAAN8C,EACK0H,EAEL1H,IAAM9C,EACDwK,EAAIyuB,GAEbn2B,GAAK9C,EAAI,GACD,EACEi5B,EAAI,EAAK,IAAM,IAAMn2B,EAAI,IAAM0H,EAEjCyuB,EAAI,IAAO,KAAM,KAAQn2B,GAAK,GAAK0H,gBAyKC4vB,CAACt3B,EAAG0H,EAAGyuB,EAAGj5B,KACtD8C,GAAK9C,EAAI,GACD,EACEi5B,EAAI,EAAKn2B,GAAK,EAAI0H,GAEnByuB,EAAI,KAAQn2B,GAAKA,EAAI,GAAK,GAAK0H,iBAzPK6vB,CAACv3B,EAAG0H,EAAGyuB,EAAGj5B,KACvD8C,GAAK9C,EAAI,GACD,EACEi5B,EAAI,EAAKn2B,GAAK,EAAI0H,GAEnByuB,EAAI,IAAOn2B,GAAK,GAAKA,GAAK,EAAI,GAAK0H,iBAkBC8vB,CAACx3B,EAAG0H,EAAGyuB,EAAGj5B,KACvD8C,GAAK9C,EAAI,GACD,EACEi5B,EAAI,EAAKn2B,GAAK,EAAI0H,EAEpByuB,EAAI,IAAOn2B,EAAI,IAAM,EAAI,GAAK0H,gBAkBM+vB,CAACz3B,EAAG0H,EAAGyuB,EAAGj5B,KACpDi5B,EAAI,GAAMn/B,KAAKiH,IAAKjH,KAAK0B,GAAKsH,EAAK9C,GAAK,GAAKwK,aA0LNgwB,CAAC13B,EAAG0H,EAAGyuB,EAAGj5B,IAAMi5B,GAAKn2B,GAAK9C,GAAK8C,EAAI0H,cArPlCiwB,CAAC33B,EAAG0H,EAAGyuB,EAAGj5B,IACpDi5B,GAAKn2B,GAAK9C,GAAK8C,GAAK,EAAI0H,cAsBkBkwB,CAAC53B,EAAG0H,EAAGyuB,EAAGj5B,IACpDi5B,GAAKn2B,EAAI9C,IAAM,EAAIwK,aAsBsBmwB,CAAC73B,EAAG0H,EAAGyuB,EAAGj5B,KAClDi5B,EAAIn/B,KAAKiH,IAAK+B,EAAI9C,EAAKzE,GAAU09B,EAAIzuB,cAwJI,SAAC1H,EAAG0H,EAAGyuB,EAAGj5B,GAAC,IAAEytB,EAACj4B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,QAAO,OAClEyjC,IAAMn2B,EAAIA,EAAI9C,EAAI,GAAK8C,IAAM2qB,EAAI,GAAK3qB,EAAI2qB,GAAK,GAAKjjB,CAAC,+BArGXowB,CAAC93B,EAAG0H,EAAGyuB,EAAGj5B,IACpDi5B,EAAIn/B,KAAKqB,KAAK,GAAK2H,EAAIA,EAAI9C,EAAI,GAAK8C,GAAK0H,eArHEqwB,CAAC/3B,EAAG0H,EAAGyuB,EAAGj5B,IACrDi5B,IAAMn2B,EAAI9C,EAAI,IAAM,EAAI,GAAKwK,iBAyJgBswB,CAACh4B,EAAG0H,EAAGyuB,EAAGj5B,KACvD,MACEqK,EAAI4uB,EACN,IAAIh1B,EAAI,EACR,GAAU,IAANnB,EACF,OAAO0H,EAGT,GAAU,KADV1H,GAAK9C,GAEH,OAAOwK,EAAIyuB,EAERh1B,IACHA,EAAQ,GAAJjE,GAEN,MAAQqK,EAAGqvB,EAAOjM,EAAGkM,EAAO11B,EAAG21B,EAAOX,EAAGiB,GAAUlB,GAAU3uB,EAAG4uB,EAAGh1B,EAbzD,SAcV,OACEy1B,EAAQ,KAAM,GAAM52B,GAAKhJ,KAAKoH,KAAM4B,EAAI9C,EAAI25B,GAASj+B,EAAak+B,GAClEM,EACA1vB,eArFwCuwB,CAACj4B,EAAG0H,EAAGyuB,EAAGj5B,IACpD8C,IAAM9C,EAAIwK,EAAIyuB,EAAIA,IAAM,KAAO,GAAMn2B,EAAK9C,GAAK,GAAKwK,cAmLVwwB,CAACl4B,EAAG0H,EAAGyuB,EAAGj5B,KACnDi5B,GAAKn2B,GAAK9C,IAAM8C,EAAI,GAAK0H,eArPiBywB,CAACn4B,EAAG0H,EAAGyuB,EAAGj5B,KACpDi5B,IAAMn2B,EAAIA,EAAI9C,EAAI,GAAK8C,GAAK,EAAI,GAAK0H,eAsBK0wB,CAACp4B,EAAG0H,EAAGyuB,EAAGj5B,IACrDi5B,IAAMn2B,EAAI9C,EAAI,IAAM,EAAI,GAAKwK,cAsBa2wB,CAACr4B,EAAG0H,EAAGyuB,EAAGj5B,IACpDi5B,EAAIn/B,KAAKoH,IAAK4B,EAAI9C,EAAKzE,GAAUiP,ICzGnC,MAAM4wB,GAAeA,KAAM,EAEpB,MAAeC,GAyCpBrmC,WAAAA,CAAWoF,GAWkB,IAXjBkhC,WACVA,EAAUC,QACVA,EAAOC,SACPA,EAAW,IAAGC,MACdA,EAAQ,EAACC,OACTA,EAAStC,GAAauC,QACtBA,EAAUrgC,EAAIsgC,SACdA,EAAWtgC,EAAIugC,WACfA,EAAavgC,EAAIwD,MACjBA,EAAQs8B,GAAYl8B,OACpBA,GACyB9E,EApC3BnF,gBAMiC,WACjCA,0BAImB,GACnBA,uBAGgB,GAsBdC,KAAK4mC,KAAO5mC,KAAK4mC,KAAKC,KAAK7mC,MAE3BA,KAAKsmC,SAAWA,EAChBtmC,KAAKumC,MAAQA,EACbvmC,KAAKwmC,OAASA,EACdxmC,KAAK8mC,SAAWL,EAChBzmC,KAAK+mC,UAAYL,EACjB1mC,KAAKgnC,YAAcL,EACnB3mC,KAAKinC,OAASr9B,EACd5J,KAAKgK,OAASA,EAEdhK,KAAKomC,WAAaA,EAClBpmC,KAAKqmC,QAAUA,EACfrmC,KAAKiE,MAAQjE,KAAKomC,WAClBpmC,KAAKknC,SAAWzmC,OAAOkG,OAAO3G,KAAKmnC,UAAUnnC,KAAKsmC,UAAUriC,MAC9D,CAEA,SAAImjC,GACF,OAAOpnC,KAAKqnC,MACd,CAEAC,MAAAA,GACE,MAAuB,YAAhBtnC,KAAKqnC,QAAwC,cAAhBrnC,KAAKqnC,MAC3C,CAYAE,KAAAA,GACE,MAAMC,EAAmCC,IACnB,YAAhBznC,KAAKqnC,SACTrnC,KAAK0nC,UAAYD,IAAc,IAAIE,KACnC3nC,KAAKqnC,OAAS,UACdrnC,KAAK8mC,WACL9mC,KAAK4mC,KAAK5mC,KAAK0nC,aAGjB1nC,KAAK4nC,WAID5nC,KAAKumC,MAAQ,EACfsB,WAAW,IAAMv0B,GAAiBk0B,GAAYxnC,KAAKumC,OAEnDjzB,GAAiBk0B,EAErB,CAEQZ,IAAAA,CAAKh5B,GACX,MAAMk6B,GAAcl6B,IAAM,IAAI+5B,MAAU3nC,KAAK0nC,UACvCK,EAAkBnjC,KAAKiJ,IAAIi6B,EAAY9nC,KAAKsmC,UAClDtmC,KAAKgoC,iBAAmBD,EAAkB/nC,KAAKsmC,SAC/C,MAAMriC,MAAEA,EAAKgkC,cAAEA,GAAkBjoC,KAAKmnC,UAAUY,GAChD/nC,KAAKiE,MAAQxD,OAAOkG,OAAO1C,GAC3BjE,KAAKioC,cAAgBA,EAED,YAAhBjoC,KAAKqnC,SAGPrnC,KAAKinC,OAAOjnC,KAAKiE,MAAOjE,KAAKioC,cAAejoC,KAAKgoC,mBAEjDhoC,KAAKqnC,OAAS,UACdrnC,KAAKkoC,cACIJ,GAAc9nC,KAAKsmC,UAC5BtmC,KAAKgoC,iBAAmBhoC,KAAKioC,cAAgB,EAC7CjoC,KAAK+mC,UAAU/mC,KAAKknC,SAAUlnC,KAAKioC,cAAejoC,KAAKgoC,kBACvDhoC,KAAKqnC,OAAS,YACdrnC,KAAKgnC,YACHhnC,KAAKknC,SACLlnC,KAAKioC,cACLjoC,KAAKgoC,kBAEPhoC,KAAKkoC,eAELloC,KAAK+mC,UAAU/mC,KAAKiE,MAAOjE,KAAKioC,cAAejoC,KAAKgoC,kBACpD10B,GAAiBtT,KAAK4mC,OAE1B,CAEQgB,QAAAA,GACNx+B,GAAkBsB,KAAK1K,KACzB,CAEQkoC,UAAAA,GACN9+B,GAAkBC,OAAOrJ,KAC3B,CAEA4J,KAAAA,GACE5J,KAAKqnC,OAAS,UACdrnC,KAAKkoC,YACP,ECjKK,MAAMC,WAAuBhC,GAClCrmC,WAAAA,CAAWoF,GAIe,IAJdkhC,WACVA,EAAa,EAACc,SACdA,EAAW,OACRnc,GACmB7lB,EACtB9E,MAAM,IACD2qB,EACHqb,aACAC,QAASa,EAAWd,GAExB,CAEUe,SAAAA,CAAUiB,GAClB,MAAMnkC,EAAQjE,KAAKwmC,OACjB4B,EACApoC,KAAKomC,WACLpmC,KAAKqmC,QACLrmC,KAAKsmC,UAEP,MAAO,CACLriC,QACAgkC,cAAerjC,KAAKmH,KAAK9H,EAAQjE,KAAKomC,YAAcpmC,KAAKqmC,SAE7D,ECxBK,MAAMgC,WAAuBlC,GAClCrmC,WAAAA,CAAWoF,GAIe,IAJdkhC,WACVA,EAAa,CAAC,GAAEc,SAChBA,EAAW,CAAC,QACThlC,GACmBgD,EACtB9E,MAAM,IACD8B,EACHkkC,aACAC,QAASa,EAASvuB,IAAI,CAAC1U,EAAOwH,IAAMxH,EAAQmiC,EAAW36B,KAE3D,CACU07B,SAAAA,CAAUiB,GAClB,MAAM9uB,EAAStZ,KAAKomC,WAAWztB,IAAI,CAAC1U,EAAOwH,IACzCzL,KAAKwmC,OAAO4B,EAAankC,EAAOjE,KAAKqmC,QAAQ56B,GAAIzL,KAAKsmC,SAAU76B,IAElE,MAAO,CACLxH,MAAOqV,EACP2uB,cAAerjC,KAAKmH,KACjBuN,EAAO,GAAKtZ,KAAKomC,WAAW,IAAMpmC,KAAKqmC,QAAQ,IAGtD,ECdF,MAAMiC,GAAsCA,CAC1CF,EACAhC,EACAC,EACAC,IAGOF,EAAaC,GADK,EAAIzhC,KAAKiH,IAAKu8B,EAAc9B,EAAYjgC,IAI7DkiC,GACJj4B,GAEAA,GAAQ,EACNk4B,EAAwBP,EAAuBD,IAC/C13B,EAAS,IAAI0oB,GAAMwP,GAAM7O,SAAUsO,EAAeD,IAE/C,MAAMS,WAAuBtC,GAClCrmC,WAAAA,CAAWoF,GAQe,IARdkhC,WACVA,EAAUc,SACVA,EAAQV,OACRA,EAAS8B,GAAkB5B,SAC3BA,EAAQC,WACRA,EAAU/8B,MACVA,KACG1H,GACmBgD,EACtB,MAAMwjC,EAAa,IAAI1P,GAAMoN,GAAY3M,YACnCkP,EAAW,IAAI3P,GAAMkO,GAAUzN,YACrCr5B,MAAM,IACD8B,EACHkkC,WAAYsC,EACZrC,QAASsC,EAAShwB,IAChB,CAAC1U,EAAOwH,IAAMxH,EAAQykC,EAAWj9B,IAEnC+6B,SACAE,SAAU6B,GAAkB7B,GAC5BC,WAAY4B,GAAkB5B,GAC9B/8B,MAAO2+B,GAAkB3+B,IAE7B,CACUu9B,SAAAA,CAAUiB,GAClB,MAAOhzB,EAAG+iB,EAAG7iB,EAAGH,GAAKnV,KAAKomC,WAAWztB,IAAI,CAAC1U,EAAOwH,IAC/CzL,KAAKwmC,OAAO4B,EAAankC,EAAOjE,KAAKqmC,QAAQ56B,GAAIzL,KAAKsmC,SAAU76B,IAE5DxH,EAAQ,IACT,CAACmR,EAAG+iB,EAAG7iB,GAAGqD,IAAI/T,KAAKopB,OACtBoV,GAAS,EAAGjuB,EAAG,IAEjB,MAAO,CACLlR,QACAgkC,cAEEhkC,EACG0U,IAAI,CAAC5J,EAAGtD,IACa,IAApBzL,KAAKqmC,QAAQ56B,GACT7G,KAAKmH,KAAKgD,EAAI/O,KAAKomC,WAAW36B,IAAMzL,KAAKqmC,QAAQ56B,IACjD,GAELhI,KAAMsL,GAAY,IAANA,IAAY,EAEjC,EChBK,SAAS65B,GAGd1mC,GACA,MAAMyH,EA1CNzH,IAEON,MAAMwN,QAAQlN,EAAQkkC,aAAexkC,MAAMwN,QAAQlN,EAAQglC,UAyChE2B,CAAiB3mC,GACb,IAAImmC,GAAenmC,GACnB,IAAIimC,GAAejmC,GAGzB,OADAyH,EAAU49B,QACH59B,CACT,CAEO,SAASm/B,GAAa5mC,GAC3B,MAAMyH,EAAY,IAAI8+B,GAAevmC,GAErC,OADAyH,EAAU49B,QACH59B,CACT,CClEO,MAAMo/B,GAKXjpC,WAAAA,CAAYkpC,GACVhpC,KAAKgpC,OAASA,EACdhpC,KAAK2qB,OAAS,EAChB,CAOQ1Z,QAAAA,CAAS4P,GACf,OAAO7gB,KAAK2qB,OAAOzZ,KAAMnC,GAAMA,EAAEzB,GAAGuT,GACtC,CAOQooB,MAAAA,GAAyC,IAAA,IAAAvnC,EAAApB,UAAAC,OAA/BoqB,EAAM,IAAA/oB,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAN8oB,EAAM9oB,GAAAvB,UAAAuB,GAMtB,OALA7B,KAAK2qB,OAAS3qB,KAAK2qB,OAAOnf,OACxBmf,EAAO7gB,OAAQ+W,IACL7gB,KAAKiR,SAAS4P,KAGnB7gB,IACT,CAWA,uBAAOkpC,CAAiBC,EAAUC,EAAUtO,GAA4B,IAAlBuO,EAAQ/oC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAC5D,GAAI8oC,EAAE97B,GAAGwtB,GAGP,OAAOqO,EAAE77B,GAAG87B,GACP,GAAIA,EAAE/8B,IAAMyuB,EAAEzuB,EAGnB,OACE88B,EAAE98B,IAAM+8B,EAAE/8B,IACTg9B,GAAaF,EAAE/8B,GAAKxH,KAAKiJ,IAAIu7B,EAAEh9B,EAAG0uB,EAAE1uB,IAAM+8B,EAAE/8B,GAAKxH,KAAKC,IAAIukC,EAAEh9B,EAAG0uB,EAAE1uB,IAE/D,GAAIg9B,EAAEh9B,IAAM0uB,EAAE1uB,EAGnB,OACE+8B,EAAE/8B,IAAMg9B,EAAEh9B,IACTi9B,GAAaF,EAAE98B,GAAKzH,KAAKiJ,IAAIu7B,EAAE/8B,EAAGyuB,EAAEzuB,IAAM88B,EAAE98B,GAAKzH,KAAKC,IAAIukC,EAAE/8B,EAAGyuB,EAAEzuB,IAE/D,CAKL,MAAMi9B,EAAKhd,GAAa8c,EAAGtO,GAErBvC,EADKjM,GAAa8c,EAAGD,GACdh8B,OAAOm8B,GACpB,OAAOD,EACHzkC,KAAKmH,IAAIwsB,EAAElsB,KAAOzH,KAAKmH,IAAIwsB,EAAEnsB,GAC7BmsB,EAAElsB,IAAMksB,EAAEnsB,GAAKmsB,EAAElsB,GAAK,GAAKksB,EAAElsB,GAAK,CACxC,CACF,CASA,uBAAOk9B,CAAiB1oB,EAAc8J,GACpC,MAAM6e,EAAQ,IAAIr9B,GAAM0U,GAAOzS,KAC7BxJ,KAAKiJ,IAAIgT,EAAMxU,EAAI,KAAMse,EAAOhS,IAAK5J,GAAMA,EAAE1C,KAE/C,IAAIo9B,EAAO,EACX,IAAK,IAAIngC,EAAQ,EAAGA,EAAQqhB,EAAOpqB,OAAQ+I,IAAS,CAClD,MAAMogC,EAAQ1pC,KAAK2pC,wBAEjBhf,EAAOrhB,GACPqhB,GAAQrhB,EAAQ,GAAKqhB,EAAOpqB,QAE5BsgB,EACA2oB,GAEF,GAAIE,EAAMz4B,SAAS4P,GAEjB,OAAO,EAET4oB,GAAQzvB,OAAwB,iBAAjB0vB,EAAMV,OACvB,CACA,OAAOS,EAAO,GAAM,CACtB,CAcA,wBAAOG,CACLC,EACAC,EACAC,EACAC,GAGc,IAFdC,IAAS3pC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GACT4pC,IAAS5pC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAET,MAAM6pC,EAASL,EAAGz9B,EAAIw9B,EAAGx9B,EACvB+9B,EAASN,EAAG19B,EAAIy9B,EAAGz9B,EACnBi+B,EAASL,EAAG39B,EAAI09B,EAAG19B,EACnBi+B,EAASN,EAAG59B,EAAI29B,EAAG39B,EACnBm+B,EAASV,EAAGx9B,EAAI09B,EAAG19B,EACnBm+B,EAASX,EAAGz9B,EAAI29B,EAAG39B,EACnBq+B,EAAMJ,EAASG,EAASF,EAASC,EACjCG,EAAMP,EAASK,EAASJ,EAASG,EACjCI,EAAKL,EAASH,EAASE,EAASD,EAClC,GAAW,IAAPO,EAAU,CACZ,MAAMC,EAAKH,EAAME,EACfE,EAAKH,EAAMC,EACb,OACGV,GAAc,GAAKW,GAAMA,GAAM,KAC/BV,GAAc,GAAKW,GAAMA,GAAM,GAEzB,IAAI9B,GAAa,gBAAgBE,OACtC,IAAI98B,GAAM09B,EAAGx9B,EAAIu+B,EAAKT,EAAQN,EAAGz9B,EAAIw+B,EAAKR,IAGrC,IAAIrB,EAEf,CACE,GAAY,IAAR0B,GAAqB,IAARC,EAAW,CAC1B,MAAMI,EACJb,GACAC,GACAnB,GAAaG,iBAAiBW,EAAIE,EAAIC,IACtCjB,GAAaG,iBAAiBY,EAAIC,EAAIC,IACtCjB,GAAaG,iBAAiBa,EAAIF,EAAIC,IACtCf,GAAaG,iBAAiBc,EAAIH,EAAIC,GACxC,OAAO,IAAIf,GAAa+B,EAAmB,kBAAetqC,EAC5D,CACE,OAAO,IAAIuoC,GAAa,WAG9B,CAWA,2BAAOgC,CACLC,EACAC,EACAC,EACAC,GAEA,OAAOpC,GAAaa,kBAAkBoB,EAAIC,EAAIC,EAAIC,GAAI,GAAO,EAC/D,CAWA,8BAAOxB,CACLE,EACAC,EACAC,EACAC,GAEA,OAAOjB,GAAaa,kBAAkBC,EAAIC,EAAIC,EAAIC,GAAI,GAAO,EAC/D,CAcA,2BAAOoB,CACLvB,EACAC,EACAnf,GAEc,IADd0e,IAAQ/oC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,GAER,MAAM+qC,EAAS,IAAItC,GACbxoC,EAASoqB,EAAOpqB,OAEtB,IAAK,IAAWwpC,EAAIC,EAAIN,EAAfj+B,EAAI,EAAkBA,EAAIlL,EAAQkL,IAAK,CAI9C,GAHAs+B,EAAKpf,EAAOlf,GACZu+B,EAAKrf,GAAQlf,EAAI,GAAKlL,GACtBmpC,EAAQX,GAAaa,kBAAkBC,EAAIC,EAAIC,EAAIC,EAAIX,GAAU,GAC5C,eAAjBK,EAAMV,OACR,OAAOU,EAET2B,EAAOpC,UAAUS,EAAM/e,OACzB,CAMA,OAJI0gB,EAAO1gB,OAAOpqB,OAAS,IACzB8qC,EAAOrC,OAAS,gBAGXqC,CACT,CAUA,8BAAOC,CACLzB,EACAC,EACAnf,GAEA,OAAOoe,GAAaqC,qBAAqBvB,EAAIC,EAAInf,GAAQ,EAC3D,CAWA,8BAAO4gB,CACLC,EACAC,GAEA,MAAMJ,EAAS,IAAItC,GACjBxoC,EAASirC,EAAQjrC,OACbmrC,EAA+B,GAErC,IAAK,IAAIjgC,EAAI,EAAGA,EAAIlL,EAAQkL,IAAK,CAC/B,MAAMo+B,EAAK2B,EAAQ//B,GACjBq+B,EAAK0B,GAAS//B,EAAI,GAAKlL,GACvBmpC,EAAQX,GAAauC,wBAAwBzB,EAAIC,EAAI2B,GAClC,eAAjB/B,EAAMV,QACR0C,EAAahhC,KAAKg/B,GAClB2B,EAAOpC,OAAOY,EAAIC,IAElBuB,EAAOpC,UAAUS,EAAM/e,OAE3B,CAEA,OAAI+gB,EAAanrC,OAAS,GAAKmrC,EAAanrC,SAAWirC,EAAQjrC,OACtD,IAAIwoC,GAAa,eACfsC,EAAO1gB,OAAOpqB,OAAS,IAChC8qC,EAAOrC,OAAS,gBAGXqC,EACT,CAUA,gCAAOM,CACLhhB,EACAihB,EACAC,GAEA,MAAMh+B,EAAM+9B,EAAG/9B,IAAIg+B,GACjBhnC,EAAM+mC,EAAG/mC,IAAIgnC,GACbC,EAAW,IAAI3/B,GAAMtH,EAAIwH,EAAGwB,EAAIzB,GAChC2/B,EAAa,IAAI5/B,GAAM0B,EAAIxB,EAAGxH,EAAIuH,GAEpC,OAAO28B,GAAawC,wBAAwB5gB,EAAQ,CAClD9c,EACAi+B,EACAjnC,EACAknC,GAEJ,ECvRK,MAAMC,WACHj5B,GAyCRk5B,IAAAA,GACE,OAAOjsC,KAAKksC,QAAQ7/B,CACtB,CAKA+B,IAAAA,CAAKnK,GACHjE,KAAKmO,MAAMnO,KAAKksC,QAAQ99B,KAAKnK,GAC/B,CAKAkoC,IAAAA,GACE,OAAOnsC,KAAKksC,QAAQ9/B,CACtB,CAKAiC,IAAAA,CAAKpK,GACHjE,KAAKmO,MAAMnO,KAAKksC,QAAQ79B,KAAKpK,GAC/B,CAMAmoC,YAAAA,GACE,OAAOpsC,KAAKmS,IACd,CAMAk6B,YAAAA,CAAapoC,GACXjE,KAAKmS,KAAOlO,CACd,CAMAqoC,YAAAA,GACE,OAAOtsC,KAAKoS,GACd,CAMAm6B,YAAAA,CAAatoC,GACXjE,KAAKoS,IAAMnO,CACb,CAKAioC,KAAAA,GACE,MAAMM,EAAmBxsC,KAAKysC,gBAC9B,OAAOzsC,KAAK0sC,MACRz3B,GAAeu3B,EAAkBxsC,KAAK0sC,MAAMxO,uBAC5CsO,CACN,CAYAr+B,KAAAA,CAAM0S,EAAcwM,EAAoBC,GAClCttB,KAAK0sC,QACP7rB,EAAQ5L,GACN4L,EACA3L,GAAgBlV,KAAK0sC,MAAMxO,yBAG/Bl+B,KAAK2sC,cAAc9rB,EAAOwM,EAASC,EACrC,CAKAmf,aAAAA,GACE,OAAO,IAAItgC,GAAMnM,KAAKmS,KAAMnS,KAAKoS,IACnC,CAQAu6B,aAAAA,CACE9rB,GAGA,IAFAwM,EAAiB/sB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKqtB,QACzBC,EAAiBhtB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKstB,QAEzBttB,KAAKgrB,oBAAoBnK,EAAOwM,EAASC,EAC3C,CAKUsf,gCAAAA,GACR,OAAO,CACT,CAKAC,SAAAA,GACE,MAAMr6B,GAAEA,EAAE2P,GAAEA,EAAE1P,GAAEA,EAAE2P,GAAEA,GAClBpiB,KAAK8sC,UAAY9sC,KAAK8sC,QAAU9sC,KAAK+sC,eACjCC,EAAS,CAACx6B,EAAI2P,EAAI1P,EAAI2P,GAC5B,GAAIpiB,KAAK0sC,MAAO,CACd,MAAM9+B,EAAI5N,KAAK0sC,MAAMxO,sBACrB,OAAO8O,EAAOr0B,IAAK5J,GAAMkG,GAAelG,EAAGnB,GAC7C,CACA,OAAOo/B,CACT,CAKAp6B,kBAAAA,CAAmBJ,EAAWC,GAM5B,MAA+B,iBALVs2B,GAAa4C,0BAChC3rC,KAAK6sC,YACLr6B,EACAC,GAEkBu2B,MACtB,CAOAiE,oBAAAA,CAAqBzD,GACnB,MAAM0D,EAAenE,GAAawC,wBAChCvrC,KAAK6sC,YACLrD,EAAMqD,aAGR,MAC0B,iBAAxBK,EAAalE,QACW,eAAxBkE,EAAalE,QACbQ,EAAM2D,wBAAwBntC,OAC9BA,KAAKmtC,wBAAwB3D,EAEjC,CAOA2D,uBAAAA,CAAwB3D,GAEtB,OADexpC,KAAK6sC,YACN73B,MAAO6L,GAAU2oB,EAAM12B,cAAc+N,GACrD,CAKAhO,qBAAAA,CAAsBL,EAAWC,GAC/B,MAAMN,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GAAWtS,KAAKotC,kBAC1C,OACEj7B,GAAQK,EAAGnG,GACX8F,EAAOE,GAASI,EAAGpG,GACnB+F,GAAOI,EAAGpG,GACVgG,EAAME,GAAUG,EAAGrG,CAEvB,CAEA6F,aAAAA,CAAwCu3B,GACtC,OACExpC,KAAKitC,qBAAqBzD,IAC1BxpC,KAAKmtC,wBAAwB3D,IAC7BA,EAAM2D,wBAAwBntC,KAElC,CAOA8S,aAAAA,CAAc+N,GACZ,OAAOkoB,GAAaQ,iBAAiB1oB,EAAO7gB,KAAK6sC,YACnD,CAOAQ,UAAAA,GACE,IAAKrtC,KAAKmD,OACR,OAAO,EAET,MAAMqP,GAAEA,EAAEC,GAAEA,GAAOzS,KAAKmD,OAAO+e,UAG/B,QAFeliB,KAAK6sC,YAGX37B,KACJ2P,GACCA,EAAMxU,GAAKoG,EAAGpG,GACdwU,EAAMxU,GAAKmG,EAAGnG,GACdwU,EAAMzU,GAAKqG,EAAGrG,GACdyU,EAAMzU,GAAKoG,EAAGpG,OAMhBpM,KAAK4S,mBAAmBJ,EAAIC,IAIzBzS,KAAK8S,cAAcN,EAAGvE,aAAawE,IAC5C,CAMA66B,mBAAAA,GACE,IAAKttC,KAAKmD,OACR,OAAO,EAET,MAAMqP,GAAEA,EAAEC,GAAEA,GAAOzS,KAAKmD,OAAO+e,UAC/B,GAAIliB,KAAK4S,mBAAmBJ,EAAIC,GAC9B,OAAO,EAQT,OAN4BzS,KAAK6sC,YAAY73B,MAC1C6L,IACEA,EAAMxU,GAAKoG,EAAGpG,GAAKwU,EAAMxU,GAAKmG,EAAGnG,KACjCwU,EAAMzU,GAAKqG,EAAGrG,GAAKyU,EAAMzU,GAAKoG,EAAGpG,KAGRpM,KAAK8S,cAAcN,EAAGvE,aAAawE,GACnE,CAOA26B,eAAAA,GACE,OAAO1iB,GAA0B1qB,KAAK6sC,YACxC,CAOAU,cAAAA,GACE,OAAOvtC,KAAKwtC,4BAA4BnhC,CAC1C,CAOAohC,eAAAA,GACE,OAAOztC,KAAKwtC,4BAA4BphC,CAC1C,CAOA+P,KAAAA,CAAMlY,GACJjE,KAAKmT,KAAKpL,EAAS9D,GACnBjE,KAAKmT,KAAKnL,EAAS/D,GACnBjE,KAAKggB,WACP,CAOA0tB,YAAAA,CAAazpC,GAEX,MAAM0pC,EACJ3tC,KAAKotC,kBAAkB/6B,MAAQrS,KAAKutC,iBACtC,OAAOvtC,KAAKmc,MAAMlY,EAAQjE,KAAKqS,MAAQs7B,EACzC,CAOAC,aAAAA,CAAc3pC,GAEZ,MAAM0pC,EACJ3tC,KAAKotC,kBAAkB96B,OAAStS,KAAKytC,kBACvC,OAAOztC,KAAKmc,MAAMlY,EAAQjE,KAAKsS,OAASq7B,EAC1C,CAEAE,sBAAAA,GAAyB,IAAAC,EACvB,OAAkB,QAAXA,EAAA9tC,KAAKmD,cAAM,IAAA2qC,OAAA,EAAXA,EAAa7tB,qBAAsB,CAC5C,CAMA8tB,aAAAA,GACE,OAAO/tC,KAAK0sC,MACR73B,GAAiBgB,GAAkB7V,KAAKk+B,wBACxCl+B,KAAK8L,KACX,CAMAkiC,oBAAAA,GAA+B,IAAAC,EAC7B,eAAOA,EAAAjuC,KAAKmD,cAAM,IAAA8qC,OAAA,EAAXA,EAAahvB,oBAAsBvY,EAAQ8E,QACpD,CAOAuhC,WAAAA,GACE,MAAMmB,EAAez3B,GAAmB,CAAE3K,MAAO9L,KAAK8L,SACpDO,EAAEA,EAACD,EAAEA,GAAMpM,KAAKuuB,yBAChB4f,EAAU33B,GAAsBnK,EAAGD,GACnCgiC,EAAc/4B,GAA0B84B,EAASD,GACjDG,EAAMruC,KAAKwtC,4BACXc,EAAID,EAAIhiC,EAAI,EACZisB,EAAI+V,EAAIjiC,EAAI,EACd,MAAO,CAELoG,GAAIyC,GAAe,CAAE5I,GAAIiiC,EAAGliC,GAAIksB,GAAK8V,GACrCjsB,GAAIlN,GAAe,CAAE5I,EAAGiiC,EAAGliC,GAAIksB,GAAK8V,GACpChsB,GAAInN,GAAe,CAAE5I,GAAIiiC,EAAGliC,EAAGksB,GAAK8V,GACpC37B,GAAIwC,GAAe,CAAE5I,EAAGiiC,EAAGliC,EAAGksB,GAAK8V,GAEvC,CAOApuB,SAAAA,GACEhgB,KAAK8sC,QAAU9sC,KAAK+sC,aACtB,CAEAwB,kBAAAA,GAAgD,IAA7BC,EAASluC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GACtBmuC,EAAmB,GAqBvB,OApBKD,GAAaxuC,KAAK0sC,QACrB+B,EAASzuC,KAAK0sC,MAAM6B,mBAAmBC,IAEzCC,EAAO/jC,KACL1K,KAAKoS,IACLpS,KAAKmS,KACLnS,KAAKqS,MACLrS,KAAKsS,OACLtS,KAAKkW,OACLlW,KAAKmW,OACLnW,KAAK8L,MACL9L,KAAKq9B,YACLr9B,KAAKoW,MACLpW,KAAKqW,OACJrW,KAAKoX,OACLpX,KAAKqX,MACN2U,GAAchsB,KAAKqtB,SACnBrB,GAAchsB,KAAKstB,UAGdmhB,CACT,CASAvQ,mBAAAA,GAA+C,IAA3BsQ,EAASluC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GACvBgX,EAAStX,KAAK8qB,gBAClB,GAAI0jB,IAAcxuC,KAAK0sC,MACrB,OAAOp1B,EAET,MAAM/V,EAAMvB,KAAKuuC,mBAAmBC,GAClC1pC,EAAQ9E,KAAK0uC,YACf,OAAI5pC,GAASA,EAAMvD,IAAIyT,MAAM,CAAC3I,EAAGZ,IAAMY,IAAM9K,EAAIkK,IACxC3G,EAAMb,OAEXjE,KAAK0sC,QACPp1B,EAASjC,GACPrV,KAAK0sC,MAAMxO,qBAAoB,GAC/B5mB,IAGJtX,KAAK0uC,YAAc,CACjBntC,MACA0C,MAAOqT,GAEFA,EACT,CAOAwT,aAAAA,GACE,MAAMvpB,EAAMvB,KAAKuuC,oBAAmB,GAClCzpC,EAAQ9E,KAAK2uC,eACf,GAAI7pC,GAASA,EAAMvD,IAAIyT,MAAM,CAAC3I,EAAGZ,IAAMY,IAAM9K,EAAIkK,IAC/C,OAAO3G,EAAMb,MAEf,MAAMmhB,EAASplB,KAAKuuB,yBAClBrsB,EAAU,CACR4J,MAAO9L,KAAK8L,MACZwK,WAAY8O,EAAO/Y,EACnBkK,WAAY6O,EAAOhZ,EACnB8J,OAAQlW,KAAKkW,OACbC,OAAQnW,KAAKmW,OACbC,MAAOpW,KAAKoW,MACZC,MAAOrW,KAAKqW,MACZe,MAAOpX,KAAKoX,MACZC,MAAOrX,KAAKqX,OAEdpT,EAAQsT,GAAcrV,GAKxB,OAJAlC,KAAK2uC,eAAiB,CACpBptC,MACA0C,SAEKA,CACT,CAOA2qC,4BAAAA,GACE,OAAO,IAAIziC,GAAMnM,KAAKqS,MAAOrS,KAAKsS,QAAQ7F,UAAUzM,KAAKq9B,YAC3D,CASAwR,2BAAAA,CAA4B3sC,GAC1B,OAAOlC,KAAKwtC,0BAA0BtrC,GACnC8M,UAAUhP,KAAKguC,wBAAwB,GACvCvhC,UAAU,EAAIzM,KAAKquB,QACxB,CA2CAmf,yBAAAA,GAAoD,IAA1BtrC,EAAY5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACvC,MAAMwuC,EAAa,CAIjB54B,OAAQlW,KAAKkW,OACbC,OAAQnW,KAAKmW,OACbC,MAAOpW,KAAKoW,MACZC,MAAOrW,KAAKqW,MACZhE,MAAOrS,KAAKqS,MACZC,OAAQtS,KAAKsS,OACb+qB,YAAar9B,KAAKq9B,eAEfn7B,GAGCm7B,EAAcyR,EAAWzR,YAC/B,IAAI0R,EAAwB1R,EAC1B2R,EAAyB,EAEvBhvC,KAAK8+B,gBACPiQ,EAAwB,EACxBC,EAAyB3R,GAE3B,MAAMjS,EAAO0jB,EAAWz8B,MAAQ08B,EAC9B1jB,EAAOyjB,EAAWx8B,OAASy8B,EAE7B,IAAIE,EAcJ,OAZEA,EAH8B,IAArBH,EAAW14B,OAAoC,IAArB04B,EAAWz4B,MAG5B,IAAIlK,GACpBif,EAAO0jB,EAAW54B,OAClBmV,EAAOyjB,EAAW34B,QAGFgV,GAChBC,EACAC,EACAlU,GAAqB23B,IAIlBG,EAAgBxiC,UAAUuiC,EACnC,CAWAxgB,sBAAAA,CACE3N,EACAquB,EACAC,EACAC,EACAC,GAEA,IAAIhjC,EAAIwU,EAAMxU,EACZD,EAAIyU,EAAMzU,EACZ,MAAMsO,EAAUsR,GAAcojB,GAAapjB,GAAckjB,GACvD3qB,EAAUyH,GAAcqjB,GAAarjB,GAAcmjB,GAErD,GAAIz0B,GAAW6J,EAAS,CACtB,MAAM8pB,EAAMruC,KAAKwtC,4BACjBnhC,GAAKqO,EAAU2zB,EAAIhiC,EACnBD,GAAKmY,EAAU8pB,EAAIjiC,CACrB,CAEA,OAAO,IAAID,GAAME,EAAGD,EACtB,CASAkjC,sBAAAA,CACEzuB,EACAwM,EACAC,GAEA,GAAID,IAAYvmB,GAAUwmB,IAAYxmB,EACpC,OAAO+Z,EAET,MAAM9R,EAAI/O,KAAKwuB,uBACb3N,EACAwM,EACAC,EACAxmB,EACAA,GAEF,OAAI9G,KAAK8L,MACAiD,EAAEN,OAAOkG,GAAiB3U,KAAK8L,OAAQ+U,GAEzC9R,CACT,CASAwgC,sBAAAA,CACEnqB,EACAiI,EACAC,GAEA,MAAMve,EAAI/O,KAAKwuB,uBACbpJ,EACAte,EACAA,EACAumB,EACAC,GAEF,OAAIttB,KAAK8L,MACAiD,EAAEN,OAAOkG,GAAiB3U,KAAK8L,OAAQsZ,GAEzCrW,CACT,CAMA4V,cAAAA,GACE,MAAM6qB,EAAYxvC,KAAKuuB,yBACvB,OAAOvuB,KAAK0sC,MACRz3B,GAAeu6B,EAAWxvC,KAAK0sC,MAAMxO,uBACrCsR,CACN,CAMAjhB,sBAAAA,GACE,OAAOvuB,KAAKsvC,uBACV,IAAInjC,GAAMnM,KAAKmS,KAAMnS,KAAKoS,KAC1BpS,KAAKqtB,QACLrtB,KAAKstB,QAET,CAMAmiB,gBAAAA,CAAiBpiB,EAAmBC,GAClC,OAAOttB,KAAK0vC,oBAAoBriB,EAASC,EAC3C,CAcAoiB,mBAAAA,CAAoBriB,EAAmBC,GACrC,OAAOttB,KAAKuvC,uBACVvvC,KAAKuuB,yBACLlB,EACAC,EAEJ,CASAtC,mBAAAA,CAAoB2kB,EAAYtiB,EAAmBC,GACjD,MAAMlI,EAASplB,KAAKsvC,uBAAuBK,EAAKtiB,EAASC,GACvD7R,EAAWzb,KAAKuvC,uBACdnqB,EACAplB,KAAKqtB,QACLrtB,KAAKstB,SAETttB,KAAKuF,IAAI,CAAE4M,KAAMsJ,EAASpP,EAAG+F,IAAKqJ,EAASrP,GAC7C,CAKAwjC,iBAAAA,GACE,OAAO5vC,KAAK0vC,oBAAoB3oC,EAAMC,EACxC,CAOA6oC,iBAAAA,CAAkB9gC,GAChB,OAAO/O,KAAKgrB,oBAAoBjc,EAAGhI,EAAMC,EAC3C,SCznBK,MAAM8oC,UAMH9D,GAiJR,kBAAOvsB,GACL,OAAOqwB,EAAapwB,WACtB,CAuBA,QAAI1W,GACF,MAAM+mC,EAAQ/vC,KAAKF,YAAoCkJ,KACvD,MAAa,iBAAT+mC,EACK,SAEFA,EAAK1qC,aACd,CAEA,QAAI2D,CAAK/E,GACPzC,EAAI,OAAQ,6BAA8ByC,EAC5C,CAMAnE,WAAAA,CAAYoC,GACV9B,QA/HFL,uBAQiD,MAwH/CU,OAAOC,OAAOV,KAAM8vC,EAAapwB,aACjC1f,KAAKgwC,WAAW9tC,EAClB,CAMA+tC,kBAAAA,GACEjwC,KAAKyjB,aAAe5P,KACpB7T,KAAKkwC,cAAgBlwC,KAAKyjB,aAAargB,WAAW,MAClDpD,KAAKmwC,qBAELnwC,KAAK6jC,OAAQ,CACf,CAWAuM,eAAAA,CACEC,GAEA,MAAMh+B,EAAQg+B,EAAKh+B,MACjBC,EAAS+9B,EAAK/9B,OACdzN,EAAM1E,EAAOmwC,kBACbziC,EAAM1N,EAAOowC,kBACf,GACEl+B,GAASxN,GACTyN,GAAUzN,GACVwN,EAAQC,GAAUnS,EAAO4F,mBAQzB,OANIsM,EAAQxE,IACVwiC,EAAKh+B,MAAQxE,GAEXyE,EAASzE,IACXwiC,EAAK/9B,OAASzE,GAETwiC,EAET,MAAMvqC,EAAKuM,EAAQC,GAChBk+B,EAAMC,GAAQ3rC,EAAMe,gBAAgBC,GACrCuG,EAAI+2B,GAASv1B,EAAK2iC,EAAM3rC,GACxBuH,EAAIg3B,GAASv1B,EAAK4iC,EAAM5rC,GAW1B,OAVIwN,EAAQhG,IACVgkC,EAAK/sB,OAASjR,EAAQhG,EACtBgkC,EAAKh+B,MAAQhG,EACbgkC,EAAKK,QAAS,GAEZp+B,EAASlG,IACXikC,EAAK9sB,OAASjR,EAASlG,EACvBikC,EAAK/9B,OAASlG,EACdikC,EAAKK,QAAS,GAETL,CACT,CAQAM,yBAAAA,GACE,MAAMC,EAAc5wC,KAAK6wC,wBAEvBxC,EAAMruC,KAAKwtC,0BAA0B,CAAEp3B,MAAO,EAAGC,MAAO,IACxDy6B,EAAWzC,EAAIhiC,EAAIukC,EAAYvkC,EAAKrM,KAAKkW,OACzC66B,EAAW1C,EAAIjiC,EAAIwkC,EAAYxkC,EAAKpM,KAAKmW,OAC3C,MAAO,CAIL9D,MAAOzN,KAAKosC,KAAKF,ErDlbO,GqDmbxBx+B,OAAQ1N,KAAKosC,KAAKD,ErDnbM,GqDobxBztB,MAAOstB,EAAYvkC,EACnBkX,MAAOqtB,EAAYxkC,EACnBC,EAAGykC,EACH1kC,EAAG2kC,EAEP,CAQAZ,kBAAAA,GACE,MAAMhtC,EAASnD,KAAKyjB,aAClBrhB,EAAUpC,KAAKkwC,eACf79B,MAAEA,EAAKC,OAAEA,EAAMgR,MAAEA,EAAKC,MAAEA,EAAKlX,EAAEA,EAACD,EAAEA,GAAMpM,KAAKowC,gBAC3CpwC,KAAK2wC,6BAEPM,EAAoB5+B,IAAUlP,EAAOkP,OAASC,IAAWnP,EAAOmP,OAChE4+B,EAAclxC,KAAKsjB,QAAUA,GAAStjB,KAAKujB,QAAUA,EAEvD,IAAKpgB,IAAWf,EACd,OAAO,EAKT,GAFqB6uC,GAAqBC,EAExB,CACZ7+B,IAAUlP,EAAOkP,OAASC,IAAWnP,EAAOmP,QAC9CnP,EAAOkP,MAAQA,EACflP,EAAOmP,OAASA,IAEhBlQ,EAAQ+uC,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GACpC/uC,EAAQkf,UAAU,EAAG,EAAGne,EAAOkP,MAAOlP,EAAOmP,SAE/C,MAAM8+B,EAAe/kC,EAAI,EACnBglC,EAAgBjlC,EAAI,EAS1B,OARApM,KAAK0jB,kBACH9e,KAAKopB,MAAM7qB,EAAOkP,MAAQ,EAAI++B,GAAgBA,EAChDpxC,KAAK2jB,kBACH/e,KAAKopB,MAAM7qB,EAAOmP,OAAS,EAAI++B,GAAiBA,EAClDjvC,EAAQkvC,UAAUtxC,KAAK0jB,kBAAmB1jB,KAAK2jB,mBAC/CvhB,EAAQ+Z,MAAMmH,EAAOC,GACrBvjB,KAAKsjB,MAAQA,EACbtjB,KAAKujB,MAAQA,GACN,CACT,CACA,OAAO,CACT,CAQUysB,UAAAA,GAA8C,IAAnC9tC,EAA4B5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAClDN,KAAKgT,YAAY9Q,EACnB,CAMA8M,SAAAA,CAAUgN,GACR,MAAMu1B,EACHvxC,KAAK0sC,QAAU1sC,KAAK0sC,MAAM3pB,gBAC1B/iB,KAAK0sC,OAAS1sC,KAAKmD,QAAU6Y,IAAShc,KAAKmD,OAAkBquC,WAC1DhtB,EAAIxkB,KAAKk+B,qBAAqBqT,GACpCv1B,EAAIhN,UAAUwV,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAChD,CAMAitB,gBAAAA,GAKE,IAAKzxC,KAAK0sC,MACR,OAAO,IAAIvgC,GAAMvH,KAAKmH,IAAI/L,KAAKkW,QAAStR,KAAKmH,IAAI/L,KAAKmW,SAGxD,MAAMjU,EAAU6T,GAAY/V,KAAKk+B,uBACjC,OAAO,IAAI/xB,GAAMvH,KAAKmH,IAAI7J,EAAQgU,QAAStR,KAAKmH,IAAI7J,EAAQiU,QAC9D,CAMA06B,qBAAAA,GACE,MAAM10B,EAAQnc,KAAKyxC,mBACnB,GAAIzxC,KAAKmD,OAAQ,CACf,MAAM2lB,EAAO9oB,KAAKmD,OAAOsd,UACnBixB,EAAS1xC,KAAK6tC,yBACpB,OAAO1xB,EAAMlP,eAAe6b,EAAO4oB,EACrC,CACA,OAAOv1B,CACT,CAMAw1B,gBAAAA,GACE,IAAI3U,EAAUh9B,KAAKg9B,QAInB,OAHIh9B,KAAK0sC,QACP1P,GAAWh9B,KAAK0sC,MAAMiF,oBAEjB3U,CACT,CASA4U,eAAAA,CAAgB3tC,GACd,OAAIW,KAAKmH,IAAI9H,GAASjE,KAAKwjC,cACrBv/B,EAAQ,GACFjE,KAAKwjC,cAENxjC,KAAKwjC,cAEK,IAAVv/B,EACF,KAEFA,CACT,CAQAkP,IAAAA,CAAK5R,EAAa0C,GACZ1C,IAAQwG,GAAWxG,IAAQyG,IAC7B/D,EAAQjE,KAAK4xC,gBAAgB3tC,IAE3B1C,IAAQwG,GAAW9D,EAAQ,GAC7BjE,KAAKoX,OAASpX,KAAKoX,MACnBnT,IAAS,GACQ,WAAR1C,GAAoB0C,EAAQ,GACrCjE,KAAKqX,OAASrX,KAAKqX,MACnBpT,IAAS,GAEQ,WAAR1C,IAAoB0C,GAAWA,aAAiB2+B,KACzD3+B,EAAQ,IAAI2+B,GAAO3+B,IAGrB,MAAM4tC,EAAY7xC,KAAKuB,KAAuB0C,EAqB9C,OApBAjE,KAAKuB,GAAqB0C,EAIxB4tC,GACC7xC,KAAKF,YAAoCwjC,gBAAgBryB,SAAS1P,KAEnEvB,KAAK6jC,OAAQ,GAKf7jC,KAAK8xC,SACF9xC,KAAK6jC,OACHgO,GACE7xC,KAAKF,YAAoCujC,gBAAgBpyB,SACxD1P,KAENvB,KAAK8xC,OAAO3+B,KAAK,SAAS,GAErBnT,IACT,CAMA+xC,YAAAA,GACE,OACmB,IAAjB/xC,KAAKg9B,UACHh9B,KAAKqS,QAAUrS,KAAKsS,QAA+B,IAArBtS,KAAKq9B,cACpCr9B,KAAK2S,OAEV,CAMAkR,MAAAA,CAAO7H,GAEDhc,KAAK+xC,gBAIP/xC,KAAKmD,QACLnD,KAAKmD,OAAOyb,gBACX5e,KAAK0sC,QACL1sC,KAAKqtC,eAIRrxB,EAAI2G,OACJ3iB,KAAKgyC,yBAAyBh2B,GAC9Bhc,KAAKiyC,wBAAwBj2B,GAC7Bhc,KAAKgP,UAAUgN,GACfhc,KAAKkyC,YAAYl2B,GACjBhc,KAAKmyC,WAAWn2B,GACZhc,KAAK8iB,eACN9iB,KAA6BgjB,cAC7BhjB,KAA6BoyC,kBAAkBp2B,KAEhDhc,KAAKqyC,qBACLryC,KAAKsyC,WAAWt2B,GAAK,EAAO,CAAA,GAC5Bhc,KAAK6jC,OAAQ,GAEf7nB,EAAI6G,UACN,CAEAovB,uBAAAA,CAAwB3vB,GACtB,CAGFU,WAAAA,CAAuC9gB,GAKrC,GAJAA,EAAUA,GAAW,CAAA,EAChBlC,KAAKyjB,cAAiBzjB,KAAKkwC,eAC9BlwC,KAAKiwC,qBAEHjwC,KAAKuyC,gBAAkBvyC,KAAKkwC,cAAe,CAC7C,MAAM5sB,MAAEA,EAAKC,MAAEA,EAAKG,kBAAEA,EAAiBC,kBAAEA,GAAsB3jB,MACzDqS,MAAEA,EAAKC,OAAEA,GAAWtS,KAAKyjB,aAC/BzjB,KAAKsyC,WAAWtyC,KAAKkwC,cAAehuC,EAAQ+gB,YAAa,CACvDK,QACAC,QACAG,oBACAC,oBACAtR,QACAC,SACAkgC,gBAAiB,KAEnBxyC,KAAK6jC,OAAQ,CACf,CACF,CAKAwO,kBAAAA,GACEryC,KAAKyjB,kBAAejjB,EACpBR,KAAKkwC,cAAgB,IACvB,CAYAuC,SAAAA,GACE,QACIzyC,KAAK69B,QAA0B,gBAAhB79B,KAAK69B,QAAiD,IAArB79B,KAAKq9B,WAE3D,CAYAqV,OAAAA,GACE,QAAS1yC,KAAK+jB,MAAsB,gBAAd/jB,KAAK+jB,IAC7B,CAUA4uB,gBAAAA,GAEE,SACE3yC,KAAKm/B,aAAe/2B,GACpBpI,KAAK0yC,WACL1yC,KAAKyyC,aACHzyC,KAAK89B,WAIL99B,KAAKyiB,QAIX,CAWAK,WAAAA,GAIE,OAHA9iB,KAAK4yC,WACF5yC,KAAKyjC,iBAAmBzjC,KAAK8xC,SAAW9xC,KAAK8xC,OAAOe,eACrD7yC,KAAK2yC,mBACA3yC,KAAK4yC,UACd,CAQAE,cAAAA,GACE,QACI9yC,KAAK89B,SAAmC,IAAxB99B,KAAK89B,OAAOpjB,SAAyC,IAAxB1a,KAAK89B,OAAOvZ,QAE/D,CAOAwuB,mBAAAA,CACE/2B,EACAyG,EACAuwB,GAEAh3B,EAAI2G,OAGAF,EAASihB,SACX1nB,EAAIqH,yBAA2B,kBAE/BrH,EAAIqH,yBAA2B,iBAEjCrH,EAAIm1B,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GAChCn1B,EAAIwH,UAAUwvB,EAAoB,EAAG,GACrCh3B,EAAI6G,SACN,CAQAyvB,UAAAA,CACEt2B,EACAiH,EACA7gB,GAEA,MAAM6wC,EAAejzC,KAAK+jB,KACxBmvB,EAAiBlzC,KAAK69B,OACpB5a,GACFjjB,KAAK+jB,KAAO,QACZ/jB,KAAK69B,OAAS,GACd79B,KAAKmzC,uBAAuBn3B,IAE5Bhc,KAAK0iB,kBAAkB1G,GAEzBhc,KAAKozC,QAAQp3B,GACbhc,KAAKqzC,cAAcr3B,EAAKhc,KAAKyiB,SAAUrgB,GACvCpC,KAAK+jB,KAAOkvB,EACZjzC,KAAK69B,OAASqV,CAChB,CAEQI,mBAAAA,CAEN7wB,EACArgB,GAEA,MAAMe,EAAS8Q,GAAuB7R,GAChC4Z,EAAM7Y,EAAOC,WAAW,MAQ9B,GAPA4Y,EAAIs1B,UAAUlvC,EAAQshB,kBAAmBthB,EAAQuhB,mBACjD3H,EAAIG,MAAM/Z,EAAQkhB,MAAOlhB,EAAQmhB,OACjCd,EAASgB,aAAetgB,EACxBf,EAAQowC,gBAAgBzxC,QAASwyC,IAC/BA,EAAavkC,UAAUgN,KAEzB5Z,EAAQowC,gBAAgB9nC,KAAK+X,GACzBA,EAASuc,mBAAoB,CAC/B,MAAMxa,EAAItP,GAAgBlV,KAAKk+B,uBAC/BliB,EAAIhN,UAAUwV,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAChD,CAGA,OAFA/B,EAASzT,UAAUgN,GACnByG,EAAS6vB,WAAWt2B,GAAK,EAAM5Z,GACxBe,CACT,CAOAkwC,aAAAA,CACEr3B,EACAyG,EACArgB,GAEA,IAAKqgB,EACH,OAIFA,EAASM,gBAAiB,EAC1B,MAAM5f,EAAUnD,KAA6BszC,oBAC3C7wB,EACArgB,GAEFpC,KAAK+yC,oBAAoB/2B,EAAKyG,EAAUtf,EAC1C,CAMAivC,iBAAAA,CAA6Cp2B,GAC3CA,EAAIG,MAAM,EAAInc,KAAKsjB,MAAO,EAAItjB,KAAKujB,OACnCvH,EAAIwH,UACFxjB,KAAKyjB,cACJzjB,KAAK0jB,mBACL1jB,KAAK2jB,kBAEV,CAUA4uB,YAAAA,GAAiC,IAApBiB,EAAUlzC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GACrB,GAAIN,KAAK+xC,eACP,OAAO,EAET,MAAM5uC,EAASnD,KAAKyjB,aACdzH,EAAMhc,KAAKkwC,cACjB,SAAI/sC,IAAU6Y,GAAQw3B,IAAcxzC,KAAKmwC,0BAInCnwC,KAAK6jC,OAAU7jC,KAAKyiB,UAAYziB,KAAKyiB,SAASuc,sBAC5C77B,GAAU6Y,IAAQw3B,IACpBx3B,EAAI2G,OACJ3G,EAAIm1B,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GAChCn1B,EAAIsF,UAAU,EAAG,EAAGne,EAAOkP,MAAOlP,EAAOmP,QACzC0J,EAAI6G,YAEC,EAIb,CAOAH,iBAAAA,CAAkB1G,GAChB,IAAKhc,KAAKse,gBACR,OAEF,MAAM+vB,EAAMruC,KAAK4uC,+BACjB5yB,EAAIsI,UAAYtkB,KAAKse,gBAErBtC,EAAIy3B,UAAUpF,EAAIhiC,EAAI,GAAIgiC,EAAIjiC,EAAI,EAAGiiC,EAAIhiC,EAAGgiC,EAAIjiC,GAGhDpM,KAAK0zC,cAAc13B,EACrB,CAMAk2B,WAAAA,CAAYl2B,GACNhc,KAAK0sC,QAAU1sC,KAAK0sC,MAAM3pB,eAC5B/G,EAAI23B,YAAc3zC,KAAK2xC,mBAEvB31B,EAAI23B,aAAe3zC,KAAKg9B,OAE5B,CAEA4W,gBAAAA,CACE53B,EACA63B,GAUA,MAAMhW,EAASgW,EAAKhW,OAChBA,IACF7hB,EAAI83B,UAAYD,EAAKxW,YACrBrhB,EAAI+3B,QAAUF,EAAKrW,cACnBxhB,EAAIg4B,eAAiBH,EAAKtW,iBAC1BvhB,EAAIi4B,SAAWJ,EAAKpW,eACpBzhB,EAAIk4B,WAAaL,EAAKnW,iBAClBtjB,GAASyjB,GAEwC,eAAhDA,EAA8BsW,eAC9BtW,EAA8BpZ,mBAC9BoZ,EAAmBnZ,iBAMpB1kB,KAAKo0C,oCAAoCp4B,EAAK6hB,IAG9C7hB,EAAIq4B,YAAcxW,EAAOvjB,OAAO0B,GAChChc,KAAKs0C,+BAA+Bt4B,EAAK6hB,IAI3C7hB,EAAIq4B,YAAcR,EAAKhW,OAG7B,CAEA0W,cAAAA,CAAev4B,EAA6B9W,GAAgC,IAA9B6e,KAAEA,GAA0B7e,EACpE6e,IACE3J,GAAS2J,IACX/H,EAAIsI,UAAYP,EAAKzJ,OAAO0B,GAC5Bhc,KAAKs0C,+BAA+Bt4B,EAAK+H,IAEzC/H,EAAIsI,UAAYP,EAGtB,CAEAovB,sBAAAA,CAAuBn3B,GACrBA,EAAI23B,YAAc,EAClB33B,EAAIq4B,YAAc,cAClBr4B,EAAIsI,UAAY,SAClB,CAQAkwB,YAAAA,CAAax4B,EAA+By4B,GACrCA,GAAkC,IAArBA,EAAUl0C,QAG5Byb,EAAI04B,YAAYD,EAClB,CAMAtC,UAAAA,CAAWn2B,GACT,IAAKhc,KAAK89B,OACR,OAGF,MAAMA,EAAS99B,KAAK89B,OAClB36B,EAASnD,KAAKmD,OACd8Y,EAAgBjc,KAAK6tC,0BACpB8G,EAAE,CAAA,CAAMC,IAAMzxC,aAAM,EAANA,EAAQ8b,oBAAqBvY,EAC5CmuC,EAAQF,EAAK14B,EACb64B,EAAQF,EAAK34B,EACb84B,EAAUjX,EAAOqF,WAAa,IAAIh3B,GAAM,EAAG,GAAKnM,KAAKyxC,mBACvDz1B,EAAIg5B,YAAclX,EAAO7E,MACzBjd,EAAIi5B,WACDnX,EAAOiF,KACN5iC,EAAO+0C,2BACNL,EAAQC,IACRC,EAAQ1oC,EAAI0oC,EAAQ3oC,GACvB,EACF4P,EAAIm5B,cAAgBrX,EAAOpjB,QAAUm6B,EAAQE,EAAQ1oC,EACrD2P,EAAIo5B,cAAgBtX,EAAOvZ,QAAUuwB,EAAQC,EAAQ3oC,CACvD,CAMAsnC,aAAAA,CAAc13B,GACPhc,KAAK89B,SAIV9hB,EAAIg5B,YAAc,GAClBh5B,EAAIi5B,WAAaj5B,EAAIm5B,cAAgBn5B,EAAIo5B,cAAgB,EAC3D,CAOAd,8BAAAA,CACEt4B,EACA3B,GAEA,IAAKD,GAASC,GACZ,MAAO,CAAEK,QAAS,EAAG6J,QAAS,GAEhC,MAAM3W,EACHyM,EAA8BoK,mBAC9BpK,EAAmBqK,iBAChBhK,GAAW1a,KAAKqS,MAAQ,EAAIgI,EAAOK,SAAW,EAClD6J,GAAWvkB,KAAKsS,OAAS,EAAI+H,EAAOkK,SAAW,EAUjD,MARqD,eAAhDlK,EAA8B85B,cACjCn4B,EAAIhN,UAAUhP,KAAKqS,MAAO,EAAG,EAAGrS,KAAKsS,OAAQoI,EAAS6J,GAEtDvI,EAAIhN,UAAU,EAAG,EAAG,EAAG,EAAG0L,EAAS6J,GAEjC3W,GACFoO,EAAIhN,UAAUpB,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAEzC,CAAE8M,QAASA,EAAS6J,QAASA,EACtC,CAMA8wB,mBAAAA,CAAoBr5B,GACdhc,KAAKm/B,aAAe/2B,GACtBpI,KAAKs1C,cAAct5B,GACnBhc,KAAKu1C,YAAYv5B,KAEjBhc,KAAKu1C,YAAYv5B,GACjBhc,KAAKs1C,cAAct5B,GAEvB,CASAo3B,OAAAA,CAAQ9wB,GACN,CAOFizB,WAAAA,CAAYv5B,GACLhc,KAAK+jB,OAIV/H,EAAI2G,OACJ3iB,KAAKu0C,eAAev4B,EAAKhc,MACH,YAAlBA,KAAKo9B,SACPphB,EAAI+H,KAAK,WAET/H,EAAI+H,OAEN/H,EAAI6G,UACN,CAMAyyB,aAAAA,CAAct5B,GACZ,GAAKhc,KAAK69B,QAA+B,IAArB79B,KAAKq9B,YAAzB,CASA,GALIr9B,KAAK89B,SAAW99B,KAAK89B,OAAOoF,cAC9BljC,KAAK0zC,cAAc13B,GAGrBA,EAAI2G,OACA3iB,KAAK8+B,cAAe,CACtB,MAAMiW,EAAU/0C,KAAKyxC,mBACrBz1B,EAAIG,MAAM,EAAI44B,EAAQ1oC,EAAG,EAAI0oC,EAAQ3oC,EACvC,CACApM,KAAKw0C,aAAax4B,EAAKhc,KAAKs9B,iBAC5Bt9B,KAAK4zC,iBAAiB53B,EAAKhc,MAC3Bgc,EAAI6hB,SACJ7hB,EAAI6G,SAdJ,CAeF,CAaAuxB,mCAAAA,CACEp4B,EACA3B,GACA,IAAAm7B,EACA,MAAMnF,EAAOrwC,KAAKowC,gBAAgBpwC,KAAK2wC,6BACrC10B,EAAgBjc,KAAK6tC,yBACrBx7B,EAAQg+B,EAAKhkC,EAAIrM,KAAKkW,OAAS+F,EAC/B3J,EAAS+9B,EAAKjkC,EAAIpM,KAAKmW,OAAS8F,EAChCw5B,EAAUxhC,GAAuB,CAG/B5B,MAAOzN,KAAKosC,KAAK3+B,GACjBC,OAAQ1N,KAAKosC,KAAK1+B,KAGhBojC,EAAOD,EAAQryC,WAAW,MAC3BsyC,IAGLA,EAAKxxB,YACLwxB,EAAKvxB,OAAO,EAAG,GACfuxB,EAAKtxB,OAAO/R,EAAO,GACnBqjC,EAAKtxB,OAAO/R,EAAOC,GACnBojC,EAAKtxB,OAAO,EAAG9R,GACfojC,EAAKrxB,YACLqxB,EAAKpE,UAAUj/B,EAAQ,EAAGC,EAAS,GACnCojC,EAAKv5B,MACHk0B,EAAK/sB,MAAQtjB,KAAKkW,OAAS+F,EAC3Bo0B,EAAK9sB,MAAQvjB,KAAKmW,OAAS8F,GAE7Bjc,KAAKs0C,+BAA+BoB,EAAMr7B,GAC1Cq7B,EAAKpxB,UAAYjK,EAAOC,OAAO0B,GAC/B05B,EAAK3xB,OACL/H,EAAIs1B,WACDtxC,KAAKqS,MAAQ,EAAIrS,KAAKq9B,YAAc,GACpCr9B,KAAKsS,OAAS,EAAItS,KAAKq9B,YAAc,GAExCrhB,EAAIG,MACDF,EAAgBjc,KAAKkW,OAAUm6B,EAAK/sB,MACpCrH,EAAgBjc,KAAKmW,OAAUk6B,EAAK9sB,OAEvCvH,EAAIq4B,YAAsD,QAA3CmB,EAAGE,EAAKC,cAAcF,EAAS,oBAAY,IAAAD,EAAAA,EAAI,GAChE,CAUAI,sBAAAA,GACE,OAAO,IAAIzpC,GAAMnM,KAAKmS,KAAOnS,KAAKqS,MAAQ,EAAGrS,KAAKoS,IAAMpS,KAAKsS,OAAS,EACxE,CAOA9D,KAAAA,CAAM8W,GACJ,MAAMuwB,EAAa71C,KAAKwa,SAAS8K,GACjC,OAAQtlB,KAAKF,YAAoC8Y,WAC/Ci9B,EAEJ,CAqBAC,YAAAA,CAAa5zC,GACX,MAAMkS,EAAWpU,KAAK2oB,gBAAgBzmB,GAGtC,OAAO,IADYyG,GAAcE,SAA6B,SACvD,CAAeuL,EACxB,CAiBAuU,eAAAA,GAA4D,IAA5CzmB,EAAqC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACtD,MAAMy1C,EAAa7qB,GAAoBlrB,MACrCg2C,EAAgBh2C,KAAK0sC,MACrBuJ,EAAiBj2C,KAAK89B,OACtB/xB,EAAMnH,KAAKmH,IACXkQ,EAAgB/Z,EAAQ2c,oBAAsBna,IAAwB,EACtE+jB,GAAcvmB,EAAQumB,YAAc,GAAKxM,EACzCi6B,EACEh0C,EAAQg0C,gBAAc,CACpBx6B,GACA,IAAIyD,GAAazD,EAAI,CACnBmD,qBAAqB,EACrBF,mBAAmB,EACnBC,eAAe,YAEhB5e,KAAK0sC,MACRxqC,EAAQi0C,kBACVlrB,GAAqBjrB,MAEnBkC,EAAQk0C,gBACVp2C,KAAK89B,OAAS,MAEZ57B,EAAQ+c,mBACV2M,GAAkB5rB,KAAMA,KAAKguC,wBAG/BhuC,KAAKggB,YACL,MAAMtE,EAAK7H,KACTwiC,EAAer2C,KAAKotC,kBACpBtP,EAAS99B,KAAK89B,OACdwY,EAAe,IAAInqC,GAErB,GAAI2xB,EAAQ,CACV,MAAMmX,EAAanX,EAAOiF,KACpBgS,EAAUjX,EAAOqF,WACnB,IAAIh3B,GAAM,EAAG,GACbnM,KAAKyxC,mBAET6E,EAAajqC,EACX,EAAIzH,KAAKopB,MAAMjiB,EAAI+xB,EAAOpjB,SAAWu6B,GAAclpC,EAAIgpC,EAAQ1oC,GACjEiqC,EAAalqC,EACX,EAAIxH,KAAKopB,MAAMjiB,EAAI+xB,EAAOvZ,SAAW0wB,GAAclpC,EAAIgpC,EAAQ3oC,EACnE,CACA,MAAMiG,EAAQgkC,EAAahkC,MAAQikC,EAAajqC,EAC9CiG,EAAS+jC,EAAa/jC,OAASgkC,EAAalqC,EAG9CsP,EAAGrJ,MAAQzN,KAAKosC,KAAK3+B,GACrBqJ,EAAGpJ,OAAS1N,KAAKosC,KAAK1+B,GACtB,MAAMnP,EAAS+yC,EAAex6B,GACP,SAAnBxZ,EAAQmS,SACVlR,EAAOmb,gBAAkB,QAE3Bte,KAAKgrB,oBACH,IAAI7e,GAAMhJ,EAAOkP,MAAQ,EAAGlP,EAAOmP,OAAS,GAC5CxL,EACAA,GAEF,MAAMyvC,EAAiBv2C,KAAKmD,OAG5BA,EAAOkM,SAAW,CAACrP,MACnBA,KAAKuF,IAAI,SAAUpC,GACnBnD,KAAKggB,YACL,MAAM5L,EAAWjR,EAAOwlB,gBAAgBF,GAAc,EAAGvmB,GAczD,OAbAlC,KAAKuF,IAAI,SAAUgxC,GACnBv2C,KAAK89B,OAASmY,EACVD,IACFh2C,KAAK0sC,MAAQsJ,GAEfh2C,KAAKuF,IAAIwwC,GACT/1C,KAAKggB,YAIL7c,EAAOkM,SAAW,GAElBlM,EAAOqmB,UACApV,CACT,CAiBAD,SAAAA,GAA0C,IAAhCjS,EAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACpC,OAAO6T,GACLnU,KAAK2oB,gBAAgBzmB,GACrBA,EAAQmS,QAAU,MAClBnS,EAAQoS,SAAW,EAEvB,CACAC,MAAAA,GAAuC,IAAhCrS,EAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACjC,OAAOiU,GACLvU,KAAK2oB,gBAAgBzmB,GACrBA,EAAQmS,QAAU,MAClBnS,EAAQoS,SAAW,EAEvB,CAgBA1D,MAAAA,GAA2B,IAAA,IAAAlP,EAAApB,UAAAC,OAAjBkQ,EAAK,IAAA7O,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAL4O,EAAK5O,GAAAvB,UAAAuB,GACb,OACE4O,EAAMQ,SAAUjR,KAAKF,YAAoCkJ,OACzDyH,EAAMQ,SAASjR,KAAKgJ,KAExB,CAMAoI,UAAAA,GACE,OAAO,CACT,CAMAqU,MAAAA,GAEE,OAAOzlB,KAAKwa,UACd,CAMA/L,MAAAA,CAAO3C,GACL,MAAM63B,iBAAEA,EAAgBtW,QAAEA,EAAOC,QAAEA,GAAYttB,KAE/C,GAAI2jC,EAAkB,CACpB,MAAMt3B,EAAEA,EAACD,EAAEA,GAAMpM,KAAKuuB,yBACtBvuB,KAAKqtB,QAAUvmB,EACf9G,KAAKstB,QAAUxmB,EACf9G,KAAKmS,KAAO9F,EACZrM,KAAKoS,IAAMhG,CACb,CAIA,GAFApM,KAAKuF,IAAI,QAASuG,GAEd63B,EAAkB,CACpB,MAAMt3B,EAAEA,EAACD,EAAEA,GAAMpM,KAAK0vC,oBAAoBriB,EAASC,GACnDttB,KAAKmS,KAAO9F,EACZrM,KAAKoS,IAAMhG,EACXpM,KAAKqtB,QAAUA,EACfrtB,KAAKstB,QAAUA,CACjB,CACF,CAQAkpB,UAAAA,GACE,CAQFxE,wBAAAA,CAAyBh2B,GACnBhc,KAAKqjB,2BACPrH,EAAIqH,yBAA2BrjB,KAAKqjB,yBAExC,CAMA9e,OAAAA,GACE6E,GAAkBa,eAAejK,MACjCA,KAAKyK,MACLzK,KAAKmT,KAAK,cAAU3S,GAEpBR,KAAKyjB,cAAgBvf,IAASK,QAAQvE,KAAKyjB,cAC3CzjB,KAAKyjB,kBAAejjB,EACpBR,KAAKkwC,cAAgB,IACvB,CAqBAtH,OAAAA,CACE6N,EACAv0C,GAEA,OAAOzB,OAAO8J,QAAQksC,GAAYp1C,OAChC,CAACC,EAAGuJ,KAAsB,IAAnBtJ,EAAK2lC,GAASr8B,EAEnB,OADAvJ,EAAIC,GAAOvB,KAAK02C,SAASn1C,EAAK2lC,EAAUhlC,GACjCZ,GAET,CAAA,EAEJ,CAQAo1C,QAAAA,CACEn1C,EACA2lC,GAEe,IADfhlC,EAAqC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAExC,MAAMkiB,EAAOjhB,EAAIi6B,MAAM,KACjBmb,EACJ32C,KAAKF,YACL82C,gBAAgB3lC,SAASuR,EAAKA,EAAKjiB,OAAS,KACxCqJ,MAAEA,EAAKw8B,WAAEA,EAAUM,SAAEA,EAAQC,WAAEA,GAAezkC,EAC9C20C,EAAmB,IACpB30C,EACH8H,OAAQhK,KAERomC,WACEA,QAAAA,EAAc5jB,EAAKnhB,OAAO,CAAC2P,EAAWzP,IAAQyP,EAAKzP,GAAMvB,MAC3DknC,WACAt9B,MAAOA,aAAK,EAALA,EAAOi9B,KAAK7mC,MACnB0mC,SAAUA,CACRziC,EACAgkC,EACAD,KAEAxlB,EAAKnhB,OAAO,CAAC2P,EAA2BzP,EAAK+H,KACvCA,IAAUkZ,EAAKjiB,OAAS,IAC1ByQ,EAAKzP,GAAO0C,GAEP+M,EAAKzP,IACXvB,MACH0mC,GAEEA,EAASziC,EAAOgkC,EAAeD,IAEnCrB,WAAYA,CACV1iC,EACAgkC,EACAD,KAEAhoC,KAAKggB,YACL2mB,GAEEA,EAAW1iC,EAAOgkC,EAAeD,KAIvC,OACE2O,EACI7N,GAAa+N,GACbjO,GACEiO,EAGV,CAgBAC,cAAAA,CAAe9sC,GACb,MAAM8nC,OAAEA,EAAMpF,MAAEA,GAAU1sC,KAC1B,OACE8xC,IAAW9nC,GACX0iC,IAAU1iC,KAEP8nC,GAAUA,EAAOgF,eAAe9sC,MAChC0iC,GAASA,IAAUoF,GAAUpF,EAAMoK,eAAe9sC,EAEzD,CAKA+sC,YAAAA,GACE,MAAMC,EAAyB,GAE/B,IAAIlF,EAAgC9xC,KACpC,GACE8xC,EAASA,EAAOA,OAChBA,GAAUkF,EAAUtsC,KAAKonC,SAClBA,GACT,OAAOkF,CACT,CAQAC,mBAAAA,CAAoCzN,GAClC,GAAIxpC,OAASwpC,EACX,MAAO,CACL0N,KAAM,GACNC,UAAW,GACXC,OAAQ,CAACp3C,QAASA,KAAK+2C,iBAG3B,MAAMC,EAAYh3C,KAAK+2C,eACjBM,EAAiB7N,EAAMuN,eAE7B,GACuB,IAArBC,EAAUz2C,QACV82C,EAAe92C,OAAS,GACxBP,OAASq3C,EAAeA,EAAe92C,OAAS,GAEhD,MAAO,CACL22C,KAAM,GACNC,UAAW,CACT3N,KACG6N,EAAerd,MAAM,EAAGqd,EAAe92C,OAAS,IAErD62C,OAAQ,CAACp3C,OAIb,IAAK,IAAWs3C,EAAP7rC,EAAI,EAAaA,EAAIurC,EAAUz2C,OAAQkL,IAAK,CAEnD,GADA6rC,EAAWN,EAAUvrC,GACjB6rC,IAAa9N,EACf,MAAO,CACL0N,KAAM,CAACl3C,QAASg3C,EAAUhd,MAAM,EAAGvuB,IACnC0rC,UAAW,GACXC,OAAQJ,EAAUhd,MAAMvuB,IAG5B,IAAK,IAAI8rC,EAAI,EAAGA,EAAIF,EAAe92C,OAAQg3C,IAAK,CAC9C,GAAIv3C,OAASq3C,EAAeE,GAC1B,MAAO,CACLL,KAAM,GACNC,UAAW,CAAC3N,KAAU6N,EAAerd,MAAM,EAAGud,IAC9CH,OAAQ,CAACp3C,QAASg3C,IAGtB,GAAIM,IAAaD,EAAeE,GAC9B,MAAO,CACLL,KAAM,CAACl3C,QAASg3C,EAAUhd,MAAM,EAAGvuB,IACnC0rC,UAAW,CAAC3N,KAAU6N,EAAerd,MAAM,EAAGud,IAC9CH,OAAQJ,EAAUhd,MAAMvuB,GAG9B,CACF,CAEA,MAAO,CACLyrC,KAAM,CAACl3C,QAASg3C,GAChBG,UAAW,CAAC3N,KAAU6N,GACtBD,OAAQ,GAEZ,CAOAI,kBAAAA,CAAmChO,GACjC,MAAMiO,EAAkBz3C,KAAKi3C,oBAAoBzN,GACjD,OAAOiO,KAAqBA,EAAgBL,OAAO72C,MACrD,CAOAm3C,WAAAA,CAA4BlO,GAC1B,GAAIxpC,OAASwpC,EACX,OAEF,MAAMmO,EAAe33C,KAAKi3C,oBAAoBzN,GAE9C,GAAImO,EAAaT,KAAKjmC,SAASu4B,GAC7B,OAAO,EAET,GAAImO,EAAaR,UAAUlmC,SAASjR,MAClC,OAAO,EAIT,MAAM43C,EAAsBD,EAAaP,OAAO,IAAMp3C,KAAKmD,OAC3D,IAAKy0C,EACH,OAEF,MAAMC,EAAaF,EAAaT,KAAKY,MACnCC,EAAkBJ,EAAaR,UAAUW,MACzCE,EAAaJ,EAAoCvoC,SAAS9F,QACxDsuC,GAEFI,EAAcL,EAAoCvoC,SAAS9F,QACzDwuC,GAEJ,OAAOC,MAAkBA,EAAYC,CACvC,CAcAz9B,QAAAA,GACE,MAAM09B,GAD2B53C,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,IACckL,OAChDskC,EAAaqI,iBACZn4C,KAAKF,YAAoCq4C,kBAAoB,IAEhE,IAAIxyB,EACJ,MAAMzL,EAAsB/Z,EAAO+Z,qBAC7BuI,SACJA,EAAQsB,KACRA,EAAI8Z,OACJA,EAAMC,OACNA,EAAMR,gBACNA,EAAenrB,KACfA,EAAIC,IACJA,EAAGib,QACHA,EAAOC,QACPA,EAAOjb,MACPA,EAAKC,OACLA,EAAM+qB,YACNA,EAAWG,cACXA,EAAaD,iBACbA,EAAgBE,eAChBA,EAAcqB,cACdA,EAAapB,iBACbA,EAAgBxnB,OAChBA,EAAMC,OACNA,EAAMrK,MACNA,EAAKsL,MACLA,EAAKC,MACLA,EAAK2lB,QACLA,EAAOrqB,QACPA,EAAO2L,gBACPA,EAAe8e,SACfA,EAAQ+B,WACRA,EAAU9b,yBACVA,EAAwBjN,MACxBA,EAAKC,MACLA,GACErW,KACAyiB,IAAaA,EAASmD,oBACxBD,EAAelD,EAASjI,SACtB09B,EAAsB1sC,OAAO,WAAY,wBAG7C,MAAM4sC,EAAgBC,GAAgBz+B,GAAQy+B,EAAKn+B,GAC7CxK,EAAS,IACV8J,GAAKxZ,KAAMk4C,GACdlvC,KAAOhJ,KAAKF,YAAoCkJ,KAChD8c,QAAS3f,EACTknB,UACAC,UACAnb,KAAMimC,EAAajmC,GACnBC,IAAKgmC,EAAahmC,GAClBC,MAAO+lC,EAAa/lC,GACpBC,OAAQ8lC,EAAa9lC,GACrByR,KAAMxJ,GAAqBwJ,GAAQA,EAAKvJ,WAAauJ,EACrD8Z,OAAQtjB,GAAqBsjB,GAAUA,EAAOrjB,WAAaqjB,EAC3DR,YAAa+a,EAAa/a,GAC1BC,gBAAiBA,EACbA,EAAgB9xB,SAChB8xB,EACJE,gBACAD,mBACAE,iBACAqB,gBACApB,iBAAkB0a,EAAa1a,GAC/BxnB,OAAQkiC,EAAaliC,GACrBC,OAAQiiC,EAAajiC,GACrBrK,MAAOssC,EAAatsC,GACpBsL,QACAC,QACA2lB,QAASob,EAAapb,GACtBc,OAAQA,EAASA,EAAOtjB,WAAasjB,EACrCnrB,UACA2L,kBACA8e,WACA+B,aACA9b,2BACAjN,MAAOgiC,EAAahiC,GACpBC,MAAO+hC,EAAa/hC,MAChBsP,EAAe,CAAElD,SAAUkD,GAAiB,MAGlD,OAAQ3lB,KAAKye,qBAET/O,EADA1P,KAAKs4C,qBAAqB5oC,EAEhC,CAOA6V,gBAAAA,CAAiBD,GAEf,OAAOtlB,KAAKwa,SAAS8K,EACvB,CAMAgzB,oBAAAA,CAAuC5oC,GAGrC,MAAMtO,EAAYpB,KAAKF,YAAoC2f,cAErD84B,EADyB93C,OAAOU,KAAKC,GAAUb,OAAS,EAE1Da,EACAX,OAAO+3C,eAAex4C,MAE1B,OAAO0Z,GAAOhK,EAAQ,CAACzL,EAAO1C,KAC5B,GAAIA,IAAQwF,GAAQxF,IAAQyF,GAAe,SAARzF,EACjC,OAAO,EAET,MAAMk3C,EAAYF,EAAWh3C,GAC7B,OACE0C,IAAUw0C,KAGR72C,MAAMwN,QAAQnL,IACdrC,MAAMwN,QAAQqpC,IACG,IAAjBx0C,EAAM1D,QACe,IAArBk4C,EAAUl4C,SAIlB,CAMA2N,QAAAA,GACE,MAAO,KAAMlO,KAAKF,YAAoCkJ,OACxD,CAWA,kBAAO0vC,CAAWttC,GAGJ,IAFZpC,KAAEA,KAAS2vC,GAAkDvtC,GAC7DwtC,WAAEA,KAAe12C,GAA8C5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAElE,OAAO6Y,GAA6Bw/B,EAAyBz2C,GAAS2W,KACnEggC,GAGKD,UACKC,EAAqBD,GACrB,IAAI54C,KACT24C,EAAwBC,GAExBC,IAGK,IAAI74C,KAAK64C,GAIxB,CASA,iBAAOjgC,CACLlJ,EACAxN,GAEA,OAAOlC,KAAK04C,YAAYhpC,EAAQxN,EAClC,GAprDAnC,EAzCW+vC,GAAY,kBA+CYzM,IAEnCtjC,EAjDW+vC,GAAY,kBAwDYxM,IAAevjC,EAxDvC+vC,GAAY,cAqJFvM,IAAyBxjC,EArJnC+vC,GAAY,OAqKT,gBAAc/vC,EArKjB+vC,GAAY,kBAizCY,CAAC3nC,EAAMC,EAAQ,oBAAkBrI,EAjzCzD+vC,GAAY,mBAkiDa,IA8LtCnnC,GAAcG,SAASgnC,IACvBnnC,GAAcG,SAASgnC,GAAc,UC74D9B,MAAMgJ,GAAYA,CACvBtuC,EACAtI,KACG,IAAAgsB,EACH,MACElf,WAAWhF,OAAEA,IACX9H,EACS,QAAbgsB,EAAAlkB,EAAO7G,cAAM,IAAA+qB,GAAbA,EAAe7iB,KAAK,UAAUb,IAAa,IACtCtI,EACH8H,WAEFA,EAAOqB,KAAKb,EAAWtI,ICDZ62C,GAAoBA,CAI/BvuC,EACAwuC,EACAC,IAEQ,CAACtrB,EAAW3e,EAAW3C,EAAGD,KAChC,MAAM8sC,EAAkBF,EAAcrrB,EAAW3e,EAAW3C,EAAGD,GAO/D,OANI8sC,GACFJ,GAAUtuC,EAAW,IAChBkjB,GAAgBC,EAAW3e,EAAW3C,EAAGD,MACzC6sC,IAGAC,GCvBJ,SAASC,GACdH,GAEA,MAAQ,CAACrrB,EAAW3e,EAAW3C,EAAGD,KAChC,MAAMpC,OAAEA,EAAMqjB,QAAEA,EAAOC,QAAEA,GAAYte,EACnCoqC,EAAapvC,EAAO0lC,oBAAoBriB,EAASC,GACjD4rB,EAAkBF,EAAcrrB,EAAW3e,EAAW3C,EAAGD,GAQ3D,OALApC,EAAOghB,oBACLouB,EACApqC,EAAUqe,QACVre,EAAUse,SAEL4rB,EAEX,CCjBO,MAAMG,GACXA,CACEC,EACA3qC,EACA4qC,EACAp9B,IAEF,CAACwR,EAAW3e,EAAW3C,EAAGD,KACxB,MAOMotC,EAPavrB,GACjBjf,EACAA,EAAUqe,QACVre,EAAUse,QACVjhB,EACAD,GAEiCmtC,GAE7BttB,EAAcD,GAAchd,EAAUL,IAC5C,GACkB,IAAhBsd,GACCA,EAAc,GAAKutB,EAAkB,GACrCvtB,EAAc,GAAKutB,EAAkB,EACtC,CACA,MAAMxvC,OAAEA,GAAWgF,EACjByqC,EACEzvC,EAAOqzB,aAAerzB,EAAO80B,cAAgB90B,EAAOmS,GAAS,GAC/DsM,EAAa2E,GAAoBpe,GAAa,EAAI,EAClD0qC,EAAW1vC,EAAOsvC,GAClBK,EACE/0C,KAAKmH,IAAKytC,EAAkB/wB,EAAcze,EAAOmS,IACjDs9B,EAGJ,OAFAzvC,EAAOzE,IAAI+zC,EAAW10C,KAAKC,IAAI80C,EAAU,IAElCD,IAAa1vC,EAAOsvC,EAC7B,CACA,OAAO,GAcEM,GACXP,GAAyB,QAAS,UAAW,IAAK,UAavCQ,GACXR,GAAyB,SAAU,UAAW,IAAK,UAKxCS,GAAcf,GACzBrxC,EACAyxC,GAAoBS,KAMTG,GAAehB,GAC1BrxC,EACAyxC,GAAoBU,KCjDf,SAASG,GAEdh+B,EACA7J,EACAC,EACA6nC,EACA9qC,GAEA6M,EAAI2G,OACJ,MAAMkb,OAAEA,EAAMqc,MAAEA,EAAKC,MAAEA,EAAKC,OAAEA,GAAWp6C,KAAKq6C,kBAC5Cr+B,EACA7J,EACAC,EACAjD,EACA8qC,GAEF,IAAInqC,EAAOoqC,EAEPA,EAAQC,EACVn+B,EAAIG,MAAM,EAAKg+B,EAAQD,GACdC,EAAQD,IACjBpqC,EAAOqqC,EACPn+B,EAAIG,MAAM+9B,EAAQC,EAAO,IAE3Bn+B,EAAIkI,YACJlI,EAAIs+B,IAAI,EAAG,EAAGxqC,EAAO,EAAG,EAAGtJ,GAAW,GACtCwV,EAAIo+B,KACAvc,GACF7hB,EAAI6hB,SAEN7hB,EAAI6G,SACN,CAaO,SAAS03B,GAEdv+B,EACA7J,EACAC,EACA6nC,EACA9qC,GAEA6M,EAAI2G,OACJ,MAAMkb,OAAEA,EAAMqc,MAAEA,EAAKC,MAAEA,EAAKC,OAAEA,GAAWp6C,KAAKq6C,kBAC1Cr+B,EACA7J,EACAC,EACAjD,EACA8qC,GAEFO,EAAWN,EAAQ,EACnBO,EAAWN,EAAQ,EAIrBn+B,EAAI,GAAGo+B,UAAeI,GAAWC,EAAUP,EAAOC,GAC9Ctc,GACF7hB,EAAI0+B,YAAYF,GAAWC,EAAUP,EAAOC,GAE9Cn+B,EAAI6G,SACN,CCnFO,MAAM83B,GAyHX76C,WAAAA,CAAYoC,GAxHZnC,kBAQU,GAEVA,oBAWa+H,GAEb/H,eAOQ,GAERA,WAOI,GAEJA,WAOI,GAEJA,iBAYU,GAEVA,iBAMU,GAEVA,eAMQ,GAERA,eAMQ,GAERA,oBAMa,GAEbA,oBAMa,GAEbA,qBAMc,aAEdA,yBAMiB,GAGfU,OAAOC,OAAOV,KAAMkC,EACtB,CAgCA04C,cAAAA,CACEC,EACA1rC,EACAye,EAAc1oB,GAEd,IAAA41C,EAAA,IADAtoC,GAAEA,EAAE2P,GAAEA,EAAE1P,GAAEA,EAAE2P,GAAEA,GAAkBld,EAGhC,OACqB,QAAnB41C,EAAA3rC,EAAahM,cAAM,IAAA23C,OAAA,EAAnBA,EAAqBC,qBAAsB5rC,GAC3CA,EAAa6rC,iBAAiBH,IAC9B9R,GAAaQ,iBAAiB3b,EAAS,CAACpb,EAAI2P,EAAI1P,EAAI2P,GAExD,CASA64B,gBAAAA,CACEttB,EACAxe,EACA2e,GAEA,OAAO9tB,KAAKg5C,aACd,CASAkC,mBAAAA,CACEvtB,EACAxe,EACA2e,GAEA,OAAO9tB,KAAKm7C,gBACd,CAUAC,iBAAAA,CACEztB,EACAxe,EACA2e,GAEA,OAAO9tB,KAAKq7C,cACd,CAWAC,kBAAAA,CACE3tB,EACAG,EACA3e,EACA4e,GAEA,OAAOD,EAAQytB,WACjB,CASAC,aAAAA,CACE7tB,EACAG,EACA3e,GAEA,OAAO2e,EAAQ2tB,UACjB,CAQAC,aAAAA,CAAcvsC,EAAuC0rC,GAAoB,IAAAc,EAAAC,EACvE,OAAqD,QAArDD,UAAAC,EAAOzsC,EAAa0sC,2BAAmB,IAAAD,OAAA,EAAhCA,EAAmCf,cAAWc,EAAAA,EAAI37C,KAAK2S,OAChE,CAOAmpC,aAAAA,CACEne,EACAoS,EACA5gC,GAEAnP,KAAK2S,QAAUgrB,CACjB,CAEAoe,eAAAA,CACE1N,EACAD,EACAj/B,EACA6sC,GAEA,OAAO,IAAI7vC,GACTnM,KAAKqM,EAAIgiC,EAAIhiC,EAAIrM,KAAK0a,QACtB1a,KAAKoM,EAAIiiC,EAAIjiC,EAAIpM,KAAKukB,SACtBvV,UAAUo/B,EACd,CAWA6N,gBAAAA,CACEnwC,EACAowC,EACAC,EACAC,EACAC,EACAltC,GAEA,MAAMvB,EAAI4H,GAA6B,CACrCgB,GAAsB2lC,EAASC,GAC/B3lC,GAAmB,CAAE3K,UACrB+K,IACGwlC,EAAUr8C,KAAKs8C,WAAat8C,KAAKu8C,QAAUL,GAC3CG,EAAUr8C,KAAKw8C,WAAax8C,KAAKy8C,QAAUP,KAGhD,MAAO,CACL1pC,GAAI,IAAIrG,IAAM,IAAM,IAAM6C,UAAUpB,GACpCuU,GAAI,IAAIhW,GAAM,IAAK,IAAM6C,UAAUpB,GACnC6E,GAAI,IAAItG,GAAM,GAAK,IAAK6C,UAAUpB,GAClCwU,GAAI,IAAIjW,IAAM,GAAM,IAAK6C,UAAUpB,GAEvC,CAQAysC,iBAAAA,CACEr+B,EACA7J,EACAC,EACAjD,GAQA,IAPA8qC,EAA4C35C,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAQ/C,MAAMo8C,WAAEA,EAAUC,YAAEA,EAAWC,mBAAEA,EAAkBC,kBAAEA,GACjD5C,EACF6C,EAAgBJ,GAAcvtC,EAAautC,WAC3CxC,EAAQl6C,KAAKu8C,OAASO,EACtB3C,EAAQn6C,KAAKy8C,OAASK,EACtBC,OACgC,IAAvBH,EACHA,EACAztC,EAAaytC,mBACnBxC,EAAS2C,EAAc30C,EAASD,EAChC60C,EAAcH,GAAqB1tC,EAAa0tC,kBAChDhf,GAAUkf,KAAiBC,EAM7B,OALAhhC,EAAIsI,UAAYq4B,GAAextC,EAAawtC,aAAe,GAC3D3gC,EAAIq4B,YAAc2I,GAAe,GACjChhC,EAAIs1B,UAAUn/B,EAAMC,GAEpB4J,EAAIvN,OAAOkG,GAAiBxF,EAAa4+B,kBAClC,CACLlQ,SACAqc,QACAC,QACAyC,mBAAoBG,EACpB3C,SAEJ,CAcAv2B,MAAAA,CACE7H,EACA7J,EACAC,EACA6nC,EACA9qC,GAGA,GACO,aAFP8qC,EAAgBA,GAAiB,CAAA,GACXgD,aAAe9tC,EAAa8tC,aAE9CjD,GAAoB/uC,KAClBjL,KACAgc,EACA7J,EACAC,EACA6nC,EACA9qC,QAIForC,GAAoBtvC,KAClBjL,KACAgc,EACA7J,EACAC,EACA6nC,EACA9qC,EAGR,ECxZK,MAAM+tC,GAA8CA,CACzDvvB,EACAG,EACA3e,IAEIA,EAAaguC,aACRhwB,GAEFW,EAAQytB,YAsDJ6B,GAAuBrE,GAClCxxC,EACA4xC,GA3CuDkE,CACvD1vB,EAASzoB,EAETmH,EACAD,KACG,IAHHpC,OAAEA,EAAMszC,GAAEA,EAAEC,GAAEA,EAAEC,MAAEA,EAAKnwB,QAAEA,EAAOC,QAAEA,GAASpoB,EAI3C,MAAMu4C,EAAazzC,EAAO0lC,oBAAoBriB,EAASC,GAEvD,GAAIE,GAASxjB,EAAQ,gBACnB,OAAO,EAGT,MAAM0zC,EAAY94C,KAAKkR,MAAMynC,EAAKE,EAAWrxC,EAAGkxC,EAAKG,EAAWpxC,GAC9DsxC,EAAW/4C,KAAKkR,MAAM1J,EAAIqxC,EAAWrxC,EAAGC,EAAIoxC,EAAWpxC,GACzD,IAAIP,EAAQ+I,GAAiB8oC,EAAWD,EAAYF,GAEpD,GAAIxzC,EAAO4zC,WAAa5zC,EAAO4zC,UAAY,EAAG,CAC5C,MAAMA,EAAY5zC,EAAO4zC,UACvBC,EAAgB7zC,EAAO6zC,eAAiBD,EACxCE,EAAmBl5C,KAAKosC,KAAKllC,EAAQ8xC,GAAaA,EAClDG,EAAkBn5C,KAAKsB,MAAM4F,EAAQ8xC,GAAaA,EAEhDh5C,KAAKmH,IAAID,EAAQiyC,GAAmBF,EACtC/xC,EAAQiyC,EACCn5C,KAAKmH,IAAID,EAAQgyC,GAAoBD,IAC9C/xC,EAAQgyC,EAEZ,CAGIhyC,EAAQ,IACVA,EAAQ,IAAMA,GAEhBA,GAAS,IAET,MAAMkyC,EAAah0C,EAAO8B,QAAUA,EAGpC,OADA9B,EAAO8B,MAAQA,EACRkyC,KC1CF,SAASC,GACdtwB,EACAxe,GAEA,MAAMhM,EAASgM,EAAahM,OAC1B+6C,EAAmBvwB,EAAUxqB,EAAOg7C,aACtC,OACGh7C,EAAOi7C,iBAAmBF,IACzB/6C,EAAOi7C,gBAAkBF,CAE/B,CASO,SAASG,GACdlvC,EACAmvC,EACAC,GAEA,MAAMC,EAAQhxB,GAASre,EAAc,gBACnCsvC,EAAQjxB,GAASre,EAAc,gBACjC,GAAIqvC,GAASC,EACX,OAAO,EAET,IAAKH,IAAOE,GAASC,IAAUF,EAC7B,OAAO,EAET,GAAIC,GAAgB,MAAPF,EACX,OAAO,EAET,GAAIG,GAAgB,MAAPH,EACX,OAAO,EAIT,MAAMjsC,MAAEA,EAAKC,OAAEA,EAAM+qB,YAAEA,GAAgBluB,EACvC,OAAc,IAAVkD,GAA+B,IAAhBgrB,GAA4B,MAAPihB,GAGzB,IAAXhsC,GAAgC,IAAhB+qB,GAA4B,MAAPihB,CAI3C,CAEA,MAAMI,GAAW,CAAC,IAAK,KAAM,IAAK,KAAM,IAAK,KAAM,IAAK,KAAM,KASjDC,GAAiDA,CAC5DhxB,EACAG,EACA3e,EACA4e,KAEA,MAAMwwB,EAAsBN,GAAoBtwB,EAAWxe,GAO3D,GAAIkvC,GAAmBlvC,EALL,IAAd2e,EAAQzhB,GAAyB,IAAdyhB,EAAQ1hB,EACvB,IACc,IAAd0hB,EAAQzhB,GAAyB,IAAdyhB,EAAQ1hB,EACzB,IACA,GAC+BmyC,GACvC,OAAOpxB,GAET,MAAMyxB,EAAI/wB,GAAmB1e,EAAc2e,EAASC,GACpD,MAAO,GAAG2wB,GAASE,aAerB,SAASC,GACPlxB,EACA3e,EACA3C,EACAD,GAEA,IADAlK,EAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE5B,MAAM0J,EAASgF,EAAUhF,OACvBs0C,EAAKp8C,EAAQo8C,GACbC,EAAsBN,GAAoBtwB,EAAW3jB,GAEvD,IAAI+W,EAAU7K,EAAQC,EAAQk4B,EAAKyQ,EAAOC,EAE1C,GAHkBV,GAAmBr0C,EAAQs0C,EAAIC,GAI/C,OAAO,EAET,GAAIvvC,EAAUgwC,aACZ9oC,EAASlH,EAAUkH,OAASlH,EAAUgwC,aACtC7oC,EAASnH,EAAUmH,OAASnH,EAAUgwC,iBACjC,CAsBL,GArBAj+B,EAAWkN,GACTjf,EACAA,EAAUqe,QACVre,EAAUse,QACVjhB,EACAD,GAOF0yC,EAAe,MAAPR,EAAa15C,KAAKsH,KAAK6U,EAAS1U,GAAK2C,EAAU8vC,OAAS,GAAK,EACrEC,EAAe,MAAPT,EAAa15C,KAAKsH,KAAK6U,EAAS3U,GAAK4C,EAAU+vC,OAAS,GAAK,EAChE/vC,EAAU8vC,QACb9vC,EAAU8vC,MAAQA,GAEf9vC,EAAU+vC,QACb/vC,EAAU+vC,MAAQA,GAIlBvxB,GAASxjB,EAAQ,qBAChBgF,EAAU8vC,QAAUA,GAAS9vC,EAAU+vC,QAAUA,GAElD,OAAO,EAKT,GAFA1Q,EAAMrkC,EAAOwjC,4BAET+Q,IAAwBD,EAAI,CAE9B,MAAMW,EAAWr6C,KAAKmH,IAAIgV,EAAS1U,GAAKzH,KAAKmH,IAAIgV,EAAS3U,IACxD8yC,SAAEA,GAAalwC,EAIfmN,EAAQ8iC,GAFNr6C,KAAKmH,IAAKsiC,EAAIhiC,EAAI6yC,EAAShpC,OAAUlM,EAAOkM,QAC5CtR,KAAKmH,IAAKsiC,EAAIjiC,EAAI8yC,EAAS/oC,OAAUnM,EAAOmM,SAEhDD,EAASgpC,EAAShpC,OAASiG,EAC3BhG,EAAS+oC,EAAS/oC,OAASgG,CAC7B,MACEjG,EAAStR,KAAKmH,IAAKgV,EAAS1U,EAAIrC,EAAOkM,OAAUm4B,EAAIhiC,GACrD8J,EAASvR,KAAKmH,IAAKgV,EAAS3U,EAAIpC,EAAOmM,OAAUk4B,EAAIjiC,GAGnDghB,GAAoBpe,KACtBkH,GAAU,EACVC,GAAU,GAERnH,EAAU8vC,QAAUA,GAAgB,MAAPR,IAC/BtvC,EAAUqe,QAAUE,GAAave,EAAUqe,SAC3CnX,IAAU,EACVlH,EAAU8vC,MAAQA,GAEhB9vC,EAAU+vC,QAAUA,GAAgB,MAAPT,IAC/BtvC,EAAUse,QAAUC,GAAave,EAAUse,SAC3CnX,IAAU,EACVnH,EAAU+vC,MAAQA,EAEtB,CAEA,MAAMI,EAAYn1C,EAAOkM,OACvBkpC,EAAYp1C,EAAOmM,OASrB,OARKmoC,GAKI,MAAPA,GAAct0C,EAAOzE,IAAIwC,EAASmO,GAC3B,MAAPooC,GAAct0C,EAAOzE,IAAIyC,EAASmO,MALjCqX,GAASxjB,EAAQ,iBAAmBA,EAAOzE,IAAIwC,EAASmO,IACxDsX,GAASxjB,EAAQ,iBAAmBA,EAAOzE,IAAIyC,EAASmO,IAMpDgpC,IAAcn1C,EAAOkM,QAAUkpC,IAAcp1C,EAAOmM,MAC7D,CAWO,MA6CMkpC,GAAiBtG,GAC5BzxC,EACA6xC,GA/C2EmG,CAC3E3xB,EACA3e,EACA3C,EACAD,IAEOyyC,GAAYlxB,EAAW3e,EAAW3C,EAAGD,KA4CjCmzC,GAAWxG,GACtBzxC,EACA6xC,GAlC2DqG,CAC3D7xB,EACA3e,EACA3C,EACAD,IAEOyyC,GAAYlxB,EAAW3e,EAAW3C,EAAGD,EAAG,CAAEkyC,GAAI,QA+B1CmB,GAAW1G,GACtBzxC,EACA6xC,GArB2DuG,CAC3D/xB,EACA3e,EACA3C,EACAD,IAEOyyC,GAAYlxB,EAAW3e,EAAW3C,EAAGD,EAAG,CAAEkyC,GAAI,QC/OjDqB,GAUF,CACFtzC,EAAG,CACDuzC,YAAa,IACbzjC,MAAOpU,EACP83C,KAAM53C,EACN63C,YAAa,eACbnxC,OAAQ,UACRoxC,KAAM,SAER3zC,EAAG,CACDwzC,YAAa,IACbzjC,MAAOnU,EACP63C,KAAM33C,EACN43C,YAAa,eACbnxC,OAAQ,UACRoxC,KAAM,UAIJC,GAAU,CAAC,KAAM,OAAQ,KAAM,QASxBC,GAAgDA,CAC3DtyB,EACAG,EACA3e,EACA4e,KAEA,GAAkB,IAAdD,EAAQzhB,GAAWmhB,GAASre,EAAc,gBAC5C,OAAOge,GAET,GAAkB,IAAdW,EAAQ1hB,GAAWohB,GAASre,EAAc,gBAC5C,OAAOge,GAET,MAAMyxB,EAAI/wB,GAAmB1e,EAAc2e,EAASC,GAAS,EAC7D,MAAO,GAAGiyB,GAAQpB,aAwEpB,SAASsB,GACPC,EACAxyB,EACA3e,EACA3C,EACAD,GAEA,MAAMpC,OAAEA,GAAWgF,GACjB4wC,YACEA,EACAjxC,OAAQyxC,EACRN,YAAaO,EACbR,KAAMS,EACNP,KAAMQ,GACJZ,GAAUQ,GAChB,GAAI3yB,GAASxjB,EAAQq2C,GACnB,OAAO,EAGT,MAAQ1xC,OAAQ6xC,EAAkBT,KAAMU,GACpCd,GAAUC,GACZc,EACE10B,GAAchd,EAAUwxC,KACvBx2C,EAAOy2C,IAAkB,EAAK,GAKjCE,GAAgB/7C,KAAKsH,KAAKw0C,IACvB12C,EAAOu2C,IAAW,EAAK,GAW1B5xC,EAA6B,MATL,IAApB3E,EAAOs2C,IAEPryB,GAAcjf,EAAWlI,EAAQA,EAAQuF,EAAGD,GAAG+zC,GAAQ,GAEzDn2C,EAAOs2C,GAAW,EACd,GACA,GAAMK,GAGuB,GAE/BC,EAAe7H,GACnBtxC,EACA0xC,GAAoB,CAACxrB,EAAW3e,EAAW3C,EAAGD,IA7GlD,SACE+zC,EAAWj7C,EAEX0oB,GACA,IAFA5jB,OAAEA,EAAMszC,GAAEA,EAAEC,GAAEA,EAAEoD,YAAEA,KAAgB3xC,GAA0B9J,EAG5D,MAAQ26C,KAAMS,GAAYX,GAAUQ,GAClC9iC,EAASuQ,EACNhhB,SAAS,IAAIT,GAAMmxC,EAAIC,IACvBpwC,OAAO,IAAIhB,GAAMnC,EAAOkM,OAAQlM,EAAOmM,SAASgqC,GACnDU,EAAgB72C,EAAOs2C,GACvBQ,EAAe9xC,EAAUsxC,GACzBS,EAAgBn8C,KAAKmS,IAAIpC,GAAiBmsC,IAM1CxrC,EACW,MAAT6qC,EACIn2C,EAAOwjC,0BAA0B,CAC/Bt3B,OAAQ,EACRC,OAAQ,EAERC,MAAO,IACN/J,EACHrC,EAAOwjC,0BAA0B,CAC/Bt3B,OAAQ,EACRC,OAAQ,IACP/J,EAEL40C,EACH,EAAI3jC,EAASsjC,EAEZ/7C,KAAKC,IAAIyQ,EAAG,GAEdyrC,EAEIE,EAAUpsC,GAAiBjQ,KAAKs8C,KAAKF,IAE3Ch3C,EAAOzE,IAAI+6C,EAASW,GACpB,MAAME,EAAUN,IAAkB72C,EAAOs2C,GAEzC,GAAIa,GAAoB,MAAThB,EAAc,CAG3B,MAAM/pC,MAAEA,EAAKF,OAAEA,GAAWlM,EACxBo3C,EAAYp3C,EAAOwjC,0BAA0B,CAAEn3B,MAAOwqC,IACtDQ,EAAWr3C,EAAOwjC,4BAClB8T,EAA+B,IAAVlrC,EAAcgrC,EAAU/0C,EAAIg1C,EAASh1C,EAAI,EACzC,IAAvBi1C,GACEt3C,EAAOzE,IAAIwC,EAASu5C,EAAqBprC,EAC7C,CAEA,OAAOirC,CACT,CAwDMI,CAAWpB,EAAMnxC,EAAW,IAAI7C,GAAME,EAAGD,MAI7C,OAAOw0C,EACLjzB,EACA,IACK3e,EACHoxC,CAACA,GAAYzxC,EACbgyC,eAEFt0C,EACAD,EAEJ,CAWO,MAAMo1C,GAAuCA,CAClD7zB,EACA3e,EACA3C,EACAD,IAEO8zC,GAAY,IAAKvyB,EAAW3e,EAAW3C,EAAGD,GAYtCq1C,GAAuCA,CAClD9zB,EACA3e,EACA3C,EACAD,IAEO8zC,GAAY,IAAKvyB,EAAW3e,EAAW3C,EAAGD,GC7OnD,SAASs1C,GAAY/zB,EAA0B3jB,GAC7C,OAAO2jB,EAAU3jB,EAAO7G,OAAQw+C,aAClC,CASO,MAAMC,GAETA,CAACj0B,EAAWG,EAAS3e,KACvB,MAAM0yC,EAAgBH,GAAY/zB,EAAWxe,GAC7C,OAAkB,IAAd2e,EAAQzhB,EAEHw1C,EAAgB55C,EAASD,EAEhB,IAAd8lB,EAAQ1hB,EAEHy1C,EAAgB35C,EAASH,EAE3B,IAUI+5C,GAAqDA,CAChEn0B,EACAG,EACA3e,EACA4e,IAEO2zB,GAAY/zB,EAAWxe,GAC1B8wC,GAAuBtyB,EAAWG,EAAS3e,EAAc4e,GACzD4wB,GAAwBhxB,EAAWG,EAAS3e,EAAc4e,GAWnDg0B,GAA6CA,CACxDp0B,EACA3e,EACA3C,EACAD,IAEOs1C,GAAY/zB,EAAW3e,EAAUhF,QACpCy3C,GAAa9zB,EAAW3e,EAAW3C,EAAGD,GACtCmzC,GAAS5xB,EAAW3e,EAAW3C,EAAGD,GAY3B41C,GAA6CA,CACxDr0B,EACA3e,EACA3C,EACAD,IAEOs1C,GAAY/zB,EAAW3e,EAAUhF,QACpCw3C,GAAa7zB,EAAW3e,EAAW3C,EAAGD,GACtCqzC,GAAS9xB,EAAW3e,EAAW3C,EAAGD,GC/E3B61C,GAA8BA,KAAAA,CACzCC,GAAI,IAAIvH,GAAQ,CACdtuC,GAAG,GACHD,EAAG,EACHkvC,mBAAoBwG,GACpB9I,cAAe+I,GACfvG,cAAeoG,KAGjBO,GAAI,IAAIxH,GAAQ,CACdtuC,EAAG,GACHD,EAAG,EACHkvC,mBAAoBwG,GACpB9I,cAAe+I,GACfvG,cAAeoG,KAGjBQ,GAAI,IAAIzH,GAAQ,CACdtuC,EAAG,EACHD,EAAG,GACHkvC,mBAAoBwG,GACpB9I,cAAegJ,GACfxG,cAAeoG,KAGjBS,GAAI,IAAI1H,GAAQ,CACdtuC,EAAG,EACHD,GAAG,GACHkvC,mBAAoBwG,GACpB9I,cAAegJ,GACfxG,cAAeoG,KAGjBpvC,GAAI,IAAImoC,GAAQ,CACdtuC,GAAG,GACHD,GAAG,GACHkvC,mBAAoBqD,GACpB3F,cAAeqG,KAGjBl9B,GAAI,IAAIw4B,GAAQ,CACdtuC,EAAG,GACHD,GAAG,GACHkvC,mBAAoBqD,GACpB3F,cAAeqG,KAGjBj9B,GAAI,IAAIu4B,GAAQ,CACdtuC,GAAG,GACHD,EAAG,GACHkvC,mBAAoBqD,GACpB3F,cAAeqG,KAGjB5sC,GAAI,IAAIkoC,GAAQ,CACdtuC,EAAG,GACHD,EAAG,GACHkvC,mBAAoBqD,GACpB3F,cAAeqG,KAGjBiD,IAAK,IAAI3H,GAAQ,CACftuC,EAAG,EACHD,GAAG,GACH4sC,cAAeoE,GACf9B,mBAAoB4B,GACpB34B,SAAS,GACTg+B,gBAAgB,EAChB9G,WAAYj0C,MAIHg7C,GAAuBA,KAAAA,CAClCL,GAAI,IAAIxH,GAAQ,CACdtuC,EAAG,GACHD,EAAG,EACH4sC,cAAec,GACfwB,mBAAoBwG,GACpBrG,WAAY/zC,IAEdw6C,GAAI,IAAIvH,GAAQ,CACdtuC,GAAG,GACHD,EAAG,EACH4sC,cAAec,GACfwB,mBAAoBwG,GACpBrG,WAAY/zC,MAIH+6C,GAA+BA,KAAAA,IACvCR,QACAO,OC9DE,MAAME,WAKH5S,GA4FR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNijC,GAAwBhjC,YAE/B,CAMA5f,WAAAA,CAAYoC,GACV9B,QACAK,OAAOC,OACLV,KACCA,KAAKF,YAA+C6iD,iBACrDD,GAAwBhjC,aAE1B1f,KAAKgwC,WAAW9tC,EAClB,CAQA,qBAAOygD,GACL,MAAO,CAAEv0B,SAAU6zB,KACrB,CAQA9R,kBAAAA,GACE,MAAMyS,EAAe5iD,KAAKmD,OAC1B,GAAInD,KAAK6iD,cAAgBD,GAAgBA,EAAaE,kBAAmB,CACvE,MAAM9zC,EAAY4zC,EAAaE,kBAC7B94C,EAASgF,EAAUhF,OACnB+4C,EAAS/zC,EAAU+zC,OACrB,GACE/iD,OAAUgK,GACV+4C,GACAA,EAAOC,WAAWl7C,GAElB,OAAO,CAEX,CACA,OAAO1H,MAAM+vC,oBACf,CAEA8S,gBAAAA,GACE,MAAM1hD,EAAMvB,KAAKkjD,SACjB,OAAO3hD,EACH,CACEA,MACAusB,QAAS9tB,KAAKouB,SAAS7sB,GACvBwsB,MAAO/tB,KAAKmjD,QAAQ5hD,SAEtBf,CACN,CAaA4iD,WAAAA,CACEx1B,GAE+D,IAD/Dy1B,EAAQ/iD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAER,IAAKN,KAAKsjD,cAAgBtjD,KAAKmD,OAC7B,OAGFnD,KAAKkjD,cAAW1iD,EAChB,MAAM+iD,EAAgB9iD,OAAO8J,QAAQvK,KAAKmjD,SAC1C,IAAK,IAAI13C,EAAI83C,EAAchjD,OAAS,EAAGkL,GAAK,EAAGA,IAAK,CAClD,MAAOlK,EAAK4sB,GAAUo1B,EAAc93C,GAC9BqiB,EAAU9tB,KAAKouB,SAAS7sB,GAE9B,GACEusB,EAAQ8sB,eACNr5C,EACAvB,KACA4tB,EACAy1B,EAAWl1B,EAAOq1B,YAAcr1B,EAAOA,QAMzC,OAFAnuB,KAAKkjD,SAAW3hD,EAET,CAAEA,MAAKusB,UAASC,MAAO/tB,KAAKmjD,QAAQ5hD,GAE/C,CAGF,CASAkiD,WAAAA,GACE,MAAM9iC,EAAM3gB,KAAKguC,uBACf5oB,EAASplB,KAAK2kB,iBACdwpB,EAAU33B,GAAsB4O,EAAO/Y,EAAG+Y,EAAOhZ,GACjDs3C,EAAUjtC,GAAmB,CAC3B3K,MAAO9L,KAAK+tC,iBAAqB/tC,KAAK0sC,OAAS1sC,KAAKoX,MAAQ,IAAM,KAEpEusC,EAAiBtuC,GAA0B84B,EAASuV,GACpDE,EAAcvuC,GAA0BsL,EAAKgjC,GAC7CvV,EAAc/4B,GAA0BuuC,EAAa,CACnD,EAAIjjC,EAAI,GACR,EACA,EACA,EAAIA,EAAI,GACR,EACA,IAEFkjC,EAAmB7jD,KAAK0sC,MACpB32B,GAAY/V,KAAKk+B,4BACjB19B,EAEFqjD,IACFA,EAAiB3tC,OAAStR,KAAKmH,IAAI83C,EAAiB3tC,QACpD2tC,EAAiB1tC,OAASvR,KAAKmH,IAAI83C,EAAiB1tC,SAEtD,MAAMk4B,EAAMruC,KAAK6uC,4BAA4BgV,GAC3C7W,EAAkC,CAAA,EA0BpC,OAxBAhtC,KAAK8jD,eAAe,CAACh2B,EAASvsB,KAC5B,MAAMka,EAAWqS,EAAQiuB,gBAAgB1N,EAAKD,EAAapuC,KAAM8tB,GAIjEkf,EAAOzrC,GAAOd,OAAOC,OACnB+a,EACAzb,KAAK+jD,kBAAkBj2B,EAASrS,MAiB7BuxB,CACT,CASQ+W,iBAAAA,CAAkBj2B,EAAkBrS,GAC1C,MAAM3P,EAAQ9L,KAAK+tC,gBAiBnB,MAAO,CAAE5f,OAhBML,EAAQmuB,iBACrBnwC,EACA9L,KAAK08C,WACLjhC,EAASpP,EACToP,EAASrP,GACT,EACApM,MAUewjD,YARG11B,EAAQmuB,iBAC1BnwC,EACA9L,KAAKgkD,gBACLvoC,EAASpP,EACToP,EAASrP,GACT,EACApM,MAGJ,CAOAggB,SAAAA,GACE5f,MAAM4f,YACNhgB,KAAKmD,SAAWnD,KAAKmjD,QAAUnjD,KAAKyjD,cACtC,CAOAK,cAAAA,CACEG,GAMA,IAAK,MAAMx4C,KAAKzL,KAAKouB,SACnB61B,EAAGjkD,KAAKouB,SAAS3iB,GAAIA,EAAGzL,KAE5B,CAYAiyC,uBAAAA,CAAwBj2B,GACtB,IACGhc,KAAKkkD,0BACLlkD,KAAKmD,QAAWnD,KAAKmD,OAAOghD,gBAAsCnkD,KAEnE,OAEFgc,EAAI2G,OACJ,MAAMyC,EAASplB,KAAKuuB,yBAClB61B,EAAKpkD,KAAK6uC,8BACVluB,EAAM3gB,KAAKguC,uBACbhyB,EAAIs1B,UAAUlsB,EAAO/Y,EAAG+Y,EAAOhZ,GAC/B4P,EAAIG,MAAM,EAAIwE,EAAI,GAAI,EAAIA,EAAI,IAC9B3E,EAAIvN,OAAOkG,GAAiB3U,KAAK8L,QACjCkQ,EAAIsI,UAAYtkB,KAAKkkD,yBACrBloC,EAAIy3B,UAAU2Q,EAAG/3C,EAAI,GAAI+3C,EAAGh4C,EAAI,EAAGg4C,EAAG/3C,EAAG+3C,EAAGh4C,GAC5C4P,EAAI6G,SACN,CAOAwhC,aAAAA,CAAcroC,EAA+BlM,GAC3CkM,EAAI0+B,YAAY5qC,EAAKzD,EAAI,GAAIyD,EAAK1D,EAAI,EAAG0D,EAAKzD,EAAGyD,EAAK1D,EACxD,CAQAk4C,YAAAA,CACEtoC,EACAlM,GAEM,IADNmqC,EAA6B35C,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEhC,MAAM4B,EAAU,CACdohD,YAAatjD,KAAKsjD,YAClBiB,YAAavkD,KAAKukD,YAClBC,gBAAiBxkD,KAAKwkD,mBACnBvK,GAELj+B,EAAI2G,OACJ3G,EAAIq4B,YAAcnyC,EAAQqiD,YAC1BvkD,KAAKw0C,aAAax4B,EAAK9Z,EAAQsiD,iBAC/BxkD,KAAKqkD,cAAcroC,EAAKlM,GACxB5N,EAAQohD,aAAetjD,KAAKykD,4BAA4BzoC,EAAKlM,GAC7DkM,EAAI6G,SACN,CASA6hC,eAAAA,CACE1oC,GAEA,IADAi+B,EAA6B35C,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEhC,MAAMqkD,WAAEA,EAAUrB,YAAEA,GAAgBtjD,KAC9B4kD,EAAe,CACnBD,aACArB,iBACGrJ,GAECt5B,EAAM3gB,KAAKguC,uBACf6W,EAAoBD,EAAaD,WACjCG,EAAqBF,EAAatB,YAC9BhsC,EAASjC,GAA0BsL,EAAK3gB,KAAKk+B,uBAC7Ch8B,EAAU6T,GAAYuB,GAC5B0E,EAAI2G,OACJ3G,EAAIs1B,UAAUpvC,EAAQoU,WAAYpU,EAAQqU,YAC1CyF,EAAI83B,UAAY9zC,KAAK+kD,kBAMjB/kD,KAAK0sC,QAAU1sC,KAAK8xC,SACtB91B,EAAI23B,YAAc3zC,KAAKglD,SAAWhlD,KAAKilD,wBAA0B,GAE/DjlD,KAAKoX,QACPlV,EAAQ4J,OAAS,KAEnBkQ,EAAIvN,OAAOkG,GAAiB3U,KAAK0sC,MAAQxqC,EAAQ4J,MAAQ9L,KAAK8L,QAC9D+4C,GAAqB7kD,KAAKklD,YAAYlpC,EAAK9Z,EAAS+3C,GACpD6K,GAAsB9kD,KAAKqiB,aAAarG,EAAKi+B,GAC7Cj+B,EAAI6G,SACN,CAUAqiC,WAAAA,CACElpC,EACA9Z,EACA+3C,GAEA,IAAInqC,EACJ,GAAKmqC,GAAiBA,EAAckL,oBAAuBnlD,KAAK0sC,MAAO,CACrE,MAAMphB,EAAOH,GACTnrB,KAAKqS,MACLrS,KAAKsS,OACL6E,GAAqBjV,IAEvB27B,EAAU79B,KAAK4sC,mCAOXh+B,IANC5O,KAAK8+B,eACF,IAAI3yB,IAAQM,UAAUzM,KAAKmD,OAASnD,KAAKmD,OAAOsd,UAAY,GAG5D,IAAItU,GAAMjK,EAAQgU,OAAQhU,EAAQiU,SACpClJ,eAAejN,KAAKq9B,aAE5BvtB,EAAOwb,EACJhf,IAAIuxB,GACJpxB,UAAUzM,KAAK+kD,mBACft4C,UAAyB,EAAfzM,KAAKquB,QACpB,MACEve,EAAO9P,KAAK6uC,8BAA8BpiC,UACxCzM,KAAK+kD,mBAGT/kD,KAAKskD,aAAatoC,EAAKlM,EAAMmqC,EAC/B,CASAwK,2BAAAA,CACEzoC,EACAlM,GAEA,IAAIs1C,GAAe,EAEnBppC,EAAIkI,YACJlkB,KAAK8jD,eAAe,CAACh2B,EAASvsB,KAGxBusB,EAAQy0B,gBAAkBz0B,EAAQ4tB,cAAc17C,KAAMuB,KAExD6jD,GAAe,EACfppC,EAAImI,OAAO2J,EAAQzhB,EAAIyD,EAAKzD,EAAGyhB,EAAQ1hB,EAAI0D,EAAK1D,GAChD4P,EAAIoI,OACF0J,EAAQzhB,EAAIyD,EAAKzD,EAAIyhB,EAAQpT,QAC7BoT,EAAQ1hB,EAAI0D,EAAK1D,EAAI0hB,EAAQvJ,YAInC6gC,GAAgBppC,EAAI6hB,QACtB,CAYAxb,YAAAA,CACErG,GAEA,IADAi+B,EAA4C35C,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE/C0b,EAAI2G,OACJ,MAAM1G,EAAgBjc,KAAK6tC,0BACrBgP,kBAAEA,EAAiBwI,gBAAEA,EAAe1I,YAAEA,GAAgB38C,KACtDkC,EAAU,CACd26C,oBACAwI,kBACA1I,iBACG1C,GAELj+B,EAAIm1B,aAAal1B,EAAe,EAAG,EAAGA,EAAe,EAAG,GACxDD,EAAIq4B,YAAcr4B,EAAIsI,UAAYpiB,EAAQy6C,YACrC38C,KAAK48C,qBACR5gC,EAAIq4B,YAAcnyC,EAAQ26C,mBAE5B78C,KAAKw0C,aAAax4B,EAAK9Z,EAAQmjD,iBAC/BrlD,KAAK8jD,eAAe,CAACh2B,EAASvsB,KAC5B,GAAIusB,EAAQ4tB,cAAc17C,KAAMuB,GAAM,CACpC,MAAMwN,EAAI/O,KAAKmjD,QAAQ5hD,GACvBusB,EAAQjK,OAAO7H,EAAKjN,EAAE1C,EAAG0C,EAAE3C,EAAGlK,EAASlC,KACzC,IAEFgc,EAAI6G,SACN,CAQAm4B,gBAAAA,CAAiBH,GACf,OACE76C,KAAKouB,SAASysB,IACd76C,KAAKouB,SAASysB,GAAYa,cAAc17C,KAAM66C,EAElD,CAUAyK,iBAAAA,CAAkBzK,EAAoBloC,GAC/B3S,KAAK67C,sBACR77C,KAAK67C,oBAAsB,CAAA,GAE7B77C,KAAK67C,oBAAoBhB,GAAcloC,CACzC,CAOA4yC,qBAAAA,GAA6D,IAAvCrjD,EAAgC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACvDG,OAAO8J,QAAQrI,GAASnB,QAAQmE,IAAA,IAAE21C,EAAYld,GAAWz4B,EAAA,OACvDlF,KAAKslD,kBAAkBzK,EAAYld,IAEvC,CAYA6nB,eAAAA,CACEC,GAEA,IAAKzlD,KAAKmD,OACR,OAEF,MAAM6Y,EAAMhc,KAAKmD,OAAOquC,WACxB,IAAKx1B,EACH,OAEF,MAAMuG,EAAIviB,KAAKmD,OAAO8b,kBACtBjD,EAAI2G,OACJ3G,EAAIhN,UAAUuT,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAC9CviB,KAAKgP,UAAUgN,GAEf,MAAM3J,EAAQrS,KAAKqS,MAAQ,EACzBC,EAAStS,KAAKsS,OAAS,EAIzB,OAHA0J,EAAIsF,WAAWjP,EAAQ,GAAIC,EAAS,EAAGD,EAAOC,GAE9CmzC,GAAmBzpC,EAAI6G,UAChB7G,CACT,CAUA0pC,UAAAA,CAAWC,GAKT,OAAO,CACT,CAQAC,QAAAA,CAASD,GAEP,OAAO,CACT,CAOAE,mBAAAA,CAAoBC,GAClB,OAAO,CACT,CAOAC,WAAAA,CAAYD,GACV,OAAO,CACT,CAQAE,OAAAA,CAAQF,GACN,OAAO,CACT,CASAG,sBAAAA,CAAuBH,GACrB,CAWFI,sBAAAA,CAAuBJ,GACrB,EC/sBG,SAASK,GACdC,EACAC,GAaA,OAXAA,EAAatlD,QAASulD,IACpB7lD,OAAO8lD,oBAAoBD,EAASE,WAAWzlD,QAASgvC,IAC7C,gBAATA,GACEtvC,OAAOgmD,eACLL,EAAYI,UACZzW,EACAtvC,OAAOimD,yBAAyBJ,EAASE,UAAWzW,IAClDtvC,OAAOkmD,OAAO,WAIjBP,CACT,CDwGErmD,EAnFW2iD,GAAuB,crBwDhC,CACFG,cAAc,EACd+D,eAAe,EACfC,eAAe,EACf1J,cAAc,EACd2J,cAAc,EACdC,cAAc,EACdC,cAAc,EACdC,cAAc,EACdC,iBAAiB,EACjBxK,WAAY,GACZsH,gBAAiB,GACjBpH,oBAAoB,EACpBD,YAAa,mBACbE,kBAAmB,GACnBI,YAAa,OACboI,gBAAiB,KACjB/B,aAAa,EACbiB,YAAa,mBACbC,gBAAiB,KACjBS,wBAAyB,GACzBF,kBAAmB,EACnBJ,YAAY,EACZT,yBAA0B,GAC1BxxC,YAAY,EACZy0C,SAAS,EACTC,oBAAoB,EACpBC,SAAU,OACVC,YAAa,KACbC,WAAY,OuB1GP,MAAMzX,WAIH4S,IAEVyD,GAAYrW,GAAc,CAAC7S,KAE3Bt0B,GAAcG,SAASgnC,IACvBnnC,GAAcG,SAASgnC,GAAc,UCrB9B,MAAM0X,GAAgBA,CAC3BxrC,EACA3P,EACAD,EACAq7C,KAGA,MAAM33C,EAAmB,GADzB23C,EAAY7iD,KAAKopB,MAAMy5B,IACM,GACvBxhC,KAAEA,GAASjK,EAAI0rC,aAAar7C,EAAIo7C,EAAWr7C,EAAIq7C,EAAW33C,EAAMA,GAGtE,IAAK,IAAIrE,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CAEvC,GADqBwa,EAAKxa,GACP,EACjB,OAAO,CAEX,CACA,OAAO,GCfF,MAAek8C,GAMpB7nD,WAAAA,CAAYoC,GACVlC,KAAKkC,QAAUA,EACflC,KAAK4nD,0BAA4B5nD,KAAKkC,QAAQm7B,YAAc,EAC5Dr9B,KAAKmc,MAAQ,IAAIhQ,GAAMnM,KAAKkC,QAAQgU,OAAQlW,KAAKkC,QAAQiU,QACzDnW,KAAK6nD,oBAAsB7nD,KAAKkC,QAAQ48B,cACpC,IAAI3yB,GAAM,EAAInM,KAAKkC,QAAQgU,OAAQ,EAAIlW,KAAKkC,QAAQiU,QACpD,IAAIhK,GAAM,EAAG,EACnB,CAKU27C,gBAAAA,CAAiBt8B,EAAUE,GACnC,MAAMnJ,EAAI+J,GAAad,EAAME,GAC7B,OAAO1rB,KAAKkC,QAAQ48B,cAAgBvc,EAAEvV,SAAShN,KAAKmc,OAASoG,CAC/D,CAQUwlC,mBAAAA,CAAoBv8B,EAAaE,EAAWa,GACpD,OAAOvsB,KAAKgoD,UACVx8B,EAAKlf,IAAItM,KAAKioD,yBAAyBz8B,EAAME,EAAIa,IAErD,CAEU27B,QAAAA,GACR,OAA8B,IAAvBloD,KAAKkC,QAAQkU,OAAsC,IAAvBpW,KAAKkC,QAAQmU,KAClD,CAEU2xC,SAAAA,CAAUnnC,GAClB,MAAM9R,EAAI,IAAI5C,GAAM0U,GAIpB,OAFA9R,EAAE3C,GAAK2C,EAAE1C,EAAIzH,KAAKmS,IAAIpC,GAAiB3U,KAAKkC,QAAQmU,QACpDtH,EAAE1C,GAAK0C,EAAE3C,EAAIxH,KAAKmS,IAAIpC,GAAiB3U,KAAKkC,QAAQkU,QAC7CrH,CACT,CAEUo5C,eAAAA,CAAgBC,EAAmB17C,GAC3C,OAAO07C,EAAWp7C,SAAShN,KAAK6nD,qBAAqB56C,eAAeP,EACtE,EC1CF,MAAM27C,GAAa,IAAIl8C,GAchB,MAAMm8C,WAAkCX,GA8B7C,kCAAOY,CAA4BC,EAAgBC,GACjD,MAAM38C,EAAQ28C,EACVj8B,GAAwBg8B,EAASC,GACjC97B,GAAmB67B,GACvB,OAAO5jD,KAAKmH,IAAID,GAASzF,GAAS,EAAK,CACzC,CAEAvG,WAAAA,CAAYspC,EAAOtO,EAAO4tB,EAAOxmD,GAC/B9B,MAAM8B,GAzBRnC,EAAAC,KAAA,UAAA,GAIAD,EAAAC,KAAA,UAAA,GAIAD,EAAAC,KAAA,aAAA,GAIAD,EAAAC,KAAA,gBAAA,GAcEA,KAAKopC,EAAI,IAAIj9B,GAAMi9B,GACnBppC,KAAK86B,EAAI,IAAI3uB,GAAM2uB,GACnB96B,KAAK0oD,EAAI,IAAIv8C,GAAMu8C,GACnB1oD,KAAKspC,GAAKtpC,KAAK8nD,iBAAiB9nD,KAAKopC,EAAGppC,KAAK86B,GAC7C96B,KAAK2oD,GAAK3oD,KAAK8nD,iBAAiB9nD,KAAKopC,EAAGppC,KAAK0oD,GAC7C1oD,KAAKm6B,MAAQ3N,GAAwBxsB,KAAKspC,GAAItpC,KAAK2oD,IACnD3oD,KAAK4oD,SAAWh8B,GAGdR,GAAapsB,KAAKspC,GAAGh8B,GAAG+6C,IAAcroD,KAAK2oD,GAAK3oD,KAAKspC,GAAItpC,KAAKm6B,MAAQ,GAE1E,CAEA8tB,wBAAAA,CACEz8B,EACAE,GAEA,IADAa,EAAiBjsB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAK4nD,0BAEzB,MAAMv7B,EAASrsB,KAAK8nD,iBAAiBt8B,EAAME,GACrCm9B,EAAuBh8B,GAAqBR,GAC5Cy8B,EAAcR,GAA0BC,4BAC5CM,EACA7oD,KAAK4oD,UAEP,OAAO5oD,KAAKmoD,gBAAgBU,EAAsBt8B,EAAYu8B,EAChE,CAQAC,YAAAA,GACE,MAAMC,EAAuB,GAU7B,OARChpD,KAAKm6B,MAAQ3zB,IAAc,EAAI,CAACxG,KAAK86B,GAAK,CAAC96B,KAAK86B,EAAG96B,KAAK0oD,IAAI3nD,QAC1D2qB,IACCs9B,EAAYt+C,KAAK1K,KAAK+nD,oBAAoB/nD,KAAKopC,EAAG1d,IAClDs9B,EAAYt+C,KACV1K,KAAK+nD,oBAAoB/nD,KAAKopC,EAAG1d,GAAK1rB,KAAK4nD,8BAI1CoB,CACT,CASAC,YAAAA,GACE,MAAMD,EAAuB,GAC3B7uB,EAAQv1B,KAAKmH,IAAI/L,KAAKm6B,OACtB+uB,EAAkB,EAAItkD,KAAKoH,IAAImuB,EAAQ,GACvCgvB,EAAcnpD,KAAKmoD,gBACjBnoD,KAAK4oD,UACJ5oD,KAAK4nD,0BAA4BsB,GAQhCxrB,EAAmB19B,KAAKkC,QAAQ48B,cAClCvS,GACEvsB,KAAKmoD,gBAAgBnoD,KAAK4oD,SAAU5oD,KAAKkC,QAAQw7B,mBAEnD19B,KAAKkC,QAAQw7B,iBAcjB,OAXEnR,GAAU48B,GAAenpD,KAAK4nD,2BAC9BlqB,GAEAsrB,EAAYt+C,KAAK1K,KAAKgoD,UAAUhoD,KAAKopC,EAAE98B,IAAI68C,KAM7CH,EAAYt+C,QAAQ1K,KAAK+oD,gBAElBC,CACT,CAQQI,kBAAAA,CAAmBC,EAAoBC,GAC7C,MAAMN,EAAuB,GAE3BF,EAAc,IAAI38C,GAChBm8C,GAA0BC,4BAA4BvoD,KAAK4oD,UAC3DN,GAA0BC,4BACxB,IAAIp8C,GAAMnM,KAAK4oD,SAASx8C,EAAGpM,KAAK4oD,SAASv8C,KAiB/C,MALA,CATkB,IAAIF,GAAM,EAAG,GAC1Bc,eAAejN,KAAK4nD,2BACpB56C,SAAShN,KAAK6nD,qBACd76C,SAAS87C,GACI,IAAI38C,GAAM,EAAG,GAC1Bc,eAAejN,KAAK4nD,2BACpB56C,SAAShN,KAAK6nD,qBACd76C,SAAS87C,IAEiB/nD,QAASsrB,IAClCU,GAAiBV,EAAQg9B,EAAaC,IACxCN,EAAYt+C,KAAK1K,KAAKopC,EAAE98B,IAAI+f,MAGzB28B,CACT,CASQO,oBAAAA,CAAqBF,EAAoBC,GAC/C,MAAMN,EAAuB,IAEvB5yC,MAAEA,EAAKC,MAAEA,EAAKH,OAAEA,EAAMC,OAAEA,EAAM2oB,cAAEA,GAAkB9+B,KAAKkC,QAC3D8+C,EAAW,IAAI70C,GACbvH,KAAKmS,IAAIpC,GAAiByB,IAC1BxR,KAAKmS,IAAIpC,GAAiB0B,KAGxBmzC,EAAexpD,KAAK4nD,0BACxB6B,EAAO3qB,EACH0qB,EACArzC,EACAvR,KAAKqB,KAAK,EAAIkQ,GAAU,EAAK,EAAID,GAAU,EAAK8qC,EAAS50C,GAAK,GAC9Do9C,EAAe5kD,KAAKqB,KAAK,EAAI+6C,EAAS50C,GAAK,GAC/Cs9C,EAAY,IAAIv9C,GAGdvH,KAAKqB,KAAKrB,KAAKC,IAAI2kD,GAAgB,EAAIC,GAAQ,EAAG,IAClDA,GAEFE,EAAO7qB,EACH0qB,EACA5kD,KAAKqB,KACH,EACG+6C,EAAS30C,GAAK,GAAK,EAAI8J,IAAW,GAChC,EAAID,EAAU,EAAIA,EAAU8qC,EAAS30C,EAAI20C,EAAS50C,IAAM,GAE/Do9C,EACA5kD,KAAKqB,KAAK,EAAI+6C,EAAS30C,GAAK,GAAK,EAAI20C,EAAS30C,EAAI20C,EAAS50C,IAAM,GACrEw9C,EAAY,IAAIz9C,GACdw9C,EACA/kD,KAAKqB,KAAKrB,KAAKC,IAAI2kD,GAAgB,EAAIG,GAAQ,EAAG,KAsBtD,MAnBA,CACEC,EACAA,EAAU38C,gBAAe,GACzBy8C,EACAA,EAAUz8C,oBAIT0L,IAAK0T,GACJrsB,KAAKgoD,UACHlpB,EAAgBzS,EAAOrf,SAAShN,KAAK6nD,qBAAuBx7B,IAG/DtrB,QAASsrB,IACJU,GAAiBV,EAAQg9B,EAAaC,IACxCN,EAAYt+C,KAAK1K,KAAKgoD,UAAUhoD,KAAKopC,GAAG98B,IAAI+f,MAI3C28B,CACT,CAEAa,YAAAA,GACE,MAAMb,EAAuB,GAI7BA,EAAYt+C,QAAQ1K,KAAK+oD,gBAGzB,MAAMe,EAAiB9pD,KAAKm6B,MAAQ3zB,IAAc,EAGhDujD,EAAY/pD,KAAKgoD,UAAUhoD,KAAKopC,GAChC4gB,EAAQhB,EAAYc,EAAiB,EAAI,GAAGl9C,SAASm9C,GACrDE,EAAQjB,EAAYc,EAAiB,EAAI,GAAGl9C,SAASm9C,GAErDG,EAAmBJ,EACf9pD,KAAKgoD,UAAUhoD,KAAKspC,GAAGr8B,gBAAe,IACtCjN,KAAKgoD,UACHhoD,KAAK4oD,SAAS57C,SAAShN,KAAK6nD,qBAAqB56C,gBAAe,IAGtEk9C,EAAe19B,GAAau9B,EAAOE,GAAoB,EACvDb,EAAcc,EAAeH,EAAQC,EACrCX,EAAYa,EAAeF,EAAQD,EAMrC,OALKhqD,KAAKkoD,WAGRc,EAAYt+C,QAAQ1K,KAAKupD,qBAAqBF,EAAaC,IAF3DN,EAAYt+C,QAAQ1K,KAAKopD,mBAAmBC,EAAaC,IAIpDN,CACT,CAQUoB,aAAAA,GACR,OAAQpqD,KAAKkC,QAAQu7B,gBACnB,IAAK,QACH,OAAOz9B,KAAKipD,eACd,IAAK,QACH,OAAOjpD,KAAK6pD,eACd,QACE,OAAO7pD,KAAK+oD,eAElB,CAEOsB,OAAAA,GACL,OAAOrqD,KAAKoqD,gBAAgBzxC,IAAKkI,IAAK,CACpCypC,YAAatqD,KAAKopC,EAClBmhB,eAAgB1pC,EAChB/U,MAAO9L,KAAKm6B,MACZyuB,SAAU5oD,KAAK4oD,WAEnB,ECrSK,MAAM4B,WAAiC7C,GAU5C7nD,WAAAA,CAAYspC,EAAOD,EAAOjnC,GACxB9B,MAAM8B,GACNlC,KAAKopC,EAAI,IAAIj9B,GAAMi9B,GACnBppC,KAAKmpC,EAAI,IAAIh9B,GAAMg9B,EACrB,CAEA8e,wBAAAA,CACEz8B,EACAE,GAEA,IADAa,EAAiBjsB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAK4nD,0BAEzB,MAAMv7B,EAASrsB,KAAK8nD,iBAAiBt8B,EAAME,GAC3C,OAAO1rB,KAAKmoD,gBAAgBt7B,GAAqBR,GAASE,EAC5D,CAQAk+B,WAAAA,GACE,MAAO,CACLzqD,KAAK+nD,oBAAoB/nD,KAAKopC,EAAGppC,KAAKmpC,EAAGnpC,KAAK4nD,2BAC9C5nD,KAAK+nD,oBAAoB/nD,KAAKopC,EAAGppC,KAAKmpC,GAAInpC,KAAK4nD,2BAEnD,CAQAiC,YAAAA,GACE,MAAMb,EAAuB,GAE7B,IAAKhpD,KAAKkoD,YAAcloD,KAAKopC,EAAE97B,GAAGtN,KAAKmpC,GAAI,CAKzC,MAAMuhB,EAAa,IAAIv+C,GAAM,EAAG,GAC7Bc,eAAejN,KAAK4nD,2BACpB56C,SAAShN,KAAK6nD,qBACjBmB,EAAYt+C,KACV1K,KAAKgoD,UAAUhoD,KAAKopC,EAAE98B,IAAIo+C,IAC1B1qD,KAAKgoD,UAAUhoD,KAAKopC,EAAEx8B,SAAS89C,IAEnC,MACE1B,EAAYt+C,QACP,IAAI49C,GACLtoD,KAAKopC,EACLppC,KAAKmpC,EACLnpC,KAAKmpC,EACLnpC,KAAKkC,SACL2nD,gBAIN,OAAOb,CACT,CAQA2B,aAAAA,GACE,MAAM3B,EAAuB,GAE7B,GAAIhpD,KAAKopC,EAAE97B,GAAGtN,KAAKmpC,GAAI,CAKrB,MAAMuhB,EAAa,IAAIv+C,GAAM,EAAG,GAC7Bc,eAAejN,KAAK4nD,2BACpB56C,SAAShN,KAAK6nD,qBACjBmB,EAAYt+C,KAAK1K,KAAKopC,EAAE98B,IAAIo+C,GAAa1qD,KAAKopC,EAAEx8B,SAAS89C,GAC3D,KAAO,CACL,MAAM7B,EAAuB7oD,KAAKioD,yBAChCjoD,KAAKopC,EACLppC,KAAKmpC,EACLnpC,KAAK4nD,2BAEDgD,EAAoB5qD,KAAKmoD,gBAC7Bv7B,GAAc5sB,KAAK8nD,iBAAiB9nD,KAAKopC,EAAGppC,KAAKmpC,KAChDnpC,KAAK4nD,2BAEFiD,EAAa7qD,KAAKopC,EAAE98B,IAAIs+C,GAC9B5B,EAAYt+C,KACVmgD,EAAWv+C,IAAIu8C,GACfgC,EAAWj+C,SAASi8C,GAExB,CAEA,OAAOG,EAAYrwC,IAAK5J,GAAM/O,KAAKgoD,UAAUj5C,GAC/C,CAEUq7C,aAAAA,GACR,OAAQpqD,KAAKkC,QAAQs7B,eACnB,IAAK,QACH,OAAOx9B,KAAK6pD,eACd,IAAK,SACH,OAAO7pD,KAAK2qD,gBACd,QACE,OAAO3qD,KAAKyqD,cAElB,CAEOJ,OAAAA,GACL,OAAOrqD,KAAKoqD,gBAAgBzxC,IAAKkI,IAAK,CACpCypC,YAAatqD,KAAKopC,EAClBmhB,eAAgB1pC,IAEpB,ECnIK,MAAMiqC,GAAwB,SACnCngC,EACAzoB,GAEkB,IADlB6oD,EAAQzqD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAER,MAAM0oD,EAA6B,GAEnC,GAAsB,IAAlBr+B,EAAOpqB,OACT,OAAOyoD,EAIT,MAAMgC,EAAUrgC,EAAOtpB,OACrB,CAAC2pD,EAASnqC,KACHmqC,EAAQA,EAAQzqD,OAAS,GAAG+M,GAAGuT,IAClCmqC,EAAQtgD,KAAK,IAAIyB,GAAM0U,IAElBmqC,GAET,CAAC,IAAI7+C,GAAMwe,EAAO,MAGpB,GAAuB,IAAnBqgC,EAAQzqD,OACVwqD,GAAW,OACN,IAAKA,EAAU,CAGpB,MAAMxjB,EAAQyjB,EAAQ,GAChB1hD,EC3CoB2hD,EAC5Bt/C,EACAgO,KAEA,IAAK,IAAIrQ,EAAQqC,EAAMpL,OAAS,EAAG+I,GAAS,EAAGA,IAC7C,GAAIqQ,EAAUhO,EAAMrC,GAAQA,EAAOqC,GACjC,OAAOrC,EAGX,OAAO,GDkCS2hD,CAAeD,EAAUnqC,IAAWA,EAAMvT,GAAGi6B,IAC3DyjB,EAAQxhD,OAAOF,EAAQ,EACzB,CAkCA,OAhCA0hD,EAAQjqD,QAAQ,CAACqoC,EAAG9/B,EAAOqhB,KACzB,IAAImQ,EAAO4tB,EACG,IAAVp/C,GACFo/C,EAAI/9B,EAAO,GACXmQ,EAAIiwB,EAAW3hB,EAAIze,EAAOA,EAAOpqB,OAAS,IACjC+I,IAAUqhB,EAAOpqB,OAAS,GACnCu6B,EAAInQ,EAAOrhB,EAAQ,GACnBo/C,EAAIqC,EAAW3hB,EAAIze,EAAO,KAE1BmQ,EAAInQ,EAAOrhB,EAAQ,GACnBo/C,EAAI/9B,EAAOrhB,EAAQ,IAGjByhD,GAA8B,IAAlBpgC,EAAOpqB,OACrByoD,EAAYt+C,QACP,IAAI8/C,GAAyBphB,EAAGA,EAAGlnC,GAASmoD,YAExCU,GAAuB,IAAVzhD,GAAeA,IAAUqhB,EAAOpqB,OAAS,EAS/DyoD,EAAYt+C,QACP,IAAI49C,GAA0Blf,EAAGtO,EAAG4tB,EAAGxmD,GAASmoD,WATrDrB,EAAYt+C,QACP,IAAI8/C,GACLphB,EACU,IAAV9/B,EAAco/C,EAAI5tB,EAClB54B,GACAmoD,aASDrB,CACT,EE9EakC,GAAe1vC,IAC1B,MAAM2vC,EAAoB,CAAA,EAO1B,OANA1qD,OAAOU,KAAKqa,GAAOza,QAASQ,IAC1B4pD,EAAO5pD,GAAO,CAAA,EACdd,OAAOU,KAAKqa,EAAMja,IAAMR,QAASqqD,IAC/BD,EAAO5pD,GAAK6pD,GAAY,IAAK5vC,EAAMja,GAAK6pD,QAGrCD,GCUIE,GAAaC,GACxBA,EACG38B,QAAQ,KAAM,SACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,QAEnB,IAAI48B,GAEJ,MAiBaC,GAAiBC,IAE5B,GADAF,IAjBKA,KACHA,GACE,SAAU9mD,KACV,cAAeinD,MACf,IAAIA,KAAKC,eAAUnrD,EAAW,CAC5BorD,YAAa,cAafL,GAAW,CACb,MAAMM,EAAWN,GAAUO,QAAQL,GACnC,OAAO7pD,MAAM4pB,KAAKqgC,GAAUlzC,IAAIzT,IAAA,IAAC4mD,QAAEA,GAAS5mD,EAAA,OAAK4mD,GACnD,CAGA,OAAOC,GAAkBN,IAGrBM,GAAqBN,IACzB,MAAMO,EAAsB,GAC5B,IAAK,IAAWC,EAAPxgD,EAAI,EAAQA,EAAIggD,EAAWlrD,OAAQkL,KACE,KAAvCwgD,EAAMC,GAAaT,EAAYhgD,KAGpCugD,EAAUthD,KAAKuhD,GAEjB,OAAOD,GAIHE,GAAeA,CAACC,EAAa1gD,KACjC,MAAM2gD,EAAOD,EAAIE,WAAW5gD,GAC5B,GAAI6gD,MAAMF,GACR,MAAO,GAET,GAAIA,EAAO,OAAUA,EAAO,MAC1B,OAAOD,EAAII,OAAO9gD,GAKpB,GAAI,OAAU2gD,GAAQA,GAAQ,MAAQ,CACpC,GAAID,EAAI5rD,QAAUkL,EAAI,EACpB,KAAM,iDAER,MAAM+gD,EAAOL,EAAIE,WAAW5gD,EAAI,GAChC,GAAI,MAAS+gD,GAAQA,EAAO,MAC1B,KAAM,iDAER,OAAOL,EAAII,OAAO9gD,GAAK0gD,EAAII,OAAO9gD,EAAI,EACxC,CAEA,GAAU,IAANA,EACF,KAAM,iDAER,MAAMghD,EAAON,EAAIE,WAAW5gD,EAAI,GAIhC,GAAI,MAASghD,GAAQA,EAAO,MAC1B,KAAM,iDAIR,OAAO,mDA9FiB,SAACnB,GAAc,IAAEoB,EAAepsD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAAQ,MAChE,GAAGgrD,EAAOiB,OAAO,GAAG3zB,gBAClB8zB,EAAkBpB,EAAOtxB,MAAM,GAAKsxB,EAAOtxB,MAAM,GAAG30B,eACpD,kCCOG,MAAMsnD,GAAkB,SAC7BC,EACAC,GAA+B,IAC/BC,EAAYxsD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAAQ,OAEpBssD,EAAU7oC,OAAS8oC,EAAU9oC,MAC7B6oC,EAAU/uB,SAAWgvB,EAAUhvB,QAC/B+uB,EAAUvvB,cAAgBwvB,EAAUxvB,aACpCuvB,EAAU9wB,WAAa+wB,EAAU/wB,UACjC8wB,EAAU5rD,aAAe6rD,EAAU7rD,YACnC4rD,EAAUxnD,aAAeynD,EAAUznD,YACnCwnD,EAAUznD,YAAc0nD,EAAU1nD,WAClCynD,EAAUG,0BAA4BF,EAAUE,yBAChDH,EAAUrsB,sBAAwBssB,EAAUtsB,qBAC5CqsB,EAAUhsB,SAAWisB,EAAUjsB,QAC9BksB,IACEF,EAAUzsB,WAAa0sB,EAAU1sB,UAChCysB,EAAU1sB,YAAc2sB,EAAU3sB,WAClC0sB,EAAUxsB,cAAgBysB,EAAUzsB,YAAa,EAU1C4sB,GAAgBA,CAC3BtlC,EACAulC,KAEA,MAAMC,EAAYD,EAAKzxB,MAAM,MAC3B2xB,EAAc,GAChB,IAAIC,GAAY,EACdR,EAAY,CAAA,EAEdllC,EAASwjC,GAAYxjC,GAGrB,IAAK,IAAIjc,EAAI,EAAGA,EAAIyhD,EAAU3sD,OAAQkL,IAAK,CACzC,MAAM4hD,EAAQ7B,GAAc0B,EAAUzhD,IACtC,GAAKic,EAAOjc,GAOZ,IAAK,IAAIs4B,EAAI,EAAGA,EAAIspB,EAAM9sD,OAAQwjC,IAAK,CACrCqpB,IACA,MAAMP,EAAYnlC,EAAOjc,GAAGs4B,GAExB8oB,GAAapsD,OAAOU,KAAK0rD,GAAWtsD,OAAS,IAC3CosD,GAAgBC,EAAWC,GAAW,GACxCM,EAAYziD,KAAK,CACf68B,MAAO6lB,EACPE,IAAKF,EAAY,EACjB5xC,MAAOqxC,IAITM,EAAYA,EAAY5sD,OAAS,GAAG+sD,OAGxCV,EAAYC,GAAa,CAAA,CAC3B,MAtBEO,GAAaC,EAAM9sD,OACnBqsD,EAAY,CAAA,CAsBhB,CACA,OAAOO,GAWII,GAAkBA,CAC7B7lC,EACAulC,KAEA,IAAKrrD,MAAMwN,QAAQsY,GAEjB,OAAOwjC,GAAYxjC,GAErB,MAAMwlC,EAAYD,EAAKzxB,MAAMp0B,GAC3BomD,EAA0B,CAAA,EAC5B,IAAIJ,GAAY,EACdK,EAAa,EAEf,IAAK,IAAIhiD,EAAI,EAAGA,EAAIyhD,EAAU3sD,OAAQkL,IAAK,CACzC,MAAM4hD,EAAQ7B,GAAc0B,EAAUzhD,IAGtC,IAAK,IAAIs4B,EAAI,EAAGA,EAAIspB,EAAM9sD,OAAQwjC,IAChCqpB,IAGE1lC,EAAO+lC,IACP/lC,EAAO+lC,GAAYlmB,OAAS6lB,GAC5BA,EAAY1lC,EAAO+lC,GAAYH,MAG/BE,EAAa/hD,GAAK+hD,EAAa/hD,IAAM,CAAA,EAErC+hD,EAAa/hD,GAAGs4B,GAAK,IAAKrc,EAAO+lC,GAAYjyC,OAEzC4xC,IAAc1lC,EAAO+lC,GAAYH,IAAM,GACzCG,IAIR,CACA,OAAOD,GCjIIE,GAAoB,CAC/B,UACA,YACAvlD,EACA,eACA,YACA,UACAC,EACA,mBACA,iBACA,oBACA,kBACA,oBACA,iBACA,eACA,KACA,cACA,gBACA,sBACA,aCzBK,SAASulD,GACd75C,EACA85C,GAEA,MAAMC,EAAW/5C,EAAQ+5C,SACnBC,EAAah6C,EAAQi6C,aAAa,SAClCp6C,EAAKG,EAAQi6C,aAAa,MAC1BC,EAAO,mBACb,IAAIC,EASJ,GANAA,EAAU,IAAI3uB,OAAO,IAAMuuB,EAAU,KACrCD,EAAWA,EAASj/B,QAAQs/B,EAAS,IACjCt6C,GAAMi6C,EAASrtD,SACjB0tD,EAAU,IAAI3uB,OAAO,IAAM3rB,EAAKq6C,EAAM,KACtCJ,EAAWA,EAASj/B,QAAQs/B,EAAS,KAEnCH,GAAcF,EAASrtD,OAAQ,CACjC,MAAM2tD,EAAkBJ,EAAWtyB,MAAM,KACzC,IAAK,IAAI/vB,EAAIyiD,EAAgB3tD,OAAQkL,KACnCwiD,EAAU,IAAI3uB,OAAO,MAAQ4uB,EAAgBziD,GAAKuiD,EAAM,KACxDJ,EAAWA,EAASj/B,QAAQs/B,EAAS,GAEzC,CACA,OAA2B,IAApBL,EAASrtD,MAClB,CClBO,SAAS4tD,GACdr6C,EACAs6C,GAEA,IAAIC,GAAiB,EAErB,MAAMC,EAAgBX,GAAgB75C,EAASs6C,EAAUtW,OAIzD,OAHIwW,GAAiBF,EAAU7tD,SAC7B8tD,ECbG,SACLv6C,EACAs6C,GAEA,IAAIR,EACFS,GAAiB,EACnB,KACEv6C,EAAQy6C,eAC2B,IAAnCz6C,EAAQy6C,cAAchzC,UACtB6yC,EAAU7tD,QAEN8tD,IACFT,EAAWQ,EAAUtW,OAGvBuW,EAAiBV,GADjB75C,EAAUA,EAAQy6C,cACwBX,GAE5C,OAA4B,IAArBQ,EAAU7tD,MACnB,CDLqBiuD,CAAoB16C,EAASs6C,IAEzCE,GAAiBD,GAAuC,IAArBD,EAAU7tD,MACtD,CEXO,SAASkuD,GACd36C,GAEA,IADA46C,EAAkBpuD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEjBonB,EAAiC,CAAA,EACrC,IAAK,MAAMinC,KAAQD,EACbP,GAAmBr6C,EAAS66C,EAAKnzB,MAAM,QACzC9T,EAAS,IACJA,KACAgnC,EAASC,KAIlB,OAAOjnC,CACT,CCnBO,MAAMknC,GACXC,IAAyC,IAAAC,EAAA,OACmB,QADnBA,EAC9B9sB,GAAc6sB,UAAmC,IAAAC,EAAAA,EAAID,GCD5DE,GAAQ,IAAIzvB,OAAO,IAAIoC,MAAU,MCWjC3yB,GAAI,IAAI2yB,MACRtrB,GAAQurB,OAAOC,GAAG,YAAY7yB,OAC9BsH,GAAQsrB,OAAOC,GAAG,YAAY7yB,OAC9BN,GAASkzB,OAAOC,GAAG,aAAa7yB,SAAQA,MAAKA,SAC7CoN,GAAQwlB,OAAOC,GAAG,YAAY7yB,SAAQA,SACtCuiC,GAAY3P,OAAOC,GAAG,gBAAgB7yB,SAAQA,SAE9CC,GAAY,MADH2yB,OAAOC,GAAG,aAAa7yB,MAAKA,MAAKA,MAAKA,MAAKA,MAAKA,UAC7BuiC,MAAa7iC,MAAU0N,MAAS/F,MAASC,MACrE24C,GAAa,MAAMhgD,OACnBigD,GAAgBttB,OAAOC,GAAG,UAAUotB,WAEpCE,GAAkB,IAAI5vB,OAAO2vB,IAC7BE,GAAc,IAAI7vB,OAAOtwB,IACzBogD,GAAiB,IAAI9vB,OAAOtwB,GAAW,KAQtC,SAASqgD,GAAwBC,GAOtC,MAAM75C,EAAqB,GAI3B,KATA65C,EDhCkCA,IAClC5gC,GACE4gC,EACG3gC,QAAQogC,GAAO,QAEfpgC,QAAQ,MAAO,MC2BH4gC,CAAoBD,GAElC3gC,QAAQ,iBAAkB,QAS1B2gC,IAAmBJ,GAAgBM,KAAKF,GAEzC,MAAO,IAAI5oD,GAGb,IAAK,MAAMu0B,KAASq0B,EAAeG,SAASL,IAAiB,CAC3D,MAAMM,EAAiBP,GAAYnzB,KAAKf,EAAM,IAC9C,IAAKy0B,EACH,SAEF,IAAIp4C,EAAiB5Q,EACrB,MAAMipD,EAAgBD,EAAe5lD,OAAQ0a,KAAQA,KAC5CorC,KAAcC,GAAWF,GAC3BvlD,EAAM0lD,EAAMC,EAAMC,EAAMC,EAAMC,GAAQL,EAAQl3C,IAAKw3C,GACxDp2C,WAAWo2C,IAGb,OAAQP,GACN,IAAK,YACHt4C,EAASd,GAAsBpM,EAAM0lD,GACrC,MACF,KAAKtoD,EACH8P,EAASb,GAAmB,CAAE3K,MAAO1B,GAAQ,CAAEiC,EAAGyjD,EAAM1jD,EAAG2jD,IAC3D,MACF,KAAKjoD,EACHwP,EAAST,GAAkBzM,EAAM0lD,GACjC,MACF,KAAK7nD,EACHqP,EAASN,GAAkB5M,GAC3B,MACF,KAAKlC,EACHoP,EAASJ,GAAkB9M,GAC3B,MACF,IAAK,SACHkN,EAAS,CAAClN,EAAM0lD,EAAMC,EAAMC,EAAMC,EAAMC,GAK5Cz6C,EAAS/K,KAAK4M,EAChB,CAEA,OAAO9B,GAA6BC,EACtC,CCrFO,SAAS26C,GACdvB,EACA5qD,EACAosD,EACAv0B,GAEA,MAAM1sB,EAAUxN,MAAMwN,QAAQnL,GAC9B,IAAIqsD,EACAC,EAA0DtsD,EAC9D,GAAK4qD,IAAS1mD,GAAQ0mD,IAASzmD,GAAWnE,IAAUkD,EAE7C,IAAa,kBAAT0nD,EACT,MAAiB,uBAAV5qD,EACF,GAAa,oBAAT4qD,EAEP0B,EADEtsD,IAAUkD,EACC,KAEAlD,EAAM0qB,QAAQ,KAAM,KAAK6M,MAAM,OAAO7iB,IAAIoB,iBAEpD,GAAa,oBAAT80C,EAEP0B,EADEF,GAAoBA,EAAiBG,gBAC1Bn7C,GACXg7C,EAAiBG,gBACjBnB,GAAwBprD,IAGborD,GAAwBprD,QAElC,GAAa,YAAT4qD,EACT0B,EAAatsD,IAAUkD,GAAkB,WAAVlD,EAE3BosD,IAAiD,IAA7BA,EAAiB19C,UACvC49C,GAAa,QAEV,GAAa,YAAT1B,EACT0B,EAAax2C,WAAW9V,GACpBosD,QAAwD,IAA7BA,EAAiBrzB,UAC9CuzB,GAAcF,EAAiBrzB,cAE5B,GAAa,eAAT6xB,EACT0B,EAAuB,UAAVtsD,EAAoB8C,EAAiB,QAAV9C,EAAkBiD,EAAQJ,OAC7D,GAAa,gBAAT+nD,GAA0BA,IAAStvB,GAE5C+wB,EAAUz0B,GAAU53B,EAAO63B,GAAYA,EAAY,SAC9C,GAAa,eAAT+yB,EAAuB,CAChC,MAAM4B,EAAYxsD,EAAMsF,QAAQpB,GAC1BuoD,EAAczsD,EAAMsF,QAAQnB,GAClCmoD,EAAapoD,GACTsoD,GAAY,GAAMC,GAAc,GAAMA,EAAcD,QAE7CA,GAAoBC,GAAc,KAD3CH,EAAanoD,EAIjB,KAAO,IACI,SAATymD,GACS,eAATA,GACS,SAATA,GACS,OAATA,EAEA,OAAO5qD,EACF,GAAa,mBAAT4qD,EACT,MAAiB,oBAAV5qD,EAEPqsD,EAASlhD,EACJnL,EAAmB0U,IAAIkjB,IACxBA,GAAU53B,EAAO63B,EACvB,OAxDEy0B,EAAa,GA0Df,OAAQnhD,GAAWk9C,MAAMgE,GAAqBC,EAAaD,CAC7D,CCrEO,SAASK,GACdn1C,EACAo1C,GAEAp1C,EACGmT,QAAQ,QAAS,IACjB6M,MAAM,KACNz6B,QAAS8vD,IACR,IAAKA,EAAO,OACZ,MAAOhC,EAAM5qD,GAAS4sD,EAAMr1B,MAAM,KAClCo1B,EAAO/B,EAAKtyB,OAAOl3B,eAAiBpB,EAAMs4B,QAEhD,CCVO,SAASu0B,GACdh9C,GAEA,MAAM88C,EAA8B,CAAA,EAClCp1C,EAAQ1H,EAAQi6C,aAAa,SAE/B,OAAKvyC,GAIgB,iBAAVA,EACTm1C,GAAiBn1C,EAAOo1C,GCbrB,SACLp1C,EACAo1C,GAEAnwD,OAAO8J,QAAQiR,GAAOza,QAAQmE,IAAmB,IAAjB+N,EAAMhP,GAAMiB,OAC5B1E,IAAVyD,IAGJ2sD,EAAO39C,EAAK5N,eAAiBpB,IAEjC,CDKI8sD,CAAiBv1C,EAAOo1C,GAGnBA,GATEA,CAUX,CErBA,MAAMI,GAAqB,CACzBnzB,OAAQ,gBACR9Z,KAAM,eCYD,SAASktC,GACdn9C,EACAo9C,EACAxC,GAEA,IAAK56C,EACH,MAAO,CAAA,EAGT,IACEgoB,EADEu0B,EAA2C,CAAA,EAE7Cc,EAAiBvqD,EAIjBkN,EAAQuH,YACRmnB,GAAqBgtB,KAAK17C,EAAQuH,WAAWwyC,YAE7CwC,EAAmBY,GACjBn9C,EAAQy6C,cACR2C,EACAxC,GAEE2B,EAAiBv0B,WACnBA,EAAWq1B,EAAiBt1B,GAAUw0B,EAAiBv0B,YAI3D,MAAMs1B,EAAwC,IACzCF,EAAW7vD,OAA+B,CAACgQ,EAAMw9C,KAClD,MAAM5qD,EAAQ6P,EAAQi6C,aAAac,GAInC,OAHI5qD,IACFoN,EAAKw9C,GAAQ5qD,GAERoN,GACN,CAAA,MAGAo9C,GAA0B36C,EAAS46C,MACnCoC,GAAoBh9C,IAGrBs9C,EAAc/uB,KAChBvuB,EAAQoI,aAAammB,GAAO+uB,EAAc/uB,KAExC+uB,EAAchvB,MAEhBtG,EAAWD,GAAUu1B,EAAchvB,IAAQ+uB,GAC3CC,EAAchvB,IAAS,GAAGtG,KAI5B,MAAMu1B,EAGF,CAAA,EACJ,IAAK,MAAMxC,KAAQuC,EAAe,CAChC,MAAME,EAAiB1C,GAAcC,GAC/B0C,EAAkBnB,GACtBkB,EACAF,EAAcvC,GACdwB,EACAv0B,GAEFu1B,EAAgBC,GAAkBC,CACpC,CACIF,GAAmBA,EAAgBG,MC3ElC,SACLvtD,EACA2sD,GAEA,MAAM31B,EAAQh3B,EAAMg3B,MAAM8G,IAE1B,IAAK9G,EACH,OAEF,MAAM91B,EAAY81B,EAAM,GAGtB71B,EAAa61B,EAAM,GACnBa,EAAWb,EAAM,GACjBqF,EAAarF,EAAM,GACnBj6B,EAAai6B,EAAM,GAEjB91B,IACFyrD,EAAOzrD,UAAYA,GAEjBC,IACFwrD,EAAOxrD,WAAaknD,MAAMvyC,WAAW3U,IACjCA,EACA2U,WAAW3U,IAEb02B,IACF80B,EAAO90B,SAAWD,GAAUC,IAE1B96B,IACF4vD,EAAO5vD,WAAaA,GAElBs/B,IACFswB,EAAOtwB,WAAaA,IAAe93B,EAAS,EAAI83B,EAEpD,CD0CImxB,CAAqBJ,EAAgBG,KAAgBH,GAEvD,MAAMK,EAAc,IAAKrB,KAAqBgB,GAC9C,OAAO7uB,GAAqBgtB,KAAK17C,EAAQ+5C,UACrC6D,ED3EC,SACLR,GAEA,MAAM9vD,EAAW0uC,GAAarwB,cAsB9B,OArBAhf,OAAO8J,QAAQymD,IAAoBjwD,QAAQmE,IAAuB,IAArB2pD,EAAM8C,GAAUzsD,EAC3D,QACmC,IAA1BgsD,EAAWS,IACG,KAArBT,EAAWrC,GAEX,OAEF,QAAgC,IAArBqC,EAAWrC,GAAuB,CAC3C,IAAKztD,EAASytD,GACZ,OAEFqC,EAAWrC,GAAQztD,EAASytD,EAC9B,CACA,GAAyC,IAArCqC,EAAWrC,GAAMtlD,QAAQ,QAC3B,OAEF,MAAM0vB,EAAQ,IAAID,GAAMk4B,EAAWrC,IACnCqC,EAAWrC,GAAQ51B,EAChBiB,SAAStgB,GAAQqf,EAAMgB,WAAai3B,EAAWS,GAAY,IAC3Dh4B,WAEEu3B,CACT,CCkDMU,CAAqBF,EAC3B,CEjFO,MAgBDG,GAAa,CAAC,KAAM,MAEnB,MAAMC,WAKHhiB,GAqBR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNqyC,GAAKpyC,YAEZ,CAMA5f,WAAAA,CAAYoC,GACV9B,QACAK,OAAOC,OAAOV,KAAM8xD,GAAKpyC,aACzB1f,KAAKgwC,WAAW9tC,GAChBlC,KAAK+xD,WACP,CAKAA,SAAAA,GACE,MAAMC,GAAEA,EAAEC,GAAEA,GAAOjyD,KACfgyD,IAAOC,EACTjyD,KAAKiyD,GAAKD,EACDC,IAAOD,IAChBhyD,KAAKgyD,GAAKC,EAEd,CAMA7e,OAAAA,CAAQp3B,GACN,MAAQ3J,MAAOi8B,EAAGh8B,OAAQgmB,GAAMt4B,KAC1BqM,GAAKiiC,EAAI,EACTliC,GAAKksB,EAAI,EACT05B,EAAKhyD,KAAKgyD,GAAKptD,KAAKiJ,IAAI7N,KAAKgyD,GAAI1jB,EAAI,GAAK,EAC1C2jB,EAAKjyD,KAAKiyD,GAAKrtD,KAAKiJ,IAAI7N,KAAKiyD,GAAI35B,EAAI,GAAK,EAC1C45B,EAAmB,IAAPF,GAAmB,IAAPC,EAE9Bj2C,EAAIkI,YAEJlI,EAAImI,OAAO9X,EAAI2lD,EAAI5lD,GAEnB4P,EAAIoI,OAAO/X,EAAIiiC,EAAI0jB,EAAI5lD,GACvB8lD,GACEl2C,EAAIm2C,cACF9lD,EAAIiiC,EAAIznC,EAAQmrD,EAChB5lD,EACAC,EAAIiiC,EACJliC,EAAIvF,EAAQorD,EACZ5lD,EAAIiiC,EACJliC,EAAI6lD,GAGRj2C,EAAIoI,OAAO/X,EAAIiiC,EAAGliC,EAAIksB,EAAI25B,GAC1BC,GACEl2C,EAAIm2C,cACF9lD,EAAIiiC,EACJliC,EAAIksB,EAAIzxB,EAAQorD,EAChB5lD,EAAIiiC,EAAIznC,EAAQmrD,EAChB5lD,EAAIksB,EACJjsB,EAAIiiC,EAAI0jB,EACR5lD,EAAIksB,GAGRtc,EAAIoI,OAAO/X,EAAI2lD,EAAI5lD,EAAIksB,GACvB45B,GACEl2C,EAAIm2C,cACF9lD,EAAIxF,EAAQmrD,EACZ5lD,EAAIksB,EACJjsB,EACAD,EAAIksB,EAAIzxB,EAAQorD,EAChB5lD,EACAD,EAAIksB,EAAI25B,GAGZj2C,EAAIoI,OAAO/X,EAAGD,EAAI6lD,GAClBC,GACEl2C,EAAIm2C,cAAc9lD,EAAGD,EAAIvF,EAAQorD,EAAI5lD,EAAIxF,EAAQmrD,EAAI5lD,EAAGC,EAAI2lD,EAAI5lD,GAElE4P,EAAIqI,YAEJrkB,KAAKq1C,oBAAoBr5B,EAC3B,CAOAxB,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,OAAOF,MAAMoa,SAAS,IAAIq3C,MAAevsC,GAC3C,CAOA6Y,MAAAA,GACE,MAAM9rB,MAAEA,EAAKC,OAAEA,EAAM0/C,GAAEA,EAAEC,GAAEA,GAAOjyD,KAClC,MAAO,CACL,SACA,eACA,OAAOqS,EAAQ,UACZC,EAAS,UACH0/C,UAAWC,aAAc5/C,cAAkBC,UAExD,CAuBA,wBAAa8/C,CACXt+C,EACA5R,EACAwsD,GAEA,MAAMv8C,KACJA,EAAO,EAACC,IACRA,EAAM,EAACC,MACPA,EAAQ,EAACC,OACTA,EAAS,EAACK,QACVA,GAAU,KACP0/C,GACDpB,GAAgBn9C,EAAS9T,KAAKsyD,gBAAiB5D,GAEnD,OAAO,IAAI1uD,KAAK,IACXkC,KACAmwD,EACHlgD,OACAC,MACAC,QACAC,SACAK,QAAS4/C,QAAQ5/C,GAAWN,GAASC,IAEzC,EA5KAvS,EAdW+xD,GAAI,OAoBD,QAAM/xD,EApBT+xD,GAAI,kBAsBU,IAAIxuB,MAAoBuuB,KAAW9xD,EAtBjD+xD,GAAI,cAlBiD,CAChEE,GAAI,EACJC,GAAI,IAwCkClyD,EAxB3B+xD,GAAI,kBAkJU,IACpBpE,GACH,IACA,IACA,KACA,KACA,QACA,WAsCJ/kD,GAAcG,SAASgpD,IACvBnpD,GAAcQ,YAAY2oD,IC5NnB,MAAMU,GAA6B,iBAC7BC,GAAoB,QACpBC,GAAsB,UACtBC,GAAyB,aCYzBC,GAAkBA,CAC7BC,EACAnjD,KAEA,MAAMovB,cACJA,EAAazB,YACbA,EAAWhrB,MACXA,EAAKC,OACLA,EACAo6B,MAAOomB,GACLpjD,EACE9B,EACJklD,GAAgBA,IAAiBD,EAC7BtnC,GACEunC,EAAa50B,sBACb20B,EAAiB30B,uBAEnB,KACA60B,EAAenlD,EACjB8B,EAAO6e,yBAAyBvf,UAAUpB,GAC1C8B,EAAO6e,yBACLykC,GAAoBtjD,EAAyC,mCAC7DujD,EACJn0B,GAAiBk0B,EACbrnC,GACE,IAAIxf,GAAMkxB,EAAaA,QACvB78B,EACAqyD,EAAiB30B,uBAEnBtvB,GACAskD,GACHp0B,GAAiBk0B,EAAmB31B,EAAc,EAC/C81B,EAAahoC,GACjB9Y,EAAQ6gD,EACR5gD,EAAS4gD,EACT19C,GAA6B,CAAC5H,EAAG8B,EAAOob,kBAAkB,IAEzDxe,IAAI2mD,GACJ7lD,aAAa,GAChB,MAAO,CAAC2lD,EAAanmD,SAASumD,GAAaJ,EAAazmD,IAAI6mD,KClCvD,MAAeC,GAYbC,gBAAAA,CACLjxD,EACAyN,GAEA,GAAI7P,KAAKszD,oBAAoBlxD,GAC3B,OAAOpC,KAAKuzD,gBAAgB1jD,EAASzN,EAEzC,CAEAkxD,mBAAAA,CAAmBpuD,GAAwD,IAAvD8D,KAAEA,EAAIwqD,aAAEA,EAAYC,SAAEA,GAA+BvuD,EACvE,OACE8D,IAASwpD,IACTxpD,IAAS2pD,MACNa,GAAgBC,IAAaD,CAEpC,CAEAE,oBAAAA,CAAoB7oD,GAAsD,IAArD7B,KAAEA,EAAMgB,QAAQyY,SAAEA,IAAiC5X,EACtE,OACE7B,IAASwpD,IACT/vC,IACCA,EAASuc,kBAEd,CAEA20B,cAAAA,CACEvxD,EACAipC,GAEA,OAAOA,EAAOv7B,IAChB,CAKAyjD,eAAAA,CACE1jD,EACAzN,GAEA,MAAM4G,KAAEA,EAAIgB,OAAEA,GAAW5H,EACzB,GAAI4G,IAAS2pD,IAA0BvwD,EAAQwxD,UAC7C,OAAOxxD,EAAQwxD,UAEjB,GAAuB,IAAnB/jD,EAAQtP,OACV,OAEF,MAAM4R,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GAAWoY,GACnC7a,EACG8I,IAAKjJ,GAAWkjD,GAAgB5oD,EAAQ0F,IACxCrO,OAAgB,CAAC2rC,EAAQp3B,IAASo3B,EAAOxhC,OAAOoK,GAAO,KAEtDi+C,EAAW,IAAI1nD,GAAMkG,EAAOC,GAE5BwhD,EADc,IAAI3nD,GAAMgG,EAAMC,GACL9F,IAAIunD,EAASzmD,aAAa,IAEzD,GAAIpE,IAASwpD,GAA4B,CACvC,MAAMuB,EAAa/zD,KAAK2zD,eAAevxD,EAAS,CAC9C0N,KAAM+jD,EACNzuC,OAAQ0uC,IAEV,MAAO,CAEL1uC,OAAQ0uC,EAERE,mBAAoB,IAAI7nD,GAAM,EAAG,GACjC2D,KAAMikD,EAEV,CAGE,MAAO,CACL3uC,OAFa0uC,EAAW9kD,UAAUhF,EAAO8gB,iBAGzChb,KAAM+jD,EAGZ,EAtFA9zD,EADoBqzD,GAAc,OAIpB,YCjBT,MAAMa,WAAyBb,GAQpCE,mBAAAA,CAAoBlxD,GAClB,OAAO,CACT,EACDrC,EAXYk0D,GAAgB,OACJ,eAYzBtrD,GAAcG,SAASmrD,ICiBvB,MAAMC,GAAiB,gBAOhB,MAAMC,GAMXr0D,WAAAA,GAA+D,IAAnD2zD,EAAwBnzD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,IAAI2zD,GAAkBl0D,EAAAC,KAAA,gBAAA,GAC3DA,KAAKyzD,SAAWA,EAChBzzD,KAAKo0D,eAAiB,IAAIpvD,GAC5B,CAEOqvD,aAAAA,CAAcjyD,GACnB,MAAMkyD,EAAqC,CACzCC,SAAS,EACTd,SAAUzzD,KAAKyzD,YACZrxD,EACHoxD,aAAcxzD,KAAKw0D,oBACnB/pC,eAAAA,GACEzqB,KAAKu0D,SAAU,CACjB,GAGFv0D,KAAKy0D,eAAeH,GAEpB,MAAMI,EAAe10D,KAAK20D,gBAAgBL,GACtCI,GACF10D,KAAK40D,aAAaN,EAAeI,GAGnC10D,KAAK60D,cAAcP,EAAeI,GAClC10D,KAAKw0D,oBAAsBF,EAAcb,QAC3C,CAUUqB,cAAAA,CACRplD,EACAtN,GAEA,MAAM4H,OAAEA,GAAW5H,EACnB,MACE,CACEiG,EACAhB,EACAK,EACAH,EACAD,EACAG,EACAI,EACAF,EACAC,GAEF+Q,IAAKpX,GACLmO,EAAOvF,GAAG5I,EAAMgpB,GACdvqB,KAAKq0D,cACH9yD,IAAQ8G,EACJ,CACEW,KJvG2B,kBIwG3B+rD,QAASxzD,EACTgpB,IACAvgB,UAEF,CACEhB,KJ5G4B,mBI6G5B+rD,QAASxzD,EACTgpB,IACAvgB,YAKd,CAQUgrD,SAAAA,CACRtlD,EACAtN,GAEApC,KAAKi1D,YAAYvlD,EAAQtN,GACzB,MAAMwI,EAAY5K,KAAK80D,eAAeplD,EAAQtN,GAC9CpC,KAAKo0D,eAAe7uD,IAAImK,EAAQ9E,EAClC,CAKUqqD,WAAAA,CACRvlD,EACAwlD,IAECl1D,KAAKo0D,eAAe3uD,IAAIiK,IAAW,IAAI3O,QAAS+J,GAAMA,KACvD9K,KAAKo0D,eAAexuD,OAAO8J,EAC7B,CAEAylD,kBAAAA,CACE/yD,GAEAA,EAAQgzD,QAAQr0D,QAAS2O,GAAW1P,KAAKi1D,YAAYvlD,EAAQtN,GAC/D,CAEAizD,gBAAAA,CACEjzD,GAEAA,EAAQgzD,QAAQr0D,QAAS2O,GAAW1P,KAAKg1D,UAAUtlD,EAAQtN,GAC7D,CAEUqyD,cAAAA,CAAeryD,GACvB,MAAM4H,OAAEA,EAAMhB,KAAEA,GAAS5G,GACnBe,OAAEA,GAAW6G,EAkBnB,GAfIhB,IAASwpD,IAA8BxpD,IAASypD,GAClDzyD,KAAKq1D,iBAAiBjzD,GACb4G,IAAS0pD,IAClB1yD,KAAKm1D,mBAAmB/yD,GAG1B4H,EAAOqB,KAAK,gBAAiB,CAC3BjJ,YAEFe,GACEA,EAAOkI,KAAK,uBAAwB,CAClCrB,SACA5H,YAGA4G,IAAS2pD,IAA0BvwD,EAAQ4O,KAAM,CACnD,MAAQyiD,SAAU/+C,KAAM4gD,GAAqBlzD,EAE7C4H,EAAOqG,cACJX,GACEA,EAAiB6lD,eACjB7lD,EAAiB6lD,cAAclB,cAAc,IACzCiB,EACHf,SAAS,EACTvqD,OAAQ0F,IAGhB,CACF,CAEUilD,eAAAA,CACRvyD,GAEA,MAAM4H,OAAEA,EAAMypD,SAAEA,EAAQzqD,KAAEA,GAAS5G,EAE7BipC,EAASooB,EAASJ,iBAAiBjxD,EAAS4H,EAAOuG,cAEzD,IAAK86B,EACH,OAGF,MAAMmqB,EACJxsD,IAASwpD,GACL,IAAIrmD,GACJnC,EAAOukB,0BAGXnJ,OAAQqwC,EAAUC,WAClBA,EAAa,IAAIvpD,GAAO6nD,mBACxBA,EAAqB,IAAI7nD,IACvBk/B,EACEhuB,EAASm4C,EACZ5oD,SAAS6oD,GACTnpD,IAAIopD,GACJ1mD,UAEChG,IAASwpD,GACL9rD,EACAwO,GAAgBlL,EAAO8gB,kBAC3B,GAEDxe,IAAI0nD,GAEP,MAAO,CACL3oB,SACAmqB,aACAC,aACAp4C,SAEJ,CAEUu3C,YAAAA,CACRxyD,EACAsyD,GAEA,MAAM1qD,OAAEA,GAAW5H,GAEjBipC,QAAQv7B,KAAEA,GAAM2lD,WAChBA,GACEf,EAO6C,IAAAiB,EAAAC,GALjD5rD,EAAOzE,IAAI,CAAE8M,MAAOvC,EAAKzD,EAAGiG,OAAQxC,EAAK1D,IAEzCpM,KAAK61D,cAAczzD,EAASsyD,GAGxBtyD,EAAQ4G,OAASwpD,IAEnBxoD,EAAOzE,IAAI,CACT4M,KACW,QADPwjD,EACFvzD,EAAQiK,SAAC,IAAAspD,EAAAA,EAAIF,EAAWppD,EAAIyD,EAAKzD,EAAI2f,GAAchiB,EAAOqjB,SAC5Djb,IAAc,QAAXwjD,EAAExzD,EAAQgK,SAAC,IAAAwpD,EAAAA,EAAIH,EAAWrpD,EAAI0D,EAAK1D,EAAI4f,GAAchiB,EAAOsjB,YAGjEtjB,EAAOghB,oBAAoByqC,EAAY3uD,EAAQA,GAE/CkD,EAAOgW,YACPhW,EAAOzE,IAAI,SAAS,GAExB,CAEUswD,aAAAA,CACRzzD,EACAsyD,GAEA,MAAM1qD,OAAEA,GAAW5H,EAEnB4H,EAAOqG,cAAeX,IACpBA,EAAOg9B,QAAU1iC,GACfhK,KAAK81D,aAAa1zD,EAASsyD,EAAchlD,KAG7CtN,EAAQqxD,SAASC,qBAAqBtxD,IACpCpC,KAAK81D,aAAa1zD,EAASsyD,EAAc1qD,EAAOyY,SACpD,CAMUqzC,YAAAA,CACR1zD,EAA4B8C,EAE5BwK,GACA,IAFA2N,OAAEA,GAAgCnY,EAMlCwK,EAAOnK,IAAI,CACT4M,KAAMzC,EAAOyC,KAAOkL,EAAOhR,EAC3B+F,IAAK1C,EAAO0C,IAAMiL,EAAOjR,GAE7B,CAEUyoD,aAAAA,CACRzyD,EACAsyD,GAEA,MAAM1qD,OACJA,EAAMypD,SACNA,EAAQc,QACRA,EACAf,aAAc9+C,KACXqhD,GACD3zD,GACEe,OAAEA,GAAW6G,EAGnBA,EAAOqB,KAAK,eAAgB,CAC1BjJ,UACAipC,OAAQqpB,IAEVvxD,GACEA,EAAOkI,KAAK,sBAAuB,CACjCjJ,UACAipC,OAAQqpB,EACR1qD,WAIJ,MAAM8nC,EAAS9nC,EAAO8nC,OAClByiB,SAAWziB,GAAAA,EAAQyjB,iBAEpBQ,EAAgBvzC,OAASuzC,EAAgBvzC,KAAO,KAAK9X,KAAKV,GAE3D8nC,EAAOyjB,cAAclB,cAAc,IAC9B0B,EACH/rD,OAAQ8nC,KAGZ9nC,EAAOzE,IAAI,SAAS,EACtB,CAEAhB,OAAAA,GACE,MAAM6vD,eAAEA,GAAmBp0D,KAC3Bo0D,EAAerzD,QAAS6J,GAAcA,EAAU7J,QAAS+J,GAAMA,MAC/DspD,EAAe7yC,OACjB,CAEA/G,QAAAA,GACE,MAAO,CACLxR,KAAMkrD,GACNT,SAAWzzD,KAAKyzD,SAAS3zD,YAAsCkJ,KAEnE,CAEAyc,MAAAA,GACE,OAAOzlB,KAAKwa,UACd,EAGF7R,GAAcG,SAASqrD,GAAeD,ICzTtC,MAAM8B,WAA0B7B,GAC9BE,aAAAA,GAAiB,EAoCZ,MAAM4B,WACH3mD,GACNwgC,KAwCF,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNw2C,GAAMv2C,YAEb,CAQA5f,WAAAA,GAA6E,IAAjE+P,EAAuBvP,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAAI4B,EAA4B5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACvEF,QA5BFL,wBAM2C,IAAEA,EAAAC,KAAA,gCAAA,GAAAD,EAAAC,KAAA,iCAAA,GAuB3CS,OAAOC,OAAOV,KAAMi2D,GAAMv2C,aAC1B1f,KAAKgwC,WAAW9tC,GAChBlC,KAAKk2D,UAAUrmD,EAAS3N,EAC1B,CAMUg0D,SAAAA,CACRrmD,EACA3N,GAKA,IAAAi0D,EACAn2D,KAAKqP,SAAW,IAAIQ,GAEpB7P,KAAKo2D,yBAA2Bp2D,KAAKq2D,yBAAyBxvB,KAC5D7mC,MACA,GAEFA,KAAKs2D,0BAA4Bt2D,KAAKq2D,yBAAyBxvB,KAC7D7mC,MACA,GAGFA,KAAKqQ,cAAeX,IAClB1P,KAAKu2D,WAAW7mD,GAAQ,KAI1B1P,KAAKu1D,cAAqC,QAAxBY,EAAGj0D,EAAQqzD,yBAAaY,EAAAA,EAAI,IAAIhC,GAClDn0D,KAAKu1D,cAAclB,cAAc,CAC/BrrD,KAAMwpD,GACNxoD,OAAQhK,KACRo1D,QAAS,IAAIvlD,GAIbxD,EAAGnK,EAAQiQ,KACX/F,EAAGlK,EAAQkQ,KAEf,CAQAokD,aAAAA,CAAc9mD,GACZ,OAAIA,IAAW1P,MAAQA,KAAK82C,eAAepnC,IAEzClO,EACE,QACA,4EAEK,QACExB,KAAKqP,SAAS9F,QAAQmG,KAE/BlO,EACE,QACA,qFAEK,EAGX,CAOUi1D,iCAAAA,CAAkC5mD,GAC1C,OAAOA,EAAQ/F,OAAO,CAAC4F,EAAQpG,EAAOqC,IAE7B3L,KAAKw2D,cAAc9mD,IAAW/D,EAAMpC,QAAQmG,KAAYpG,EAEnE,CAMAgD,GAAAA,GAAgC,IAAA,IAAA5K,EAAApB,UAAAC,OAAzBsP,EAAO,IAAAjO,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAPgO,EAAOhO,GAAAvB,UAAAuB,GACZ,MAAM60D,EAAiB12D,KAAKy2D,kCAAkC5mD,GACxDC,EAAO1P,MAAMkM,OAAOoqD,GAE1B,OADA12D,KAAK22D,sBAAsBlE,GAAmBiE,GACvC5mD,CACT,CAOAC,QAAAA,CAASzG,GAA2C,IAAA,IAAA0G,EAAA1P,UAAAC,OAAzBsP,MAAOjO,MAAAoO,EAAA,EAAAA,OAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAPJ,EAAOI,EAAA,GAAA3P,UAAA2P,GAChC,MAAMymD,EAAiB12D,KAAKy2D,kCAAkC5mD,GACxDC,EAAO1P,MAAM2P,SAASzG,KAAUotD,GAEtC,OADA12D,KAAK22D,sBAAsBlE,GAAmBiE,GACvC5mD,CACT,CAOAzG,MAAAA,GACE,MAAM6G,EAAU9P,MAAMiJ,UAAO/I,WAE7B,OADAN,KAAK22D,sBAAsBjE,GAAqBxiD,GACzCA,CACT,CAEAT,cAAAA,CAAeC,GACb1P,KAAKu2D,WAAW7mD,GAAQ,GACxB1P,KAAKqL,KAAK,eAAgB,CAAErB,OAAQ0F,IACpCA,EAAOrE,KAAK,QAAS,CAAErB,OAAQhK,MACjC,CAOA2P,gBAAAA,CAAiBD,EAAsBknD,GACrC52D,KAAK62D,UAAUnnD,EAAQknD,GACvB52D,KAAKqL,KAAK,iBAAkB,CAAErB,OAAQ0F,IACtCA,EAAOrE,KAAK,UAAW,CAAErB,OAAQhK,MACnC,CAOA22D,qBAAAA,CAAsB3tD,EAA2BosD,GAC/Cp1D,KAAKu1D,cAAclB,cAAc,CAC/BrrD,OACAosD,UACAprD,OAAQhK,MAEZ,CAEA4P,oBAAAA,GACE5P,KAAKmT,KAAK,SAAS,EACrB,CAOAA,IAAAA,CAAK5R,EAAa0C,GAChB,MAAMwoD,EAAOzsD,KAAKuB,GAOlB,OANAnB,MAAM+S,KAAK5R,EAAK0C,GACJ,WAAR1C,GAAoBkrD,IAASxoD,IAC9BjE,KAAKqP,UAAY,IAAItO,QAAS2O,IAC7BA,EAAOyD,KAAK5R,EAAK0C,KAGdjE,IACT,CAKA82D,sBAAAA,GACE,OAAO92D,KAAK+2D,cACd,CAMAC,SAAAA,GAEE,OADAh3D,KAAKi3D,eAAiB,GACfj3D,KAAKqJ,UAAUrJ,KAAKqP,SAC7B,CAMAgnD,wBAAAA,CACEa,EAAWhyD,GAIX,IAFE8E,OAAQ0F,GACiDxK,EAE3D,MAAMiyD,EAAgBn3D,KAAKi3D,eAC3B,GAAIC,EACFC,EAAczsD,KAAKgF,GACnB1P,KAAKmT,KAAK,SAAS,QACd,GAAIgkD,EAAc52D,OAAS,EAAG,CACnC,MAAM+I,EAAQ6tD,EAAc5tD,QAAQmG,GAChCpG,GAAQ,IACV6tD,EAAc3tD,OAAOF,EAAO,GAC5BtJ,KAAKmT,KAAK,SAAS,GAEvB,CACF,CAOAikD,YAAAA,CAAaC,EAAgB3nD,GAE3B2nD,GAASr3D,KAAKo3D,cAAa,EAAO1nD,GAC9B2nD,GACF3nD,EAAOvF,GAAG,WAAYnK,KAAKo2D,0BAC3B1mD,EAAOvF,GAAG,aAAcnK,KAAKs2D,6BAE7B5mD,EAAOjF,IAAI,WAAYzK,KAAKo2D,0BAC5B1mD,EAAOjF,IAAI,aAAczK,KAAKs2D,2BAElC,CAOAC,UAAAA,CAAW7mD,EAAsBknD,GAC/BlnD,EAAOg9B,OAASh9B,EAAOg9B,MAAMrjC,OAAOqG,GACpCA,EAAOyD,KAAK,SAAUnT,MACtBA,KAAKs3D,YAAY5nD,EAAQknD,EAC3B,CAOAU,WAAAA,CAAY5nD,EAAsBknD,GAC5BA,GAEF/rC,GACEnb,EACA2F,GACEH,GAAgBlV,KAAKk+B,uBACrBxuB,EAAOwuB,wBAIbl+B,KAAK82D,0BAA4BpnD,EAAOsQ,YACxCtQ,EAAOyD,KAAK,QAASnT,MACrB0P,EAAOyD,KAAK,SAAUnT,KAAKmD,QAC3BnD,KAAKo3D,cAAa,EAAM1nD,GACxB,MAAM6nD,EACJv3D,KAAKmD,QACLnD,KAAKmD,OAAO43C,iBACZ/6C,KAAKmD,OAAO43C,kBAGZwc,IACCA,IAAiB7nD,GAAUA,EAAOonC,eAAeygB,KAElDv3D,KAAKi3D,eAAevsD,KAAKgF,EAE7B,CAOAmnD,SAAAA,CAAUnnD,EAAsBknD,GAC9B52D,KAAKw3D,WAAW9nD,EAAQknD,GACxBlnD,EAAOyD,KAAK,cAAU3S,GACtBkP,EAAOyD,KAAK,cAAU3S,EACxB,CAWAg3D,UAAAA,CAAW9nD,EAAsBknD,GAC/BlnD,EAAOyD,KAAK,aAAS3S,GAChBo2D,IACH/rC,GACEnb,EACA2F,GACErV,KAAKk+B,sBACLxuB,EAAOwuB,wBAGXxuB,EAAOsQ,aAEThgB,KAAKo3D,cAAa,EAAO1nD,GACzB,MAAMpG,EACJtJ,KAAKi3D,eAAe12D,OAAS,EAAIP,KAAKi3D,eAAe1tD,QAAQmG,IAAU,EACrEpG,GAAQ,GACVtJ,KAAKi3D,eAAeztD,OAAOF,EAAO,EAEtC,CASAwZ,WAAAA,GACE,MAAM20C,EAAW3nB,GAAa0W,UAAU1jC,YAAY7X,KAAKjL,MACzD,GAAIy3D,EACF,IAAK,IAAIhsD,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IACxC,GAAIzL,KAAKqP,SAAS5D,GAAGqnC,iBAEnB,OADA9yC,KAAK4yC,YAAa,GACX,EAIb,OAAO6kB,CACT,CAMA3kB,cAAAA,GACE,GAAI1yC,MAAM0yC,iBACR,OAAO,EAET,IAAK,IAAIrnC,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IACxC,GAAIzL,KAAKqP,SAAS5D,GAAGqnC,iBACnB,OAAO,EAGX,OAAO,CACT,CAMAD,UAAAA,GACE,OAAO7yC,KAAK4yC,cAAiB5yC,KAAK8xC,QAAU9xC,KAAK8xC,OAAOe,YAC1D,CAMAP,UAAAA,CACEt2B,EACAiH,EACA7gB,GAEApC,KAAK0iB,kBAAkB1G,GACvB,IAAK,IAAIvQ,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IAAK,CAAA,IAAAqiC,EAC7C,MAAM38B,EAAMnR,KAAKqP,SAAS5D,WAEtBqiC,EAAA9tC,KAAKmD,cAAM,IAAA2qC,GAAXA,EAAa4pB,wBAA0BvmD,EAAIu7B,QAAU1sC,MACvDgc,EAAI2G,OACJ3G,EAAIhN,aAAakG,GAAgBlV,KAAKk+B,wBACtC/sB,EAAI0S,OAAO7H,GACXA,EAAI6G,WACK1R,EAAIu7B,QAAU1sC,MACvBmR,EAAI0S,OAAO7H,EAEf,CACAhc,KAAKqzC,cAAcr3B,EAAKhc,KAAKyiB,SAAUrgB,EACzC,CAMA4d,SAAAA,GACE5f,MAAM4f,YACNhgB,KAAK82D,0BACH92D,KAAKqQ,cAAeX,GAAWA,EAAOsQ,YAC1C,CAEA23C,aAAAA,GAAqD,IAAvCz1D,EAAgC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC/CN,KAAKu1D,cAAclB,cAAc,CAC/BrqD,OAAQhK,KACRgJ,KAAM2pD,MACHzwD,GAEP,CAMA2hB,MAAAA,CAAO7H,GACLhc,KAAK+iB,gBAAiB,EACtB3iB,MAAMyjB,OAAO7H,GACbhc,KAAK+iB,gBAAiB,CACxB,CASA60C,kBAAAA,CACEC,EACAvyC,GAEA,MAAMwyC,EAAwB93D,KAAKye,qBACnC,OAAOze,KAAKqP,SACTvF,OAAO,SAAUqH,GAChB,OAAQA,EAAIyU,iBACd,GACCjN,IAAI,SAAUxH,GACb,MAAM4mD,EAAmB5mD,EAAIsN,qBAC7BtN,EAAIsN,qBAAuBq5C,EAC3B,MAAM7xC,EAAO9U,EAAI0mD,GAAU,YAAYvyC,GAGvC,OAFAnU,EAAIsN,qBAAuBs5C,EAEpB9xC,CACT,EACJ,CAOAzL,QAAAA,GAMoE,IAAlE8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAMi1D,EAAgBv1D,KAAKu1D,cAAc/6C,WAEzC,MAAO,IACFpa,MAAMoa,SAAS,CAChB,iBACA,iBACG8K,OAE0B,gBAA3BiwC,EAAc9B,UAA8BzzD,KAAKye,qBACjD,CAAE82C,iBACF,GACJ1lD,QAAS7P,KAAK43D,mBACZ,WACAtyC,GAGN,CAEApX,QAAAA,GACE,MAAO,aAAalO,KAAKoR,gBAC3B,CAEA7M,OAAAA,GACEvE,KAAKu1D,cAAcJ,mBAAmB,CACpCC,QAASp1D,KAAKuQ,aACdvG,OAAQhK,OAEVA,KAAKi3D,eAAiB,GACtBj3D,KAAKqQ,cAAeX,IAClB1P,KAAKo3D,cAAa,EAAO1nD,GACzBA,EAAOnL,YAETnE,MAAMmE,SACR,CAKAyzD,gBAAAA,CAAiBx/C,GACf,IAAKxY,KAAKse,gBACR,MAAO,GAET,MAAM25C,EAAanG,GAAKtL,UAAUroB,OAAOlzB,KAAKjL,MACxCk4D,EAAUD,EAAW1uD,QAAQ,gBACnC0uD,EAAWC,GAAW,eACtB,MAAM3xC,EAAS0xC,EAAW99C,KAAK,IAC/B,OAAO3B,EAAUA,EAAQ+N,GAAUA,CACrC,CAOA4X,MAAAA,CAAO3lB,GACL,MAAM2/C,EAAY,CAAC,MAAO,eAAgB,QACpCC,EAAKp4D,KAAKg4D,iBAAiBx/C,GACjC4/C,GAAMD,EAAUztD,KAAK,OAAQ0tD,GAC7B,IAAK,IAAI3sD,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IACxC0sD,EAAUztD,KAAK,OAAQ1K,KAAKqP,SAAS5D,GAAG6a,MAAM9N,IAGhD,OADA2/C,EAAUztD,KAAK,UACRytD,CACT,CAMAj7B,YAAAA,GACE,MAAMF,OACsB,IAAjBh9B,KAAKg9B,SAA4C,IAAjBh9B,KAAKg9B,QACxC,YAAYh9B,KAAKg9B,WACjB,GACNW,EAAa39B,KAAK2S,QAAU,GAAK,uBACnC,MAAO,CAACqqB,EAASh9B,KAAK49B,eAAgBD,GAAYxjB,KAAK,GACzD,CAOAkN,aAAAA,CAAc7O,GACZ,MAAM2/C,EAAY,GACZC,EAAKp4D,KAAKg4D,iBAAiBx/C,GACjC4/C,GAAMD,EAAUztD,KAAK,KAAM0tD,GAC3B,IAAK,IAAI3sD,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IACxC0sD,EAAUztD,KAAK,KAAM1K,KAAKqP,SAAS5D,GAAG4b,cAAc7O,IAEtD,OAAOxY,KAAKs+B,6BAA6B65B,EAAW,CAClD3/C,WAEJ,CAQA,iBAAOI,CAAU/N,EAEfwtD,GACA,IAFArvD,KAAEA,EAAI6G,QAAEA,EAAU,GAAE0lD,cAAEA,KAAkBrzD,GAAY2I,EAGpD,OAAO2J,QAAQkE,IAAI,CACjBH,GAA6B1I,EAASwoD,GACtCl/C,GAAwBjX,EAASm2D,KAChCx/C,KAAKzN,IAAgC,IAA9ByE,EAASyoD,GAAgBltD,EACjC,MAAMshC,EAAQ,IAAI1sC,KAAK6P,EAAS,IAC3B3N,KACAo2D,EACH/C,cAAe,IAAIS,KAErB,GAAIT,EAAe,CACjB,MAAMgD,EAAc5vD,GAAcE,SAChC0sD,EAAcvsD,MAEVwvD,EAAgB7vD,GAAcE,SAClC0sD,EAAc9B,UAEhB/mB,EAAM6oB,cAAgB,IAAIgD,EAAY,IAAIC,EAC5C,MACE9rB,EAAM6oB,cAAgB,IAAIpB,GAQ5B,OANAznB,EAAM6oB,cAAcF,iBAAiB,CACnCrsD,KAAMwpD,GACNxoD,OAAQ0iC,EACR0oB,QAAS1oB,EAAMn8B,eAEjBm8B,EAAM1sB,YACC0sB,GAEX,EACD3sC,EAznBYk2D,GAAK,OAoCF,SAAOl2D,EApCVk2D,GAAK,cAZkD,CAClE54B,YAAa,EACb05B,gBAAgB,EAChB0B,aAAa,IAooBf9vD,GAAcG,SAASmtD,IClsBhB,MCAMyC,GAAiBA,CAACj/C,EAAek/C,IAC5C/zD,KAAKiJ,IACH8qD,EAAYtmD,MAAQoH,EAAOpH,MAC3BsmD,EAAYrmD,OAASmH,EAAOnH,QAWnBsmD,GAAmBA,CAACn/C,EAAek/C,IAC9C/zD,KAAKC,IACH8zD,EAAYtmD,MAAQoH,EAAOpH,MAC3BsmD,EAAYrmD,OAASmH,EAAOnH,QCzB1BumD,GAAW,aAQX9pD,GAAI,GAAG8pD,MAAYn3B,MAoBZo3B,GAAqB,GAAG/pD,KAAIA,KAAIA,KAAI8pD,WAAiBA,WAAiB9pD,KAAIA,KCCjFgqD,GAA8C,CAClDv0C,EAAG,IACHw0C,EAAG,KAiBCC,GAAkBA,CACtBC,EACAC,EACAC,EACAC,EACArH,EACAC,EACAqH,EACAC,EACAC,EACAC,EACAC,KAEA,MAAMC,EAAS9tD,GAAIqtD,GACjBU,EAAS5tD,GAAIktD,GACbW,EAAShuD,GAAIstD,GACbW,EAAS9tD,GAAImtD,GACbY,EAAMX,EAAQpH,EAAK6H,EAASR,EAAQpH,EAAK6H,EAASR,EAClDU,EAAMX,EAAQrH,EAAK6H,EAAST,EAAQnH,EAAK6H,EAASP,EAMpD,MAAO,CAAC,IALCE,EAAQD,IAAOJ,EAAQpH,EAAK4H,EAASP,EAAQpH,EAAK0H,GAClDD,EAAQF,IAAOH,EAAQrH,EAAK4H,EAASR,EAAQnH,EAAK0H,GAClDI,EAAMP,GAAMJ,EAAQpH,EAAK8H,EAAST,EAAQpH,EAAK4H,GAC/CG,EAAMR,GAAMH,EAAQrH,EAAK8H,EAASV,EAAQnH,EAAK4H,GAEnBE,EAAKC,IA8GtCC,GAAkBA,CACtBC,EACAC,EACAC,EACAC,KAEA,MAAMC,EAAK11D,KAAKkR,MAAMqkD,EAAID,GACxBK,EAAK31D,KAAKkR,MAAMukD,EAAID,GACtB,OAAIG,GAAMD,EACDC,EAAKD,EAEL,EAAI11D,KAAK0B,IAAMg0D,EAAKC,IAyBxB,SAASC,GACdC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GAEA,IAAIC,EACJ,GAAI96D,EAAO+6D,sBAETD,EAAa,IAAI36D,WAAW6Z,OACxBrV,EAAMq2D,mBAAmBF,IAC3B,OAAOn2D,EAAMq2D,mBAAmBF,GAIpC,MAAMh1D,EAAOrB,KAAKqB,KAChB8F,EAAMnH,KAAKmH,IACXqvD,EAAU,GACVC,EAA2D,CACzD,CAAC,EAAG,GACJ,CAAC,EAAG,IAGR,IAAI/lD,EAAI,EAAImlD,EAAO,GAAKE,EAAO,EAAIE,EAC/B1lD,GAAI,EAAKslD,EAAO,EAAIE,EAAO,EAAIE,EAAO,EAAIE,EAC1Ch3B,EAAI,EAAI42B,EAAO,EAAIF,EAEvB,IAAK,IAAIhvD,EAAI,EAAGA,EAAI,IAAKA,EAAG,CAO1B,GANIA,EAAI,IACN6J,EAAI,EAAIolD,EAAO,GAAKE,EAAO,EAAIE,EAC/B3lD,GAAI,EAAKulD,EAAO,EAAIE,EAAO,EAAIE,EAAO,EAAIE,EAC1Cj3B,EAAI,EAAI62B,EAAO,EAAIF,GAGjB3uD,EAAIoJ,GAAK,MAAO,CAClB,GAAIpJ,EAAIuJ,GAAK,MACX,SAEF,MAAM1H,GAAKm2B,EAAIzuB,EACX,EAAI1H,GAAKA,EAAI,GACfwtD,EAAQ1wD,KAAKkD,GAEf,QACF,CACA,MAAM0tD,EAAOhmD,EAAIA,EAAI,EAAIyuB,EAAI5uB,EAC7B,GAAImmD,EAAO,EACT,SAEF,MAAMC,EAAWt1D,EAAKq1D,GAChBE,IAAOlmD,EAAIimD,IAAa,EAAIpmD,GAC9B,EAAIqmD,GAAMA,EAAK,GACjBJ,EAAQ1wD,KAAK8wD,GAEf,MAAMC,IAAOnmD,EAAIimD,IAAa,EAAIpmD,GAC9B,EAAIsmD,GAAMA,EAAK,GACjBL,EAAQ1wD,KAAK+wD,EAEjB,CAEA,IAAIlkB,EAAI6jB,EAAQ76D,OAChB,MAAMm7D,EAAOnkB,EACPokB,EAAWC,GACfnB,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GAEF,KAAOzjB,KAAK,CACV,MAAMlrC,EAAEA,EAACD,EAAEA,GAAMuvD,EAASP,EAAQ7jB,IAClC8jB,EAAO,GAAG9jB,GAAKlrC,EACfgvD,EAAO,GAAG9jB,GAAKnrC,CACjB,CAEAivD,EAAO,GAAGK,GAAQjB,EAClBY,EAAO,GAAGK,GAAQhB,EAClBW,EAAO,GAAGK,EAAO,GAAKX,EACtBM,EAAO,GAAGK,EAAO,GAAKV,EACtB,MAAM3vB,EAAsB,CAC1B,IAAIl/B,GAAMvH,KAAKiJ,OAAOwtD,EAAO,IAAKz2D,KAAKiJ,OAAOwtD,EAAO,KACrD,IAAIlvD,GAAMvH,KAAKC,OAAOw2D,EAAO,IAAKz2D,KAAKC,OAAOw2D,EAAO,MAKvD,OAHIl7D,EAAO+6D,sBACTp2D,EAAMq2D,mBAAmBF,GAAe5vB,GAEnCA,CACT,CAQO,MAAMwwB,GAAmBA,CAC9BC,EACAC,EAAU72D,KAE6B,IADtCwP,EAAGs9C,EAAIC,EAAI+J,EAAKC,EAAOC,EAAOC,EAAIC,GAAsBl3D,EAEzD,MAAMm3D,EA7OcC,EACpBvC,EACAC,EACAhI,EACAC,EACAgK,EACAC,EACAK,KAEA,GAAW,IAAPvK,GAAmB,IAAPC,EACd,MAAO,GAET,IAAIwH,EAAQ,EACVC,EAAQ,EACR8C,EAAO,EACT,MAAMl2D,EAAK1B,KAAK0B,GACdk3C,EAAQ+e,EAAU91D,EAClBg2D,EAAWzwD,GAAIwxC,GACf4b,EAAQvtD,GAAI2xC,GACZkf,EAAK,KAAQtD,EAAQW,EAAM0C,EAAWzC,GACtC2C,EAAK,KAAQvD,EAAQY,EAAMyC,EAAW1C,GACtC6C,EAAM5K,GAAM,EACZ6K,EAAM5K,GAAM,EACZ6K,EAAMH,GAAM,EACZI,EAAML,GAAM,EACZM,EAAKJ,EAAMC,EAAMD,EAAME,EAAMD,EAAME,EACrC,IAAIE,EAAMr4D,KAAKmH,IAAIimD,GACfkL,EAAMt4D,KAAKmH,IAAIkmD,GAEnB,GAAI+K,EAAK,EAAG,CACV,MAAMzkC,EAAI3zB,KAAKqB,KAAK,EAAI+2D,GAAMJ,EAAMC,IACpCI,GAAO1kC,EACP2kC,GAAO3kC,CACT,MACEikC,GACGP,IAAUC,GAAQ,EAAO,GAAOt3D,KAAKqB,KAAK+2D,GAAMJ,EAAME,EAAMD,EAAME,IAGvE,MAAM96B,EAAMu6B,EAAOS,EAAMN,EAAMO,EAC7Bh7B,GAAOs6B,EAAOU,EAAMR,EAAMO,EAC1B3D,EAAMF,EAAQn3B,EAAKw6B,EAAWv6B,EAAW,GAAN63B,EACnCR,EAAMkD,EAAWx6B,EAAKm3B,EAAQl3B,EAAW,GAAN83B,EACrC,IAAImD,EAASlD,GAAgB,EAAG,GAAIyC,EAAKz6B,GAAMg7B,GAAMN,EAAKz6B,GAAMg7B,GAC5DE,EAASnD,IACVyC,EAAKz6B,GAAMg7B,GACXN,EAAKz6B,GAAMg7B,IACVR,EAAKz6B,GAAMg7B,IACXN,EAAKz6B,GAAMg7B,GAGD,IAAVhB,GAAekB,EAAS,EAC1BA,GAAU,EAAI92D,EACK,IAAV41D,GAAekB,EAAS,IACjCA,GAAU,EAAI92D,GAIhB,MAAMulD,EAAWjnD,KAAKosC,KAAKpsC,KAAKmH,IAAKqxD,EAAS92D,EAAM,IAClD+kC,EAAS,GACTgyB,EAASD,EAASvR,EAClB2N,EACI,EAAI,EAAK50D,KAAKoH,IAAIqxD,EAAS,GAAKz4D,KAAKoH,IAAIqxD,EAAS,GACpDz4D,KAAKoH,IAAIqxD,EAAS,GACtB,IAAIC,EAAMH,EAASE,EAEnB,IAAK,IAAI5xD,EAAI,EAAGA,EAAIogD,EAAUpgD,IAC5B4/B,EAAO5/B,GAAKwtD,GACVkE,EACAG,EACAlE,EACAqD,EACAQ,EACAC,EACA5D,EACAC,EACAC,EACAC,EACAC,GAEFD,EAAQpuB,EAAO5/B,GAAG,GAClBiuD,EAAQruB,EAAO5/B,GAAG,GAClB0xD,EAASG,EACTA,GAAOD,EAET,OAAOhyB,GAyJUixB,CAAcH,EAAKL,EAAIM,EAAKL,EAAI/J,EAAIC,EAAIgK,EAAOC,EAAOF,GAEvE,IAAK,IAAIvwD,EAAI,EAAGmY,EAAMy4C,EAAS97D,OAAQkL,EAAImY,EAAKnY,IAC9C4wD,EAAS5wD,GAAG,IAAMqwD,EAClBO,EAAS5wD,GAAG,IAAMswD,EAClBM,EAAS5wD,GAAG,IAAMqwD,EAClBO,EAAS5wD,GAAG,IAAMswD,EAClBM,EAAS5wD,GAAG,IAAMqwD,EAClBO,EAAS5wD,GAAG,IAAMswD,EAEpB,OAAOM,GAcIkB,GAAmB/6C,IAI9B,IAAInW,EAAI,EACND,EAAI,EAIFoxD,EAAK,EACPC,EAAK,EAGP,MAAMC,EAAmC,GACzC,IAAIC,EAEFC,EAAW,EACXC,EAAW,EACb,IAAK,MAAMC,KAAiBt7C,EAAM,CAChC,MAAMlR,EAAiC,IAAIwsD,GAC3C,IAAIC,EACJ,OACEzsD,EAAQ,IAER,IAAK,IACHA,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACHC,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAK1xD,EAAGD,GACrB,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EAEhB,IAAK,IACHA,EAAIiF,EAAQ,GACZysD,EAAY,CAAC,IAAK1xD,EAAGD,GACrB,MACF,IAAK,IACHkF,EAAQ,IAAMlF,EAEhB,IAAK,IACHA,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAK1xD,EAAGD,GACrB,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACHC,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZksD,EAAKlsD,EAAQ,GACbmsD,EAAKnsD,EAAQ,GACbysD,EAAY,CAAC,IAAK1xD,EAAGD,GACrB,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EACdkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EACdkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACHwxD,EAAWtsD,EAAQ,GACnBusD,EAAWvsD,EAAQ,GACnBjF,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAKzsD,EAAQ,GAAIA,EAAQ,GAAIssD,EAAUC,EAAUxxD,EAAGD,GACjE,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EACdkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IAEc,MAAbuxD,GAEFC,EAAW,EAAIvxD,EAAIuxD,EACnBC,EAAW,EAAIzxD,EAAIyxD,IAInBD,EAAWvxD,EACXwxD,EAAWzxD,GAEbC,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAKH,EAAUC,EAAUvsD,EAAQ,GAAIA,EAAQ,GAAIjF,EAAGD,GAGjEwxD,EAAWG,EAAU,GACrBF,EAAWE,EAAU,GACrB,MACF,IAAK,IACHzsD,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EACdkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACHwxD,EAAWtsD,EAAQ,GACnBusD,EAAWvsD,EAAQ,GACnBjF,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAKH,EAAUC,EAAUxxD,EAAGD,GACzC,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACc,MAAbuxD,GAEFC,EAAW,EAAIvxD,EAAIuxD,EACnBC,EAAW,EAAIzxD,EAAIyxD,IAInBD,EAAWvxD,EACXwxD,EAAWzxD,GAEbC,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZysD,EAAY,CAAC,IAAKH,EAAUC,EAAUxxD,EAAGD,GACzC,MACF,IAAK,IACHkF,EAAQ,IAAMjF,EACdiF,EAAQ,IAAMlF,EAEhB,IAAK,IACHyvD,GAAiBxvD,EAAGD,EAAGkF,GAASvQ,QAASuU,GAAMooD,EAAgBhzD,KAAK4K,IACpEjJ,EAAIiF,EAAQ,GACZlF,EAAIkF,EAAQ,GACZ,MACF,IAAK,IACL,IAAK,IACHjF,EAAImxD,EACJpxD,EAAIqxD,EACJM,EAAY,CAAC,KAIbA,GACFL,EAAgBhzD,KAAKqzD,GACrBJ,EAAWI,EAAU,IAErBJ,EAAW,EAEf,CACA,OAAOD,GAYHM,GAAiBA,CACrBR,EACAC,EACAQ,EACAC,IACWt5D,KAAKqB,MAAMg4D,EAAKT,IAAO,GAAKU,EAAKT,IAAO,GAa/C7B,GACJA,CACEnB,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,IAEDmD,IACC,MAAMC,EAASD,GA1Va,EA2V1BE,EA1VOzwD,IAAc,EAAIA,GAAK,GAAK,EAAIA,GA0VlC0wD,CAAIH,GACTI,EA1VO3wD,IAAc,EAAIA,GAAK,EAAIA,IAAM,EA0VnC4wD,CAAIL,GACTM,EA1VO7wD,KAAe,EAAIA,IAAM,EA0V3B8wD,CAAIP,GACX,OAAO,IAAIhyD,GACT4uD,EAAOqD,EAAKvD,EAAOwD,EAAK1D,EAAO4D,EAAK9D,EAAOgE,EAC3CzD,EAAOoD,EAAKtD,EAAOuD,EAAKzD,EAAO2D,EAAK7D,EAAO+D,IAI3CE,GAAO/wD,GAAcA,GAAK,EAC1BgxD,GAAOhxD,GAAc,EAAIA,GAAK,EAAIA,GAClCixD,GAAOjxD,IAAe,EAAIA,IAAM,EAEhCkxD,GACJA,CACEC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,IAEDnB,IACC,MAAMoB,EAAMZ,GAAIR,GACdqB,EAAMZ,GAAIT,GACVsB,EAAMZ,GAAIV,GACVuB,EACE,GAAKD,GAAOR,EAAMF,GAAOS,GAAOL,EAAMF,GAAOM,GAAOF,EAAMF,IAC5DQ,EACE,GAAKF,GAAOP,EAAMF,GAAOQ,GAAOJ,EAAMF,GAAOK,GAAOD,EAAMF,IAC9D,OAAOx6D,KAAKkR,MAAM6pD,EAAUD,IAG1BE,GACJA,CACEb,EACAC,EACAC,EACAC,EACAC,EACAC,IAEDjB,IACC,MAAMC,EAAKO,GAAIR,GACbE,EAAKO,GAAIT,GACTI,EAAKM,GAAIV,GACX,OAAO,IAAIhyD,GACTgzD,EAAMf,EAAKa,EAAMZ,EAAKU,EAAMR,EAC5Ba,EAAMhB,EAAKc,EAAMb,EAAKW,EAAMT,IAI5BsB,GACJA,CACEd,EACAC,EACAC,EACAC,EACAC,EACAC,IAEDjB,IACC,MAAM2B,EAAO,EAAI3B,EACfuB,EAAW,GAAKI,GAAQb,EAAMF,GAAOZ,GAAOgB,EAAMF,IAClDU,EAAW,GAAKG,GAAQZ,EAAMF,GAAOb,GAAOiB,EAAMF,IACpD,OAAOt6D,KAAKkR,MAAM6pD,EAAUD,IAK1BK,GAAeA,CACnBpE,EACA6B,EACAC,KAEA,IAAIuC,EAAQ,IAAI7zD,GAAMqxD,EAAIC,GACxBwC,EAAS,EACX,IAAK,IAAIC,EAAO,EAAGA,GAAQ,IAAKA,GAAQ,EAAG,CACzC,MAAMnxD,EAAI4sD,EAASuE,EAAO,KAC1BD,GAAUjC,GAAegC,EAAM3zD,EAAG2zD,EAAM5zD,EAAG2C,EAAE1C,EAAG0C,EAAE3C,GAClD4zD,EAAQjxD,CACV,CACA,OAAOkxD,GAWHE,GAA4BA,CAChCC,EACAnhB,KAEA,IAIEohB,EAJEH,EAAO,EACTD,EAAS,EACTD,EAAY,CAAE3zD,EAAG+zD,EAAQ/zD,EAAGD,EAAGg0D,EAAQh0D,GACvC2C,EAAQ,IAAKixD,GAEbM,EAAW,IACXC,EAAW,EAGb,MAAM5E,EAAWyE,EAAQzE,SACvB6E,EAAcJ,EAAQI,YACxB,KAAOP,EAAShhB,GAAYqhB,EAAW,MACrCvxD,EAAI4sD,EAASuE,GACbK,EAAWL,EACXG,EAAUrC,GAAegC,EAAM3zD,EAAG2zD,EAAM5zD,EAAG2C,EAAE1C,EAAG0C,EAAE3C,GAE9Ci0D,EAAUJ,EAAShhB,GAErBihB,GAAQI,EACRA,GAAY,IAEZN,EAAQjxD,EACRmxD,GAAQI,EACRL,GAAUI,GAGd,MAAO,IAAKtxD,EAAGjD,MAAO00D,EAAYD,KAQvBE,GACXj+C,IAEA,IAOEm5C,EACA+E,EAREC,EAAc,EAGhBnD,EAAK,EACLC,EAAK,EACLQ,EAAK,EACLC,EAAK,EAGP,MAAM0C,EAA2B,GACjC,IAAK,MAAMtvD,KAAWkR,EAAM,CAC1B,MAAMq+C,EAAmE,CACvEx0D,EAAGmxD,EACHpxD,EAAGqxD,EACHqD,QAASxvD,EAAQ,GACjB/Q,OAAQ,GAEV,OACE+Q,EAAQ,IAER,IAAK,IACHovD,EAAwCG,EACxCH,EAASr0D,EAAI4xD,EAAKT,EAAKlsD,EAAQ,GAC/BovD,EAASt0D,EAAI8xD,EAAKT,EAAKnsD,EAAQ,GAC/B,MACF,IAAK,IACHovD,EAAwCG,EACxCH,EAASngE,OAASy9D,GAAeR,EAAIC,EAAInsD,EAAQ,GAAIA,EAAQ,IAC7DksD,EAAKlsD,EAAQ,GACbmsD,EAAKnsD,EAAQ,GACb,MACF,IAAK,IACHqqD,EAAWC,GACT4B,EACAC,EACAnsD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IAEVovD,EAA4BG,EAC5BH,EAAS/E,SAAWA,EACpB+E,EAASF,YAAc1B,GACrBtB,EACAC,EACAnsD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IAEVovD,EAASngE,OAASw/D,GAAapE,EAAU6B,EAAIC,GAE7CD,EAAKlsD,EAAQ,GACbmsD,EAAKnsD,EAAQ,GACb,MACF,IAAK,IACHqqD,EAAWiE,GACTpC,EACAC,EACAnsD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IAEVovD,EAA4BG,EAC5BH,EAAS/E,SAAWA,EACpB+E,EAASF,YAAcX,GACrBrC,EACAC,EACAnsD,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IAEVovD,EAASngE,OAASw/D,GAAapE,EAAU6B,EAAIC,GAC7CD,EAAKlsD,EAAQ,GACbmsD,EAAKnsD,EAAQ,GACb,MACF,IAAK,IAEHovD,EAAyBG,EACzBH,EAASK,MAAQ9C,EACjByC,EAASM,MAAQ9C,EACjBwC,EAASngE,OAASy9D,GAAeR,EAAIC,EAAIQ,EAAIC,GAC7CV,EAAKS,EACLR,EAAKS,EAGTyC,GAAeD,EAASngE,OACxBqgE,EAAKl2D,KAAKg2D,EACZ,CAEA,OADAE,EAAKl2D,KAAK,CAAEnK,OAAQogE,EAAat0D,EAAGmxD,EAAIpxD,EAAGqxD,IACpCmD,GASIK,GAAiB,SAC5Bz+C,EACAy8B,GAE4B,IAD5BiiB,EAAyB5gE,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGmgE,GAAoBj+C,GAE5C/W,EAAI,EACR,KAAOwzC,EAAWiiB,EAAMz1D,GAAGlL,OAAS,GAAKkL,EAAIy1D,EAAM3gE,OAAS,GAC1D0+C,GAAYiiB,EAAMz1D,GAAGlL,OACrBkL,IAEF,MAAM20D,EAAUc,EAAMz1D,GACpB01D,EAAaliB,EAAWmhB,EAAQ7/D,OAChCurD,EAAUtpC,EAAK/W,GAEjB,OAAQ20D,EAAQU,SACd,IAAK,IACH,MAAO,CAAEz0D,EAAG+zD,EAAQ/zD,EAAGD,EAAGg0D,EAAQh0D,EAAGN,MAAO,GAC9C,IAAK,IACH,MAAO,IACF,IAAIK,GAAMi0D,EAAQ/zD,EAAG+zD,EAAQh0D,GAAGuB,KACjC,IAAIxB,GAAMi0D,EAAQW,MAAOX,EAAQY,OACjCG,GAEFr1D,MAAOlH,KAAKkR,MAAMsqD,EAAQY,MAAQZ,EAAQh0D,EAAGg0D,EAAQW,MAAQX,EAAQ/zD,IAEzE,IAAK,IACH,MAAO,IACF,IAAIF,GAAMi0D,EAAQ/zD,EAAG+zD,EAAQh0D,GAAGuB,KACjC,IAAIxB,GAAM2/C,EAAQ,GAAKA,EAAQ,IAC/BqV,GAEFr1D,MAAOlH,KAAKkR,MAAMg2C,EAAQ,GAAMsU,EAAQh0D,EAAG0/C,EAAQ,GAAMsU,EAAQ/zD,IAErE,IAAK,IAEL,IAAK,IACH,OAAO8zD,GAA0BC,EAASnhB,GAIhD,EAEMmiB,GAAe,IAAI9hC,ODlxBI,6BCkxBkB,MACzC+hC,GAAyB,IAAI/hC,OAAOw5B,GAAoB,KACxDwI,GAAU,IAAIhiC,OAAOoC,GAAO,MAC5B6/B,GAAiB,CACrB/8C,EAAG,EACHgU,EAAG,EACHF,EAAG,EACH/V,EAAG,EACHwhB,EAAG,EACHxL,EAAG,EACHN,EAAG,EACHrqB,EAAG,EACHuH,EAAG,GAaQqsD,GAAaC,IAAyC,IAAAC,EACjE,MAAMC,EAA0B,GAC1BjpD,EAAoC,QAAjCgpD,EAAGD,EAAWxmC,MAAMmmC,WAAa,IAAAM,EAAAA,EAAI,GAC9C,IAAK,MAAME,KAAYlpD,EAAK,CAE1B,MAAMmpD,EAAgBD,EAAS,GAE/B,GAAsB,MAAlBC,GAA2C,MAAlBA,EAAuB,CAClDF,EAAMj3D,KAAK,CAACm3D,IACZ,QACF,CACA,MAAMC,EACJP,GACEM,EAAcx8D,eAGlB,IAAI08D,EAAW,GACf,GAAsB,MAAlBF,GAA2C,MAAlBA,EAAuB,CAKlDR,GAAuBW,UAAY,EACnC,IAAK,IAAIC,EAAM,KAAOA,EAAMZ,GAAuBrlC,KAAK4lC,IACtDG,EAASr3D,QAAQu3D,EAAIjoC,MAAM,GAE/B,MACE+nC,EAAWH,EAAS3mC,MAAMqmC,KAAY,GAKxC,IAAK,IAAI71D,EAAI,EAAGA,EAAIs2D,EAASxhE,OAAQkL,GAAKq2D,EAAe,CACvD,MAAMI,EAAa,IAAItgE,MAAMkgE,GACvBK,EAAqBpJ,GAAiB8I,GAC5CK,EAAW,GACTz2D,EAAI,GAAK02D,EAAqBA,EAAqBN,EACrD,IAAK,IAAItqB,EAAI,EAAGA,EAAIuqB,EAAevqB,IACjC2qB,EAAW3qB,EAAI,GAAKx9B,WAAWgoD,EAASt2D,EAAI8rC,IAE9CoqB,EAAMj3D,KAAKw3D,EACb,CACF,CACA,OAAOP,GAUIS,GAA0B,SACrCz3C,GAEoB,IADpB+qC,EAAUp1D,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EAET+hE,EAAK,IAAIl2D,GAAMwe,EAAO,IACxB23C,EAAK,IAAIn2D,GAAMwe,EAAO,IACtB43C,EAAY,EACZC,EAAY,EACd,MAAMhgD,EAAwB,GAC5BoB,EAAM+G,EAAOpqB,OACbkiE,EAAa7+C,EAAM,EAWrB,IAAInY,EACJ,IAVIg3D,IACFF,EAAY53C,EAAO,GAAGte,EAAIi2D,EAAGj2D,GAAI,EAAKse,EAAO,GAAGte,IAAMi2D,EAAGj2D,EAAI,EAAI,EACjEm2D,EAAY73C,EAAO,GAAGve,EAAIk2D,EAAGl2D,GAAI,EAAKue,EAAO,GAAGve,IAAMk2D,EAAGl2D,EAAI,EAAI,GAEnEoW,EAAK9X,KAAK,CACR,IACA23D,EAAGh2D,EAAIk2D,EAAY7M,EACnB2M,EAAGj2D,EAAIo2D,EAAY9M,IAGhBjqD,EAAI,EAAGA,EAAImY,EAAKnY,IAAK,CACxB,IAAK42D,EAAG/0D,GAAGg1D,GAAK,CACd,MAAMI,EAAWL,EAAGp0D,aAAaq0D,GAIjC9/C,EAAK9X,KAAK,CAAC,IAAK23D,EAAGh2D,EAAGg2D,EAAGj2D,EAAGs2D,EAASr2D,EAAGq2D,EAASt2D,GACnD,CACAi2D,EAAK13C,EAAOlf,GACRA,EAAI,EAAIkf,EAAOpqB,SACjB+hE,EAAK33C,EAAOlf,EAAI,GAEpB,CAUA,OATIg3D,IACFF,EAAYF,EAAGh2D,EAAIse,EAAOlf,EAAI,GAAGY,EAAI,EAAIg2D,EAAGh2D,IAAMse,EAAOlf,EAAI,GAAGY,EAAI,GAAI,EACxEm2D,EAAYH,EAAGj2D,EAAIue,EAAOlf,EAAI,GAAGW,EAAI,EAAIi2D,EAAGj2D,IAAMue,EAAOlf,EAAI,GAAGW,EAAI,GAAI,GAE1EoW,EAAK9X,KAAK,CACR,IACA23D,EAAGh2D,EAAIk2D,EAAY7M,EACnB2M,EAAGj2D,EAAIo2D,EAAY9M,IAEdlzC,CACT,EA6EamgD,GAAWA,CAACC,EAA2B9oD,IAClD8oD,EACGjqD,IAAKmzC,GACGA,EACJnzC,IAAI,CAACw3C,EAAK1kD,IACC,IAANA,QACsBjL,IAAnBsZ,EADaq2C,EAGhBv2C,GAAQu2C,EAAKr2C,IAElBK,KAAK,MAETA,KAAK,KC7gCG0oD,GAAeA,CAACh1D,EAAahJ,IACxCD,KAAKsB,MAAMtB,KAAKk+D,UAAYj+D,EAAMgJ,EAAM,IAAMA,ECgCnCk1D,GAAqCA,CAChDrzD,EACAszD,KAEA,IAAI59C,EAAS1V,EAAOkmC,yBAChBlmC,EAAO8gD,kBA3BX9gD,KAEA,GAAIA,EAAO8gD,gBAAiB,CAC1B,MAAMt6C,OAAEA,EAAMC,OAAEA,EAAMrK,MAAEA,EAAKsK,MAAEA,GAAUL,GACvCrG,EAAO8gD,iBAET9gD,EAAO0H,OAAQ,EACf1H,EAAO2H,OAAQ,EACf3H,EAAOnK,IAAIwC,EAASmO,GACpBxG,EAAOnK,IAAIyC,EAASmO,GACpBzG,EAAO5D,MAAQA,EACf4D,EAAO0G,MAAQA,EACf1G,EAAO2G,MAAQ,CACjB,GAeE4sD,CAA4BvzD,GAC5B0V,EAASA,EAAOpW,UAAUU,EAAO8gD,yBAE5B9gD,EAAO8gD,gBACVwS,IACFtzD,EAAOwG,QAAU8sD,EAA2B9sD,OAC5CxG,EAAOyG,QAAU6sD,EAA2B7sD,OAC3CzG,EAAuBwzD,MAAQF,EAA2BE,MAC1DxzD,EAAuByzD,MAAQH,EAA2BG,MAC3D/9C,EAAO/Y,GAAK22D,EAA2BI,WACvCh+C,EAAOhZ,GAAK42D,EAA2BK,UACvC3zD,EAAO2C,MAAQ2wD,EAA2B3wD,MAC1C3C,EAAO4C,OAAS0wD,EAA2B1wD,QAE7C5C,EAAOsb,oBAAoB5F,EAAQte,EAAQA,0R5F/B3C3D,IACsB,IAAAmgE,EACtB,MAAMpvD,EAAYD,GAAuB9Q,GAEzC,OAD0B,QAA1BmgE,EAAApvD,EAAU9Q,WAAW,iBAAKkgE,GAA1BA,EAA4B9/C,UAAUrgB,EAAQ,EAAG,GAC1C+Q,oc0F48B4BqvD,CACnCC,EACAC,KAEA,MAAMC,EAA2B,EAAV9+D,KAAK0B,GAAUk9D,EAGtC,IAAIG,GAAsBt9D,EACtBm9D,EAAc,GAAM,IACtBG,GAAsBD,EAAgB,GAExC,MAAM54D,EAAI,IAAIlJ,MAAM4hE,EAAc,GAClC,IAAK,IAAI/3D,EAAI,EAAGA,EAAI+3D,EAAa/3D,IAAK,CACpC,MAAMm4D,EAAMn4D,EAAIi4D,EAAgBC,GAC1Bt3D,EAAEA,EAACD,EAAEA,GAAM,IAAID,GAAMN,GAAI+3D,GAAM53D,GAAI43D,IAAM32D,eAAew2D,GAC9D34D,EAAEW,GAAK,CAAO,IAANA,EAAU,IAAM,IAAKY,EAAGD,EAClC,CAEA,OADAtB,EAAE04D,GAAe,CAAC,KACX14D,+CjEn/BwB9B,IAC/B,MAAM66D,EAAmB,CAAC,sBAAuB,QAAS,KAAM,SAChE,OAAQ76D,GACN,IAAK,iBACH,OAAO66D,EAAiBr4D,OAAO,CAC7B,KACA,KACA,KACA,KACA,gBACA,sBAEJ,IAAK,iBACH,OAAOq4D,EAAiBr4D,OAAO,CAC7B,gBACA,oBACA,KACA,KACA,IACA,KACA,KACA,OAEJ,IAAK,OACH,OAAOq4D,EAAiBr4D,OAAO,CAAC,SAAU,aAAc,iBAE5D,OAAOq4D,qC8D3BuBC,CAC9BxkD,EACApd,IAEIod,GAAgC,IAApBA,EAAS/e,OAChB+e,EAAS,GAEX,IAAI22C,GAAM32C,EAAUpd,sOMIC6hE,CAAC3F,EAAkBC,KAAqB,IAAA2F,EACpE,IAAI7uD,EAAIipD,EACN9oD,EAAI+oD,EACFlpD,EAAEuuB,WAAapuB,EAAEouB,WAEnBvuB,EAAIkpD,EACJ/oD,EAAI8oD,GAGNxyC,GAAkBtW,EAAU,QAAT0uD,EAAE1uD,EAAEo3B,aAAK,IAAAs3B,OAAA,EAAPA,EAAS9lC,sBAAuB/oB,EAAE+oB,uBAEvD,MAAMwF,EAAWvuB,EAAEuuB,UAAYpuB,EAAEouB,SAKjC,OAJIA,IAEFvuB,EAAEuuB,SAAWpuB,EAAEouB,UAAW,GAErB,IAAIuyB,GAAM,CAAC9gD,GAAI,CAAEsN,SAAUnN,EAAGouB,2P9EfEugC,CACvCv0D,EACAV,KAEA,MAAM00B,EAAWxuB,GAAgBlG,GAC/Bk1D,EAAiB7uD,GACfquB,EACAh0B,EAAOob,iBAEXD,GAAuBnb,EAAQw0D,sT2Es6BJC,CAC3B3hD,EACAxT,EACAo1D,KAEIA,IACFp1D,EAAYqG,GAA0BrG,EAAW,CAC/C,EACA,EACA,EACA,GACCo1D,EAAW/3D,GACX+3D,EAAWh4D,KAGToW,EAAK7J,IAAK0rD,IACf,MAAMC,EAAmC,IAAID,GAC7C,IAAK,IAAI54D,EAAI,EAAGA,EAAI44D,EAAY9jE,OAAS,EAAGkL,GAAK,EAAG,CAElD,MAAMY,EAAEA,EAACD,EAAEA,GAAM6I,GACf,CACE5I,EAAGg4D,EAAY54D,GACfW,EAAGi4D,EAAY54D,EAAI,IAErBuD,GAEFs1D,EAAW74D,GAAKY,EAChBi4D,EAAW74D,EAAI,GAAKW,CACtB,CACA,OAAOk4D,yBI39BJ,SAASC,GAASzwD,EAAsB4T,GAC7C,MAAM88C,EAAe1wD,EAAQ0H,MACxBgpD,GAGL/jE,OAAO8J,QAAQmd,GAAQ3mB,QAAQmE,IAAA,IAAEmO,EAAUpP,GAAMiB,EAAA,OAC/Cs/D,EAAaC,YAAYpxD,EAAUpP,IAEvC,CCJO,MAAMygE,WAAyBloD,GAIpC1c,WAAAA,CACEsK,GAWA,IAVA4U,oBACEA,GAAsB,EAAK2lD,eAC3BA,EAAiB,IAOlBrkE,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEJF,MAAMgK,GAAMrK,EAAAC,KAAA,aAAA,GAAAD,EAAAC,KAAA,iBAAA,GACZ,MAAQ0b,GAAI0D,GAAkBpf,KAAK0c,MAC7BkoD,EAAgB5kE,KAAK6kE,oBAC3B7kE,KAAK8kE,MAAQ,CAAEppD,GAAIkpD,EAAe5oD,IAAK4oD,EAAcxhE,WAAW,OAChEpD,KAAK+kE,iBAAiB3lD,EAAe,CACnCJ,wBAEFhf,KAAK+kE,iBAAiBH,EAAe,CACnC5lD,sBACA0I,OAAQ,CACNjM,SAAU,WACVtJ,KAAM,IACNC,IAAK,OAGT,MAAM4yD,EAAYhlE,KAAKilE,yBACvBD,EAAUjoD,UAAUzQ,IAAIq4D,GACpBvlD,EAAc/D,YAChB+D,EAAc/D,WAAW6pD,aAAaF,EAAW5lD,GAEnD4lD,EAAU/7B,OAAO7pB,EAAewlD,GAChC5kE,KAAKglE,UAAYA,CACnB,CAEUH,iBAAAA,GACR,MAAQnpD,GAAI0D,GAAkBpf,KAAK0c,MAC7BhB,EAAK7H,KAUX,OARA6H,EAAGypD,UAAY/lD,EAAc+lD,UAE7BzpD,EAAGqB,UAAU1T,OAAO,gBAEpBqS,EAAGqB,UAAUzQ,IAAI,gBACjBoP,EAAGQ,aAAa,cAAe,OAC/BR,EAAGF,MAAMsB,QAAUsC,EAAc5D,MAAMsB,QACvCpB,EAAGQ,aAAa,YAAa,QACtBR,CACT,CAEUupD,sBAAAA,GACR,MAAMD,EAAYxgE,IAAoBuP,cAAc,OAMpD,OALAixD,EAAU9oD,aAAa,cAAe,WACtCqoD,GAASS,EAAW,CAClBvpD,SAAU,aAEZY,GAAwB2oD,GACjBA,CACT,CAMUD,gBAAAA,CACRjxD,EACA5R,GAKA,MAAMwlB,OAAEA,EAAM1I,oBAAEA,GAAwB9c,EACxCqiE,GAASzwD,EAAS,IACb4T,EACH,eAAgB1I,EAAsB,eAAiB7X,IAEzDkV,GAAwBvI,EAC1B,CAEAoJ,aAAAA,CAAcpN,EAAamM,GACzB7b,MAAM8c,cAAcpN,EAAMmM,GAC1B,MAAMP,GAAEA,EAAEM,IAAEA,GAAQhc,KAAK8kE,MACzB/oD,GAAoBL,EAAIM,EAAKlM,EAAMmM,EACrC,CAEAG,gBAAAA,CAAiBtM,GACf1P,MAAMgc,iBAAiBtM,GACvBsM,GAAiBpc,KAAK8kE,MAAMppD,GAAI5L,GAChCsM,GAAiBpc,KAAKglE,UAAWl1D,EACnC,CAEAkN,UAAAA,CAAWlN,GACT,MAAMk1D,EAAYhlE,KAAKglE,WACnBtpD,GAAI0D,GAAkBpf,KAAK0c,OAC3BhB,GAAIkpD,GAAkB5kE,KAAK8kE,MAC/B1kE,MAAM4c,WAAWlN,GACjBk1D,EAAUI,YAAYR,GACtBI,EAAUI,YAAYhmD,GAClB4lD,EAAU3pD,YACZ2pD,EAAU3pD,WAAW6pD,aAAa9lD,EAAe4lD,EAErD,CAEAzgE,OAAAA,GACEnE,MAAMmE,UACNL,IAASK,QAAQvE,KAAK8kE,MAAMppD,WAErB1b,KAAK8kE,aAEL9kE,KAAKglE,SACd,EC8HK,MC/OMK,GAAsCA,CACjD13C,EACA3e,EACA3C,EACAD,KAEA,MAAMpC,OAAEA,EAAM0Q,QAAEA,EAAO6J,QAAEA,GAAYvV,EACnCs2D,EAAUj5D,EAAIqO,EACd6qD,EAASn5D,EAAImY,EACbihD,GAASh4C,GAASxjB,EAAQ,kBAAoBA,EAAOmI,OAASmzD,EAC9DG,GAASj4C,GAASxjB,EAAQ,kBAAoBA,EAAOoI,MAAQmzD,EAM/D,OALAC,GAASx7D,EAAOzE,IAAIwB,EAAMu+D,GAC1BG,GAASz7D,EAAOzE,IAAIyB,EAAKu+D,IACrBC,GAASC,IACX3sB,GAAUzxC,EAAQqmB,GAAgBC,EAAW3e,EAAW3C,EAAGD,IAEtDo5D,GAASC,GCfZC,GAAmC/9D,EAQ5Bg+D,GAA6BC,GACjC,SAAUv3B,EAAYD,EAAqBy3B,GAChD,MAAMl7C,OAAEA,EAAMy5C,WAAEA,GAAeyB,EAC/B,OAAO,IAAI15D,GAAMwe,EAAOi7C,IACrBh5D,SAASw3D,GACTp1D,UACCqG,GACEwwD,EAAW73B,uBACX63B,EAAW3nC,uBAGnB,EAUW4nC,GAAoBA,CAC/Bn4C,EACA3e,EACA3C,EACAD,KAEA,MAAMpC,OAAEA,EAAM47D,WAAEA,GAAe52D,EACzB+2D,EAAO/7D,EACPg8D,EAAqBv6C,GACzB,IAAItf,GAAME,EAAGD,QACb5L,EACAulE,EAAKj7C,iBAMP,OAHAi7C,EAAKp7C,OAAOi7C,GAAcI,EAAmB15D,IAAIy5D,EAAK3B,YACtD2B,EAAK7oD,gBACL6oD,EAAKxgE,IAAI,SAAS,IACX,GAMI0gE,GAA2BA,CACtCL,EACA3hB,IAEO,SACLt2B,EACA3e,EACA3C,EACAD,GAEA,MAAM25D,EAAO/2D,EAAUhF,OACrBk8D,EAAc,IAAI/5D,GAChB45D,EAAKp7C,QAAQi7C,EAAa,EAAIA,EAAaG,EAAKp7C,OAAOpqB,QAAU,IAEnE4lE,EAA2BD,EACxBt5D,SAASm5D,EAAK3B,YACdp1D,UAAU+2D,EAAKj7C,iBAClBouB,EAAkB+K,EAAGt2B,EAAW,IAAK3e,EAAW42D,cAAcv5D,EAAGD,GAM7Dg6D,EAJ8BF,EACjCt5D,SAASm5D,EAAK3B,YACdp1D,UAAU+2D,EAAKj7C,iBAEuBle,SAASu5D,GAIlD,OAHAJ,EAAK5zD,MAAQi0D,EAAK/5D,EAClB05D,EAAK3zD,KAAOg0D,EAAKh6D,EAEV8sC,CACT,EAGWmtB,GAA2BT,GACtC7sB,GACE2sB,GACAO,GAAyBL,EAAYE,KCrFzC,MAUMQ,GAAwBA,CAC5BC,EACAC,EACAZ,KAEA,MAAMpjD,KAAEA,EAAI4hD,WAAEA,GAAemC,EACvBzF,EAAUt+C,EAAKgkD,GACrB,OAAO,IAAIr6D,GACR20D,EAAQ8E,GAAyBxB,EAAW/3D,EAC5Cy0D,EAAQ8E,EAAa,GAAgBxB,EAAWh4D,GACjD4C,UACAqG,GACEkxD,EAAWv4B,uBACXu4B,EAAWroC,yBAkDjB,SAASuoC,GAEPp4B,EACAD,EACAm4B,GAEA,MAAMC,aAAEA,EAAYZ,WAAEA,GAAe5lE,KACrC,OAAOsmE,GAAsBC,EAAYC,EAAcZ,EACzD,CASA,SAASc,GAEP/4C,EACA3e,EACA3C,EACAD,GAEA,MAAMpC,OAAEA,GAAWgF,GACbw3D,aAAEA,EAAYZ,WAAEA,GAAe5lE,KAC/Bk5C,EAvEcytB,EACpBJ,EACAl6D,EACAD,EACAo6D,EACAZ,KAEA,MAAMpjD,KAAEA,EAAI4hD,WAAEA,GAAemC,EAEvBK,EACJpkD,GAAMgkD,EAAe,EAAIA,EAAehkD,EAAKjiB,QAAU,GACnD2lE,EAAc,IAAI/5D,GACtBy6D,EAAchB,GACdgB,EAAchB,EAAa,IAGvBO,EAA2BD,EAC9Bt5D,SAASw3D,GACTp1D,UAAUu3D,EAAWz7C,iBAElBk7C,EAAqBv6C,GACzB,IAAItf,GAAME,EAAGD,QACb5L,EACA+lE,EAAWz7C,iBAGbtI,EAAKgkD,GAAcZ,GAAcI,EAAmB35D,EAAI+3D,EAAW/3D,EACnEmW,EAAKgkD,GAAcZ,EAAa,GAAKI,EAAmB55D,EAAIg4D,EAAWh4D,EACvEm6D,EAAWrpD,gBAEX,MAIMkpD,EAJ8BF,EACjCt5D,SAAS25D,EAAWnC,YACpBp1D,UAAUu3D,EAAWz7C,iBAEiBle,SAASu5D,GAIlD,OAHAI,EAAWp0D,MAAQi0D,EAAK/5D,EACxBk6D,EAAWn0D,KAAOg0D,EAAKh6D,EACvBm6D,EAAWhhE,IAAI,SAAS,IACjB,GAiCiBohE,CACtB38D,EACAqC,EACAD,EACAo6D,EACAZ,GASF,OANE9sB,GAAU94C,KAAKy7C,WAAmC,IAC7C/tB,GAAgBC,EAAW3e,EAAW3C,EAAGD,GAC5Co6D,eACAZ,eAGG1sB,CACT,CAKA,MAAM2tB,WAAyBlsB,GAK7B76C,WAAAA,CAAYoC,GACV9B,MAAM8B,EACR,CAEA2hB,MAAAA,CACE7H,EACA7J,EACAC,EACA6nC,EACA9qC,GAEA,MAAMykD,EAA2C,IAC5C3Z,EACH0C,YAAa38C,KAAK8mE,YAClBjqB,kBAAmB78C,KAAK+mE,cACxBnqB,oBAAqB58C,KAAK8mE,aAE5B1mE,MAAMyjB,OAAO7H,EAAK7J,EAAMC,EAAKwhD,EAAWzkD,EAC1C,EAGF,MAAM63D,WAAgCH,GAIpC/mE,WAAAA,CAAYoC,GACV9B,MAAM8B,EACR,CAEA2hB,MAAAA,CAEE7H,EACA7J,EACAC,EACA6nC,EACA9qC,GAEA,MAAMqT,KAAEA,GAASrT,GACXq3D,aACJA,EAAYZ,WACZA,EAAUqB,sBACVA,EAAqBC,oBACrBA,GACElnE,KACJgc,EAAI2G,OACJ3G,EAAIq4B,YAAcr0C,KAAK+mE,cACnB/mE,KAAKmnE,qBACPnrD,EAAI04B,YAAY10C,KAAKmnE,qBAEvB,MAAOC,GAAe5kD,EAAKgkD,GACrB3lD,EAAQylD,GACZn3D,EACA83D,EACAC,GAGF,GAAoB,MAAhBE,EAAqB,CAEvB,MAAMC,EAASf,GACbn3D,EACAq3D,EACAZ,EAAa,GAEf5pD,EAAImI,OAAOkjD,EAAOh7D,EAAGg7D,EAAOj7D,GAC5B4P,EAAIoI,OAAOjS,EAAMC,EACnB,MACE4J,EAAImI,OAAOhS,EAAMC,GAEnB4J,EAAIoI,OAAOvD,EAAMxU,EAAGwU,EAAMzU,GAC1B4P,EAAI6hB,SACJ7hB,EAAI6G,UAEJziB,MAAMyjB,OAAO7H,EAAK7J,EAAMC,EAAK6nC,EAAe9qC,EAC9C,EAGF,MAAMm4D,GAAgBA,CACpBC,EACAC,EACAC,EACAvlE,EAIA+kE,EACAC,IAEA,IAAKO,EAAiBT,GAA0BH,IAAkB,CAChEL,aAAce,EACd3B,WAAY4B,EACZ/rB,WAtNqC,aAuNrCM,gBAAiB0qB,GACjBztB,cAAe0tB,GACfO,wBACAC,yBACGhlE,KACCulE,EAAiBvlE,EAAQwlE,kBAAoBxlE,EAAQylE,8KAGtD,SACLnlD,GAKyB,IAJzBtgB,EAGC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEJ,MAAM8tB,EAAW,CAAA,EACjB,IAAIw5C,EAA+C,IA4CnD,OA3CAplD,EAAKA,KAAKzhB,QAAQ,CAAC+/D,EAAS0F,KAC1B,MAAMY,EAActG,EAAQ,GAU5B,OARoB,MAAhBsG,IACFh5C,EAAS,KAAKo4C,KAAgBY,KAAiBE,GAC7Cd,EACA1F,EAAQvgE,OAAS,GACjB,EACA2B,IAGIklE,GACN,IAAK,IACHh5C,EAAS,KAAKo4C,YAAyBc,GACrCd,EACA,GACA,EACAtkE,EACAskE,EAAe,EAtIKoB,IACJ,MAAxBA,EAA8B,EAA4B,MAAxBA,EAA8B,EAAI,EAsI5DC,CAAqBD,IAEvBx5C,EAAS,KAAKo4C,YAAyBc,GACrCd,EACA,GACA,EACAtkE,EACAskE,EACA,GAEF,MACF,IAAK,IACHp4C,EAAS,KAAKo4C,YAAyBc,GACrCd,EACA,GACA,EACAtkE,EACAskE,EACA,GAINoB,EAAsBR,IAEjBh5C,CACT,gDDpLO,SACLhkB,GAEA,IADAlI,EAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE5B,MAAM8tB,EAAW,CAAA,EACjB,IACE,IAAIxiB,EAAM,EACVA,GAAuB,iBAATxB,EAAoBA,EAAOA,EAAKugB,OAAOpqB,QACrDqL,IAEAwiB,EAAS,IAAIxiB,KAAS,IAAI+uC,GAAQ,CAChCc,WAAYiqB,GACZ3pB,gBAAiB4pB,GAA0B/5D,GAC3CotC,cAAeqtB,GAAwBz6D,MACpC1J,IAGP,OAAOksB,CACT,uhBE2CO,MAAM05C,WACH3oD,GAEVrf,WAAAA,GAAAM,SAAAE,WA0DEP,yBAKkC,IASlCA,2BAMsC,MAEtCA,wBAaW,MAEXA,0BAMkB,EAAK,CA6BvB,kBAAO0f,GACL,MAAO,IAAKrf,MAAMqf,iBAAkBqoD,GAAiBpoD,YACvD,CAGA,iBAAIklD,GAAgB,IAAAmD,EAClB,OAA0B,QAA1BA,EAAO/nE,KAAKsf,SAASwlD,aAAK,IAAAiD,OAAA,EAAnBA,EAAqBrsD,EAC9B,CACA,cAAI81B,GAAa,IAAAw2B,EACf,OAA0B,QAA1BA,EAAOhoE,KAAKsf,SAASwlD,aAAK,IAAAkD,OAAA,EAAnBA,EAAqBhsD,GAC9B,CACA,aAAIisD,GACF,OAAOjoE,KAAKsf,SAAS0lD,SACvB,CAQUrlD,YAAAA,CAAajE,GACrB1b,KAAKsf,SAAW,IAAIolD,GAAiBhpD,EAAI,CACvCsD,oBAAqBhf,KAAKgf,oBAC1B2lD,eAAgB3kE,KAAK2kE,iBAEvB3kE,KAAKiwC,oBACP,CAMAxgC,cAAAA,CAAe0B,GACbnR,KAAKkoE,sBAAmB1nE,EACxBJ,MAAMqP,eAAe0B,EACvB,CAMAxB,gBAAAA,CAAiBwB,GACfnR,KAAKkoE,sBAAmB1nE,EAEpB2Q,IAAQnR,KAAKmkD,gBACfnkD,KAAKqL,KAAK,2BAA4B,CAAE88D,WAAY,CAACh3D,KACrDnR,KAAKooE,uBACLpoE,KAAKqL,KAAK,oBAAqB,CAAE88D,WAAY,CAACh3D,KAC9CA,EAAI9F,KAAK,aAAc,CACrBrB,OAAQmH,KAGRA,IAAQnR,KAAKqoE,iBACfroE,KAAKqoE,oBAAiB7nE,EACtBR,KAAKsoE,gBAAkB,IAEzBloE,MAAMuP,iBAAiBwB,EACzB,CAEAvB,oBAAAA,GACE5P,KAAKkoE,sBAAmB1nE,EACxBJ,MAAMwP,sBACR,CAOA24D,sBAAAA,GACE,MAAMhR,EAAev3D,KAAKmkD,cAC1B,OAAQnkD,KAAK03D,wBAA0BH,EACnCv3D,KAAKqP,SACFvF,OAAQ4F,IAAYA,EAAOg9B,OAASh9B,IAAW6nD,GAC/C/rD,OAAO+rD,GACVv3D,KAAKqP,QACX,CAKAqS,SAAAA,GACE1hB,KAAK2hB,wBACD3hB,KAAK4hB,aAGL5hB,KAAKwoE,iBAAoBxoE,KAAKyoE,gBAAmBzoE,KAAK0oE,gBACxD1oE,KAAKqhB,aAAarhB,KAAKwxC,YACvBxxC,KAAKwoE,iBAAkB,GAErBxoE,KAAKwgB,iBACPxgB,KAAK2oE,eAAe3oE,KAAKwxC,YACzBxxC,KAAKwgB,gBAAiB,IAEvBxgB,KAAKkoE,mBACHloE,KAAKkoE,iBAAmBloE,KAAKuoE,0BAChCvoE,KAAK6hB,aAAa7hB,KAAKoD,aAAcpD,KAAKkoE,kBAC5C,CAKAS,cAAAA,CAAe3sD,GACbA,EAAI2G,OACA3iB,KAAK0oE,eAAiB1oE,KAAK4oE,sBAC7B5oE,KAAK6oE,kBAAoB7oE,KAAK6oE,iBAAiBz1B,UAC/CpzC,KAAKwoE,iBAAkB,GAGrBxoE,KAAK8oE,WAAa9oE,KAAKyoE,iBACzBzoE,KAAK+oE,eAAe/sD,GACpBhc,KAAKwoE,iBAAkB,GAEzBxsD,EAAI6G,SACN,CAOAmmD,SAAAA,GACE,MAAMhtD,EAAMhc,KAAKwxC,WACjBxxC,KAAKqhB,aAAarF,GAClBhc,KAAK2oE,eAAe3sD,GAEpBhc,KAAKqL,KAAK,eAAgB,CAAE2Q,OAC9B,CAOAitD,sBAAAA,CAAuBhlE,GACrBA,EAAQW,KAAKopB,MAAM/pB,GACnBjE,KAAKkpE,oBAAsBjlE,EAC3B,MAAMytC,EAAS1xC,KAAKigB,mBACdnQ,EAAOlL,KAAKosC,MAAc,EAAR/sC,EAAY,GAAKytC,GACzC1xC,KAAKmpE,kBAAkB92D,MAAQrS,KAAKmpE,kBAAkB72D,OAASxC,EAC/D9P,KAAKopE,iBAAiBjtD,MAAMu1B,EAAQA,EACtC,CAYA23B,mBAAAA,CAAoBr/D,EAAsBqC,EAAWD,GACnD,MAAMq7C,EAAYznD,KAAKkpE,oBACjBltD,EAAMhc,KAAKopE,iBACjBppE,KAAKqhB,aAAarF,GAClBA,EAAI2G,OACJ3G,EAAIs1B,WAAWjlC,EAAIo7C,GAAYr7C,EAAIq7C,GACnCzrC,EAAIhN,aAAahP,KAAKif,mBACtB,MAAMqqD,EAAet/D,EAAOk6C,yBAC5Bl6C,EAAOk6C,yBAA2B,GAClCl6C,EAAO6Z,OAAO7H,GACdhS,EAAOk6C,yBAA2BolB,EAClCttD,EAAI6G,UAGJ,MAAM0mD,EAAoB3kE,KAAKopB,MAAMy5B,EAAYznD,KAAKigB,oBACtD,OAAOunC,GACLxrC,EACAutD,EACAA,EACAA,EAEJ,CAOAC,sBAAAA,CAAuBj/C,GACrB,MAAMk/C,EAAOzpE,KAAK0pE,aAClB,QAAKD,IAGD7nE,MAAMwN,QAAQq6D,KACPA,EAAKhmE,KAAMlC,KAAUA,IAAkB,IAAXgpB,EAAEhpB,IAEhCgpB,EAAEk/C,GAEb,CAOAE,qBAAAA,CACEp/C,EACAvgB,GAEA,MAAMmtD,EAAgBn3D,KAAK4pE,mBACzBrS,EAAev3D,KAAKmkD,cAEtB,UACGn6C,GACAA,GACCutD,GACAJ,EAAc52D,OAAS,IACW,IAAlC42D,EAAc5tD,QAAQS,IACtButD,IAAiBvtD,IAChBhK,KAAKwpE,uBAAuBj/C,IAC9BvgB,IAAWA,EAAOm9C,SAClBn9C,IAAWA,EAAO0I,YAAc6kD,GAAgBA,IAAiBvtD,EAEtE,CAeQ6/D,sBAAAA,CACN7/D,EACA+4C,EACA+mB,GAEA,IAAK9/D,EACH,OAGF,IAAI+/D,EAaJ,OAVEhnB,IAAWj7C,GACXi7C,IAAWh7C,GACXg7C,IAAW/6C,GACX+6C,IAAWr7C,EAEXqiE,EAAkB/pE,KAAK4jC,iBAAmB55B,EAAO45B,gBACxCmf,IAAWv7C,IACpBuiE,EAAkB/pE,KAAK2jC,kBAAoB35B,EAAO25B,kBAG7ComC,GAAmBD,EAAqBA,CACjD,CASAE,oBAAAA,CACEhgE,EACAigE,GAEA,MAAMt7D,EAAS,CACbtC,EAAGrC,EAAOqjB,QACVjhB,EAAGpC,EAAOsjB,SAGZ,OAAK28C,GAKD,CAAC,KAAM,KAAM,MAAMh5D,SAASg5D,GAC9Bt7D,EAAOtC,EAAInF,EAEF,CAAC,KAAM,KAAM,MAAM+J,SAASg5D,KACrCt7D,EAAOtC,EAAItF,GAGT,CAAC,KAAM,KAAM,MAAMkK,SAASg5D,GAC9Bt7D,EAAOvC,EAAInF,EAEF,CAAC,KAAM,KAAM,MAAMgK,SAASg5D,KACrCt7D,EAAOvC,EAAIpF,GAEN2H,GAjBEA,CAkBX,CAQAu7D,sBAAAA,CACE3/C,EACAvgB,EACAmgE,GACM,IAAAC,EACN,MAAMx8C,EAAU5jB,EAAO0iC,MAEnBjhB,GACEzrB,KAAKqqE,cAAc9/C,QACnB/pB,EACAwJ,EAAO0iC,MAAMxO,uBAEfl+B,KAAKqqE,cAAc9/C,IACfhpB,IAAK4sB,EAAS,GAAEL,QAAEA,GAAY9jB,EAAOi5C,oBAAsB,CAAA,EACjEjK,EACEmxB,GAAmBr8C,EAC6B,QADtBs8C,EACtBt8C,EAAQmtB,iBAAiB1wB,EAAGvgB,EAAQ8jB,UAAQ,IAAAs8C,OAAA,EAA5CA,EAA8CvjC,KAAK/Y,GACnDu3C,GACNtiB,EjFvlB6BunB,EACjCH,EACAh8C,EACA5D,EACAvgB,KAEA,IAAKmkB,IAAWg8C,EACd,MAAO,OAET,MAAMr8C,EAAU9jB,EAAOokB,SAASD,GAChC,OAAOL,EAAQ0tB,cAAcjxB,EAAGuD,EAAS9jB,IiF6kB5BsgE,CAAoBH,EAAiBh8C,EAAQ5D,EAAGvgB,GACzDugE,EAAShgD,EAAEvqB,KAAKwqE,aAChB77D,EAAS3O,KAAK6pE,uBAAuB7/D,EAAQ+4C,EAAQwnB,GAChD,CAAEl+D,EAAGvF,EAAQsF,EAAGtF,GACjB9G,KAAKgqE,qBAAqBhgE,EAAQmkB,IACtCjY,OACEA,EAAMC,OACNA,EAAMC,MACNA,EAAKC,MACLA,EAAKlE,KACLA,EAAIC,IACJA,EAAGtG,MACHA,EAAKuG,MACLA,EAAKC,OACLA,EAAM4wD,MACNA,EAAKC,MACLA,GACEn5D,EAKJgF,EAAuB,CACrBhF,SACA+4C,SACA/J,gBACAE,iBAAiB,EACjB/qB,SACAjY,SACAC,SACAC,QACAC,QACAqE,QAASkT,EAAQvhB,EAAI8F,EACrBoS,QAASqJ,EAAQxhB,EAAIgG,EACrBib,QAAS1e,EAAOtC,EAChBihB,QAAS3e,EAAOvC,EAChBkxC,GAAI1vB,EAAQvhB,EACZkxC,GAAI3vB,EAAQxhB,EACZq+D,MAAO78C,EAAQvhB,EACfq+D,MAAO98C,EAAQxhB,EACfoxC,MAAO7oC,GAAiB7I,GACxBuG,QACAC,SACAq4D,SAAUpgD,EAAEogD,SACZJ,SACArrB,SAAU,IACLh0B,GAAoBlhB,GACvBqjB,QAAS1e,EAAOtC,EAChBihB,QAAS3e,EAAOvC,EAChB82D,QACAC,UAINnjE,KAAK8iD,kBAAoB9zC,EAEzBhP,KAAKqL,KAAK,mBAAoB,CAC5Bkf,IACAvb,aAEJ,CAOA47D,SAAAA,CAAU3mE,GACRjE,KAAK4kE,cAAcppD,MAAMqvD,OAAS5mE,CACpC,CAMA8kE,cAAAA,CAAe/sD,GACb,MAAM3P,EAAEA,EAACD,EAAEA,EAAC0+D,OAAEA,EAAMlqC,OAAEA,GAAW5gC,KAAKyoE,eACpClhC,EAAQ,IAAIp7B,GAAME,EAAGD,GAAG4C,UAAUhP,KAAKif,mBACvC8rD,EAAS,IAAI5+D,GAAME,EAAIy+D,EAAQ1+D,EAAIw0B,GAAQ5xB,UACzChP,KAAKif,mBAEP+rD,EAAehrE,KAAKirE,mBAAqB,EAC3C,IAAIC,EAAOtmE,KAAKiJ,IAAI05B,EAAMl7B,EAAG0+D,EAAO1+D,GAClC8+D,EAAOvmE,KAAKiJ,IAAI05B,EAAMn7B,EAAG2+D,EAAO3+D,GAChCg/D,EAAOxmE,KAAKC,IAAI0iC,EAAMl7B,EAAG0+D,EAAO1+D,GAChCg/D,EAAOzmE,KAAKC,IAAI0iC,EAAMn7B,EAAG2+D,EAAO3+D,GAE9BpM,KAAKsrE,iBACPtvD,EAAIsI,UAAYtkB,KAAKsrE,eACrBtvD,EAAIy3B,SAASy3B,EAAMC,EAAMC,EAAOF,EAAMG,EAAOF,IAG1CnrE,KAAKirE,oBAAuBjrE,KAAKurE,uBAGtCvvD,EAAI83B,UAAY9zC,KAAKirE,mBACrBjvD,EAAIq4B,YAAcr0C,KAAKurE,qBAEvBL,GAAQF,EACRG,GAAQH,EACRI,GAAQJ,EACRK,GAAQL,EAGRl7B,GAAa0W,UAAUhS,aAAavpC,KAClCjL,KACAgc,EACAhc,KAAKwrE,oBAEPxvD,EAAI0+B,WAAWwwB,EAAMC,EAAMC,EAAOF,EAAMG,EAAOF,GACjD,CAWAM,UAAAA,CAAWlhD,GAGT,GAAIvqB,KAAK0rE,YACP,OAAO1rE,KAAK0rE,YAGd,GAAI1rE,KAAK2rE,eACP,MAAO,CACLC,WAAY,GACZC,kBAAmB,IAIvB,MAAMj+C,EAAU5tB,KAAKqqE,cAAc9/C,GACjCgtC,EAAev3D,KAAKmkD,cACpB2nB,EAAW9rE,KAAK4pE,mBAChBmC,EAAa/rE,KAAKgsE,sBAAsBhsE,KAAKqP,SAAUue,IAGvDg+C,WAAYC,EACZ7G,UAAWiH,EACXjiE,OAAQkiE,GACNH,EAEEI,EAA+C,IAChDJ,EACHF,oBACAI,mBACAC,iBAIF,IAAK3U,EACH,OAAO4U,EAIT,MAAMC,EAAuD,IACxDpsE,KAAKgsE,sBAAsB,CAACzU,GAAe3pC,GAC9Ci+C,oBACAI,mBACAC,iBASF,GAN4B3U,EAAanU,YACvCpjD,KAAKqsE,iBAAiB9hD,GACtBH,GAAaG,IAKb,MAAO,IACF6hD,EACHpiE,OAAQutD,GAKZ,GAAI6U,EAAuBpiE,OAAQ,CACjC,GAAI8hE,EAASvrE,OAAS,EAGpB,OAAO6rE,EAKT,IAAKpsE,KAAK03D,uBAER,OAAO0U,EAMT,GACEpsE,KAAK03D,wBACLntC,EAAEvqB,KAAKssE,iBAGP,OAAOF,CAEX,CAGA,OAAOD,CACT,CASQI,6BAAAA,CAA8Bp7D,EAAmB0P,GAEvD,IAAImsB,EAAS77B,EAAI07B,YACjB,MAAM2/B,EAAexsE,KAAKygB,UACpB4N,EAAUld,EAAIkd,QAAUm+C,EAC9B,GAAIn+C,EAAS,CACX,MAAO7b,EAAI2P,EAAI1P,EAAI2P,GAAM4qB,EAKnBy/B,EAAe7nE,KAAKkR,MAAMqM,EAAG/V,EAAIoG,EAAGpG,EAAG+V,EAAG9V,EAAImG,EAAGnG,GACrDqgE,EAAO7gE,GAAI4gE,GAAgBp+C,EAC3Bs+C,EAAO3gE,GAAIygE,GAAgBp+C,EAC3Bu+C,EAAWF,EAAOC,EAClBE,EAAgBH,EAAOC,EAEzB3/B,EAAS,CACP,IAAI7gC,GAAMqG,EAAGnG,EAAIwgE,EAAer6D,EAAGpG,EAAIwgE,GACvC,IAAIzgE,GAAMgW,EAAG9V,EAAIugE,EAAUzqD,EAAG/V,EAAIygE,GAClC,IAAI1gE,GAAMsG,EAAGpG,EAAIwgE,EAAep6D,EAAGrG,EAAIwgE,GACvC,IAAIzgE,GAAMiW,EAAG/V,EAAIugE,EAAUxqD,EAAGhW,EAAIygE,GAStC,CACA,OAAO9jC,GAAaQ,iBAAiB1oB,EAAOmsB,EAC9C,CAUA8/B,YAAAA,CAAa37D,EAAmByc,GAC9B,GACEzc,GACAA,EAAIwB,SACJxB,EAAIg2C,SACJnnD,KAAKusE,8BAA8Bp7D,EAAKyc,GACxC,CACA,IACG5tB,KAAKonD,qBAAsBj2C,EAAIi2C,oBAC9Bj2C,EAAyB47D,UAO3B,OAAO,EANP,CACA,MAAMC,EAAgBp/C,EAAQ5e,UAAUhP,KAAKif,mBAC7C,IAAKjf,KAAKqpE,oBAAoBl4D,EAAK67D,EAAc3gE,EAAG2gE,EAAc5gE,GAChE,OAAO,CAEX,CAGF,CACA,OAAO,CACT,CAWA6gE,sBAAAA,CACEp9D,EACA+d,EACAg+C,GAEA,IAAIngE,EAAIoE,EAAQtP,OAGhB,KAAOkL,KAAK,CACV,MAAMzB,EAAS6F,EAAQpE,GACvB,GAAIzL,KAAK8sE,aAAa9iE,EAAQ4jB,GAAU,CACtC,GAAI1e,GAAalF,IAAWA,EAAO+sD,eAAgB,CACjD,MAAQ/sD,OAAQkjE,GAAcltE,KAAKitE,uBACjCjjE,EAAOqF,SACPue,EACAg+C,GAEFsB,GAAatB,EAAWlhE,KAAKwiE,EAC/B,CACA,MAAO,CACLljE,SACA4hE,aAEJ,CACF,CACA,MAAO,CACLA,WAAY,GAEhB,CASAI,qBAAAA,CACEn8D,EACA+d,GAEA,MAAMm+C,EAAuC/rE,KAAKitE,uBAChDp9D,EACA+d,EACA,IAIFm+C,EAAW/G,UAAY+G,EAAW/hE,OAClC,MAAMg7D,UAAEA,EAAS4G,WAAEA,GAAeG,EAElC,GACE/G,GACA91D,GAAa81D,IACbA,EAAUvM,aACVmT,EAAW,GACX,CAKA,IAAK,IAAIngE,EAAImgE,EAAWrrE,OAAS,EAAGkL,EAAI,EAAGA,IAAK,CAC9C,MAAMmC,EAAIg+D,EAAWngE,GACrB,IAAMyD,GAAatB,KAAMA,EAAE6qD,YAIzB,OADAsT,EAAW/hE,OAAS4D,EACbm+D,CAEX,CAEA,OADAA,EAAW/hE,OAAS4hE,EAAW,GACxBG,CACT,CAEA,OAAOA,CACT,CAgBAM,gBAAAA,CAAiB9hD,GACf,OAAIvqB,KAAKmtE,eACAntE,KAAKmtE,eAEPntE,KAAKotE,gBAAgB7iD,GAAG,EACjC,CAcA8/C,aAAAA,CAAc9/C,GACZ,OAAIvqB,KAAKqtE,YACArtE,KAAKqtE,YAEPrtE,KAAKotE,gBAAgB7iD,EAC9B,CAWU6iD,eAAAA,CAAgB7iD,GAA+C,IAA7B+iD,EAAYhtE,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GACtD,MAAMskE,EAAgB5kE,KAAK4kE,cACzBvJ,EAASuJ,EAAc7mD,wBACzB,IAAI6P,EAAUjE,GAAWY,GACvBgjD,EAAclS,EAAOhpD,OAAS,EAC9Bm7D,EAAenS,EAAO/oD,QAAU,EAE7Bi7D,GAAgBC,IACfxmE,KAAOq0D,GAAUp0D,KAAUo0D,IAC7BmS,EAAe5oE,KAAKmH,IAAIsvD,EAAOjpD,IAAMipD,EAAOvvC,SAE1C5kB,KAASm0D,GAAUt0D,KAAQs0D,IAC7BkS,EAAc3oE,KAAKmH,IAAIsvD,EAAOtvC,MAAQsvC,EAAOlpD,QAIjDnS,KAAKmd,aACLyQ,EAAQvhB,EAAIuhB,EAAQvhB,EAAIrM,KAAKkgB,QAAQ/N,KACrCyb,EAAQxhB,EAAIwhB,EAAQxhB,EAAIpM,KAAKkgB,QAAQ9N,IAChCk7D,IACH1/C,EAAUnC,GAAiBmC,OAASptB,EAAWR,KAAKif,oBAGtD,MAAMhD,EAAgBjc,KAAKigB,mBACL,IAAlBhE,IACF2R,EAAQvhB,GAAK4P,EACb2R,EAAQxhB,GAAK6P,GAIf,MAAMwxD,EACY,IAAhBF,GAAsC,IAAjBC,EACjB,IAAIrhE,GAAM,EAAG,GACb,IAAIA,GACFy4D,EAAcvyD,MAAQk7D,EACtB3I,EAActyD,OAASk7D,GAG/B,OAAO5/C,EAAQ5gB,SAASygE,EAC1B,CAMU7tD,kBAAAA,CACRS,EACAne,GAGAlC,KAAK0tE,2BACLttE,MAAMwf,mBAAmBS,EAAYne,GACjClC,KAAK4oE,qBACP5oE,KAAK6oE,kBACH7oE,KAAK6oE,iBAAiB8E,gBAAgB3tE,KAAKwxC,WAEjD,CAEUvB,kBAAAA,GACRjwC,KAAKmpE,kBAAoBt1D,KACzB7T,KAAKopE,iBAAmBppE,KAAKmpE,kBAAkB/lE,WAAW,KAAM,CAC9DwqE,oBAAoB,IAEtB5tE,KAAKipE,uBAAuBjpE,KAAKkpE,oBACnC,CAMA2E,aAAAA,GACE,OAAO7tE,KAAKsf,SAASwlD,MAAM9oD,GAC7B,CAOA8xD,mBAAAA,GACE,OAAO9tE,KAAKsf,SAASwlD,MAAM9oD,GAC7B,CAMA+xD,mBAAAA,GACE,OAAO/tE,KAAKsf,SAASwlD,MAAMppD,EAC7B,CAMAq/B,eAAAA,GACE,OAAO/6C,KAAKmkD,aACd,CAMAylB,gBAAAA,GACE,MAAMoE,EAAShuE,KAAKmkD,cACpB,OAAOxpC,GAAkBqzD,GACrBA,EAAOz9D,aACPy9D,EACE,CAACA,GACD,EACR,CAQAC,oBAAAA,CAAqBC,EAA4B3jD,GAC/C,IAAI4jD,GAAmB,EACrBC,GAAa,EACf,MAAMv+D,EAAU7P,KAAK4pE,mBACnByE,EAAwB,GACxBn+D,EAA0B,GAE5Bg+D,EAAWntE,QAASiJ,IACb6F,EAAQoB,SAASjH,KACpBmkE,GAAmB,EACnBnkE,EAAOqB,KAAK,aAAc,CACxBkf,IACAvgB,WAEFkG,EAAQxF,KAAKV,MAIjB6F,EAAQ9O,QAASiJ,IACVkkE,EAAWj9D,SAASjH,KACvBmkE,GAAmB,EACnBnkE,EAAOqB,KAAK,WAAY,CACtBkf,IACAvgB,WAEFqkE,EAAM3jE,KAAKV,MAIXkkE,EAAW3tE,OAAS,GAAKsP,EAAQtP,OAAS,GAC5C6tE,GAAa,EACbD,GACEnuE,KAAKqL,KAAK,oBAAqB,CAC7Bkf,IACA2sC,SAAUmX,EACVlG,WAAYj4D,KAEPL,EAAQtP,OAAS,GAC1B6tE,GAAa,EACbpuE,KAAKqL,KAAK,oBAAqB,CAC7Bkf,IACA2sC,SAAUmX,KAEHH,EAAW3tE,OAAS,IAC7B6tE,GAAa,EACbpuE,KAAKqL,KAAK,oBAAqB,CAC7Bkf,IACA49C,WAAYj4D,KAGhBk+D,IAAepuE,KAAKkoE,sBAAmB1nE,EACzC,CAQA8tE,eAAAA,CAAgB5+D,EAAsB6a,GAEpC,MAAMgkD,EAAiBvuE,KAAK4pE,mBACtB1S,EAAWl3D,KAAKwuE,iBAAiB9+D,EAAQ6a,GAE/C,OADAvqB,KAAKiuE,qBAAqBM,EAAgBhkD,GACnC2sC,CACT,CAUAsX,gBAAAA,CAAiB9+D,EAAsB6a,GACrC,MAAMkkD,EAAmBzuE,KAAKmkD,cAC9B,OAAIsqB,IAAqB/+D,OAIpB1P,KAAKooE,qBAAqB79C,EAAG7a,IAAW1P,KAAKmkD,kBAI9Cz0C,EAAOk2C,SAAS,CAAEr7B,QAItBvqB,KAAKmkD,cAAgBz0C,EAEjBiL,GAAkBjL,IAAW++D,IAAqB/+D,GACpDA,EAAOnK,IAAI,SAAUvF,MAEvB0P,EAAOsQ,aAEA,IACT,CAUAooD,oBAAAA,CACE79C,EACA7a,GAEA,MAAMyB,EAAMnR,KAAKmkD,cACjB,QAAIhzC,KAEEA,EAAIu0C,WAAW,CAAEn7B,IAAG7a,aAGpB1P,KAAK8iD,mBAAqB9iD,KAAK8iD,kBAAkB94C,SAAWmH,GAC9DnR,KAAK0uE,oBAAoBnkD,GAEvB5P,GAAkBxJ,IAAQA,IAAQnR,KAAKqoE,iBACzCroE,KAAKqoE,oBAAiB7nE,GAExBR,KAAKmkD,mBAAgB3jD,GACd,GAGX,CAUAmuE,mBAAAA,CAAoBpkD,GAClB,MAAMgkD,EAAiBvuE,KAAK4pE,mBAC1BrS,EAAev3D,KAAK+6C,kBAClBwzB,EAAehuE,QACjBP,KAAKqL,KAAK,2BAA4B,CACpCkf,IACA49C,WAAY,CAAC5Q,KAGjB,MAAMqX,EAAY5uE,KAAKooE,qBAAqB79C,GAE5C,OADAvqB,KAAKiuE,qBAAqBM,EAAgBhkD,GACnCqkD,CACT,CAQAF,mBAAAA,CAAoBnkD,GAClB,MAAMvb,EAAYhP,KAAK8iD,kBACvB9iD,KAAK6uE,0BAA0BtkD,GAC3Bvb,GAAaA,EAAUhF,SAEzBgF,EAAUhF,OAAOg7C,UAAW,GAE9BhlD,KAAK8iD,kBAAoB,IAC3B,CAMA+rB,yBAAAA,CAA0BtkD,GACxB,MAAMvb,EAAYhP,KAAK8iD,kBACrB94C,EAASgF,EAAUhF,OACnB9H,EAAU,CACRqoB,IACAvgB,SACAgF,YACA+zC,OAAQ/zC,EAAU+zC,QAGlB/4C,EAAO8kE,WACT9kE,EAAO8kE,UAAW,GAGpB9kE,EAAOgW,YAEHhR,EAAUkqC,kBACZl5C,KAAKqL,KAAK,kBAAmBnJ,GAC7B8H,EAAOqB,KAAKhD,EAAUnG,GAE1B,CAMAwe,oBAAAA,CAAqBC,GACnBvgB,MAAMsgB,qBAAqBC,GAC3B,MAAM42C,EAAev3D,KAAKmkD,cACtBoT,GACFA,EAAav3C,WAEjB,CAKAwJ,OAAAA,GAEE,MAAM+tC,EAAev3D,KAAKmkD,cACtBxpC,GAAkB48C,KACpBA,EAAaP,YACbO,EAAahzD,kBAGRvE,KAAKmkD,cAEZ/jD,MAAMopB,UAMNxpB,KAAKopE,iBAAmB,KAExBppE,KAAKmpE,uBAAoB3oE,CAC3B,CAKA+gB,KAAAA,GAEEvhB,KAAK2uE,sBAEL3uE,KAAKmkD,mBAAgB3jD,EACrBR,KAAKqhB,aAAarhB,KAAKwxC,YACvBpxC,MAAMmhB,OACR,CAMAc,YAAAA,CAAarG,GACX,MAAMu7C,EAAev3D,KAAKmkD,cAEtBoT,GACFA,EAAa7S,gBAAgB1oC,EAEjC,CAKU6J,SAAAA,CACR5M,EACAyM,EACAJ,GAMA,MAAMypD,EAAqB/uE,KAAKgvE,+BAA+B/1D,GAC7DvJ,EAAStP,MAAMylB,UAAU5M,EAAUyM,EAAYJ,GAGjD,OADArM,EAAS1T,IAAIwpE,GACNr/D,CACT,CAQQs/D,8BAAAA,CACN/1D,GAEA,MAAMyzB,MAAEA,GAAUzzB,EAClB,GAAIyzB,GAAS/xB,GAAkB+xB,IAAU1sC,KAAKmkD,gBAAkBzX,EAAO,CACrE,MAWMuiC,EAAiBz1D,GAAsBP,EAXzB,CAClB,QACA,QACA,QACAlS,EACAgB,EACAC,EACAC,EACAC,EACAlB,IAIF,OADA4jB,GAAqB3R,EAAUyzB,EAAM5hB,iBAC9BmkD,CACT,CACE,MAAO,CAAA,CAEX,CAKApnD,aAAAA,CACEtB,EACAtN,EACAT,GAIA,MAAMu2D,EAAqB/uE,KAAKgvE,+BAA+B/1D,GAC/D7Y,MAAMynB,cAActB,EAAQtN,EAAUT,GACtCS,EAAS1T,IAAIwpE,EACf,EACDhvE,EArxCY+nE,GAAgB,cJgF0B,CACrD1pB,gBAAgB,EAChBD,YAAa,WACbva,iBAAiB,EACjBD,kBAAkB,EAClB6mC,YAAa,SACb7oB,aAAc,WAEdmnB,WAAW,EACXY,aAAc,WACd4B,eAAgB,2BAChBE,mBAAoB,GACpBD,qBAAsB,2BACtBN,mBAAoB,EACpBiE,yBAAyB,EAEzB5nB,YAAa,OACbC,WAAY,OACZ4nB,cAAe,UACfC,kBAAmB,YACnBC,iBAAkB,cAElBjoB,oBAAoB,EACpB8hB,oBAAqB,EACrByC,gBAAgB,EAEhB2D,iBAAiB,EACjBC,gBAAgB,EAChBC,iBAAiB,EACjBC,qBAAqB,EAErB9K,eAAgB,mBAChBjN,wBAAwB,IKrRnB,MAAMgY,GAKX5vE,WAAAA,CAAYqD,GAAgBpD,iBAJO,IAAEA,EAAAC,KAAA,kBAAA,GAKnC,MAAM2vE,EAAKA,KACT,MAAMC,eAAEA,GACLzsE,EAAO43C,mBAAuC,CAAA,EACjD60B,GAAkBA,EAAeC,SAE7Bn0D,EAAKvY,EAAOyhE,cAClBlpD,EAAGxD,iBAAiB,QAASy3D,GAC7B3vE,KAAK8vE,WAAa,IAAMp0D,EAAGpD,oBAAoB,QAASq3D,EAC1D,CAEAI,eAAAA,GACE/vE,KAAKgK,YAASxJ,EACdR,KAAKo1D,QAAQr0D,QAASiJ,IAChBA,EAAO+iE,WACT/iE,EAAOgmE,eAGb,CAEA1jE,GAAAA,CAAItC,GACFhK,KAAKo1D,QAAQ1qD,KAAKV,EACpB,CAEAX,MAAAA,CAAOW,GACLhK,KAAKkoC,WAAWl+B,GAChB0B,GAAgB1L,KAAKo1D,QAASprD,EAChC,CAEA49B,QAAAA,CAAS59B,GACPhK,KAAKgK,OAASA,CAChB,CAEAk+B,UAAAA,CAAWl+B,GACLA,IAAWhK,KAAKgK,SAClBhK,KAAKgK,YAASxJ,EAElB,CAEAyvE,WAAAA,CAAY1lD,GAAkB,IAAA2lD,GACjB,QAAXA,EAAAlwE,KAAKgK,kBAAMkmE,SAAXA,EAAanD,YAAa/sE,KAAKgK,OAAOmmE,2BAA2B5lD,EACnE,CAEAhJ,KAAAA,GACEvhB,KAAKo1D,QAAU,GACfp1D,KAAKgK,YAASxJ,CAChB,CAEA+D,OAAAA,GACEvE,KAAKuhB,QACLvhB,KAAK8vE,oBAEE9vE,KAAK8vE,UACd,ECzCF,MAAMM,GAAkB,CAAEC,SAAS,GAE7BC,GAAiBA,CAACntE,EAAgBonB,KAG/B,CACLyiD,cAHoB7pE,EAAOkpE,iBAAiB9hD,GAI5CgmD,WAHiBptE,EAAOknE,cAAc9/C,KAUpCimD,GAAc,SAClB90D,GAA0B,IAAA,IAAAha,EAAApB,UAAAC,OACvByK,MAAIpJ,MAAAF,EAAA,EAAAA,OAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAJmJ,EAAInJ,EAAA,GAAAvB,UAAAuB,GAAA,OACJ6Z,EAAGxD,oBAAoBlN,EAAK,EAC3BylE,GAAiB,SACrB/0D,GAA0B,IAAA,IAAA1L,EAAA1P,UAAAC,OACvByK,MAAIpJ,MAAAoO,EAAA,EAAAA,OAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAJjF,EAAIiF,EAAA,GAAA3P,UAAA2P,GAAA,OACJyL,EAAGpD,uBAAuBtN,EAAK,EAE9B0lE,GAAuB,CAC3BC,MAAO,CACLC,GAAI,OACJ3O,IAAK,MACL4O,SAAU,YACVC,UAAW,WACXC,SAAU,aACVC,UAAW,aAEbC,KAAM,CACJL,GAAI,QACJ3O,IAAK,QACL4O,SAAU,YACVC,UAAW,YACXC,SAAU,aACVC,UAAW,eASR,MAAME,WAAepJ,GAkD1BhoE,WAAAA,CAAY4b,GACVtb,MAAMsb,EAD4Dpb,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,GAVvEP,EAAAC,KAAA,gBAAA,GAAAD,EAAAC,KAAA,qBAQqB,IAAI0vE,GAAmB1vE,OAMxC,CACE,eACA,gBACA,eACA,aACA,cACA,YAMA,gBACA,cACA,gBACA,iBACA,WACA,eACA,aACA,kBACA,cACA,eACA,eACA,WAEFe,QAASowE,IAETnxE,KAAKmxE,GAAiBnxE,KAAKmxE,GAA2BtqC,KAAK7mC,QAG7DA,KAAKoxE,YAAYZ,GACnB,CAMQa,eAAAA,GACN,OAAOrxE,KAAKyvE,oBAAsB,UAAY,OAChD,CAEA2B,WAAAA,CAAYE,GAAgC,IAAlBjuB,EAAQ/iD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,IAAAA,UAAA,GAChC,MAAMixE,EAAgBvxE,KAAK4kE,cACzB4M,EAAkBxxE,KAAKqxE,kBACzBC,EAAQ11D,GAAqB21D,GAAgB,SAAUvxE,KAAKyxE,WAC5DH,EAAQC,EAAeC,EAAkB,OAAQxxE,KAAK0xE,cACtDJ,EACEC,EACA,GAAGC,QACHxxE,KAAK2xE,aACLvB,IAEFkB,EAAQC,EAAe,GAAGC,OAAsBxxE,KAAK4xE,aACrDN,EAAQC,EAAe,GAAGC,SAAwBxxE,KAAK6xE,eACvDP,EAAQC,EAAe,QAASvxE,KAAK8xE,cAAe,CAAEzB,SAAS,IAC/DiB,EAAQC,EAAe,cAAevxE,KAAK+xE,gBACtC1uB,IACHiuB,EAAQC,EAAe,QAASvxE,KAAKgyE,UACrCV,EAAQC,EAAe,WAAYvxE,KAAKgyE,WAE1CV,EAAQC,EAAe,YAAavxE,KAAKiyE,cACzCX,EAAQC,EAAe,UAAWvxE,KAAKkyE,YACvCZ,EAAQC,EAAe,WAAYvxE,KAAKmyE,aACxCb,EAAQC,EAAe,YAAavxE,KAAKoyE,cACzCd,EAAQC,EAAe,YAAavxE,KAAKqyE,cACzCf,EAAQC,EAAe,OAAQvxE,KAAKsyE,SAC/BtyE,KAAKyvE,qBACR6B,EAAQC,EAAe,aAAcvxE,KAAKuyE,cAAenC,GAE7D,CAKAoC,eAAAA,GACExyE,KAAKoxE,YAAYX,IAEjB,MAAMe,EAAkBxxE,KAAKqxE,kBACvBx2D,EAAMC,GAAuB9a,KAAK4kE,eACxC6L,GACE51D,EACA,GAAG22D,MACHxxE,KAAKyyE,YAEPhC,GACE51D,EACA,WACA7a,KAAK0yE,YACLtC,IAEFK,GACE51D,EACA,GAAG22D,QACHxxE,KAAK2xE,aACLvB,IAEFK,GACE51D,EACA,YACA7a,KAAK2xE,aACLvB,IAEFuC,aAAa3yE,KAAK4yE,kBACpB,CAMQd,aAAAA,CAAcvnD,GACpBvqB,KAAK6yE,yBAAyBtoD,GAC9BvqB,KAAK8yE,aAAavoD,EAAG,SACrBvqB,KAAK0tE,0BACP,CAMQkE,WAAAA,CAAYrnD,GAClB,MAAMvgB,EAAShK,KAAKqoE,eACd0K,EAAS,CACbxoD,OACG+lD,GAAetwE,KAAMuqB,IAE1BvqB,KAAKqL,KAAK,YAAa,IAAK0nE,EAAQ/oE,WACpChK,KAAKqoE,oBAAiB7nE,EACtBwJ,GAAUA,EAAOqB,KAAK,WAAY,IAAK0nE,IACvC/yE,KAAKsoE,gBAAgBvnE,QAASiyE,IAC5BhzE,KAAKqL,KAAK,YAAa,IAAK0nE,EAAQ/oE,OAAQgpE,IAC5CA,GAAgBA,EAAa3nE,KAAK,WAAY,IAAK0nE,MAErD/yE,KAAKsoE,gBAAkB,EACzB,CAOQuJ,aAAAA,CAActnD,GAOpB,MAAMvgB,OAAEA,GAAWhK,KAAKyrE,WAAWlhD,GAG9BvqB,KAAK8iD,mBAAsB94C,IAC9BhK,KAAKqL,KAAK,aAAc,CACtBkf,OACG+lD,GAAetwE,KAAMuqB,KAE1BvqB,KAAKqoE,oBAAiB7nE,EACtBR,KAAKsoE,gBAAkB,GAE3B,CAOQ2J,YAAAA,CAAa1nD,GACnBvqB,KAAKizE,UAAW,EAChB,MAAM1b,EAAev3D,KAAK+6C,kBAC1B,GAAIwc,GAAgBA,EAAaxR,YAAYx7B,GAAI,CAC/CvqB,KAAKkzE,YAAc3b,EACnB,MAAMr1D,EAAU,CAAEqoB,IAAGvgB,OAAQutD,GAQ7B,OAPAv3D,KAAKqL,KAAK,YAAanJ,GACvBq1D,EAAalsD,KAAK,YAAanJ,QAC/BsuE,GACExwE,KAAK4kE,cACL,OACA5kE,KAAKmzE,gBAGT,CACA7oD,GAAUC,EACZ,CAQQ6oD,kBAAAA,CACN7oD,EACA9Q,EACAzP,GAEA,IAAI65B,GAAQ,EAEZ,MAAMwvC,EAAarzE,KAAKszE,YACpBD,GAAcA,IAAe55D,GAAU45D,IAAerpE,IACxDqpE,EAAW7tB,kBACX3hB,GAAQ,GAEVpqB,SAAAA,EAAQ+rC,kBACRx7C,IAAWyP,IAAUzP,SAAAA,EAAQw7C,mBAE7B,MAAMxpC,EAAMhc,KAAKwxC,WACjBx1B,EAAI2G,OACJ3G,EAAIhN,aAAahP,KAAKif,mBAClBxF,IACFuC,EAAI2G,OACJlJ,EAAOzK,UAAUgN,GACjBvC,EAAOwsC,uBAAuB17B,GAC9BvO,EAAI6G,UACJghB,GAAQ,GAEN75B,IACFgS,EAAI2G,OACJ3Y,EAAOgF,UAAUgN,GACjBhS,EAAOk8C,uBAAuB37B,GAC9BvO,EAAI6G,UACJghB,GAAQ,GAEV7nB,EAAI6G,UACJghB,IAAU7jC,KAAKwoE,iBAAkB,EACnC,CAQQ0J,UAAAA,CAAW3nD,GACjB,MAAMshD,kBAAEA,GAAsB7rE,KAAKyrE,WAAWlhD,GACxCgpD,IAAYhpD,EAAEipD,cAAgBjpD,EAAEipD,aAAaC,aAAetsE,EAChEksE,EAAaE,EAAUvzE,KAAKmkD,mBAAgB3jD,EAC5C0B,EAAU,CACRqoB,IACAvgB,OAAQhK,KAAKkzE,YACbtH,WAAYC,EACZ6H,WAAY1zE,KAAKkzE,YACjBK,UACAF,WAAYA,GAEhB5C,GACEzwE,KAAK4kE,cACL,OACA5kE,KAAKmzE,iBAEPnzE,KAAKqL,KAAK,UAAWnJ,GACrBlC,KAAKkzE,aAAelzE,KAAKkzE,YAAY7nE,KAAK,UAAWnJ,UAC9ClC,KAAKkzE,YAEZlzE,KAAKyyE,WAAWloD,EAClB,CAOQ4oD,eAAAA,CAAgB5oD,GACtB,MAAMroB,EAAU,CACdqoB,IACAvgB,OAAQhK,KAAKkzE,YACbQ,WAAY1zE,KAAKkzE,YACjBG,WAAYrzE,KAAK2zE,oBAEnB3zE,KAAKqL,KAAK,OAAQnJ,GAClBlC,KAAKkzE,aAAelzE,KAAKkzE,YAAY7nE,KAAK,OAAQnJ,EACpD,CAQQiwE,WAAAA,CAAY5nD,GAClB,MAAMqpD,EAAY,YACV3H,iBAAkBjiE,EAAM6hE,kBAAEA,GAAsB7rE,KAAKyrE,WAAWlhD,GAClEmpD,EAAa1zE,KAAKkzE,YAClBhxE,EAAU,CACdqoB,IACAvgB,SACA4hE,WAAYC,EACZ6H,aACA1tB,SAAS,EACTqtB,gBAAY7yE,GAEd,IAAI6yE,EAEJrzE,KAAKqL,KAAKuoE,EAAW1xE,GAGrBlC,KAAK6zE,sBAAsBtpD,EAAGvgB,EAAQ9H,GAClC8H,IACEA,EAAOg8C,QAAQz7B,KACjB8oD,EAAarpE,GAEfA,EAAOqB,KAAKuoE,EAAW1xE,IAGzB,IAAK,IAAIuJ,EAAI,EAAGA,EAAIogE,EAAkBtrE,OAAQkL,IAAK,CACjD,MAAMyhE,EAAYrB,EAAkBpgE,GAIhCyhE,EAAUlnB,QAAQz7B,KACpB8oD,EAAanG,GAEfA,EAAU7hE,KAAKuoE,EAAW1xE,EAC5B,CAEAlC,KAAKozE,mBAAmB7oD,EAAGmpD,EAAYL,GACvCrzE,KAAKszE,YAAcD,CACrB,CAOQjB,YAAAA,CAAa7nD,GACnB,MAAM0hD,iBAAEA,EAAgBJ,kBAAEA,GAAsB7rE,KAAKyrE,WAAWlhD,GAC1DroB,EAAU,CACdqoB,IACAvgB,OAAQiiE,EACRL,WAAYC,EACZ6H,WAAY1zE,KAAKkzE,aAEnBlzE,KAAKqL,KAAK,YAAanJ,GAEvBlC,KAAK6zE,sBAAsBtpD,EAAG0hD,EAAkB/pE,EAClD,CAOQmwE,YAAAA,CAAa9nD,GACnB,MAAMshD,kBAAEA,GAAsB7rE,KAAKyrE,WAAWlhD,GACxCroB,EAAU,CACdqoB,IACAvgB,OAAQhK,KAAK2zE,mBACb/H,WAAYC,EACZ6H,WAAY1zE,KAAKkzE,aAEnBlzE,KAAKqL,KAAK,YAAanJ,GAGvBlC,KAAK6zE,sBAAsBtpD,OAAG/pB,EAAW0B,GACzClC,KAAKozE,mBAAmB7oD,EAAGvqB,KAAKkzE,aAChClzE,KAAKszE,iBAAc9yE,EACnBR,KAAKsoE,gBAAkB,EACzB,CAUQgK,OAAAA,CAAQ/nD,GACd,MAAM0hD,iBAAEA,EAAgBJ,kBAAEA,GAAsB7rE,KAAKyrE,WAAWlhD,GAC1DroB,EAAUlC,KAAK8zE,mBAAmB,cAAe,CACrDvpD,IACAvgB,OAAQiiE,EACRL,WAAYC,EACZ6H,WAAY1zE,KAAKkzE,eACd5C,GAAetwE,KAAMuqB,KAG1BroB,EAAQqxE,SAAU,EAElBrxE,EAAQmxE,gBAAa7yE,EAErBR,KAAK8zE,mBAAmB,OAAQ5xE,GAIhClC,KAAKqL,KAAK,aAAcnJ,EAC1B,CAMQ6vE,cAAAA,CAAexnD,GACrB,MAAMvgB,OAAEA,EAAM4hE,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GACzCroB,EAAUlC,KAAK8zE,mBAAmB,qBAAsB,CAC5DvpD,IACAvgB,SACA4hE,eAKF,OAFA5rE,KAAKsvE,iBAAmBhlD,GAAUC,GAClCvqB,KAAK8zE,mBAAmB,cAAe5xE,IAChC,CACT,CAMQ8vE,QAAAA,CAASznD,GACf,MAAMwpD,EAASxpD,EAAEypD,OACbD,EAAS,GAAKA,EAAS,IAC3B/zE,KAAK6yE,yBAAyBtoD,GACpB,GAAVwpD,GAA0B,aAAXxpD,EAAEvhB,MAAuBhJ,KAAK8yE,aAAavoD,EAAG,YACnD,GAAVwpD,GAAe/zE,KAAK8yE,aAAavoD,EAAG,eACpCvqB,KAAK0tE,2BACP,CAQAuG,yBAAAA,CACE1pD,EACA/f,EACA0pE,GAKA,IAJAC,EAGoB7zE,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEvBN,KAAK6yE,yBAAyBtoD,GAC9B,MAAMvgB,OAAEA,EAAM4hE,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GAC7CroB,EAAU,CACRqoB,IACAvgB,SACA4hE,gBACG0E,GAAetwE,KAAMuqB,GACxBvb,UAAWhP,KAAK8iD,qBACbqxB,GAEPn0E,KAAKqL,KAAKb,EAAWtI,GAErB8H,GAAUA,EAAOqB,KAAK6oE,EAAehyE,GACrC,IAAK,IAAIuJ,EAAI,EAAGA,EAAImgE,EAAWrrE,OAAQkL,IACrCmgE,EAAWngE,KAAOzB,GAAU4hE,EAAWngE,GAAGJ,KAAK6oE,EAAehyE,GAEhElC,KAAK0tE,0BACP,CAQA0G,YAAAA,CAAaC,GACX,MAAMrqD,EAAkBqqD,EAAmBrqD,eAE3C,OAAIA,EACKA,EAAe,IAAMA,EAAe,GAAGsqD,WAG5Ct0E,KAAKyvE,oBACC4E,EAAqBE,WAGxB,CACT,CAOAC,YAAAA,CAAaH,GACX,OAAwC,IAAnCA,EAAqBI,YAGc,IAAnCJ,EAAqBI,YAGT,aAAbJ,EAAIrrE,MAA8D,IAAtCqrE,EAAmBK,QAAQn0E,UAGtD8zE,EAAmBrqD,gBAEnBqqD,EAAmBrqD,eAAe,GAAGsqD,aAAet0E,KAAK20E,aAIhE,CAMApC,aAAAA,CAAchoD,GACZvqB,KAAK6yE,yBAAyBtoD,GAE9B,IAAIqqD,GAA0B50E,KAAKgf,oBACnC,MAAM61D,EAAsB70E,KAAKmkD,mBACR3jD,IAArBR,KAAK20E,cACP30E,KAAK20E,YAAc30E,KAAKo0E,aAAa7pD,IAEvCvqB,KAAK80E,cAAcvqD,GACnB,MAAMvgB,OAAEA,GAAWhK,KAAKyrE,WAAWlhD,IAKjCvqB,KAAK0oE,eACJmM,GAAuB7qE,IAAW6qE,KAEnCD,GAAyB,GAG3BA,GAA0BrqD,EAAEC,iBAC5B,MAAM+mD,EAAgBvxE,KAAK4kE,cACzB4M,EAAkBxxE,KAAKqxE,kBACnBx2D,EAAMC,GAAuBy2D,GACnCf,GACE31D,EACA,WACA7a,KAAK0yE,YACLtC,IAGFwE,GACEpE,GACE31D,EACA,YACA7a,KAAK2xE,aACLvB,IAGJK,GACEc,EACA,GAAGC,QACHxxE,KAAK0xE,cAEP1xE,KAAK0tE,0BACP,CAMAgE,YAAAA,CAAannD,GACXvqB,KAAK6yE,yBAAyBtoD,GAC9BvqB,KAAK80E,cAAcvqD,GACnB,MAAMgnD,EAAgBvxE,KAAK4kE,cACzB4M,EAAkBxxE,KAAKqxE,kBAEzBZ,GACEc,EACA,GAAGC,QACHxxE,KAAK2xE,aACLvB,IAEF,MAAMv1D,EAAMC,GAAuBy2D,GACnCf,GAAY31D,EAAK,GAAG22D,MAAqBxxE,KAAKyyE,YAC9CjC,GACE31D,EACA,GAAG22D,QACHxxE,KAAK2xE,aACLvB,IAEFpwE,KAAK0tE,0BACP,CAMAgF,WAAAA,CAAYnoD,GACV,GAAIA,EAAEmqD,QAAQn0E,OAAS,EAErB,OAEFP,KAAK6yE,yBAAyBtoD,GAC9BvqB,KAAK+0E,YAAYxqD,GACjBvqB,KAAK0tE,kCACE1tE,KAAK20E,YACZ,MAAMnD,EAAkBxxE,KAAKqxE,kBACvBx2D,EAAMC,GAAuB9a,KAAK4kE,eACxC6L,GACE51D,EACA,WACA7a,KAAK0yE,YACLtC,IAEFK,GACE51D,EACA,YACA7a,KAAK2xE,aACLvB,IAEEpwE,KAAK4yE,mBACPD,aAAa3yE,KAAK4yE,mBAEpB5yE,KAAK4yE,kBAAoB/qC,WAAW,KAGlC2oC,GACExwE,KAAK4kE,cACL,GAAG4M,QACHxxE,KAAK0xE,cAEP1xE,KAAK4yE,kBAAoB,GACxB,IACL,CAMAH,UAAAA,CAAWloD,GACTvqB,KAAK6yE,yBAAyBtoD,GAC9BvqB,KAAK+0E,YAAYxqD,GACjB,MAAMgnD,EAAgBvxE,KAAK4kE,cACzB4M,EAAkBxxE,KAAKqxE,kBACzB,GAAIrxE,KAAKw0E,aAAajqD,GAAI,CACxB,MAAM1P,EAAMC,GAAuB9a,KAAK4kE,eACxC6L,GACE51D,EACA,GAAG22D,MACHxxE,KAAKyyE,YAEPhC,GACE51D,EACA,GAAG22D,QACHxxE,KAAK2xE,aACLvB,IAEFI,GACEe,EACA,GAAGC,QACHxxE,KAAK2xE,aACLvB,GAEJ,CACApwE,KAAK0tE,0BACP,CAMAiE,YAAAA,CAAapnD,GACXvqB,KAAK6yE,yBAAyBtoD,GAE9B,MAAMgtC,EAAev3D,KAAK+6C,mBACzB/6C,KAAKgf,uBACFu4C,IAGCA,EAAa1R,oBAAoBt7B,KACpCA,EAAEC,gBACFD,EAAEC,iBACJxqB,KAAKg1E,cAAczqD,GACnBvqB,KAAK0tE,0BACP,CAKA+D,SAAAA,GACEzxE,KAAKmd,aACLnd,KAAK0tE,0BACP,CAOAuH,aAAAA,CAAcjrE,GACZ,MAAMutD,EAAev3D,KAAK+6C,kBAI1B,QACIwc,KAAmBvtD,GACpButD,GAAgBvtD,GAAUutD,IAAiBvtD,CAEhD,CASA+qE,WAAAA,CAAYxqD,GAAkB,IAAA2qD,EAC5Bl1E,KAAK8yE,aAAavoD,EAAG,aAErB,MAAMvb,EAAYhP,KAAK8iD,kBACjBqyB,EAAUn1E,KAAKizE,UACfjpE,OAAEA,GAAWhK,KAAKyrE,WAAWlhD,IAI7B6qD,OAAEA,GAAW7qD,EACnB,GAAI6qD,EAIF,aAHEp1E,KAAKwvE,iBAA8B,IAAX4F,GACvBp1E,KAAKuvE,gBAA6B,IAAX6F,IACxBp1E,KAAK8yE,aAAavoD,EAAG,OAIzB,GAAIvqB,KAAK0oE,eAAiB1oE,KAAK4oE,oBAE7B,YADA5oE,KAAKq1E,wBAAwB9qD,GAI/B,IAAKvqB,KAAKw0E,aAAajqD,GACrB,OAEF,IAcIqD,EAASO,EAdTmnD,GAAe,EAKnB,GAJItmE,IACFhP,KAAK6uE,0BAA0BtkD,GAC/B+qD,EAAetmE,EAAUkqC,kBAEtBi8B,EAAS,CACZ,MAAMI,EAAkBvrE,IAAWhK,KAAKmkD,cACxCnkD,KAAKw1E,gBAAgBjrD,GAChB+qD,IACHA,EACEt1E,KAAKi1E,cAAcjrE,KACjBurE,GAAmBvrE,IAAWhK,KAAKmkD,cAE3C,CAEA,GAAIn6C,EAAQ,CACV,MAAMyrE,EAAQzrE,EAAOo5C,YACnBpjD,KAAKqsE,iBAAiB9hD,GACtBH,GAAaG,KAEThpB,IAAEA,EAAGusB,QAAEA,GAAY2nD,GAAS,CAAA,EAElC,GADAtnD,EAAS5sB,EAEPyI,EAAO0I,YACP1I,IAAWhK,KAAKmkD,eACI,OAApBn6C,EAAOq9C,SAEPrnD,KAAKsuE,gBAAgBtkE,EAAQugB,GAC7B+qD,GAAe,OACV,GAAIxnD,EAAS,CAClB,MAAMutB,EAAiBvtB,EAAQstB,kBAAkB7wB,EAAGvgB,EAAQ8jB,GACxDutB,IACFztB,EAAU5tB,KAAKqqE,cAAc9/C,GAC7B8wB,EAAepwC,KAAK6iB,EAASvD,EAAGvb,EAAY4e,EAAQvhB,EAAGuhB,EAAQxhB,GAEnE,CACApC,EAAOg7C,UAAW,CACpB,CAGA,GACEh2C,IACCA,EAAUhF,SAAWA,GAAUgF,EAAUmf,SAAWA,GACrD,CACA,MAAMunD,EACF1mE,EAAUhF,QAAUgF,EAAUhF,OAAOokB,SAASpf,EAAUmf,QAC1DwnD,EACED,GACAA,EAAgBt6B,kBACd7wB,EACAvb,EAAUhF,OACV0rE,GAEN9nD,EAAUA,GAAW5tB,KAAKqqE,cAAc9/C,GACxCorD,GACEA,EAAuB1qE,KACrByqE,EACAnrD,EACAvb,EACA4e,EAAQvhB,EACRuhB,EAAQxhB,EAEd,CACApM,KAAK41E,oBAAoBrrD,EAAGvgB,GAC5BhK,KAAK8yE,aAAavoD,EAAG,MACrBvqB,KAAKyoE,eAAiB,KACtBzoE,KAAK8iD,kBAAoB,KAEzB94C,IAAWA,EAAOk5C,cAAW1iD,GACzB80E,EACFt1E,KAAK+f,mBACKo1D,GAA+B,QAApBD,EAAEl1E,KAAKmkD,yBAAa+wB,GAAnBA,EAA+BnI,WACrD/sE,KAAKgpE,WAET,CAEA8K,kBAAAA,CACEF,EACA1xE,GAEA,MAAM8H,OAAEA,EAAM4hE,WAAEA,EAAa,IAAO1pE,EAIpClC,KAAKqL,KAAKuoE,EAAW1xE,GACrB8H,GAAUA,EAAOqB,KAAKuoE,EAAW1xE,GACjC,IAAK,IAAIuJ,EAAI,EAAGA,EAAImgE,EAAWrrE,OAAQkL,IACrCmgE,EAAWngE,KAAOzB,GAAU4hE,EAAWngE,GAAGJ,KAAKuoE,EAAW1xE,GAE5D,OAAOA,CACT,CAQA4wE,YAAAA,CACEvoD,EACAqpD,EACAO,GAEA,MAAMnqE,OAAEA,EAAM4hE,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GAC7CroB,EAAsC,CACpCqoB,IACAvgB,SACA4hE,gBACG0E,GAAetwE,KAAMuqB,GACxBvb,UAAWhP,KAAK8iD,qBACE,gBAAd8wB,GAA6C,SAAdA,EAC/BO,EACA,CAAA,GAEU,cAAdP,GAA2C,OAAdA,IAC9B1xE,EAAqCizE,QAAUn1E,KAAKizE,UAGvDjzE,KAAKqL,KAAK,SAASuoE,IAAa1xE,GAEhC8H,GAAUA,EAAOqB,KAAK,QAAQuoE,IAAa1xE,GAC3C,IAAK,IAAIuJ,EAAI,EAAGA,EAAImgE,EAAWrrE,OAAQkL,IACrCmgE,EAAWngE,KAAOzB,GAChB4hE,EAAWngE,GAAGJ,KAAK,QAAQuoE,IAAa1xE,EAE9C,CAMA2zE,yBAAAA,CAA0BtrD,GACxBvqB,KAAK4oE,qBAAsB,EACvB5oE,KAAK+6C,oBACP/6C,KAAK2uE,oBAAoBpkD,GACzBvqB,KAAK+f,oBAGP,MAAM6N,EAAU5tB,KAAKqqE,cAAc9/C,GACnCvqB,KAAK6oE,kBACH7oE,KAAK6oE,iBAAiBiN,YAAYloD,EAAS,CAAErD,IAAGqD,YAClD5tB,KAAK8yE,aAAavoD,EAAG,OAAQ,CAAE4/C,iBAAiB,GAClD,CAMA4L,yBAAAA,CAA0BxrD,GACxB,GAAIvqB,KAAK4oE,oBAAqB,CAC5B,MAAMh7C,EAAU5tB,KAAKqqE,cAAc9/C,GACnCvqB,KAAK6oE,kBACH7oE,KAAK6oE,iBAAiBoH,YAAYriD,EAAS,CACzCrD,IAEAqD,WAEN,CACA5tB,KAAK4qE,UAAU5qE,KAAKovE,mBACpBpvE,KAAK8yE,aAAavoD,EAAG,OACvB,CAMA8qD,uBAAAA,CAAwB9qD,GACtB,MAAMqD,EAAU5tB,KAAKqqE,cAAc9/C,GAC/BvqB,KAAK6oE,iBACP7oE,KAAK4oE,sBAAwB5oE,KAAK6oE,iBAAiBmN,UAAU,CAC3DzrD,EAAGA,EAEHqD,YAGF5tB,KAAK4oE,qBAAsB,EAE7B5oE,KAAK8yE,aAAavoD,EAAG,KACvB,CAUAuqD,aAAAA,CAAcvqD,GACZvqB,KAAKizE,UAAW,EAChBjzE,KAAK8yE,aAAavoD,EAAG,eAErB,IAAIvgB,OAAEA,GAAWhK,KAAKyrE,WAAWlhD,GAC7B4/C,IAAoBngE,GAAUA,IAAWhK,KAAKmkD,cAElD,MAAMixB,OAAEA,GAAW7qD,EACnB,GAAI6qD,EAMF,aALEp1E,KAAKwvE,iBAA8B,IAAX4F,GACvBp1E,KAAKuvE,gBAA6B,IAAX6F,IACxBp1E,KAAK8yE,aAAavoD,EAAG,OAAQ,CAC3B4/C,qBAKN,GAAInqE,KAAK0oE,cAEP,YADA1oE,KAAK61E,0BAA0BtrD,GAIjC,IAAKvqB,KAAKw0E,aAAajqD,GACrB,OAIF,GAAIvqB,KAAK8iD,kBACP,OAGF,IAAIwyB,EAAet1E,KAAKi1E,cAAcjrE,GAClCisE,GAAU,EAed,GAdIj2E,KAAKk2E,qBAAqB3rD,EAAGvgB,IAE/BA,EAAShK,KAAKmkD,cACd8xB,GAAU,EACVX,GAAe,GACNt1E,KAAK2pE,sBAAsBp/C,EAAGvgB,IACvChK,KAAK2uE,oBAAoBpkD,GASzBvqB,KAAK8oE,aACH9+D,IACEA,EAAO0I,aACL1I,EAAiB+iE,WACnB/iE,IAAWhK,KAAKmkD,eACpB,CACA,MAAMp1C,EAAI/O,KAAKqqE,cAAc9/C,GAC7BvqB,KAAKyoE,eAAiB,CACpBp8D,EAAG0C,EAAE1C,EACLD,EAAG2C,EAAE3C,EACLw0B,OAAQ,EACRkqC,OAAQ,EAEZ,CAIA,GADAX,IAAoBngE,GAAUA,IAAWhK,KAAKmkD,cAC1Cn6C,EAAQ,CACNA,EAAO0I,YAAkC,SAApB1I,EAAOq9C,UAC9BrnD,KAAKsuE,gBAAgBtkE,EAAQugB,GAE/B,MAAM9W,EAASzJ,EAAOo5C,YACpBpjD,KAAKqsE,iBAAiB9hD,GACtBH,GAAaG,IAEf,GAAIvgB,IAAWhK,KAAKmkD,gBAAkB1wC,IAAWwiE,GAAU,CACzDj2E,KAAKkqE,uBAAuB3/C,EAAGvgB,EAAQmgE,GACvC,MAAMr8C,EAAUra,EAASA,EAAOqa,aAAUttB,EACxCotB,EAAU5tB,KAAKqqE,cAAc9/C,GAC7B4wB,EACErtB,GAAWA,EAAQotB,oBAAoB3wB,EAAGvgB,EAAQ8jB,GACtDqtB,GACEA,EAAiBlwC,KACf6iB,EACAvD,EACAvqB,KAAK8iD,kBACLl1B,EAAQvhB,EACRuhB,EAAQxhB,EAEd,CACF,CAGAkpE,IAAiBt1E,KAAKkoE,sBAAmB1nE,GACzCR,KAAK8yE,aAAavoD,EAAG,OAAQ,CAAE4/C,gBAAiBA,IAEhDmL,GAAgBt1E,KAAK+f,kBACvB,CAMA2tD,wBAAAA,GACE1tE,KAAK0rE,YAAc1rE,KAAKmtE,eAAiBntE,KAAKqtE,iBAAc7sE,CAC9D,CAOAqyE,wBAAAA,CAAyBtoD,GAEvBvqB,KAAK0tE,2BACL1tE,KAAKmtE,eAAiBntE,KAAKqsE,iBAAiB9hD,GAC5CvqB,KAAKqtE,YAAc5hD,GACjBzrB,KAAKmtE,oBACL3sE,EACAR,KAAKif,mBAEPjf,KAAK0rE,YAAc1rE,KAAKyrE,WAAWlhD,GAE/BvqB,KAAK8iD,oBACP9iD,KAAK0rE,YAAY1hE,OAAShK,KAAK8iD,kBAAkB94C,OAErD,CAWAgrE,aAAAA,CAAczqD,GAIZ,GAHAvqB,KAAKizE,UAAW,EAChBjzE,KAAK8yE,aAAavoD,EAAG,eAEjBvqB,KAAK0oE,cAEP,YADA1oE,KAAK+1E,0BAA0BxrD,GAIjC,IAAKvqB,KAAKw0E,aAAajqD,GACrB,OAGF,MAAM4rD,EAAgBn2E,KAAKyoE,eAG3B,GAAI0N,EAAe,CACjB,MAAMvoD,EAAU5tB,KAAKqqE,cAAc9/C,GAEnC4rD,EAAcrL,OAASl9C,EAAQvhB,EAAI8pE,EAAc9pE,EACjD8pE,EAAcv1C,OAAShT,EAAQxhB,EAAI+pE,EAAc/pE,EAEjDpM,KAAKgpE,WACP,MAAO,GAAKhpE,KAAK8iD,kBAKf9iD,KAAKo2E,iBAAiB7rD,OALY,CAClC,MAAMvgB,OAAEA,GAAWhK,KAAKyrE,WAAWlhD,GACnCvqB,KAAK41E,oBAAoBrrD,EAAGvgB,GAC5BhK,KAAKq2E,mBAAmB9rD,EAAGvgB,EAC7B,CAGAhK,KAAKs2E,mBAAmBrG,YAAY1lD,GACpCvqB,KAAK8yE,aAAavoD,EAAG,OACvB,CAQA8rD,kBAAAA,CAAmB9rD,EAAkBvgB,GACnC,MAAMq+D,eAAEA,EAAcC,gBAAEA,GAAoBtoE,MAC1C4rE,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GACjChqB,EAASqE,KAAKC,IAAIyjE,EAAgB/nE,OAAQqrE,EAAWrrE,QAEvDP,KAAKu2E,yBAAyB,QAAS,CACrChsD,IACAvgB,SACAwsE,UAAWnO,EACXoO,YAAY,IAEd,IAAK,IAAIhrE,EAAI,EAAGA,EAAIlL,EAAQkL,IAExBmgE,EAAWngE,KAAOzB,GACjBs+D,EAAgB78D,IAAM68D,EAAgB78D,KAAO48D,GAIhDroE,KAAKu2E,yBAAyB,QAAS,CACrChsD,IACAvgB,OAAQ4hE,EAAWngE,GACnB+qE,UAAWlO,EAAgB78D,KAG/BzL,KAAKqoE,eAAiBr+D,EACtBhK,KAAKsoE,gBAAkBsD,CACzB,CAQAiI,qBAAAA,CACEtpD,EACAvgB,EACAic,GAEA,MAAMywD,EAAoB12E,KAAK2zE,mBAC7BrL,EAAkBtoE,KAAKsoE,iBACvBsD,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GACjChqB,EAASqE,KAAKC,IAAIyjE,EAAgB/nE,OAAQqrE,EAAWrrE,QAEvDP,KAAKu2E,yBAAyB,OAAQ,IACjCtwD,EACHjc,SACAwsE,UAAWE,EACXD,YAAY,IAEd,IAAK,IAAIhrE,EAAI,EAAGA,EAAIlL,EAAQkL,IAC1BzL,KAAKu2E,yBAAyB,OAAQ,IACjCtwD,EACHjc,OAAQ4hE,EAAWngE,GACnB+qE,UAAWlO,EAAgB78D,KAG/BzL,KAAK2zE,mBAAqB3pE,CAC5B,CAcAusE,wBAAAA,CACEvtE,EAAO9D,GAYP,IAXA8E,OACEA,EAAMwsE,UACNA,EAASC,WACTA,EAAUlsD,EACVA,KACGtE,GAKJ/gB,EAED,MAAM2rE,SAAEA,EAAQC,UAAEA,EAASC,SAAEA,EAAQC,UAAEA,GACrCN,GAAqB1nE,GACjB2tE,EAAgBH,IAAcxsE,EAEpC,GAAIwsE,GAAaG,EAAe,CAC9B,MAAMC,EAAyC,IAC1C3wD,EACHsE,IACAvgB,OAAQwsE,EACRK,WAAY7sE,KACTsmE,GAAetwE,KAAMuqB,IAE1BksD,GAAcz2E,KAAKqL,KAAK2lE,EAAW4F,GACnCJ,EAAUnrE,KAAKylE,EAAW8F,EAC5B,CACA,GAAI5sE,GAAU2sE,EAAe,CAC3B,MAAMG,EAAuC,IACxC7wD,EACHsE,IACAvgB,SACA+sE,eAAgBP,KACblG,GAAetwE,KAAMuqB,IAE1BksD,GAAcz2E,KAAKqL,KAAK0lE,EAAU+F,GAClC9sE,EAAOqB,KAAKwlE,EAAUiG,EACxB,CACF,CAMAV,gBAAAA,CAAiB7rD,GACf,MAAMgmD,EAAavwE,KAAKqqE,cAAc9/C,GACpCvb,EAAYhP,KAAK8iD,kBACjB94C,EAASgF,EAAUhF,OAGnBgtE,EAAehtE,EAAO0iC,MAClBjhB,GACE8kD,OACA/vE,EACAwJ,EAAO0iC,MAAMxO,uBAEfqyC,EACNvhE,EAAU27D,SAAWpgD,EAAEogD,SACvB37D,EAAUu7D,SAAWvqE,KAAKwqE,aAAejgD,EAAEvqB,KAAKwqE,aAEhDxqE,KAAKi3E,wBAAwB1sD,EAAGvb,EAAWgoE,GAC3ChoE,EAAUkqC,iBAAmBl5C,KAAK+f,kBACpC,CAKAk3D,uBAAAA,CACE1sD,EACAvb,EACA4e,GAEA,MAAMm1B,OAAEA,EAAM/J,cAAEA,EAAahvC,OAAEA,GAAWgF,EAEpCkqC,IACFF,GAAiBA,EAAczuB,EAAGvb,EAAW4e,EAAQvhB,EAAGuhB,EAAQxhB,GACpE8sC,GAAmBlvC,EAAOgW,YAGX,SAAX+iC,GAAqB7J,IACvBlqC,EAAUhF,OAAOg7C,UAAW,EAC5BhlD,KAAK4qE,UAAU57D,EAAUhF,OAAOu9C,YAAcvnD,KAAKunD,aAErDv4C,EAAUkqC,gBAAkBlqC,EAAUkqC,iBAAmBA,CAC3D,CAQA08B,mBAAAA,CAAoBrrD,EAAkBvgB,GACpC,IAAKA,EAEH,YADAhK,KAAK4qE,UAAU5qE,KAAKmvE,eAGtB,IAAI7nB,EAAct9C,EAAOs9C,aAAetnD,KAAKsnD,YAC7C,MAAM4vB,EAAkBv8D,GAAkB3a,KAAKmkD,eACzCnkD,KAAKmkD,cACL,KAEJh2B,IACI+oD,GAAmBltE,EAAO0iC,QAAUwqC,IAItCltE,EAAOo5C,YAAYpjD,KAAKqsE,iBAAiB9hD,IAE7C,GAAK4D,EAaE,CACL,MAAML,QAAEA,EAAOC,MAAEA,GAAUI,EAC3BnuB,KAAK4qE,UAAU98C,EAAQwtB,mBAAmB/wB,EAAGuD,EAAS9jB,EAAQ+jB,GAChE,KAhBa,CACX,GAAK/jB,EAAiB+sD,eAAgB,CAGpC,MAAM6U,WAAEA,GAAe5rE,KAAKyrE,WAAWlhD,GACvCqhD,EACGpgE,SACA2rE,UACAp2E,QAASq2E,IACR9vB,EAAc8vB,EAAQ9vB,aAAeA,GAE3C,CACAtnD,KAAK4qE,UAAUtjB,EACjB,CAIF,CAeU4uB,oBAAAA,CAAqB3rD,EAAkBvgB,GAC/C,MAAMutD,EAAev3D,KAAKmkD,cACpBkzB,EAAO18D,GAAkB48C,GAC/B,GAEIA,GACFv3D,KAAKwpE,uBAAuBj/C,IAC5BvqB,KAAK8oE,WAEH9+D,GACFA,EAAO0I,aAGN6kD,IAAiBvtD,GAAUqtE,KAG3BA,IACGrtE,EAAO8sC,eAAeygB,KACrBA,EAAazgB,eAAe9sC,MAEhCA,EAAO47C,SAAS,CAAEr7B,QAElBgtC,EAAatU,mBACd,CACA,GAAIo0B,EAAM,CACR,MAAMC,EAAoB/f,EAAahnD,aACvC,IAAIq7D,EAA6B,GAEjC,GAAI5hE,IAAWutD,EAAc,CAC3B,MAAM3pC,EAAU5tB,KAAKqqE,cAAc9/C,GACnC,IAAIwhD,EAAa/rE,KAAKgsE,sBACpBsL,EACA1pD,GAYF,GATIm+C,EAAW/hE,QACbA,EAAS+hE,EAAW/hE,OACpB4hE,EAAaG,EAAWH,aAExBG,EAAa/rE,KAAKgsE,sBAAsBhsE,KAAKqP,SAAUue,GACvD5jB,EAAS+hE,EAAW/hE,OACpB4hE,EAAaG,EAAWH,aAGrB5hE,IAAWA,EAAO0I,WACrB,OAAO,CAEX,CACI1I,EAAO0iC,QAAU6qB,GAEnBA,EAAaluD,OAAOW,GACpBhK,KAAKqoE,eAAiBr+D,EACtBhK,KAAKsoE,gBAAkBsD,EAEK,IAAxBrU,EAAaznD,QAGf9P,KAAKwuE,iBAAiBjX,EAAa1mD,KAAK,GAAI0Z,KAI9CgtC,EAAaggB,eAAevtE,GAC5BhK,KAAKqoE,eAAiB9Q,EACtBv3D,KAAKsoE,gBAAkBsD,GAEzB5rE,KAAKiuE,qBAAqBqJ,EAAmB/sD,EAC/C,KAAO,CACJgtC,EAAuBwV,WACrBxV,EAAuByY,cAE1B,MAEMwH,EAAqB,IADzB7uE,GAAcE,SAAiC,mBACtB,CAAU,GAAI,CAKvC1F,OAAQnD,OAEVw3E,EAAmBD,eAAehgB,EAAcvtD,GAChDhK,KAAKqoE,eAAiBmP,EAItBx3E,KAAKwuE,iBAAiBgJ,EAAoBjtD,GAC1CvqB,KAAKiuE,qBAAqB,CAAC1W,GAAehtC,EAC5C,CACA,OAAO,CACT,CACA,OAAO,CACT,CASUirD,eAAAA,CAAgBjrD,GACxB,IAAKvqB,KAAK8oE,YAAc9oE,KAAKyoE,eAC3B,OAAO,EAET,MAAMp8D,EAAEA,EAACD,EAAEA,EAAC0+D,OAAEA,EAAMlqC,OAAEA,GAAW5gC,KAAKyoE,eACpCgP,EAAS,IAAItrE,GAAME,EAAGD,GACtBi7D,EAASoQ,EAAOnrE,IAAI,IAAIH,GAAM2+D,EAAQlqC,IACtCpuB,EAAKilE,EAAO5pE,IAAIw5D,GAEhBv3D,EADK2nE,EAAO5yE,IAAIwiE,GACNz6D,SAAS4F,GAEfklE,EAAmB13E,KAAKkS,eAC5B,CACEC,KAAMK,EAAGnG,EACT+F,IAAKI,EAAGpG,EACRiG,MAAOvC,EAAKzD,EACZiG,OAAQxC,EAAK1D,GAEf,CAAEmG,qBAAsBvS,KAAKkvE,0BAGzBr/D,EAGJ4nE,EAAOnqE,GAAG+5D,GACNqQ,EAAiB,GACf,CAACA,EAAiB,IAClB,GACFA,EAAiBn3E,OAAS,EACxBm3E,EACG5tE,OAAQ4F,IAAYA,EAAOk2C,SAAS,CAAEr7B,OACtC4sD,UAEHO,EAGR,GAAuB,IAAnB7nE,EAAQtP,OAEVP,KAAKsuE,gBAAgBz+D,EAAQ,GAAI0a,QAC5B,GAAI1a,EAAQtP,OAAS,EAAG,CAE7B,MAAMo3E,EACJhvE,GAAcE,SAAiC,mBACjD7I,KAAKsuE,gBAAgB,IAAIqJ,EAAM9nE,EAAS,CAAE1M,OAAQnD,OAASuqB,EAC7D,CAIA,OADAvqB,KAAKyoE,eAAiB,MACf,CACT,CAOA9/C,eAAAA,GAGqB,IAFnBF,EAAUnoB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EACb4B,EAAiC5B,UAAAC,OAAA,EAAAD,kBAAAE,EAEjC,MAAMskE,MAAEA,GAAU9kE,KAAKsf,SACvBwlD,EAAM9oD,SAAMxb,EACZ,MAAMo3E,EAAcx3E,MAAMuoB,gBAAgBF,EAAYvmB,GAEtD,OADA4iE,EAAM9oD,IAAM8oD,EAAMppD,GAAGtY,WAAW,MACzBw0E,CACT,CAKAr2D,KAAAA,GACEvhB,KAAKs2E,mBAAmB/0D,QACxBnhB,MAAMmhB,OACR,CAKAiI,OAAAA,GACExpB,KAAKwyE,kBACLxyE,KAAKs2E,mBAAmB/xE,UACxBnE,MAAMopB,SACR,ECrkDK,MAAMquD,GAAsB,CACjCra,GAAI,EACJC,GAAI,EACJQ,GAAI,EACJC,GAAI,GAGO4Z,GAAsB,IAC9BD,GACHjsC,GAAI,EACJC,GAAI,GCJOksC,GAAQA,CAAC9zE,EAAe+zE,IAC5B1rB,MAAMroD,IAAgC,iBAAf+zE,EAA0BA,EAAa/zE,ECChE,SAASg0E,GAAUh0E,GAExB,OAAOA,GAAS,KAAKurD,KAAKvrD,IAAU+V,OAAOk+D,SAASn+D,WAAW9V,GACjE,CAQO,SAASk0E,GACdl0E,EACA+zE,GAEA,MAAM1nB,EACa,iBAAVrsD,EACHA,EACiB,iBAAVA,EACL8V,WAAW9V,IAAUg0E,GAAUh0E,GAAS,IAAM,GAC9Cm0E,IACR,OAAOh1C,GAAS,EAAG20C,GAAMznB,EAAQ0nB,GAAa,EAChD,CCzBA,MAAMK,GAAqB,UACrBC,GAAe,UAErB,SAASC,GAAe78D,EAAoB88D,GAC1C,IAAI37C,EAAYC,EAChB,MAAMthB,EAAQE,EAAGqyC,aAAa,SAC9B,GAAIvyC,EAAO,CACT,MAAMi9D,EAAgBj9D,EAAMggB,MAAM68C,IAEc,KAA5CI,EAAcA,EAAcl4E,OAAS,IACvCk4E,EAAc3gC,MAGhB,IAAK,IAAIrsC,EAAIgtE,EAAcl4E,OAAQkL,KAAO,CACxC,MAAOlK,EAAK0C,GAASw0E,EAAchtE,GAChC+vB,MAAM88C,IACN3/D,IAAK4f,GAAMA,EAAEgE,QACJ,eAARh7B,EACFs7B,EAAa54B,EACI,iBAAR1C,IACTu7B,EAAe74B,EAEnB,CACF,CAEA44B,EAAaA,GAAcnhB,EAAGqyC,aAAa,eAAiB,aAC5DjxB,EAAei7C,GACbh+D,WAAW+iB,GAAgBphB,EAAGqyC,aAAa,iBAAmB,IAC9D,GAGF,MAAM90B,EAAQ,IAAID,GAAM6D,GAIxB,OAFA5D,EAAMiB,SAASjB,EAAMgB,WAAa6C,EAAe07C,GAE1C,CACLn7D,OAAQ86D,GAAaz8D,EAAGqyC,aAAa,UAAW,GAChD90B,MAAOA,EAAMU,SAEjB,CAEO,SAAS++C,GACdh9D,EACAi9D,GAEA,MAAMC,EAA0B,GAC9BC,EAAen9D,EAAGo9D,qBAAqB,QACvCrwD,EAAa0vD,GAAaQ,EAAa,GACzC,IAAK,IAAIltE,EAAIotE,EAAat4E,OAAQkL,KAChCmtE,EAAWluE,KAAK6tE,GAAeM,EAAaptE,GAAIgd,IAElD,OAAOmwD,CACT,CCvDO,SAASG,GAAUr9D,GACxB,MAAuB,mBAAhBA,EAAGmyC,UAAiD,mBAAhBnyC,EAAGmyC,SAC1C,SACA,QACN,CAEO,SAASmrB,GAAmBt9D,GACjC,MAA4C,mBAArCA,EAAGqyC,aAAa,iBACnB,SACA,YACN,CC8BA,SAASkrB,GAASv9D,EAAwBna,GACxC,OAAOma,EAAGqyC,aAAaxsD,EACzB,CAsBO,SAAS23E,GAAYx9D,EAAwB5L,GAClD,OA9DF,SAIEqpE,EAA2Cj0E,GAE3C,IACIk0E,GAFJ/mE,MAAEA,EAAKC,OAAEA,EAAM6hC,cAAEA,GAAyDjvC,EAG1E,OAAQzE,OAAO8J,QAAQ4uE,GAA4C93E,OACjE,CAACC,EAAGuJ,KAAwB,IAArBoI,EAAMomE,GAAUxuE,EACrB,GAAkB,aAAdwuE,EACFD,EAAa,OACR,GAAkB,cAAdC,EACTD,EAAa,MACR,CACL,MAAME,EAAgC,iBAAdD,EACxBD,EAAaE,EAAWv/D,WAAWs/D,GAAaA,EAC5CC,GAAYrB,GAAUoB,KACxBD,GAAc,IACQ,WAAlBjlC,IAEW,OAATlhC,GAA0B,OAATA,GAA0B,OAATA,IACpCmmE,GAAc/mE,GAEH,OAATY,GAA0B,OAATA,IACnBmmE,GAAc9mE,IAItB,CAEA,OADAhR,EAAI2R,GAAQmmE,EACL93E,GAET,CAAA,EAEJ,CA2BSi4E,CACa,WAAlBR,GAAUr9D,GAtBP,SAA2BA,GAChC,MAAO,CACL8hD,GAAIyb,GAASv9D,EAAI,OAAS,EAC1B+hD,GAAIwb,GAASv9D,EAAI,OAAS,EAC1BuiD,GAAIgb,GAASv9D,EAAI,OAAS,OAC1BwiD,GAAI+a,GAASv9D,EAAI,OAAS,EAE9B,CAeiC89D,CAAkB99D,GAb5C,SAA2BA,GAChC,MAAO,CACL8hD,GAAIyb,GAASv9D,EAAI,OAASu9D,GAASv9D,EAAI,OAAS,MAChD+hD,GAAIwb,GAASv9D,EAAI,OAASu9D,GAASv9D,EAAI,OAAS,MAChDkwB,GAAI,EACJqyB,GAAIgb,GAASv9D,EAAI,OAAS,MAC1BwiD,GAAI+a,GAASv9D,EAAI,OAAS,MAC1BmwB,GAAIotC,GAASv9D,EAAI,MAAQ,MAE7B,CAIyD+9D,CAAkB/9D,GACvE,IACK5L,EACHqkC,cAAe6kC,GAAmBt9D,IAGxC,CC9CO,MAAMg+D,GAyEX55E,WAAAA,CAAYoC,GACV,MAAM8G,KACJA,EAAO,SAAamrC,cACpBA,EAAgB,SAAQnH,OACxBA,EAAS,CAAA,EAAE4rC,WACXA,EAAa,GAAEl+D,QACfA,EAAU,EAAC6J,QACXA,EAAU,EAACE,kBACXA,EAAiB9Q,GACjBA,GACEzR,GAAW,CAAA,EACfzB,OAAOC,OAAOV,KAAM,CAClBgJ,OACAmrC,gBACAnH,OAAQ,IACO,WAAThkC,EAAoB8uE,GAAsBD,MAC3C7qC,GAEL4rC,aACAl+D,UACA6J,UACAE,oBACA9Q,GAAIA,EAAK,GAAGA,KAAMC,OAAUA,MAEhC,CAOA+lE,YAAAA,CAAaf,GACX,IAAK,MAAMn9D,KAAYm9D,EACrB54E,KAAK44E,WAAWluE,KAAK,CACnB2S,OAAQtD,WAAW0B,GACnBwd,MAAO2/C,EAAWn9D,KAGtB,OAAOzb,IACT,CAOAwa,QAAAA,CACE8K,GAEA,MAAO,IACF9L,GAAKxZ,KAAMslB,GACdtc,KAAMhJ,KAAKgJ,KACXgkC,OAAQ,IAAKhtC,KAAKgtC,QAClB4rC,WAAY54E,KAAK44E,WAAWjgE,IAAKihE,IAAS,IAAWA,KACrDl/D,QAAS1a,KAAK0a,QACd6J,QAASvkB,KAAKukB,QACd4vB,cAAen0C,KAAKm0C,cACpB1vB,kBAAmBzkB,KAAKykB,kBACpB,IAAIzkB,KAAKykB,wBACTjkB,EAER,CAQA8lB,KAAAA,CACE5W,GAIA,IAFE6X,oBAAqBsyD,GACYv5E,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEtC,MAAMimB,EAAS,GACbvX,EACEhP,KAAKykB,kBACDzkB,KAAKykB,kBAAkBjZ,SACvB9E,EAAQ8E,SAEd2oC,EACyB,WAAvBn0C,KAAKm0C,cACD,iBACA,oBAEFykC,EAAa54E,KAAK44E,WACrBjgE,IAAKihE,IAAS,IAAWA,KACzBE,KAAK,CAAC3kE,EAAGG,IACDH,EAAEkI,OAAS/H,EAAE+H,QAGxB,IAAI3C,GAAW1a,KAAK0a,QAClB6J,GAAWvkB,KAAKukB,QtGhKCpV,MsGiKG,sBAAlBglC,GACFz5B,GAAWhL,EAAO2C,MAClBkS,GAAW7U,EAAO4C,SAElBoI,GAAWhL,EAAO2C,MAAQ,EAC1BkS,GAAW7U,EAAO4C,OAAS,ItGtKVnD,EsGyKRO,ItGpK2C,mBAA9CP,EAAsB4qE,qBsGoKe,eAAvB/5E,KAAKm0C,gBACzBz5B,GAAWhL,EAAO00D,WAAW/3D,EAC7BkY,GAAW7U,EAAO00D,WAAWh4D,GAE/B4C,EAAU,IAAM0L,EAChB1L,EAAU,IAAMuV,EAEhB,MAAMs/C,EAAmB,CACvB,aAAa7jE,KAAK2T,MAClB,kBAAkBwgC,KAClB,sBACE0lC,EAAeA,EAAe,IAAM,KACnC5/D,GAAYjL,MACf,IACAmL,KAAK,KAEP,GAAkB,WAAdna,KAAKgJ,KAAmB,CAC1B,MAAMw0D,GAAEA,EAAEC,GAAEA,EAAEQ,GAAEA,EAAEC,GAAEA,GAAOl+D,KAAKgtC,OAChCzmB,EAAO7b,KACL,mBACAm5D,EACA,QACArG,EACA,SACAC,EACA,SACAQ,EACA,SACAC,EACA,OAEJ,MAAO,GAAkB,WAAdl+D,KAAKgJ,KAAmB,CACjC,MAAMw0D,GAAEA,EAAEC,GAAEA,EAAEQ,GAAEA,EAAEC,GAAEA,EAAEtyB,GAAEA,EAAEC,GAAEA,GAAO7rC,KAChCgtC,OACGgtC,EAAYpuC,EAAKC,EAEvBtlB,EAAO7b,KACL,mBACAm5D,EACA,QACAmW,EAAYxc,EAAKS,EACjB,SACA+b,EAAYvc,EAAKS,EACjB,QACA8b,EAAYpuC,EAAKC,EACjB,SACAmuC,EAAY/b,EAAKT,EACjB,SACAwc,EAAY9b,EAAKT,EACjB,QAEEuc,IAEFpB,EAAWzB,UACXyB,EAAW73E,QAAS64E,IAClBA,EAAUv8D,OAAS,EAAIu8D,EAAUv8D,UAGrC,MAAM48D,EAAYr1E,KAAKiJ,IAAI+9B,EAAIC,GAC/B,GAAIouC,EAAY,EAAG,CAEjB,MACEC,EAAkBD,EADFr1E,KAAKC,IAAI+mC,EAAIC,GAE/B+sC,EAAW73E,QAAS64E,IAClBA,EAAUv8D,QAAU68D,GAAmB,EAAIN,EAAUv8D,SAEzD,CACF,CAaA,OAXAu7D,EAAW73E,QAAQmE,IAAuB,IAAtB+zB,MAAEA,EAAK5b,OAAEA,GAAQnY,EACnCqhB,EAAO7b,KACL,iBAA0B,IAAT2S,yBAAoC4b,aAIzD1S,EAAO7b,KACS,WAAd1K,KAAKgJ,KAAoB,oBAAsB,oBAC/C,MAGKud,EAAOpM,KAAK,GACrB,CAQAG,MAAAA,CAAO0B,GACL,MAAMwhD,GAAEA,EAAEC,GAAEA,EAAEQ,GAAEA,EAAEC,GAAEA,EAAEtyB,GAAEA,EAAEC,GAAEA,GAAO7rC,KAAKgtC,OAClCmtC,EACU,WAAdn6E,KAAKgJ,KACDgT,EAAIo+D,qBAAqB5c,EAAIC,EAAIQ,EAAIC,GACrCliD,EAAIq+D,qBAAqB7c,EAAIC,EAAI7xB,EAAIqyB,EAAIC,EAAIryB,GAMnD,OAJA7rC,KAAK44E,WAAW73E,QAAQ8J,IAAuB,IAAtBouB,MAAEA,EAAK5b,OAAEA,GAAQxS,EACxCsvE,EAASR,aAAat8D,EAAQ4b,KAGzBkhD,CACT,CAQA,uBAAavhE,CACX1W,GAEA,MAAM02E,WAAEA,EAAUn0D,kBAAEA,GAAsBviB,EAC1C,OAAO,IAAIlC,KAAK,IACXkC,EACH02E,WAAYA,EACRA,EAAWjgE,IAAKihE,IAAS,IAAWA,UACpCp5E,EACJikB,kBAAmBA,EAAoB,IAAIA,QAAqBjkB,GAEpE,CA6CA,kBAAO4xD,CACL12C,EACAzC,EACAqhE,GAEA,MAAMnmC,EAAgB6kC,GAAmBt9D,GACnC0J,EAASnM,EAAS28B,yBACxB,OAAO,IAAI51C,KAAK,CACd2T,GAAI+H,EAAGqyC,aAAa,YAASvtD,EAC7BwI,KAAM+vE,GAAUr9D,GAChBsxB,OAAQksC,GAAYx9D,EAAI,CACtBrJ,MAAOioE,EAAWC,cAAgBD,EAAWjoE,MAC7CC,OAAQgoE,EAAWE,eAAiBF,EAAWhoE,SAEjDsmE,WAAYF,GAAgBh9D,EAAI4+D,EAAWt9C,SAC3CmX,gBACA1vB,kBAAmB4qC,GACjB3zC,EAAGqyC,aAAa,sBAAwB,OAEpB,WAAlB5Z,EACA,CACEz5B,QAASzB,EAAS5G,MAAQ,EAAI+S,EAAO/Y,EACrCkY,QAAStL,EAAS3G,OAAS,EAAI8S,EAAOhZ,GAExC,CACEsO,QAAS,EACT6J,QAAS,IAGnB,EAhTAxkB,EAjEW25E,GAAQ,OAuEL,YA8ShB/wE,GAAcG,SAAS4wE,GAAU,YACjC/wE,GAAcG,SAAS4wE,GAAU,UACjC/wE,GAAcG,SAAS4wE,GAAU,UChY1B,MAAMe,GAWX,QAAIzxE,GACF,MAAO,SACT,CAEA,QAAIA,CAAK/E,GACPzC,EAAI,OAAQ,6BAA8ByC,EAC5C,CAsDAnE,WAAAA,CAAYoC,GAAyBnC,gBAhDb,UAExBA,iBAIU,GAEVA,iBAIU,GAEVA,qBAG4B,IAgC1BC,KAAK2T,GAAKC,KACVnT,OAAOC,OAAOV,KAAMkC,EACtB,CAKAw4E,aAAAA,GACE,QACI16E,KAAKyZ,QAA2D,iBAAzCzZ,KAAKyZ,OAA4BxB,GAE9D,CAKA0iE,cAAAA,GACE,QAAS36E,KAAKyZ,UAAazZ,KAAKyZ,OAA6BtF,SAC/D,CAEAymE,cAAAA,GACE,OAAO56E,KAAK06E,gBACR16E,KAAKyZ,OAAOxB,IACZjY,KAAK26E,iBACH36E,KAAKyZ,OAAOtF,YACZ,EACR,CAOAmG,MAAAA,CAAO0B,GACL,OAEGhc,KAAKyZ,UAELzZ,KAAK06E,iBACF16E,KAAKyZ,OAAOohE,UACiB,IAA7B76E,KAAKyZ,OAAOqhE,cACkB,IAA9B96E,KAAKyZ,OAAOshE,eAKX/+D,EAAI25B,cAAc31C,KAAKyZ,OAAQzZ,KAAK+nB,QAHlC,IAIX,CAOAvN,QAAAA,GAAkE,IAAzD8K,EAA6BhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GACvC,MAAMynB,OAAEA,EAAMnQ,YAAEA,GAAgB5X,KAChC,MAAO,IACFwZ,GAAKxZ,KAAMslB,GACdtc,KAAM,UACNyQ,OAAQzZ,KAAK46E,iBACb7yD,SACAnQ,cACA8C,QAASd,GAAQ5Z,KAAK0a,QAASva,EAAO+Z,qBACtCqK,QAAS3K,GAAQ5Z,KAAKukB,QAASpkB,EAAO+Z,qBACtCwK,iBAAkB1kB,KAAK0kB,iBACnB,IAAI1kB,KAAK0kB,kBACT,KAER,CAMA4B,KAAAA,CAAKphB,GAAmC,IAAlCmN,MAAEA,EAAKC,OAAEA,GAAepN,EAC5B,MAAQuU,OAAQuhE,EAAajzD,OAAEA,EAAMpU,GAAEA,GAAO3T,KAC5Ci7E,EAAiBlD,GAAM/3E,KAAK0a,QAAUrI,EAAO,GAC7C6oE,EAAiBnD,GAAM/3E,KAAKukB,QAAUjS,EAAQ,GAUhD,MAAO,CACL,sBAAsBqB,SAAUsnE,SAAsBC,aATzC,aAAXnzD,GAAoC,cAAXA,EACrB,EAAInjB,KAAKmH,IAAIkvE,GAAkB,GAC/BlD,GAAOiD,EAAmC3oE,MAAQA,EAAO,eAElD,aAAX0V,GAAoC,cAAXA,EACrB,EAAInjB,KAAKmH,IAAImvE,GAAkB,GAC/BnD,GAAOiD,EAAmC1oE,OAASA,EAAQ,OAIjE,6BACG0oE,EAAmC3oE,kBAEnC2oE,EAAmC1oE,uBACrBtS,KAAK46E,6BACtB,aACA,IACAzgE,KAAK,KACT,CAGA,uBAAavB,CAAU/N,EAOrB3I,GACkB,IAPlB8G,KACEA,EAAIyQ,OACJA,EAAMiL,iBACNA,KACGqG,GACsBlgB,EAG3B,MAAMkN,QAAYN,GAAUgC,EAAQ,IAC/BvX,EACH0V,YAAamT,EAAanT,cAE5B,OAAO,IAAI5X,KAAK,IACX+qB,EACHrG,iBACEA,GAAqBA,EAAiBsV,MAAM,GAC9CvgB,OAAQ1B,GAEZ,EACDhY,EAhMY06E,GAAO,OACJ,WAiMhB9xE,GAAcG,SAAS2xE,IAEvB9xE,GAAcG,SAAS2xE,GAAS,WC9MzB,MAAeU,GA0DpBr7E,WAAAA,CAAYqD,GAzDZpD,eAIQ,gBAERA,eAIQ,GAERA,gBAMwB,MAExBA,uBAI+B,SAE/BA,wBAIiC,SAEjCA,0BAImB,IAEnBA,yBAImC,MAEnCA,8BAMsB,GAQpBC,KAAKmD,OAASA,CAChB,CAeAwqE,eAAAA,CAAgB3xD,GACdA,EAAIq4B,YAAcr0C,KAAKi5B,MACvBjd,EAAI83B,UAAY9zC,KAAKqS,MACrB2J,EAAI+3B,QAAU/zC,KAAKw9B,cACnBxhB,EAAIk4B,WAAal0C,KAAK09B,iBACtB1hB,EAAIi4B,SAAWj0C,KAAKy9B,eACpBzhB,EAAI04B,YAAY10C,KAAKs9B,iBAAmB,GAC1C,CAOU89C,iBAAAA,CAAkBp/D,GAC1B,MAAMuG,EAAIviB,KAAKmD,OAAO8b,kBACtBjD,EAAI2G,OACJ3G,EAAIhN,UAAUuT,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAChD,CAEU84D,eAAAA,GAER,OADc,IAAIriD,GAAMh5B,KAAKi5B,OAChBgB,WAAa,KAAOj6B,KAAK89B,MACxC,CAMUqU,UAAAA,GACR,IAAKnyC,KAAK89B,SAAW99B,KAAKmD,OACxB,OAGF,MAAMA,EAASnD,KAAKmD,OAClB26B,EAAS99B,KAAK89B,OACd9hB,EAAM7Y,EAAOquC,WACb1oB,EAAO3lB,EAAOsd,UAAYtd,EAAO8c,mBAEnCjE,EAAIg5B,YAAclX,EAAO7E,MACzBjd,EAAIi5B,WAAanX,EAAOiF,KAAOja,EAC/B9M,EAAIm5B,cAAgBrX,EAAOpjB,QAAUoO,EACrC9M,EAAIo5B,cAAgBtX,EAAOvZ,QAAUuE,CACvC,CAMUwyD,YAAAA,GACR,MAAMt/D,EAAMhc,KAAKmD,OAAOquC,WAExBx1B,EAAIg5B,YAAc,GAClBh5B,EAAIi5B,WAAaj5B,EAAIm5B,cAAgBn5B,EAAIo5B,cAAgB,CAC3D,CAOUmmC,gBAAAA,CAAiB3tD,GACzB,OACEA,EAAQvhB,EAAI,GACZuhB,EAAQvhB,EAAIrM,KAAKmD,OAAOgd,YACxByN,EAAQxhB,EAAI,GACZwhB,EAAQxhB,EAAIpM,KAAKmD,OAAOid,WAE5B,ECxGK,MAAMo7D,WAIH1rC,GAuBRhwC,WAAAA,CACE0iB,GAGA,IADEA,KAAM9N,EAACvC,KAAEA,EAAIC,IAAEA,KAAQlQ,GAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAErDF,QACAK,OAAOC,OAAOV,KAAMw7E,GAAK97D,aACzB1f,KAAKgwC,WAAW9tC,GAChBlC,KAAKy7E,SAASj5D,GAAQ,IAAI,GACV,iBAATrQ,GAAqBnS,KAAKuF,IAAIwB,EAAMoL,GAC5B,iBAARC,GAAoBpS,KAAKuF,IAAIyB,EAAKoL,EAC3C,CAQAqpE,QAAAA,CAASj5D,EAAiCk5D,GACxC17E,KAAKwiB,KAAO+6C,GAAgB37D,MAAMwN,QAAQoT,GAAQA,EAAOg/C,GAAUh/C,IACnExiB,KAAK27E,eAAeD,EACtB,CAQA9lC,sBAAAA,GACE,MAAMtqB,EAAOtrB,KAAK47E,sBAClB,OAAO,IAAIzvE,GAAMmf,EAAKnZ,KAAOmZ,EAAKjZ,MAAQ,EAAGiZ,EAAKlZ,IAAMkZ,EAAKhZ,OAAS,EACxE,CAMAynE,mBAAAA,CAAoB/9D,GAClB,MAAMwc,GAAKx4B,KAAKokE,WAAW/3D,EACzBuB,GAAK5N,KAAKokE,WAAWh4D,EAEvB4P,EAAIkI,YAEJ,IAAK,MAAM48C,KAAW9gE,KAAKwiB,KACzB,OACEs+C,EAAQ,IAER,IAAK,IACH9kD,EAAIoI,OAAO08C,EAAQ,GAAKtoC,EAAGsoC,EAAQ,GAAKlzD,GACxC,MAEF,IAAK,IACHoO,EAAImI,OAAO28C,EAAQ,GAAKtoC,EAAGsoC,EAAQ,GAAKlzD,GACxC,MAEF,IAAK,IACHoO,EAAIm2C,cACF2O,EAAQ,GAAKtoC,EACbsoC,EAAQ,GAAKlzD,EACbkzD,EAAQ,GAAKtoC,EACbsoC,EAAQ,GAAKlzD,EACbkzD,EAAQ,GAAKtoC,EACbsoC,EAAQ,GAAKlzD,GAEf,MAEF,IAAK,IACHoO,EAAI6/D,iBACF/a,EAAQ,GAAKtoC,EACbsoC,EAAQ,GAAKlzD,EACbkzD,EAAQ,GAAKtoC,EACbsoC,EAAQ,GAAKlzD,GAEf,MAEF,IAAK,IACHoO,EAAIqI,YAIZ,CAMA+uB,OAAAA,CAAQp3B,GACNhc,KAAK+5E,oBAAoB/9D,GACzBhc,KAAKq1C,oBAAoBr5B,EAC3B,CAMA9N,QAAAA,GACE,MAAO,WAAWlO,KAAKoR,2BAA2BpR,KAAKoS,gBACrDpS,KAAKmS,SAET,CAOAqI,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAO,IACFF,MAAMoa,SAAS8K,GAClB9C,KAAMxiB,KAAKwiB,KAAK7J,IAAKmjE,GAAYA,EAAQ9hD,SAE7C,CAOAzU,gBAAAA,GAGsD,IAApDD,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAMqQ,EAAI3Q,KAAKwa,SAAe8K,GAK9B,OAJItlB,KAAK+7E,oBACAprE,EAAE6R,KACT7R,EAAEorE,WAAa/7E,KAAK+7E,YAEfprE,CACT,CAOAwtB,MAAAA,GAEE,MAAO,CACL,SACA,eACA,MAJWwkC,GAAS3iE,KAAKwiB,KAAMriB,EAAO+Z,oDAM1C,CAMA8hE,mBAAAA,GACE,MAAMC,EAAS97E,EAAO+Z,oBACtB,MAAO,cAAcN,IAAS5Z,KAAKokE,WAAW/3D,EAAG4vE,OAAYriE,IAC1D5Z,KAAKokE,WAAWh4D,EACjB6vE,KAEJ,CAOA50D,aAAAA,CAAc7O,GACZ,MAAM+O,EAAsBvnB,KAAKg8E,sBACjC,MACE,KACAh8E,KAAKs+B,6BAA6Bt+B,KAAKm+B,SAAU,CAC/C3lB,UACA+O,oBAAqBA,GAG3B,CAOAjB,KAAAA,CAAM9N,GACJ,MAAM+O,EAAsBvnB,KAAKg8E,sBACjC,OAAOh8E,KAAKq+B,qBAAqBr+B,KAAKm+B,SAAU,CAC9C3lB,UACA+O,oBAAqBA,GAEzB,CAMAnW,UAAAA,GACE,OAAOpR,KAAKwiB,KAAKjiB,MACnB,CAEA2c,aAAAA,GACEld,KAAK27E,gBACP,CAEAA,cAAAA,CAAeD,GACb,MAAMrpE,MAAEA,EAAKC,OAAEA,EAAM8xD,WAAEA,GAAepkE,KAAKk8E,kBAC3Cl8E,KAAKuF,IAAI,CAAE8M,QAAOC,SAAQ8xD,eAG1BsX,GAAkB17E,KAAKgrB,oBAAoBo5C,EAAYt9D,EAAQA,EACjE,CAEA80E,mBAAAA,GACE,MAAMvgB,EAAe,GACrB,IAAI8gB,EAAgB,EAClBC,EAAgB,EAChB/vE,EAAI,EACJD,EAAI,EAEN,IAAK,MAAM00D,KAAW9gE,KAAKwiB,KAEzB,OACEs+C,EAAQ,IAER,IAAK,IACHz0D,EAAIy0D,EAAQ,GACZ10D,EAAI00D,EAAQ,GACZzF,EAAO3wD,KAAK,CAAE2B,EAAG8vE,EAAe/vE,EAAGgwE,GAAiB,CAAE/vE,IAAGD,MACzD,MAEF,IAAK,IACHC,EAAIy0D,EAAQ,GACZ10D,EAAI00D,EAAQ,GACZqb,EAAgB9vE,EAChB+vE,EAAgBhwE,EAChB,MAEF,IAAK,IACHivD,EAAO3wD,QACF8vD,GACDnuD,EACAD,EACA00D,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,KAGZz0D,EAAIy0D,EAAQ,GACZ10D,EAAI00D,EAAQ,GACZ,MAEF,IAAK,IACHzF,EAAO3wD,QACF8vD,GACDnuD,EACAD,EACA00D,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,KAGZz0D,EAAIy0D,EAAQ,GACZ10D,EAAI00D,EAAQ,GACZ,MAEF,IAAK,IACHz0D,EAAI8vE,EACJ/vE,EAAIgwE,EAIV,OAAO1xD,GAA0B2wC,EACnC,CAKA6gB,eAAAA,GACE,MAAM5wD,EAAOtrB,KAAK47E,sBAElB,MAAO,IACFtwD,EACH84C,WAAY,IAAIj4D,GACdmf,EAAKnZ,KAAOmZ,EAAKjZ,MAAQ,EACzBiZ,EAAKlZ,IAAMkZ,EAAKhZ,OAAS,GAG/B,CAaA,iBAAOsG,CAAoDlJ,GACzD,OAAO1P,KAAK04C,YAAkBhpC,EAAQ,CACpCkpC,WAAY,QAEhB,CAOA,wBAAawZ,CACXt+C,EACA5R,EACAwsD,GAEA,MAAM5jD,EAAEA,KAAMuxE,GAAqBprB,GACjCn9C,EACA9T,KAAKsyD,gBACL5D,GAEF,OAAO,IAAI1uD,KAAK8K,EAAG,IACduxE,KACAn6E,EAEHiQ,UAAM3R,EACN4R,SAAK5R,GAET,EAlWAT,EALWy7E,GAAI,OAiBD,QAAMz7E,EAjBTy7E,GAAI,kBAmBU,IAAIl4C,GAAiB,OAAQ,aAAWvjC,EAnBtDy7E,GAAI,kBAoUU,IAAI9tB,GAAmB,MAsClD/kD,GAAcG,SAAS0yE,IACvB7yE,GAAcQ,YAAYqyE,ICzYnB,MAAMc,WAAoBnB,GA4B/Br7E,WAAAA,CAAYqD,GACV/C,MAAM+C,GA5BRpD,kBAKW,IAEXA,2BAOmB,GAEnBA,yBAKkD,YAQhDC,KAAKu8E,QAAU,GACfv8E,KAAKw8E,kBAAmB,CAC1B,CAEAnB,eAAAA,GACE,OAAOj7E,MAAMi7E,mBAAqBr7E,KAAKw8E,gBACzC,CAEA,kBAAOC,CAAYzgE,EAA+BqmD,EAAWC,GAC3D,MAAMI,EAAWL,EAAGp0D,aAAaq0D,GAEjC,OADAtmD,EAAI6/D,iBAAiBxZ,EAAGh2D,EAAGg2D,EAAGj2D,EAAGs2D,EAASr2D,EAAGq2D,EAASt2D,GAC/Cs2D,CACT,CAMAoT,WAAAA,CAAYloD,EAAc1oB,GAAiB,IAAfqlB,EAAEA,GAAWrlB,EAClClF,KAAKmD,OAAOqxE,aAAajqD,KAG9BvqB,KAAK08E,mBAAqB18E,KAAK28E,iBAAmBpyD,EAAEvqB,KAAK28E,iBACzD38E,KAAK48E,mBAAmBhvD,GAGxB5tB,KAAK68E,UAAUjvD,GACf5tB,KAAKozC,UACP,CAMA68B,WAAAA,CAAYriD,EAAc/iB,GAAiB,IAAf0f,EAAEA,GAAW1f,EACvC,GAAK7K,KAAKmD,OAAOqxE,aAAajqD,KAG9BvqB,KAAK08E,mBAAqB18E,KAAK28E,iBAAmBpyD,EAAEvqB,KAAK28E,mBACxB,IAA7B38E,KAAK88E,sBAAgC98E,KAAKu7E,iBAAiB3tD,KAG3D5tB,KAAK68E,UAAUjvD,IAAY5tB,KAAKu8E,QAAQh8E,OAAS,GACnD,GAAIP,KAAKq7E,kBAGPr7E,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKozC,cACA,CACL,MAAMzoB,EAAS3qB,KAAKu8E,QAClBh8E,EAASoqB,EAAOpqB,OAChByb,EAAMhc,KAAKmD,OAAOquC,WAEpBxxC,KAAKo7E,kBAAkBp/D,GACnBhc,KAAK+8E,SACP/gE,EAAIkI,YACJlI,EAAImI,OAAOnkB,KAAK+8E,OAAO1wE,EAAGrM,KAAK+8E,OAAO3wE,IAExCpM,KAAK+8E,OAAST,GAAYG,YACxBzgE,EACA2O,EAAOpqB,EAAS,GAChBoqB,EAAOpqB,EAAS,IAElByb,EAAI6hB,SACJ7hB,EAAI6G,SACN,CAEJ,CAKAmzD,SAAAA,CAAS5qE,GAAgB,IAAfmf,EAAEA,GAAWnf,EACrB,OAAKpL,KAAKmD,OAAOqxE,aAAajqD,KAG9BvqB,KAAK08E,kBAAmB,EACxB18E,KAAK+8E,YAASv8E,EACdR,KAAKg9E,uBAEE,EACT,CAMAJ,kBAAAA,CAAmBhvD,GACjB5tB,KAAKi9E,SACLj9E,KAAK68E,UAAUjvD,GACf5tB,KAAKmD,OAAOquC,WAAWrtB,OAAOyJ,EAAQvhB,EAAGuhB,EAAQxhB,EACnD,CAMAywE,SAAAA,CAAUh8D,GACR,QACE7gB,KAAKu8E,QAAQh8E,OAAS,GACtBsgB,EAAMvT,GAAGtN,KAAKu8E,QAAQv8E,KAAKu8E,QAAQh8E,OAAS,OAI1CP,KAAK08E,kBAAoB18E,KAAKu8E,QAAQh8E,OAAS,IACjDP,KAAKw8E,kBAAmB,EACxBx8E,KAAKu8E,QAAQzkC,OAEf93C,KAAKu8E,QAAQ7xE,KAAKmW,IACX,EACT,CAMAo8D,MAAAA,GACEj9E,KAAKu8E,QAAU,GACfv8E,KAAK2tE,gBAAgB3tE,KAAKmD,OAAOquC,YACjCxxC,KAAKmyC,aACLnyC,KAAKw8E,kBAAmB,CAC1B,CAOAppC,OAAAA,GAAgE,IAAxDp3B,EAA6B1b,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKmD,OAAOquC,WAC9C6wB,EAAKriE,KAAKu8E,QAAQ,GACpBja,EAAKtiE,KAAKu8E,QAAQ,GAOpB,GANAv8E,KAAKo7E,kBAAkBp/D,GACvBA,EAAIkI,YAKwB,IAAxBlkB,KAAKu8E,QAAQh8E,QAAgB8hE,EAAGh2D,IAAMi2D,EAAGj2D,GAAKg2D,EAAGj2D,IAAMk2D,EAAGl2D,EAAG,CAC/D,MAAMiG,EAAQrS,KAAKqS,MAAQ,IAC3BgwD,EAAGh2D,GAAKgG,EACRiwD,EAAGj2D,GAAKgG,CACV,CACA2J,EAAImI,OAAOk+C,EAAGh2D,EAAGg2D,EAAGj2D,GAEpB,IAAK,IAAIX,EAAI,EAAGA,EAAIzL,KAAKu8E,QAAQh8E,OAAQkL,IAGvC6wE,GAAYG,YAAYzgE,EAAKqmD,EAAIC,GACjCD,EAAKriE,KAAKu8E,QAAQ9wE,GAClB62D,EAAKtiE,KAAKu8E,QAAQ9wE,EAAI,GAKxBuQ,EAAIoI,OAAOi+C,EAAGh2D,EAAGg2D,EAAGj2D,GACpB4P,EAAI6hB,SACJ7hB,EAAI6G,SACN,CAOAq6D,sBAAAA,CAAuBvyD,GACrB,MAAM+qC,EAAa11D,KAAKqS,MAAQ,IAChC,OAAO+vD,GAAwBz3C,EAAQ+qC,EACzC,CAOAynB,UAAAA,CAAWva,GACT,MAAMpgD,EAAO,IAAIg5D,GAAK5Y,EAAU,CAC9B7+C,KAAM,KACN8Z,OAAQ79B,KAAKi5B,MACboE,YAAar9B,KAAKqS,MAClBmrB,cAAex9B,KAAKw9B,cACpBE,iBAAkB19B,KAAK09B,iBACvBD,eAAgBz9B,KAAKy9B,eACrBH,gBAAiBt9B,KAAKs9B,kBAOxB,OALIt9B,KAAK89B,SACP99B,KAAK89B,OAAOoF,cAAe,EAC3B1gB,EAAKsb,OAAS,IAAI8E,GAAO5iC,KAAK89B,SAGzBtb,CACT,CAKA46D,cAAAA,CAAezyD,EAAiBs0B,GAC9B,GAAIt0B,EAAOpqB,QAAU,EACnB,OAAOoqB,EAET,IACE0yD,EADEC,EAAY3yD,EAAO,GAEvB,MAAM7B,EAAO9oB,KAAKmD,OAAOsd,UACvB88D,EAAmB34E,KAAKqR,IAAIgpC,EAAWn2B,EAAM,GAC7C0P,EAAI7N,EAAOpqB,OAAS,EACpBi9E,EAAY,CAACF,GAEf,IAAK,IAAI7xE,EAAI,EAAGA,EAAI+sB,EAAI,EAAG/sB,IACzB4xE,EACEz4E,KAAKqR,IAAIqnE,EAAUjxE,EAAIse,EAAOlf,GAAGY,EAAG,GACpCzH,KAAKqR,IAAIqnE,EAAUlxE,EAAIue,EAAOlf,GAAGW,EAAG,GAClCixE,GAAaE,IACfD,EAAY3yD,EAAOlf,GACnB+xE,EAAU9yE,KAAK4yE,IAMnB,OADAE,EAAU9yE,KAAKigB,EAAO6N,IACfglD,CACT,CAOAR,mBAAAA,GACch9E,KAAKmD,OAAOquC,WACpBntB,YACArkB,KAAKy9E,WACPz9E,KAAKu8E,QAAUv8E,KAAKo9E,eAAep9E,KAAKu8E,QAASv8E,KAAKy9E,WAExD,MAAM7a,EAAW5iE,KAAKk9E,uBAAuBl9E,KAAKu8E,SAClD,GA3QJ,SAAwB3Z,GACtB,MAA8B,0BAAvBD,GAASC,EAClB,CAyQQ8a,CAAe9a,GAMjB,YADA5iE,KAAKmD,OAAO4c,mBAId,MAAMyC,EAAOxiB,KAAKm9E,WAAWva,GAC7B5iE,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKmD,OAAOkI,KAAK,sBAAuB,CAAEmX,KAAMA,IAChDxiB,KAAKmD,OAAOmJ,IAAIkW,GAChBxiB,KAAKmD,OAAO4c,mBACZyC,EAAKxC,YACLhgB,KAAKs7E,eAGLt7E,KAAKmD,OAAOkI,KAAK,eAAgB,CAAEmX,KAAMA,GAC3C,EC1PF,MAAMm7D,GAAe,CACnB,SACA,aACA,WACA,oBAUK,MAAMC,WAKH9tC,GAcR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNm+D,GAAOl+D,YAEd,CAMA5f,WAAAA,CAAYoC,GACV9B,QACAK,OAAOC,OAAOV,KAAM49E,GAAOl+D,aAC3B1f,KAAKgwC,WAAW9tC,EAClB,CAOAiR,IAAAA,CAAK5R,EAAa0C,GAOhB,OANA7D,MAAM+S,KAAK5R,EAAK0C,GAEJ,WAAR1C,GACFvB,KAAK69E,UAAU55E,GAGVjE,IACT,CAMAozC,OAAAA,CAAQp3B,GACNA,EAAIkI,YACJlI,EAAIs+B,IACF,EACA,EACAt6C,KAAKyjE,OACL9uD,GAAiB3U,KAAK89E,YACtBnpE,GAAiB3U,KAAK+9E,UACtB/9E,KAAK8sB,kBAEP9sB,KAAKq1C,oBAAoBr5B,EAC3B,CAMAgiE,UAAAA,GACE,OAAOh+E,KAAKyF,IAAI,UAAYzF,KAAKyF,IAAIsC,EACvC,CAMAk2E,UAAAA,GACE,OAAOj+E,KAAKyF,IAAI,UAAYzF,KAAKyF,IAAIuC,EACvC,CAKA61E,SAAAA,CAAU55E,GACRjE,KAAKyjE,OAASx/D,EACdjE,KAAKuF,IAAI,CAAE8M,MAAe,EAARpO,EAAWqO,OAAgB,EAARrO,GACvC,CAOAuW,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,OAAOF,MAAMoa,SAAS,IAAImjE,MAAiBr4D,GAC7C,CASA6Y,MAAAA,GACE,MAAMryB,GAAS9L,KAAK+9E,SAAW/9E,KAAK89E,YAAc,IAElD,GAAc,IAAVhyE,EACF,MAAO,CACL,WACA,eACA,iBACA,MACA,GAAG9L,KAAKyjE,SACR,UAEG,CACL,MAAMA,OAAEA,GAAWzjE,KACbunC,EAAQ5yB,GAAiB3U,KAAK89E,YAClCxwB,EAAM34C,GAAiB3U,KAAK+9E,UAC5BG,EAASryE,GAAI07B,GAASk8B,EACtB0a,EAASnyE,GAAIu7B,GAASk8B,EACtB2a,EAAOvyE,GAAIyhD,GAAOmW,EAClB4a,EAAOryE,GAAIshD,GAAOmW,EAGpB,MAAO,CACL,cAAcya,KAAUC,OAAY1a,KAAUA,OAHlC33D,EAAQ,IAAM,EAAI,KAClB9L,KAAK8sB,iBAAmB,EAAI,KAE4CsxD,KAAQC,MAC5F,eACA,QAEJ,CACF,CAgBA,wBAAajsB,CACXt+C,EACA5R,EACAwsD,GAEA,MAAMv8C,KACJA,EAAO,EAACC,IACRA,EAAM,EAACqxD,OACPA,EAAS,KACN6a,GACDrtB,GACFn9C,EACA9T,KAAKsyD,gBACL5D,GAKF,OAAO,IAAI1uD,KAAK,IACXs+E,EACH7a,SACAtxD,KAAMA,EAAOsxD,EACbrxD,IAAKA,EAAMqxD,GAEf,CAOA,iBAAO7qD,CAAsDlJ,GAC3D,OAAOtP,MAAMs4C,YAAoBhpC,EACnC,EACD3P,EA7LY69E,GAAM,OAaH,UAAQ79E,EAbX69E,GAAM,kBAeQ,IAAIt6C,MAAoBq6C,KAAa59E,EAfnD69E,GAAM,cAPmD,CACpEna,OAAQ,EACRqa,WAAY,EACZC,SAAU,IACVjxD,kBAAkB,IAoBsB/sB,EAjB7B69E,GAAM,kBAmJQ,CAAC,KAAM,KAAM,OAAQlwB,KA4ChD/kD,GAAcG,SAAS80E,IACvBj1E,GAAcQ,YAAYy0E,ICrPnB,MAAMW,WAAoBpD,GAS/Br7E,WAAAA,CAAYqD,GACV/C,MAAM+C,GATRpD,eAIQ,IAMNC,KAAK2qB,OAAS,EAChB,CAMA6zD,OAAAA,CAAQ5wD,GACN,MAAM/M,EAAQ7gB,KAAKy+E,SAAS7wD,GAC1B5R,EAAMhc,KAAKmD,OAAOquC,WACpBxxC,KAAKo7E,kBAAkBp/D,GACvBhc,KAAK0+E,IAAI1iE,EAAK6E,GACd7E,EAAI6G,SACN,CAEA67D,GAAAA,CAAI1iE,EAA+B6E,GACjC7E,EAAIsI,UAAYzD,EAAMkD,KACtB/H,EAAIkI,YACJlI,EAAIs+B,IAAIz5B,EAAMxU,EAAGwU,EAAMzU,EAAGyU,EAAM4iD,OAAQ,EAAa,EAAV7+D,KAAK0B,IAAQ,GACxD0V,EAAIqI,YACJrI,EAAI+H,MACN,CAKA+xD,WAAAA,CAAYloD,GACV5tB,KAAK2qB,OAAS,GACd3qB,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKmyC,aACLnyC,KAAKw+E,QAAQ5wD,EACf,CAMAwlB,OAAAA,GACE,MAAMp3B,EAAMhc,KAAKmD,OAAOquC,WACtB7mB,EAAS3qB,KAAK2qB,OAChB3qB,KAAKo7E,kBAAkBp/D,GACvB,IAAK,IAAIvQ,EAAI,EAAGA,EAAIkf,EAAOpqB,OAAQkL,IACjCzL,KAAK0+E,IAAI1iE,EAAK2O,EAAOlf,IAEvBuQ,EAAI6G,SACN,CAMAotD,WAAAA,CAAYriD,IACuB,IAA7B5tB,KAAK88E,qBAAgC98E,KAAKu7E,iBAAiB3tD,KAG3D5tB,KAAKq7E,mBACPr7E,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKy+E,SAAS7wD,GACd5tB,KAAKozC,WAELpzC,KAAKw+E,QAAQ5wD,GAEjB,CAKAooD,SAAAA,GACE,MAAM2I,EAA4B3+E,KAAKmD,OAAOwb,kBAC9C3e,KAAKmD,OAAOwb,mBAAoB,EAEhC,MAAMigE,EAAoB,GAE1B,IAAK,IAAInzE,EAAI,EAAGA,EAAIzL,KAAK2qB,OAAOpqB,OAAQkL,IAAK,CAC3C,MAAMoV,EAAQ7gB,KAAK2qB,OAAOlf,GACxBozE,EAAS,IAAIjB,GAAO,CAClBna,OAAQ5iD,EAAM4iD,OACdtxD,KAAM0O,EAAMxU,EACZ+F,IAAKyO,EAAMzU,EACXihB,QAASvmB,EACTwmB,QAASxmB,EACTid,KAAMlD,EAAMkD,OAGhB/jB,KAAK89B,SAAW+gD,EAAO/gD,OAAS,IAAI8E,GAAO5iC,KAAK89B,SAEhD8gD,EAAQl0E,KAAKm0E,EACf,CACA,MAAMnyC,EAAQ,IAAIupB,GAAM2oB,EAAS,CAAEz7E,OAAQnD,KAAKmD,SAEhDnD,KAAKmD,OAAOkI,KAAK,sBAAuB,CAAEmX,KAAMkqB,IAChD1sC,KAAKmD,OAAOmJ,IAAIogC,GAChB1sC,KAAKmD,OAAOkI,KAAK,eAAgB,CAAEmX,KAAMkqB,IAEzC1sC,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKs7E,eACLt7E,KAAKmD,OAAOwb,kBAAoBggE,EAChC3+E,KAAKmD,OAAO4c,kBACd,CAMA0+D,QAAAA,CAAQv5E,GAAkB,IAAjBmH,EAAEA,EAACD,EAAEA,GAAUlH,EACtB,MAAM45E,EAAiC,CACrCzyE,IACAD,IACAq3D,OAAQZ,GAAaj+D,KAAKC,IAAI,EAAG7E,KAAKqS,MAAQ,IAAKrS,KAAKqS,MAAQ,IAAM,EACtE0R,KAAM,IAAIiV,GAAMh5B,KAAKi5B,OAAOiB,SAAS2oC,GAAa,EAAG,KAAO,KAAKlpC,UAKnE,OAFA35B,KAAK2qB,OAAOjgB,KAAKo0E,GAEVA,CACT,EC3GK,MAAMC,WAAmB5D,GA8C9Br7E,WAAAA,CAAYqD,GACV/C,MAAM+C,GA9CRpD,eAIQ,IAERA,iBAIU,IAEVA,kBAIW,GAEXA,0BAImB,GAEnBA,wBAIgB,GAEhBA,8BAIsB,GAapBC,KAAKg/E,YAAc,GACnBh/E,KAAKi/E,WAAa,EACpB,CAMAnJ,WAAAA,CAAYloD,GACV5tB,KAAKg/E,YAAc,GACnBh/E,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKmyC,aAELnyC,KAAKk/E,cAActxD,GACnB5tB,KAAKm/E,aAAan/E,KAAKi/E,WACzB,CAMAhP,WAAAA,CAAYriD,IACuB,IAA7B5tB,KAAK88E,qBAAgC98E,KAAKu7E,iBAAiB3tD,KAG/D5tB,KAAKk/E,cAActxD,GACnB5tB,KAAKm/E,aAAan/E,KAAKi/E,YACzB,CAKAjJ,SAAAA,GACE,MAAM2I,EAA4B3+E,KAAKmD,OAAOwb,kBAC9C3e,KAAKmD,OAAOwb,mBAAoB,EAEhC,MAAMygE,EAAgB,GAEtB,IAAK,IAAI3zE,EAAI,EAAGA,EAAIzL,KAAKg/E,YAAYz+E,OAAQkL,IAAK,CAChD,MAAMwzE,EAAaj/E,KAAKg/E,YAAYvzE,GACpC,IAAK,IAAI8rC,EAAI,EAAGA,EAAI0nC,EAAW1+E,OAAQg3C,IAAK,CAC1C,MAAM8nC,EAASJ,EAAW1nC,GACpB+nC,EAAO,IAAIxtB,GAAK,CACpBz/C,MAAOgtE,EAAOhtE,MACdC,OAAQ+sE,EAAOhtE,MACfF,KAAMktE,EAAOhzE,EAAI,EACjB+F,IAAKitE,EAAOjzE,EAAI,EAChBihB,QAASvmB,EACTwmB,QAASxmB,EACTid,KAAM/jB,KAAKi5B,QAEbmmD,EAAM10E,KAAK40E,EACb,CACF,CAEA,MAAM5yC,EAAQ,IAAIupB,GAChBj2D,KAAKu/E,oBAvHX,SAAwBH,GACtB,MAAMI,EAAuC,CAAA,EACvCC,EAA2B,GAEjC,IAAK,IAAWl+E,EAAPkK,EAAI,EAAgBA,EAAI2zE,EAAM7+E,OAAQkL,IAC7ClK,EAAM,GAAG69E,EAAM3zE,GAAG0G,OAAOitE,EAAM3zE,GAAG2G,MAC7BotE,EAAYj+E,KACfi+E,EAAYj+E,IAAO,EACnBk+E,EAAiB/0E,KAAK00E,EAAM3zE,KAIhC,OAAOg0E,CACT,CA0GiCC,CAAeN,GAASA,EACnD,CACE37C,eAAe,EACfszB,gBAAgB,EAChB0B,aAAa,IAGjBz4D,KAAK89B,QAAU4O,EAAMnnC,IAAI,SAAU,IAAIq9B,GAAO5iC,KAAK89B,SACnD99B,KAAKmD,OAAOkI,KAAK,sBAAuB,CAAEmX,KAAMkqB,IAChD1sC,KAAKmD,OAAOmJ,IAAIogC,GAChB1sC,KAAKmD,OAAOkI,KAAK,eAAgB,CAAEmX,KAAMkqB,IAEzC1sC,KAAKmD,OAAOke,aAAarhB,KAAKmD,OAAOquC,YACrCxxC,KAAKs7E,eACLt7E,KAAKmD,OAAOwb,kBAAoBggE,EAChC3+E,KAAKmD,OAAO4c,kBACd,CAEAo/D,YAAAA,CAAaQ,GACX,MAAM3jE,EAAMhc,KAAKmD,OAAOquC,WACxBx1B,EAAIsI,UAAYtkB,KAAKi5B,MAErBj5B,KAAKo7E,kBAAkBp/D,GAEvB,IAAK,IAAIvQ,EAAI,EAAGA,EAAIk0E,EAAYp/E,OAAQkL,IAAK,CAC3C,MAAMoV,EAAQ8+D,EAAYl0E,GAC1BuQ,EAAI23B,YAAc9yB,EAAMmc,QACxBhhB,EAAIy3B,SAAS5yB,EAAMxU,EAAGwU,EAAMzU,EAAGyU,EAAMxO,MAAOwO,EAAMxO,MACpD,CAEA2J,EAAI6G,SACN,CAKAuwB,OAAAA,GACE,MAAMp3B,EAAMhc,KAAKmD,OAAOquC,WACxBx1B,EAAIsI,UAAYtkB,KAAKi5B,MAErBj5B,KAAKo7E,kBAAkBp/D,GAEvB,IAAK,IAAIvQ,EAAI,EAAGA,EAAIzL,KAAKg/E,YAAYz+E,OAAQkL,IAC3CzL,KAAKm/E,aAAan/E,KAAKg/E,YAAYvzE,IAErCuQ,EAAI6G,SACN,CAKAq8D,aAAAA,CAActxD,GACZ5tB,KAAKi/E,WAAa,GAClB,MAAMxb,EAASzjE,KAAKqS,MAAQ,EAE5B,IAAK,IAAI5G,EAAI,EAAGA,EAAIzL,KAAK4/E,QAASn0E,IAChCzL,KAAKi/E,WAAWv0E,KAAK,CACnB2B,EAAGw2D,GAAaj1C,EAAQvhB,EAAIo3D,EAAQ71C,EAAQvhB,EAAIo3D,GAChDr3D,EAAGy2D,GAAaj1C,EAAQxhB,EAAIq3D,EAAQ71C,EAAQxhB,EAAIq3D,GAChDpxD,MAAOrS,KAAK6/E,iBACRhd,GAEEj+D,KAAKC,IAAI,EAAG7E,KAAK8/E,SAAW9/E,KAAK6/E,kBACjC7/E,KAAK8/E,SAAW9/E,KAAK6/E,kBAEvB7/E,KAAK8/E,SACT9iD,QAASh9B,KAAK+/E,cAAgBld,GAAa,EAAG,KAAO,IAAM,IAI/D7iE,KAAKg/E,YAAYt0E,KAAK1K,KAAKi/E,WAC7B,ECvMK,MAAMe,WAAqB1D,GAGhCx8E,WAAAA,CAAYqD,GACV/C,MAAM+C,EACR,CAEA88E,aAAAA,GACE,MAEEC,EAAgBrsE,KAChBssE,EAAaD,EAAc98E,WAAW,MAiBxC,OAfA88E,EAAc7tE,MAAQ6tE,EAAc5tE,OAASwtE,GACzCK,IACFA,EAAW77D,UAAYtkB,KAAKi5B,MAC5BknD,EAAWj8D,YACXi8D,EAAW7lC,IACTwlC,GACAA,GACAA,GACA,EACU,EAAVl7E,KAAK0B,IACL,GAEF65E,EAAW97D,YACX87D,EAAWp8D,QAENm8D,CACT,CAMAE,UAAAA,CAAWpkE,GACT,OAAOA,EAAI25B,cAAc31C,KAAKyZ,QAAUzZ,KAAKigF,gBAAiB,SAChE,CAMAtS,eAAAA,CAAgB3xD,GACd5b,MAAMutE,gBAAgB3xD,GACtB,MAAMqkE,EAAUrgF,KAAKogF,WAAWpkE,GAChCqkE,IAAYrkE,EAAIq4B,YAAcgsC,EAChC,CAKAlD,UAAAA,CAAWva,GACT,MAAMpgD,EAAOpiB,MAAM+8E,WAAWva,GAC5B0d,EAAU99D,EAAKotB,oBAAoBnjC,UAAU+V,EAAK6a,YAAc,GAOlE,OALA7a,EAAKqb,OAAS,IAAI48C,GAAQ,CACxBhhE,OAAQzZ,KAAKyZ,QAAUzZ,KAAKigF,gBAC5BvlE,SAAU4lE,EAAQj0E,EAClBkY,SAAU+7D,EAAQl0E,IAEboW,CACT,ECrDF,MAAM+9D,GAAa,CAAC,KAAM,KAAM,KAAM,MAoB/B,MAAMC,WAKH1wC,GAoCRhwC,WAAAA,GAA2E,IAA9D09D,EAAIC,EAAIQ,EAAIC,GAAG59D,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAC,EAAG,EAAG,EAAG,GAAI4B,EAAuB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACrEF,QACAK,OAAOC,OAAOV,KAAMwgF,GAAK9gE,aACzB1f,KAAKgwC,WAAW9tC,GAChBlC,KAAKw9D,GAAKA,EACVx9D,KAAKi+D,GAAKA,EACVj+D,KAAKy9D,GAAKA,EACVz9D,KAAKk+D,GAAKA,EACVl+D,KAAKygF,kBACL,MAAMtuE,KAAEA,EAAIC,IAAEA,GAAQlQ,EACN,iBAATiQ,GAAqBnS,KAAKuF,IAAIwB,EAAMoL,GAC5B,iBAARC,GAAoBpS,KAAKuF,IAAIyB,EAAKoL,EAC3C,CAMAquE,eAAAA,GACE,MAAMjjB,GAAEA,EAAEC,GAAEA,EAAEQ,GAAEA,EAAEC,GAAEA,GAAOl+D,KAC3BA,KAAKqS,MAAQzN,KAAKmH,IAAIkyD,EAAKT,GAC3Bx9D,KAAKsS,OAAS1N,KAAKmH,IAAImyD,EAAKT,GAC5B,MAAMtrD,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GAAWoY,GAA0B,CAC7D,CAAEre,EAAGmxD,EAAIpxD,EAAGqxD,GACZ,CAAEpxD,EAAG4xD,EAAI7xD,EAAG8xD,KAERziD,EAAW,IAAItP,GAAMgG,EAAOE,EAAQ,EAAGD,EAAME,EAAS,GAC5DtS,KAAKgrB,oBAAoBvP,EAAU3U,EAAQA,EAC7C,CAOAqM,IAAAA,CAAK5R,EAAa0C,GAWhB,OAVA7D,MAAM+S,KAAK5R,EAAK0C,GACZs8E,GAAWtvE,SAAS1P,IAOtBvB,KAAKygF,kBAEAzgF,IACT,CAMAozC,OAAAA,CAAQp3B,GACNA,EAAIkI,YAEJ,MAAMnV,EAAI/O,KAAK0gF,iBACf1kE,EAAImI,OAAOpV,EAAEyuD,GAAIzuD,EAAE0uD,IACnBzhD,EAAIoI,OAAOrV,EAAEkvD,GAAIlvD,EAAEmvD,IAEnBliD,EAAI83B,UAAY9zC,KAAKq9B,YAKrB,MAAMsjD,EAAkB3kE,EAAIq4B,YAGrB,IAAAusC,EAFHxmE,GAASpa,KAAK69B,QAChB7hB,EAAIq4B,YAAcr0C,KAAK69B,OAAOvjB,OAAO0B,GAErCA,EAAIq4B,YAAyB,QAAdusC,EAAG5gF,KAAK69B,cAAM,IAAA+iD,EAAAA,EAAI5kE,EAAIsI,UAEvCtkB,KAAK69B,QAAU79B,KAAKs1C,cAAct5B,GAClCA,EAAIq4B,YAAcssC,CACpB,CAQA/qC,sBAAAA,GACE,OAAO,IAAIzpC,IAAOnM,KAAKw9D,GAAKx9D,KAAKi+D,IAAM,GAAIj+D,KAAKy9D,GAAKz9D,KAAKk+D,IAAM,EAClE,CAOA1jD,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAO,IACFF,MAAMoa,SAAS8K,MACftlB,KAAK0gF,iBAEZ,CAMA9xC,4BAAAA,GACE,MAAMP,EAAMjuC,MAAMwuC,+BASlB,MAR2B,SAAvB5uC,KAAKw9B,gBACY,IAAfx9B,KAAKqS,QACPg8B,EAAIjiC,GAAKpM,KAAKq9B,aAEI,IAAhBr9B,KAAKsS,SACP+7B,EAAIhiC,GAAKrM,KAAKq9B,cAGXgR,CACT,CASAqyC,cAAAA,GACE,MAAQljB,GAAIqjB,EAAK5iB,GAAI6iB,EAAKrjB,GAAIsjB,EAAK7iB,GAAI8iB,EAAG3uE,MAAEA,EAAKC,OAAEA,GAAWtS,KACxDihF,EAAQJ,GAAOC,GAAM,EAAK,EAC9BI,EAAQH,GAAOC,GAAM,EAAK,EAM5B,MAAO,CACLxjB,GANMyjB,EAAQ5uE,EAAS,EAOvB4rD,GALMgjB,GAAS5uE,EAAS,EAMxBorD,GAPMyjB,EAAQ5uE,EAAU,EAQxB4rD,GANMgjB,GAAS5uE,EAAU,EAQ7B,CASA6rB,MAAAA,GACE,MAAMq/B,GAAEA,EAAES,GAAEA,EAAER,GAAEA,EAAES,GAAEA,GAAOl+D,KAAK0gF,iBAChC,MAAO,CACL,SACA,eACA,OAAOljB,UAAWC,UAAWQ,UAAWC,UAE5C,CAcA,wBAAa9L,CACXt+C,EACA5R,EACAwsD,GAEA,MAAM8O,GACJA,EAAK,EAACC,GACNA,EAAK,EAACQ,GACNA,EAAK,EAACC,GACNA,EAAK,KACFme,GACDprB,GAAgBn9C,EAAS9T,KAAKsyD,gBAAiB5D,GACnD,OAAO,IAAI1uD,KAAK,CAACw9D,EAAIC,EAAIQ,EAAIC,GAAKme,EACpC,CASA,iBAAOzjE,CAAU1T,GAMX,IANqDs4D,GACzDA,EAAEC,GACFA,EAAEQ,GACFA,EAAEC,GACFA,KACGxuD,GACDxK,EACF,OAAOlF,KAAK04C,YACV,IACKhpC,EACHib,OAAQ,CAAC6yC,EAAIC,EAAIQ,EAAIC,IAEvB,CACEtlB,WAAY,UAGlB,EA9NA74C,EA1BWygF,GAAI,OAgCD,QAAMzgF,EAhCTygF,GAAI,kBAkCU,IAAIl9C,MAAoBi9C,KAAWxgF,EAlCjDygF,GAAI,kBA0MU9yB,GAAkBliD,OAAO+0E,KAiDpD53E,GAAcG,SAAS03E,IACvB73E,GAAcQ,YAAYq3E,ICpRnB,MAAMW,WAKHrxC,GAOR,kBAAOrwB,GACL,MAAO,IAAKrf,MAAMqf,iBAAkB0hE,GAASzhE,YAC/C,CAMA5f,WAAAA,CAAYoC,GACV9B,QACAK,OAAOC,OAAOV,KAAMmhF,GAASzhE,aAC7B1f,KAAKgwC,WAAW9tC,EAClB,CAMAkxC,OAAAA,CAAQp3B,GACN,MAAMolE,EAAWphF,KAAKqS,MAAQ,EAC5BgvE,EAAYrhF,KAAKsS,OAAS,EAE5B0J,EAAIkI,YACJlI,EAAImI,QAAQi9D,EAAUC,GACtBrlE,EAAIoI,OAAO,GAAIi9D,GACfrlE,EAAIoI,OAAOg9D,EAAUC,GACrBrlE,EAAIqI,YAEJrkB,KAAKq1C,oBAAoBr5B,EAC3B,CAOAmiB,MAAAA,GACE,MAAMijD,EAAWphF,KAAKqS,MAAQ,EAC5BgvE,EAAYrhF,KAAKsS,OAAS,EAE5B,MAAO,CAAC,YAAa,eAAgB,WAD1B,IAAI8uE,KAAYC,QAAgBA,KAAaD,KAAYC,IACX,OAC3D,EACDthF,EAtDYohF,GAAQ,OAQL,YAAUphF,EARbohF,GAAQ,cALqD,CACxE9uE,MAAO,IACPC,OAAQ,MA2DV3J,GAAcG,SAASq4E,IACvBx4E,GAAcQ,YAAYg4E,IC1DnB,MAgBDG,GAAgB,CAAC,KAAM,MAEtB,MAAMC,WAKHzxC,GAqBR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACN8hE,GAAQ7hE,YAEf,CAMA5f,WAAAA,CAAYoC,GACV9B,QACAK,OAAOC,OAAOV,KAAMuhF,GAAQ7hE,aAC5B1f,KAAKgwC,WAAW9tC,EAClB,CAQAiR,IAAAA,CAAK5R,EAAa0C,GAEhB,OADA7D,MAAM+S,KAAK5R,EAAK0C,GACR1C,GACN,IAAK,KACHvB,KAAKgyD,GAAK/tD,EACVjE,KAAKuF,IAAI,QAAiB,EAARtB,GAClB,MAEF,IAAK,KACHjE,KAAKiyD,GAAKhuD,EACVjE,KAAKuF,IAAI,SAAkB,EAARtB,GAGvB,OAAOjE,IACT,CAMAwhF,KAAAA,GACE,OAAOxhF,KAAKyF,IAAI,MAAQzF,KAAKyF,IAAIsC,EACnC,CAMA05E,KAAAA,GACE,OAAOzhF,KAAKyF,IAAI,MAAQzF,KAAKyF,IAAIuC,EACnC,CAOAwS,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,OAAOF,MAAMoa,SAAS,IAAI8mE,MAAkBh8D,GAC9C,CAOA6Y,MAAAA,GACE,MAAO,CACL,YACA,eACA,qBAAqBn+B,KAAKgyD,WAAWhyD,KAAKiyD,WAE9C,CAMA7e,OAAAA,CAAQp3B,GACNA,EAAIkI,YACJlI,EAAI2G,OACJ3G,EAAIhN,UAAU,EAAG,EAAG,EAAGhP,KAAKiyD,GAAKjyD,KAAKgyD,GAAI,EAAG,GAC7Ch2C,EAAIs+B,IAAI,EAAG,EAAGt6C,KAAKgyD,GAAI,EAAGxrD,GAAW,GACrCwV,EAAI6G,UACJ7iB,KAAKq1C,oBAAoBr5B,EAC3B,CAeA,wBAAao2C,CACXt+C,EACA5R,EACAwsD,GAEA,MAAM2tB,EAAmBprB,GACvBn9C,EACA9T,KAAKsyD,gBACL5D,GAKF,OAFA2tB,EAAiBlqE,MAAQkqE,EAAiBlqE,MAAQ,GAAKkqE,EAAiBrqB,GACxEqqB,EAAiBjqE,KAAOiqE,EAAiBjqE,KAAO,GAAKiqE,EAAiBpqB,GAC/D,IAAIjyD,KAAKq8E,EAClB,EApIAt8E,EAdWwhF,GAAO,OAoBJ,WAASxhF,EApBZwhF,GAAO,kBAsBO,IAAIj+C,MAAoBg+C,KAAcvhF,EAtBpDwhF,GAAO,cAlBoD,CACtEvvB,GAAI,EACJC,GAAI,IAwCqClyD,EAxB9BwhF,GAAO,kBA6HO,IAAI7zB,GAAmB,KAAM,KAAM,KAAM,OA0BpE/kD,GAAcG,SAASy4E,IACvB54E,GAAcQ,YAAYo4E,ICxJnB,MAAMG,GAA6D,CAIxEC,kBAAkB,GAOb,MAAMC,WAIH9xC,GAwBR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNmiE,GAASliE,YAEhB,CA4CA5f,WAAAA,GAA6D,IAAjD6qB,EAAYrqB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAAI4B,EAAc5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC9CF,QAAQL,EAAAC,KAAA,kBAAA,GACRS,OAAOC,OAAOV,KAAM4hF,GAASliE,aAC7B1f,KAAKgwC,WAAW9tC,GAChBlC,KAAK2qB,OAASA,EACd,MAAMxY,KAAEA,EAAIC,IAAEA,GAAQlQ,EACtBlC,KAAK6hF,aAAc,EACnB7hF,KAAK27E,gBAAe,GACJ,iBAATxpE,GAAqBnS,KAAKuF,IAAIwB,EAAMoL,GAC5B,iBAARC,GAAoBpS,KAAKuF,IAAIyB,EAAKoL,EAC3C,CAEU0vE,MAAAA,GACR,OAAO,CACT,CAEQC,sBAAAA,CAAuB7/E,GAC7B,OAAO4oD,GAAsB9qD,KAAK2qB,OAAQzoB,EAASlC,KAAK8hF,SAC1D,CAMA5F,eAAAA,CAAgBh6E,GACdA,EAAU,CACRgU,OAAQlW,KAAKkW,OACbC,OAAQnW,KAAKmW,OACbC,MAAOpW,KAAKoW,MACZC,MAAOrW,KAAKqW,MACZmnB,cAAex9B,KAAKw9B,cACpBC,eAAgBz9B,KAAKy9B,eACrBC,iBAAkB19B,KAAK09B,iBACvBoB,cAAe9+B,KAAK8+B,cACpBzB,YAAar9B,KAAKq9B,eACdn7B,GAAW,CAAA,GAEjB,MAAMyoB,EAAS3qB,KAAK2hF,iBAChB3hF,KAAK+hF,uBACH7/E,GACAyW,IAAK+xC,GAAeA,EAAWH,gBACjCvqD,KAAK2qB,OACT,GAAsB,IAAlBA,EAAOpqB,OACT,MAAO,CACL4R,KAAM,EACNC,IAAK,EACLC,MAAO,EACPC,OAAQ,EACR8xD,WAAY,IAAIj4D,GAChB6+D,aAAc,IAAI7+D,GAClB61E,WAAY,IAAI71E,IAGpB,MAAMmf,EAAOZ,GAA0BC,GAErCrT,EAASH,GAAqB,IAAKjV,EAASgU,OAAQ,EAAGC,OAAQ,IAC/D8rE,EAAev3D,GACb1qB,KAAK2qB,OAAOhS,IAAK5J,GAAMkG,GAAelG,EAAGuI,GAAQ,KAEnD6E,EAAQ,IAAIhQ,GAAMnM,KAAKkW,OAAQlW,KAAKmW,QACtC,IAAIuE,EAAU4Q,EAAKnZ,KAAOmZ,EAAKjZ,MAAQ,EACrCkS,EAAU+G,EAAKlZ,IAAMkZ,EAAKhZ,OAAS,EAQrC,OAPItS,KAAK2hF,mBACPjnE,GAAoB6J,EAAU3f,KAAKmS,IAAIpC,GAAiB3U,KAAKoW,QAG7DmO,GAAoB7J,EAAU9V,KAAKmS,IAAIpC,GAAiB3U,KAAKqW,SAGxD,IACFiV,EACH84C,WAAY,IAAIj4D,GAAMuO,EAAS6J,GAC/BymD,aAAc,IAAI7+D,GAAM81E,EAAa9vE,KAAM8vE,EAAa7vE,KACrDxF,SAAS,IAAIT,GAAMmf,EAAKnZ,KAAMmZ,EAAKlZ,MACnCpF,SAASmP,GACZ6lE,WAAY,IAAI71E,GAAMmf,EAAKjZ,MAAOiZ,EAAKhZ,QACpC1F,SAAS,IAAIT,GAAM81E,EAAa5vE,MAAO4vE,EAAa3vE,SACpDtF,SAASmP,GAEhB,CAQAy5B,sBAAAA,GACE,MAAMtqB,EAAOZ,GAA0B1qB,KAAK2qB,QAC5C,OAAO,IAAIxe,GAAMmf,EAAKnZ,KAAOmZ,EAAKjZ,MAAQ,EAAGiZ,EAAKlZ,IAAMkZ,EAAKhZ,OAAS,EACxE,CAEA4K,aAAAA,GACEld,KAAK27E,gBACP,CAEAA,cAAAA,CAAeD,GACb,MAAMvpE,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,EAAM8xD,WAAEA,EAAU4G,aAAEA,EAAYgX,WAAEA,GAC1DhiF,KAAKk8E,kBACPl8E,KAAKuF,IAAI,CAAE8M,QAAOC,SAAQ8xD,aAAY4G,eAAcgX,eACpDtG,GACE17E,KAAKgrB,oBACH,IAAI7e,GAAMgG,EAAOE,EAAQ,EAAGD,EAAME,EAAS,GAC3CxL,EACAA,EAEN,CAKU8lC,gCAAAA,GACR,OAAO5sC,KAAK2hF,gBACd,CAKA/yC,4BAAAA,GACE,OAAO5uC,KAAK2hF,iBAER,IAAIx1E,GAAMnM,KAAKqS,MAAOrS,KAAKsS,QAC3BlS,MAAMwuC,8BACZ,CASApB,yBAAAA,GAA6C,IAAnBtrC,EAAY5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACvC,GAAIN,KAAK2hF,iBAAkB,CACzB,IAAI7xE,EAKJ,GACErP,OAAOU,KAAKe,GAASgP,KAClB3P,GACCvB,KAAK8+B,eACJ9+B,KAAKF,YAAgCoiF,iBAAiBjxE,SACrD1P,IAGN,CAAA,IAAA4gF,EAAAC,EACA,MAAM/vE,MAAEA,EAAKC,OAAEA,GAAWtS,KAAKk8E,gBAAgBh6E,GAC/C4N,EAAO,IAAI3D,GAAmB,QAAdg2E,EAACjgF,EAAQmQ,aAAK,IAAA8vE,EAAAA,EAAI9vE,EAAqB,QAAhB+vE,EAAElgF,EAAQoQ,cAAM,IAAA8vE,EAAAA,EAAI9vE,EAC7D,KAAO,CAAA,IAAA+vE,EAAAC,EACLxyE,EAAO,IAAI3D,GACI,QADCk2E,EACdngF,EAAQmQ,aAAK,IAAAgwE,EAAAA,EAAIriF,KAAKqS,MACR,QADaiwE,EAC3BpgF,EAAQoQ,cAAM,IAAAgwE,EAAAA,EAAItiF,KAAKsS,OAE3B,CACA,OAAOxC,EAAK9C,SACV,IAAIb,GAAMjK,EAAQgU,QAAUlW,KAAKkW,OAAQhU,EAAQiU,QAAUnW,KAAKmW,QAEpE,CACE,OAAO/V,MAAMotC,0BAA0BtrC,EAE3C,CAMAiR,IAAAA,CAAK5R,EAAa0C,GAChB,MAAMk9C,EAAUnhD,KAAK6hF,aAAe7hF,KAAKuB,KAAuB0C,EAC1Ds+E,EAASniF,MAAM+S,KAAK5R,EAAK0C,GAe/B,OAbEjE,KAAK2hF,kBACLxgC,KACG5/C,IAAQwG,GAAWxG,IAAQyG,IAC5BhI,KAAK8+B,eACJ9+B,KAAKF,YAAgCoiF,iBAAiBjxE,SACrD,kBAEDjR,KAAKF,YAAgCoiF,iBAAiBjxE,SACrD1P,KAGJvB,KAAKkd,gBAEAqlE,CACT,CAOA/nE,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAO,IACFF,MAAMoa,SAAS8K,GAClBqF,OAAQ3qB,KAAK2qB,OAAOhS,IAAIzT,IAAA,IAACmH,EAAEA,EAACD,EAAEA,GAAGlH,EAAA,MAAM,CAAEmH,IAAGD,OAEhD,CAOA+xB,MAAAA,GACE,MAAMxT,EAAS,GACb63D,EAAQxiF,KAAKokE,WAAW/3D,EACxBo2E,EAAQziF,KAAKokE,WAAWh4D,EACxB8N,EAAsB/Z,EAAO+Z,oBAE/B,IAAK,IAAIzO,EAAI,EAAGmY,EAAM5jB,KAAK2qB,OAAOpqB,OAAQkL,EAAImY,EAAKnY,IACjDkf,EAAOjgB,KACLkP,GAAQ5Z,KAAK2qB,OAAOlf,GAAGY,EAAIm2E,EAAOtoE,GAClC,IACAN,GAAQ5Z,KAAK2qB,OAAOlf,GAAGW,EAAIq2E,EAAOvoE,GAClC,KAGJ,MAAO,CACL,IACGla,KAAKF,YAAgCkJ,KAAK3D,iBAI7C,eACA,WAAWslB,EAAOxQ,KAAK,YAE3B,CAMAi5B,OAAAA,CAAQp3B,GACN,MAAM4H,EAAM5jB,KAAK2qB,OAAOpqB,OACtB8L,EAAIrM,KAAKokE,WAAW/3D,EACpBD,EAAIpM,KAAKokE,WAAWh4D,EAEtB,GAAKwX,IAAO0oC,MAAMtsD,KAAK2qB,OAAO/G,EAAM,GAAGxX,GAAvC,CAKA4P,EAAIkI,YACJlI,EAAImI,OAAOnkB,KAAK2qB,OAAO,GAAGte,EAAIA,EAAGrM,KAAK2qB,OAAO,GAAGve,EAAIA,GACpD,IAAK,IAAIX,EAAI,EAAGA,EAAImY,EAAKnY,IAAK,CAC5B,MAAMoV,EAAQ7gB,KAAK2qB,OAAOlf,GAC1BuQ,EAAIoI,OAAOvD,EAAMxU,EAAIA,EAAGwU,EAAMzU,EAAIA,EACpC,EACCpM,KAAK8hF,UAAY9lE,EAAIqI,YACtBrkB,KAAKq1C,oBAAoBr5B,EARzB,CASF,CAMA5K,UAAAA,GACE,OAAOpR,KAAK2qB,OAAOpqB,MACrB,CAeA,wBAAa6xD,CACXt+C,EACA5R,EACAwsD,GAEA,MAAM/jC,ECxYH,SAA8BA,GAEnC,IAAKA,EACH,MAAO,GAIT,MAAM+3D,EAAwB/3D,EAAOgE,QAAQ,KAAM,KAAK4N,OAAOf,MAAM,OAE/DmnD,EAAe,GAErB,IAAK,IAAIl3E,EAAI,EAAGA,EAAIi3E,EAAYniF,OAAQkL,GAAK,EAC3Ck3E,EAAaj4E,KAAK,CAChB2B,EAAG0N,WAAW2oE,EAAYj3E,IAC1BW,EAAG2N,WAAW2oE,EAAYj3E,EAAI,MAQlC,OAAOk3E,CACT,CDiXmBC,CAAqB9uE,EAAQi6C,aAAa,YAGvD57C,KAAEA,EAAIC,IAAEA,KAAQiqE,GAAqBprB,GACnCn9C,EACA9T,KAAKsyD,gBACL5D,GAEJ,OAAO,IAAI1uD,KAAK2qB,EAAQ,IACnB0xD,KACAn6E,GAEP,CASA,iBAAO0W,CAAwDlJ,GAC7D,OAAO1P,KAAK04C,YAAsBhpC,EAAQ,CACxCkpC,WAAY,UAEhB,EAtXA74C,EAXW6hF,GAAQ,cAwBEF,IAAqB3hF,EAxB/B6hF,GAAQ,OA0BL,YAAU7hF,EA1Bb6hF,GAAQ,mBAuC2B,CAC5C35E,EACAC,EACA,gBACA,iBACA,mBACA,cACA,gBACA,WACDnI,EAhDU6hF,GAAQ,kBAsDM,IAAIt+C,GAAiB,WAASvjC,EAtD5C6hF,GAAQ,kBA4VM,IAAIl0B,KAwC/B/kD,GAAcG,SAAS84E,IACvBj5E,GAAcQ,YAAYy4E,IEzanB,MAAMiB,WAAgBjB,GAKjBE,MAAAA,GACR,OAAO,CACT,EACD/hF,EARY8iF,GAAO,cACGnB,IAAqB3hF,EAD/B8iF,GAAO,OAGJ,WAOhBl6E,GAAcG,SAAS+5E,IACvBl6E,GAAcQ,YAAY05E,ICOnB,MAAeC,WAIZhzC,GAeRizC,aAAAA,CAAcC,GACZ,IAAKhjF,KAAK0nB,OACR,OAAO,EAET,QAAyB,IAAds7D,IAA8BhjF,KAAK0nB,OAAOs7D,GACnD,OAAO,EAET,MAAM7xE,OACiB,IAAd6xE,EACHhjF,KAAK0nB,OACL,CAAEu7D,KAAMjjF,KAAK0nB,OAAOs7D,IAC1B,IAAK,MAAM3gB,KAAMlxD,EACf,IAAK,MAAMmxD,KAAMnxD,EAAIkxD,GACnB,IAAK,MAAM6gB,KAAM/xE,EAAIkxD,GAAIC,GACvB,OAAO,EAIb,OAAO,CACT,CASA6gB,QAAAA,CAAS9vE,EAAsC2vE,GAC7C,IAAKhjF,KAAK0nB,OACR,OAAO,EAET,QAAyB,IAAds7D,IAA8BhjF,KAAK0nB,OAAOs7D,GACnD,OAAO,EAET,MAAM7xE,OACiB,IAAd6xE,EACHhjF,KAAK0nB,OACL,CAAE,EAAG1nB,KAAK0nB,OAAOs7D,IACvB,IAAK,MAAM3gB,KAAMlxD,EACf,IAAK,MAAMmxD,KAAMnxD,EAAIkxD,GACnB,QAAqC,IAA1BlxD,EAAIkxD,GAAIC,GAAIjvD,GACrB,OAAO,EAIb,OAAO,CACT,CAUA+vE,UAAAA,CAAW/vE,GACT,IAAKrT,KAAK0nB,OACR,OAAO,EAET,MAAMvW,EAAMnR,KAAK0nB,OACjB,IACE27D,EACAC,EAFEC,EAAc,EAGhBC,GAAgC,EAChCC,EAAgB,EAClB,IAAK,MAAMphB,KAAMlxD,EAAK,CACpBkyE,EAAc,EACd,IAAK,MAAM/gB,KAAMnxD,EAAIkxD,GAAK,CACxB,MAAMqhB,EAAcvyE,EAAIkxD,GAAIC,IAAO,CAAA,EAGnCihB,SAFsD/iF,IAA1BkjF,EAAYrwE,IAKjCiwE,EAEMI,EAAYrwE,KAAciwE,IACnCE,GAAgC,GAFhCF,EAAqBI,EAAYrwE,GAK/BqwE,EAAYrwE,KAAcrT,KAAKqT,WAC1BqwE,EAAYrwE,IAGrBmwE,GAAgC,EAGM,IAApC/iF,OAAOU,KAAKuiF,GAAanjF,OAC3B8iF,WAEOlyE,EAAIkxD,GAAIC,EAEnB,CAEoB,IAAhB+gB,UACKlyE,EAAIkxD,EAEf,CAGA,IAAK,IAAI52D,EAAI,EAAGA,EAAIzL,KAAK2jF,WAAWpjF,OAAQkL,IAC1Cg4E,GAAiBzjF,KAAK2jF,WAAWl4E,GAAGlL,OAElCijF,GAAiCD,IAAgBE,IACnDzjF,KAAKqT,GAA0BiwE,EAC/BtjF,KAAK4jF,YAAYvwE,GAErB,CASAuwE,WAAAA,CAAYvwE,GACV,IAAKrT,KAAK0nB,OACR,OAEF,MAAMvW,EAAMnR,KAAK0nB,OACjB,IAAIu7D,EAAMY,EAASC,EACnB,IAAKD,KAAW1yE,EAAK,CAEnB,IAAK2yE,KADLb,EAAO9xE,EAAI0yE,GACKZ,SACPA,EAAKa,GAASzwE,GACqB,IAAtC5S,OAAOU,KAAK8hF,EAAKa,IAAUvjF,eACtB0iF,EAAKa,GAGiB,IAA7BrjF,OAAOU,KAAK8hF,GAAM1iF,eACb4Q,EAAI0yE,EAEf,CACF,CAEQE,aAAAA,CAAcz6E,EAAekS,GACnC,MAAMwnE,UAAEA,EAAS51B,UAAEA,GAAcptD,KAAKgkF,oBAAoB16E,GAErDtJ,KAAKikF,cAAcjB,IACtBhjF,KAAKkkF,cAAclB,GAGrB,MAAMmB,EAAWzqE,GACf,IAEK1Z,KAAKokF,qBAAqBpB,EAAW51B,MACrC5xC,GAGJvX,QAAoBzD,IAAVyD,GAIbjE,KAAKqkF,qBAAqBrB,EAAW51B,EAAW+2B,EAClD,CASAG,kBAAAA,CACEC,EACAC,EACA3J,GAEA,MAAMnzD,EAAiC,GACvC,IAAK,IAAIjc,EAAI84E,EAAY94E,GAAK+4E,GAAYD,GAAa94E,IACrDic,EAAOhd,KAAK1K,KAAKykF,mBAAmBh5E,EAAGovE,IAEzC,OAAOnzD,CACT,CASA+8D,kBAAAA,CAAmBhpE,EAAkBo/D,GACnC,MAAMmI,UAAEA,EAAS51B,UAAEA,GAAcptD,KAAKgkF,oBAAoBvoE,GAC1D,OAAOo/D,EACH76E,KAAK0kF,4BAA4B1B,EAAW51B,GAC5CptD,KAAKokF,qBAAqBpB,EAAW51B,EAC3C,CAQAu3B,kBAAAA,CAAmBj9D,EAAgB68D,EAAoBC,GACrD,IAAK,IAAI/4E,EAAI84E,EAAY94E,GAAK+4E,GAAYD,GAAa94E,IACrDzL,KAAK+jF,cAAct4E,EAAGic,GAGxB1nB,KAAK4kF,kBAAmB,CAC1B,CAaAR,oBAAAA,CACEpB,EACA51B,GACsB,IAAAy3B,EACtB,MAAMC,EAAY9kF,KAAK0nB,QAAU1nB,KAAK0nB,OAAOs7D,GAC7C,OAAO8B,GAAiC,QAAxBD,EAAIC,EAAU13B,cAAUy3B,EAAAA,EAAU,CAAA,CACpD,CASAH,2BAAAA,CACE1B,EACA51B,GAEA,MAAO,IACF5zC,GACDxZ,KACCA,KAAKF,YACHilF,qBAEF/kF,KAAKokF,qBAAqBpB,EAAW51B,GAE5C,CAQUi3B,oBAAAA,CACRrB,EACA51B,EACA5xC,GAEAxb,KAAK0nB,OAAOs7D,GAAW51B,GAAa5xC,CACtC,CAQUwpE,uBAAAA,CAAwBhC,EAAmB51B,UAC5CptD,KAAK0nB,OAAOs7D,GAAW51B,EAChC,CAOU62B,aAAAA,CAAcjB,GACtB,QAAShjF,KAAK0nB,OAAOs7D,EACvB,CAOUkB,aAAAA,CAAclB,GACtBhjF,KAAK0nB,OAAOs7D,GAAa,CAAA,CAC3B,CAEUiC,gBAAAA,CAAiBjC,UAClBhjF,KAAK0nB,OAAOs7D,EACrB,EACDjjF,EAtTqB+iF,GAAU,mBAQ6BljD,ICb7D,MAAMslD,GAAsB,OACtBC,GAAgB,KAEtB,SAASC,GACPnsD,EACA9mB,EACAC,EACAC,EACAC,GAEA,MAAO,OpGkIoB,SAC3B2mB,EAAa/zB,GAGV,IAFHiN,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GAAepN,EACnCzC,EAASnC,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGH,EAAO+Z,oBAEnB,MAAMmrE,EAAWzoD,GAAez0B,EAAM8wB,GAAO,IACtC5sB,EAAGD,EAAGkiC,EAAGhW,GAAK,CAACnmB,EAAMC,EAAKC,EAAOC,GAAQqG,IAAK1U,GACnD2V,GAAQ3V,EAAOxB,IAEjB,MAAO,SAAS4iF,QAAeh5E,SAASD,aAAakiC,cAAchW,YACrE,CoG5IgBgtD,CAAcrsD,EAAO,CAAE9mB,OAAMC,MAAKC,QAAOC,cACzD,CCyBA,IAAIizE,GAwFG,MAAMC,WAKH1C,GAyRR,kBAAOrjE,GACL,MAAO,IAAKrf,MAAMqf,iBAAkB+lE,GAAW9lE,YACjD,CAEA5f,WAAAA,CAAYmtD,EAAc/qD,GACxB9B,QArDFL,sBAMiC,IAgD/BU,OAAOC,OAAOV,KAAMwlF,GAAW9lE,aAC/B1f,KAAKgwC,WAAW9tC,GACXlC,KAAK0nB,SACR1nB,KAAK0nB,OAAS,CAAA,GAEhB1nB,KAAKitD,KAAOA,EACZjtD,KAAK6hF,aAAc,EACf7hF,KAAKwiB,MACPxiB,KAAKylF,cAEPzlF,KAAK0lF,iBACL1lF,KAAKggB,WACP,CAMAylE,WAAAA,GACE,MAAMjjE,EAAOxiB,KAAKwiB,KACdA,IACFA,EAAKmjE,aAAellB,GAAoBj+C,EAAKA,MAEjD,CAMAojE,UAAAA,GACE,MAAMC,EAAW7lF,KAAK8lF,oBAAoB9lF,KAAKitD,MAK/C,OAJAjtD,KAAKktD,UAAY24B,EAASE,MAC1B/lF,KAAK2jF,WAAakC,EAASG,cAC3BhmF,KAAKimF,oBAAsBJ,EAASK,gBACpClmF,KAAKmmF,MAAQN,EAASO,aACfP,CACT,CAOAH,cAAAA,GACE1lF,KAAK4lF,aACL5lF,KAAKqmF,cACLrmF,KAAK6jC,OAAQ,EACT7jC,KAAKwiB,MACPxiB,KAAKqS,MAAQrS,KAAKwiB,KAAKnQ,MACvBrS,KAAKsS,OAAStS,KAAKwiB,KAAKlQ,SAExBtS,KAAKqS,MACHrS,KAAKsmF,iBAAmBtmF,KAAKumF,aAAevmF,KAAK+gC,eACnD/gC,KAAKsS,OAAStS,KAAKwmF,kBAEjBxmF,KAAKqgC,UAAUpvB,SAASqwB,KAE1BthC,KAAKymF,eAET,CAKAA,aAAAA,GACE,IAAIC,EACFC,EACAC,EACAC,EACA5D,EACA6D,EACAC,EACF,IAAK,IAAIt7E,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IACrD,IACEzL,KAAKqgC,YAAciB,IAClB71B,IAAMmY,EAAM,IAAK5jB,KAAKgnF,gBAAgBv7E,MAIzCo7E,EAAmB,EACnB5D,EAAOjjF,KAAK2jF,WAAWl4E,GACvBk7E,EAAmB3mF,KAAKinF,aAAax7E,GAEnCk7E,EAAmB3mF,KAAKqS,QACvB00E,EAAS/mF,KAAKktD,UAAUzhD,GAAGwvB,MAAMj7B,KAAK+/B,oBACvC,CACA6mD,EAAiBG,EAAOxmF,OACxBmmF,GAAa1mF,KAAKqS,MAAQs0E,GAAoBC,EAC9C,IAAK,IAAIrvC,EAAI,EAAGA,GAAK0rC,EAAK1iF,OAAQg3C,IAChCuvC,EAAY9mF,KAAKknF,aAAaz7E,GAAG8rC,GAC7Bv3C,KAAKggC,eAAewvB,KAAKyzB,EAAK1rC,KAChCuvC,EAAUz0E,OAASq0E,EACnBI,EAAUK,aAAeT,EACzBI,EAAU30E,MAAQ00E,EAClBA,GAAoBH,GAEpBI,EAAU30E,MAAQ00E,CAGxB,CAEJ,CAOAG,eAAAA,CAAgBhE,GACd,OAAOA,IAAchjF,KAAK2jF,WAAWpjF,OAAS,CAChD,CASA6mF,oBAAAA,CAAqBC,GACnB,OAAO,CACT,CAOArD,mBAAAA,CAAoBsD,EAAwBC,GAC1C,MAAMxB,EAAQwB,EAAevnF,KAAKimF,oBAAsBjmF,KAAK2jF,WAC7D,IAAIl4E,EACJ,IAAKA,EAAI,EAAGA,EAAIs6E,EAAMxlF,OAAQkL,IAAK,CACjC,GAAI67E,GAAkBvB,EAAMt6E,GAAGlL,OAC7B,MAAO,CACLyiF,UAAWv3E,EACX2hD,UAAWk6B,GAGfA,GACEvB,EAAMt6E,GAAGlL,OAASP,KAAKonF,qBAAqB37E,EAAG87E,EACnD,CACA,MAAO,CACLvE,UAAWv3E,EAAI,EACf2hD,UACE24B,EAAMt6E,EAAI,GAAGlL,OAAS+mF,EAClBvB,EAAMt6E,EAAI,GAAGlL,OACb+mF,EAEV,CAMAp5E,QAAAA,GACE,MAAO,WAAWlO,KAAKoR,6BACrBpR,KAAKitD,yBACcjtD,KAAKgB,gBAC5B,CAaA2vC,yBAAAA,GACE,MAAMN,EAAOjwC,MAAMuwC,4BACb7U,EAAW97B,KAAK87B,SAGtB,OAFAuU,EAAKh+B,OAASypB,EAAWuU,EAAK/sB,MAC9B+sB,EAAK/9B,QAAUwpB,EAAWuU,EAAK9sB,MACxB8sB,CACT,CAMA+C,OAAAA,CAAQp3B,GACN,MAAMwG,EAAOxiB,KAAKwiB,KAClBA,IAASA,EAAKuvB,gBAAkBvvB,EAAK4wB,QAAQp3B,GAC7Chc,KAAKwnF,eAAexrE,GACpBhc,KAAKynF,2BAA2BzrE,GAChChc,KAAK0nF,sBAAsB1rE,EAAK,aAChChc,KAAKynB,YAAYzL,GACjBhc,KAAK0nF,sBAAsB1rE,EAAK,YAChChc,KAAK0nF,sBAAsB1rE,EAAK,cAClC,CAMAyL,WAAAA,CAAYzL,GACNhc,KAAKm/B,aAAe/2B,GACtBpI,KAAK2nF,kBAAkB3rE,GACvBhc,KAAK4nF,gBAAgB5rE,KAErBhc,KAAK4nF,gBAAgB5rE,GACrBhc,KAAK2nF,kBAAkB3rE,GAE3B,CAYAwrE,cAAAA,CACExrE,EACA6rE,EACAC,GAGA,GADA9rE,EAAI+rE,aAAe,aACf/nF,KAAKwiB,KACP,OAAQxiB,KAAK0gC,WACX,KAAK55B,EACHkV,EAAI+rE,aAAe,SACnB,MACF,IAAK,WACH/rE,EAAI+rE,aAAe/gF,EACnB,MACF,IAAK,YACHgV,EAAI+rE,aAAe9gF,EAIzB+U,EAAIw1C,KAAOxxD,KAAKgoF,oBAAoBH,EAAWC,EACjD,CAQAxB,aAAAA,GACE,IAAI2B,EAAWjoF,KAAKinF,aAAa,GAEjC,IAAK,IAAIx7E,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IAAK,CAC1D,MAAMk7E,EAAmB3mF,KAAKinF,aAAax7E,GACvCk7E,EAAmBsB,IACrBA,EAAWtB,EAEf,CACA,OAAOsB,CACT,CAWAC,eAAAA,CACErwB,EACA77C,EACAinE,EACA9wE,EACAC,EACA4wE,GAEAhjF,KAAKmoF,aAAatwB,EAAQ77C,EAAKinE,EAAM9wE,EAAMC,EAAK4wE,EAClD,CAOAyE,0BAAAA,CAA2BzrE,GACzB,IAAKhc,KAAKugC,sBAAwBvgC,KAAKmjF,SAAS,uBAC9C,OAEF,MAAMlwC,EAAej3B,EAAIsI,UACvB8jE,EAAapoF,KAAKqoF,iBACpB,IAAIC,EAAgBtoF,KAAKuoF,gBAEzB,IAAK,IAAI98E,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IAAK,CAC1D,MAAM+8E,EAAexoF,KAAKyoF,gBAAgBh9E,GAC1C,IACGzL,KAAKugC,sBACLvgC,KAAKmjF,SAAS,sBAAuB13E,GACtC,CACA68E,GAAiBE,EACjB,QACF,CACA,MAAM9sB,EAAO17D,KAAK2jF,WAAWl4E,GAAGlL,OAC1BmoF,EAAiB1oF,KAAK2oF,mBAAmBl9E,GAC/C,IAEIm9E,EACAC,EAHAC,EAAW,EACXC,EAAW,EAGXC,EAAYhpF,KAAKipF,qBAAqBx9E,EAAG,EAAG,uBAChD,MAAMy9E,EAAWlpF,KAAKmpF,oBAAoB19E,GAC1C,IAAK,IAAI8rC,EAAI,EAAGA,EAAImkB,EAAMnkB,IAAK,CAE7B,MAAM6xC,EAAUppF,KAAKknF,aAAaz7E,GAAG8rC,GACrCsxC,EAAe7oF,KAAKipF,qBAAqBx9E,EAAG8rC,EAAG,uBAC3Cv3C,KAAKwiB,MACPxG,EAAI2G,OACJ3G,EAAIs1B,UAAU83C,EAAQC,WAAYD,EAAQpgB,WAC1ChtD,EAAIvN,OAAO26E,EAAQt9E,OACnBkQ,EAAIsI,UAAYukE,EAChBA,GACE7sE,EAAIy3B,UACD21C,EAAQ/2E,MAAQ,GAChB62E,GAAY,EAAIlpF,KAAKmhC,mBACtBioD,EAAQ/2E,MACR62E,GAEJltE,EAAI6G,WACKgmE,IAAiBG,GAC1BJ,EAAYR,EAAaM,EAAiBK,EACtC/oF,KAAK6gC,YAAct4B,IACrBqgF,EAAY5oF,KAAKqS,MAAQu2E,EAAYE,GAEvC9sE,EAAIsI,UAAY0kE,EAChBA,GACEhtE,EAAIy3B,SAASm1C,EAAWN,EAAeQ,EAAUI,GACnDH,EAAWK,EAAQj3E,KACnB22E,EAAWM,EAAQ/2E,MACnB22E,EAAYH,GAEZC,GAAYM,EAAQjC,WAExB,CACI0B,IAAiB7oF,KAAKwiB,OACxBomE,EAAYR,EAAaM,EAAiBK,EACtC/oF,KAAK6gC,YAAct4B,IACrBqgF,EAAY5oF,KAAKqS,MAAQu2E,EAAYE,GAEvC9sE,EAAIsI,UAAYukE,EAChB7sE,EAAIy3B,SAASm1C,EAAWN,EAAeQ,EAAUI,IAEnDZ,GAAiBE,CACnB,CACAxsE,EAAIsI,UAAY2uB,EAGhBjzC,KAAK0zC,cAAc13B,EACrB,CAYAstE,YAAAA,CACEC,EACA1B,EACA2B,EACAC,GAEA,MAAMjkF,EAAYV,EAAMG,aAAa4iF,GACnC6B,EAAkB1pF,KAAKgoF,oBAAoBH,GAC3C8B,EAASH,EAAeA,EAAeD,EAAQA,EAC/CK,EACEJ,GACAE,IAAoB1pF,KAAKgoF,oBAAoByB,GAC/CI,EAAiBhC,EAAU/rD,SAAW97B,KAAK8gC,gBAC7C,IAAIzuB,EACFy3E,EACAC,EACA5C,EAYF,GAVIqC,GAAgBhkF,EAAUF,IAAIkkF,KAChCO,EAAgBvkF,EAAUC,IAAI+jF,IAE5BhkF,EAAUF,IAAIikF,KAChBpC,EAAc90E,EAAQ7M,EAAUC,IAAI8jF,IAElCK,GAAkBpkF,EAAUF,IAAIqkF,KAClCG,EAActkF,EAAUC,IAAIkkF,GAC5BxC,EAAc2C,EAAcC,QAGlBvpF,IAAV6R,QACkB7R,IAAlBupF,QACgBvpF,IAAhBspF,EACA,CACA,MAAM9tE,EArwBZ,WACE,IAAKupE,GAAkB,CACrB,MAAMpiF,EAAS8Q,GAAuB,CACpC5B,MAAO,EACPC,OAAQ,IAEVizE,GAAmBpiF,EAAOC,WAAW,KACvC,CACA,OAAOmiF,EACT,CA4vBkByE,GAEZhqF,KAAKwnF,eAAexrE,EAAK6rE,GAAW,QACtBrnF,IAAV6R,IACF80E,EAAc90E,EAAQ2J,EAAIiuE,YAAYV,GAAOl3E,MAC7C7M,EAAUD,IAAIgkF,EAAOl3E,SAED7R,IAAlBupF,GAA+BH,GAAkBJ,IACnDO,EAAgB/tE,EAAIiuE,YAAYT,GAAcn3E,MAC9C7M,EAAUD,IAAIikF,EAAcO,IAE1BH,QAAkCppF,IAAhBspF,IAEpBA,EAAc9tE,EAAIiuE,YAAYN,GAAQt3E,MACtC7M,EAAUD,IAAIokF,EAAQG,GAEtB3C,EAAc2C,EAAcC,EAEhC,CACA,MAAO,CACL13E,MAAOA,EAAQw3E,EACf1C,YAAaA,EAAe0C,EAEhC,CAQAK,eAAAA,CAAgBjH,EAAcsG,GAC5B,OAAOvpF,KAAKipF,qBAAqBhG,EAAMsG,EAAO,WAChD,CAMAY,WAAAA,CAAYnH,GACV,MAAMoH,EAAWpqF,KAAKqqF,aAAarH,GAOnC,OANyB,IAArBhjF,KAAK2gC,cACPypD,EAAS/3E,OAASrS,KAAKsqF,0BAErBF,EAAS/3E,MAAQ,IACnB+3E,EAAS/3E,MAAQ,GAEZ+3E,CACT,CAQAC,YAAAA,CAAarH,GACX,IACEuH,EACAC,EAFEn4E,EAAQ,EAIZ,MAAM8kE,EAAUn3E,KAAKygC,WAAav5B,EAChCsb,EAAOxiB,KAAKwiB,KACZygE,EAAOjjF,KAAK2jF,WAAWX,GACvByH,EAAUxH,EAAK1iF,OACfmqF,EAAa,IAAI9oF,MAAoB6oF,GAEvCzqF,KAAKknF,aAAalE,GAAa0H,EAC/B,IAAK,IAAIj/E,EAAI,EAAGA,EAAIg/E,EAASh/E,IAAK,CAChC,MAAMk/E,EAAW1H,EAAKx3E,GACtB++E,EAAexqF,KAAK4qF,gBAAgBD,EAAU3H,EAAWv3E,EAAG8+E,GAC5DG,EAAWj/E,GAAK++E,EAChBn4E,GAASm4E,EAAarD,YACtBoD,EAAeI,CACjB,CAUA,GAPAD,EAAWD,GAAW,CACpBt4E,KAAMq4E,EAAeA,EAAar4E,KAAOq4E,EAAan4E,MAAQ,EAC9DA,MAAO,EACP80E,YAAa,EACb70E,OAAQtS,KAAK87B,SACb8E,OAAQ,GAENpe,GAAQA,EAAKmjE,aAAc,CAC7B,IAAIkF,EAAiB,EACrB,MAAMC,EACJtoE,EAAKmjE,aAAanjE,EAAKmjE,aAAaplF,OAAS,GAAGA,OAClD,OAAQP,KAAKqgC,WACX,KAAKt5B,EACH8jF,EAAiB1T,EAAU2T,EAAkBz4E,EAAQ,EACrD,MACF,KAAKvL,EACH+jF,GAAkBC,EAAkBz4E,GAAS,EAC7C,MACF,KAAKnL,EACH2jF,EAAiB1T,EAAU,EAAI2T,EAAkBz4E,EAIrDw4E,GAAkB7qF,KAAKwgC,iBAAmB22C,GAAU,EAAK,GACzD,IACE,IAAI1rE,EAAI0rE,EAAUsT,EAAU,EAAI,EAChCtT,EAAU1rE,GAAK,EAAIA,EAAIg/E,EACvBtT,EAAU1rE,IAAMA,IAEhB++E,EAAeE,EAAWj/E,GACtBo/E,EAAiBC,EACnBD,GAAkBC,EACTD,EAAiB,IAC1BA,GAAkBC,GAIpB9qF,KAAK+qF,mBAAmBF,EAAgBL,GACxCK,GAAkBL,EAAarD,WAEnC,CACA,MAAO,CAAE90E,MAAOA,EAAO24E,YAAa,EACtC,CAUAD,kBAAAA,CAAmBF,EAAwBL,GACzC,MAAMS,EAAiBJ,EAAiBL,EAAarD,YAAc,EACjE3kE,EAAOxiB,KAAKwiB,KAGRo+C,EAAOK,GAAez+C,EAAKA,KAAMyoE,EAAgBzoE,EAAKmjE,cAC5D6E,EAAanB,WAAazoB,EAAKv0D,EAAImW,EAAK4hD,WAAW/3D,EACnDm+E,EAAaxhB,UAAYpI,EAAKx0D,EAAIoW,EAAK4hD,WAAWh4D,EAClDo+E,EAAa1+E,MAAQ80D,EAAK90D,OAAS9L,KAAKygC,WAAav5B,EAAQtC,KAAK0B,GAAK,EACzE,CAUAskF,eAAAA,CACED,EACA3H,EACA51B,EACAm9B,EACAW,GAEA,MAAM1vE,EAAQxb,KAAK0kF,4BAA4B1B,EAAW51B,GACxDR,EAAY29B,EACRvqF,KAAK0kF,4BAA4B1B,EAAW51B,EAAY,GACxD,CAAA,EACJwT,EAAO5gE,KAAKspF,aAAaqB,EAAUnvE,EAAO+uE,EAAc39B,GAC1D,IAEEjsB,EAFEwmD,EAAcvmB,EAAKumB,YACrB90E,EAAQuuD,EAAKvuD,MAGU,IAArBrS,KAAK2gC,cACPA,EAAc3gC,KAAKsqF,yBACnBj4E,GAASsuB,EACTwmD,GAAexmD,GAGjB,MAAM9iB,EAAoB,CACxBxL,QACAF,KAAM,EACNG,OAAQkJ,EAAMsgB,SACdqrD,cACAvmD,OAAQplB,EAAMolB,QAEhB,GAAIwsB,EAAY,IAAM89B,EAAU,CAC9B,MAAMC,EAAcnrF,KAAKknF,aAAalE,GAAW51B,EAAY,GAC7DvvC,EAAI1L,KACFg5E,EAAYh5E,KAAOg5E,EAAY94E,MAAQuuD,EAAKumB,YAAcvmB,EAAKvuD,KACnE,CACA,OAAOwL,CACT,CASQsrE,mBAAAA,CAAoBnG,GAC1B,MAAMoI,EAAKprF,KAAKqrF,cAChB,GAAID,EAAGpI,GACL,OAAOoI,EAAGpI,GAKZ,IAAIsI,EAAYtrF,KAAKkqF,gBAAgBlH,EAAW,GAChD,IAAK,IAAIv3E,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWX,GAAWziF,OAAQkL,EAAImY,EAAKnY,IAChE6/E,EAAY1mF,KAAKC,IAAI7E,KAAKkqF,gBAAgBlH,EAAWv3E,GAAI6/E,GAG3D,OAAQF,EAAGpI,GAAasI,EAAYtrF,KAAKqhC,aAC3C,CAOAonD,eAAAA,CAAgBzF,GACd,OAAOhjF,KAAKmpF,oBAAoBnG,GAAahjF,KAAKsgC,UACpD,CAKAkmD,cAAAA,GACE,IAAIl0E,EAAS,EACb,IAAK,IAAI7G,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IACrD6G,GACE7G,IAAMmY,EAAM,EAAI5jB,KAAKmpF,oBAAoB19E,GAAKzL,KAAKyoF,gBAAgBh9E,GAEvE,OAAO6G,CACT,CAMA+1E,cAAAA,GACE,OAAOroF,KAAK6gC,YAAcv4B,GAAOtI,KAAKqS,MAAQ,EAAIrS,KAAKqS,MAAQ,CACjE,CAMAk2E,aAAAA,GACE,OAAQvoF,KAAKsS,OAAS,CACxB,CAOAi5E,iBAAAA,CACEvvE,EACA67C,GAEA77C,EAAI2G,OACJ,IAAI6oE,EAAc,EAClB,MAAMr5E,EAAOnS,KAAKqoF,iBAChBj2E,EAAMpS,KAAKuoF,gBACb,IAAK,IAAI98E,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IACrDzL,KAAKkoF,gBACHrwB,EACA77C,EACAhc,KAAK2jF,WAAWl4E,GAChB0G,EAAOnS,KAAK2oF,mBAAmBl9E,GAC/B2G,EAAMo5E,EAAcxrF,KAAKmpF,oBAAoB19E,GAC7CA,GAEF+/E,GAAexrF,KAAKyoF,gBAAgBh9E,GAEtCuQ,EAAI6G,SACN,CAMA+kE,eAAAA,CAAgB5rE,IACThc,KAAK+jB,MAAS/jB,KAAKmjF,SAASh7E,KAIjCnI,KAAKurF,kBAAkBvvE,EAAK,WAC9B,CAMA2rE,iBAAAA,CAAkB3rE,IACVhc,KAAK69B,QAA+B,IAArB79B,KAAKq9B,cAAsBr9B,KAAK+iF,mBAIjD/iF,KAAK89B,SAAW99B,KAAK89B,OAAOoF,cAC9BljC,KAAK0zC,cAAc13B,GAGrBA,EAAI2G,OACJ3iB,KAAKw0C,aAAax4B,EAAKhc,KAAKs9B,iBAC5BthB,EAAIkI,YACJlkB,KAAKurF,kBAAkBvvE,EAAK,cAC5BA,EAAIqI,YACJrI,EAAI6G,UACN,CAWAslE,YAAAA,CACEtwB,EACA77C,EACAinE,EACA9wE,EACAC,EACA4wE,GAEA,MAAMyI,EAAYzrF,KAAKqgC,UAAUpvB,SAASqwB,IACxC9e,EAAOxiB,KAAKwiB,KACZkpE,GACGD,GACoB,IAArBzrF,KAAK2gC,aACL3gC,KAAK+iF,cAAcC,KAClBxgE,EACHmpE,EAAQ3rF,KAAK6gC,YAAcv4B,EAC3B4D,EAAOlM,KAAK6gC,YAAcv4B,EAAM,GAAI,EAGpCsjF,EAAmB5vE,EAAI6kB,UAEzB,IAAIgrD,EACFC,EAEA1C,EAEA2C,EACAC,EAJAC,EAAgB,GAEhBnD,EAAW,EAWb,GAPA9sE,EAAI2G,OACAipE,IAAqB5rF,KAAK6gC,YAC5B7kB,EAAI7Y,OAAO+Y,aAAa,MAAOyvE,EAAQrjF,EAAMC,GAC7CyT,EAAI6kB,UAAY8qD,EAAQrjF,EAAMC,EAC9ByT,EAAIqkB,UAAYsrD,EAAQ5kF,EAAOG,GAEjCkL,GAAOpS,KAAKmpF,oBAAoBnG,GAAahjF,KAAKmhC,kBAC9CuqD,EAKF,OAFA1rF,KAAKksF,YAAYr0B,EAAQ77C,EAAKgnE,EAAW,EAAGC,EAAK9oE,KAAK,IAAKhI,EAAMC,QACjE4J,EAAI6G,UAGN,IAAK,IAAIpX,EAAI,EAAGmY,EAAMq/D,EAAK1iF,OAAS,EAAGkL,GAAKmY,EAAKnY,IAC/CsgF,EAAetgF,IAAMmY,GAAO5jB,KAAK2gC,aAAene,EAChDypE,GAAiBhJ,EAAKx3E,GACtB29E,EAAUppF,KAAKknF,aAAalE,GAAWv3E,GACtB,IAAbq9E,GACF32E,GAAQjG,GAAQk9E,EAAQjC,YAAciC,EAAQ/2E,OAC9Cy2E,GAAYM,EAAQ/2E,OAEpBy2E,GAAYM,EAAQjC,YAElBsE,IAAcM,GACZ/rF,KAAKggC,eAAewvB,KAAKyzB,EAAKx3E,MAChCsgF,GAAe,GAGdA,IAEHF,EACEA,GAAe7rF,KAAK0kF,4BAA4B1B,EAAWv3E,GAC7DqgF,EAAY9rF,KAAK0kF,4BAA4B1B,EAAWv3E,EAAI,GAC5DsgF,EAAep/B,GAAgBk/B,EAAaC,GAAW,IAErDC,IACEvpE,GACFxG,EAAI2G,OACJ3G,EAAIs1B,UAAU83C,EAAQC,WAAYD,EAAQpgB,WAC1ChtD,EAAIvN,OAAO26E,EAAQt9E,OACnB9L,KAAKksF,YACHr0B,EACA77C,EACAgnE,EACAv3E,EACAwgF,GACCnD,EAAW,EACZ,GAEF9sE,EAAI6G,YAEJmpE,EAAc75E,EACdnS,KAAKksF,YACHr0B,EACA77C,EACAgnE,EACAv3E,EACAwgF,EACAD,EACA55E,IAGJ65E,EAAgB,GAChBJ,EAAcC,EACd35E,GAAQjG,EAAO48E,EACfA,EAAW,GAGf9sE,EAAI6G,SACN,CAaAspE,kCAAAA,CAAmC9xE,GAEjC,MAAMhI,EAAQrS,KAAKqS,MAAQrS,KAAKq9B,YAC9B/qB,EAAStS,KAAKsS,OAAStS,KAAKq9B,YAC5BoY,EAAUxhC,GAAuB,CAC/B5B,QACAC,WAEFojC,EAAOD,EAAQryC,WAAW,MAa5B,OAZAqyC,EAAQpjC,MAAQA,EAChBojC,EAAQnjC,OAASA,EACjBojC,EAAKxxB,YACLwxB,EAAKvxB,OAAO,EAAG,GACfuxB,EAAKtxB,OAAO/R,EAAO,GACnBqjC,EAAKtxB,OAAO/R,EAAOC,GACnBojC,EAAKtxB,OAAO,EAAG9R,GACfojC,EAAKrxB,YACLqxB,EAAKpE,UAAUj/B,EAAQ,EAAGC,EAAS,GACnCojC,EAAKpxB,UAAYjK,EAAOC,OAAOo7B,GAC/B11C,KAAKs0C,+BAA+BoB,EAAMr7B,GAC1Cq7B,EAAK3xB,OACE2xB,EAAKC,cAAcF,EAAS,YACrC,CAEA22C,YAAAA,CACEpwE,EACA3I,EACAgH,GAEA,IAAIK,EAAiB6J,EACrB,OAAInK,GAASC,GAEwC,eAAhDA,EAA8B85B,eAC9B95B,EAA8BoK,mBAC9BpK,EAAmBqK,kBAMpBhK,GAAW1a,KAAKqS,MAAQ,EACxBkS,GAAWvkB,KAAKsS,OAAS,EACzB0J,EAAIs1B,UAAU52B,EAAS6J,GACvBvI,EAAI3I,GAAYrT,KAAKmsF,mCAAmC9xE,GACjD,CAAEK,UAAS6J,aAGlBvI,EAAI3I,GAAYgH,EAAOC,OAAO0B,GACvBhc,KAAKs0C,+BAA+Bt4B,EAAK3B,KAIlD2B,EAAI3I,GAAYgH,EAEX,CAAEK,QAAS,EAAG6J,QAAS,GAChC,CASAqvB,gBAAAA,CACE53B,EAA6B9W,GAK7B,IAJA24B,OACEA,EAAMR,YACNA,GAC6Dn4B,EAO/D,OALA8W,EAAI83B,UAAYzW,EAChBrhB,EAAI+3B,QAAU/zC,KAAKw9B,cACnBxhB,EAAIg4B,eAAiBh0C,KAAKu9B,iBAC1BvhB,EAAIi4B,SAAWj0C,KAAKy9B,eACpBzhB,EAAIk4B,WAAal0C,KAAK09B,iBACf19B,KAAKosF,aAAapwE,EAAK,cAAe6hB,EAC/C,CASA0W,cAAAA,CAAev4B,EAA6BnR,GAAgC,IAA9BkZ,KAAEA,GAA0BlZ,EACxE,OAAO7K,KAAKosF,aAAapwE,EAAK,YAAa+H,EAC7C,CAaAmoE,WAAAA,CACEr0B,EACA77C,EACAgnE,EACA51B,EACAm8B,EACAp3E,EACAC,GAEA,MAAMyhC,EAAO7zC,KAAKokF,qBAAqBpB,EAAW51B,GAChDi/B,EAAWrsF,KAAK0kF,4BAA4B1B,EAAW51B,GACvDk/B,EAAwB,aAAXz0B,GAAyBw0B,EAAStoE,KAC/CqhC,EACa,eAAXyS,GAA2Bw0B,EAASxuD,QAAUwuD,EAAShvD,YAE3D,GAAK+nB,GAAiBknC,EAAtB,CAcA,GAXAtwE,EAAI2G,OAEJ3G,EAAIw1C,KAAOxxD,KAAKgoF,oBAAoBqE,GAEhCx4C,EAAKtT,qBACPvgC,KAAK0zC,cAAc13B,GAEjB63B,EAAKjT,SACPxuB,GAAOyhC,EAAKjT,QAGV0rD,EAAY,CACd,MAAMC,EAAcvsF,KAAKu0C,eAAev4B,EAAKqwE,GAC7CrwE,EAAIwwE,SACFjD,EACAp3E,EAAOo6E,EAAY7xE,QACnBtI,EAAMm6E,EAAYhoE,QAEtB,CAEA,GAAI6gC,EAAc,CAChB,MAAMqnC,EAAgBzsF,KAAK4zC,iBAAiB53B,EAAKqwE,GACjDrwE,EAAI0wE,WACFnD,EACAp3E,EAAOs6E,EAAc/xE,QACrBtI,EAAMq6E,EAAcloE,QAExB,CAEAvI,EAAI6G,SA9BJ,CA+BF,CAOA8pE,cAAAA,CAAeplD,EAAe+lB,GAC5BttD,KAAK4sF,WAAWrlD,EAAO+lB,EAAKttD,KAAKghC,YACnC,CAOA6rD,YAAAA,CAAatlD,EAAe+lB,GAC1BttD,KAAK4sF,WAAWrlD,EAAO+lB,EAAKttD,KAAKkhC,UACnC,CASU0rD,UAAAA,CACRrlD,EACA+lB,EACAw/B,GAKA,MAAMC,EAAM/sF,KAAKgkF,oBAAoBz8C,GAAO,GAC1CzL,EAAW97B,KAAKipF,qBACd8D,EAAI/J,UACJ+J,EAAI3/B,UACJ,YAEFp/C,EAAKhO,KAAKipF,qBAAqB8D,EAAI/J,UAAW+J,EAAI3/B,UAAW,UAC7D5xC,EAAQ,CACNsgB,SAAUA,EAAWgxD,EAAOh9E,KAC5B8wB,OAAQ5yB,EAAK8tB,EAAWgxD,EAAO7rD,UAEnCjhC,KAAK2kF,mBAAmBnpE,EAAO+rB,EAAO+lB,EACxC,CAOAq7B,kBAAAA,CAAmB3F,GACjB,MAAMlvC,EAAY9zC,KAAKinF,aAAajE,GAClCgK,EAAWhtF,KAAKqS,MAAQyhC,EACxBzT,EAAYrgC,KAAKqgC,UACjBQ,EAAY7gC,KAAK6gC,UACjBmmD,EAAkBhnF,KAAKgnF,gBAAgBhE,GACzC,IAAIoF,EAAa,EACjB,OACE/nD,IAAciB,IACbjB,IAAcoB,KAAmBulD,GACjC3mD,IAAcmB,KAAkBwlD,GAChC3mD,IAAckB,KAAiBylD,EAEzB,GAEL3mD,IAAcv5B,IAChBshF,EAAa4E,EAAW,GAEtB3sD,IAAcn5B,IAChBkhF,EAAa4E,GAEX3sD,IAAcoB,KAChB2mD,EAAa4E,EAAW,GAEtB3sD,IAAcmB,KAChB4mD,EAAa4E,GAEXnsD,IAAct4B,IACZ83B,IAAcn5B,GAASm5B,IAAcmB,GACvC4mD,EAAa,EACJ/nD,IAAct5B,GAAQs5B,IAAckB,GAC7C6mD,GAAc4E,EACL3sD,IAAcv5B,GAAUu5B,IAAcoB,KAC/C2mD,GAAc4E,EAAW,IAGtB5E,EACT,CAKA/B,WAAAA,GACErmF,KAAK4kF,kBAAmB,EACxB5kF,KAAKitF,aAAe,GACpBjtF,KAAKqrF,cAAgB,GACrBrrF,KAAKknF,aAAe,EACtB,CASAD,YAAAA,CAAajE,GACX,QAAqCxiF,IAAjCR,KAAKitF,aAAajK,GACpB,OAAOhjF,KAAKitF,aAAajK,GAG3B,MAAM3wE,MAAEA,GAAUrS,KAAKmqF,YAAYnH,GAEnC,OADAhjF,KAAKitF,aAAajK,GAAa3wE,EACxBA,CACT,CAEAi4E,sBAAAA,GACE,OAAyB,IAArBtqF,KAAK2gC,YACC3gC,KAAK87B,SAAW97B,KAAK2gC,YAAe,IAEvC,CACT,CASAsoD,oBAAAA,CACEjG,EACA51B,EACA/5C,GACS,IAAA65E,EAET,OAA2B,QAA3BA,EADkBltF,KAAKokF,qBAAqBpB,EAAW51B,GACrC/5C,UAAS,IAAA65E,EAAAA,EAAIltF,KAAKqT,EACtC,CAMAq0E,qBAAAA,CACE1rE,EACAhT,GAEA,IAAKhJ,KAAKgJ,KAAUhJ,KAAKmjF,SAASn6E,GAChC,OAEF,IAAImkF,EAAYntF,KAAKuoF,gBACrB,MAAMH,EAAapoF,KAAKqoF,iBACtB7lE,EAAOxiB,KAAKwiB,KACZme,EAAc3gC,KAAKsqF,yBACnB8C,EACW,gBAATpkF,EAAyB,GAAe,aAATA,EAAsB,EAAI,EAC3Dub,EAAUvkB,KAAKohC,QAAQp4B,GACzB,IAAK,IAAIyC,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IAAK,CAC1D,MAAM+8E,EAAexoF,KAAKyoF,gBAAgBh9E,GAC1C,IAAKzL,KAAKgJ,KAAUhJ,KAAKmjF,SAASn6E,EAAMyC,GAAI,CAC1C0hF,GAAa3E,EACb,QACF,CACA,MAAMvF,EAAOjjF,KAAK2jF,WAAWl4E,GACvB6/E,EAAY9C,EAAexoF,KAAKsgC,WAChCooD,EAAiB1oF,KAAK2oF,mBAAmBl9E,GAC/C,IAAIs9E,EAAW,EACXD,EAAW,EACXuE,EAAiBrtF,KAAKipF,qBAAqBx9E,EAAG,EAAGzC,GACjDskF,EAAWttF,KAAKipF,qBAAqBx9E,EAAG,EAAGtD,GAC3ColF,EAAevtF,KAAKipF,qBACtBx9E,EACA,EACA8zB,IAEEiuD,EAAoBH,EACpBI,EAAcH,EACdI,EAAkBH,EACtB,MAAMn7E,EAAM+6E,EAAY7B,GAAa,EAAItrF,KAAKmhC,mBAC9C,IAAIrxB,EAAO9P,KAAKkqF,gBAAgBz+E,EAAG,GAC/BuC,EAAKhO,KAAKipF,qBAAqBx9E,EAAG,EAAG,UACzC,IAAK,IAAI8rC,EAAI,EAAGmkB,EAAOunB,EAAK1iF,OAAQg3C,EAAImkB,EAAMnkB,IAAK,CACjD,MAAM6xC,EAAUppF,KAAKknF,aAAaz7E,GAAG8rC,GACrCi2C,EAAoBxtF,KAAKipF,qBAAqBx9E,EAAG8rC,EAAGvuC,GACpDykF,EAAcztF,KAAKipF,qBAAqBx9E,EAAG8rC,EAAGpvC,GAC9CulF,EAAkB1tF,KAAKipF,qBACrBx9E,EACA8rC,EACAhY,IAEF,MAAMouD,EAAc3tF,KAAKkqF,gBAAgBz+E,EAAG8rC,GACtCq2C,EAAY5tF,KAAKipF,qBAAqBx9E,EAAG8rC,EAAG,UAClD,GAAI/0B,GAAQgrE,GAAqBC,EAAa,CAC5C,MAAMI,EAAiB7tF,KAAK87B,SAAW4xD,EAAmB,IAC1D1xE,EAAI2G,OAEJ3G,EAAIsI,UAAYgpE,EAChBtxE,EAAIs1B,UAAU83C,EAAQC,WAAYD,EAAQpgB,WAC1ChtD,EAAIvN,OAAO26E,EAAQt9E,OACnBkQ,EAAIy3B,UACD21C,EAAQjC,YAAc,EACvB5iE,EAAUopE,EAAcC,EAAYR,EAAgBS,EACpDzE,EAAQjC,YACR0G,GAEF7xE,EAAI6G,SACN,MAAO,IACJ2qE,IAAsBH,GACrBI,IAAgBH,GAChBK,IAAgB79E,GAChB49E,IAAoBH,GACpBK,IAAc5/E,IAChB86E,EAAW,EACX,CACA,MAAM+E,EAAiB7tF,KAAK87B,SAAWyxD,EAAgB,IACvD,IAAI3E,EAAYR,EAAaM,EAAiBK,EAC1C/oF,KAAK6gC,YAAct4B,IACrBqgF,EAAY5oF,KAAKqS,MAAQu2E,EAAYE,GAEnCuE,GAAkBC,GAAYC,IAEhCvxE,EAAIsI,UAAYgpE,EAChBtxE,EAAIy3B,SACFm1C,EACAx2E,EAAMmS,EAAUzU,EAAO9B,EAAKo/E,EAAgBS,EAC5C/E,EACA+E,IAGJ9E,EAAWK,EAAQj3E,KACnB22E,EAAWM,EAAQ/2E,MACnBg7E,EAAiBG,EACjBD,EAAeG,EACfJ,EAAWG,EACX39E,EAAO69E,EACP3/E,EAAK4/E,CACP,MACE9E,GAAYM,EAAQjC,WAExB,CACA,IAAIyB,EAAYR,EAAaM,EAAiBK,EAC1C/oF,KAAK6gC,YAAct4B,IACrBqgF,EAAY5oF,KAAKqS,MAAQu2E,EAAYE,GAEvC9sE,EAAIsI,UAAYmpE,EAChB,MAAMI,EAAiB7tF,KAAK87B,SAAW4xD,EAAmB,IAC1DF,GACEC,GACAC,GACA1xE,EAAIy3B,SACFm1C,EACAx2E,EAAMmS,EAAUzU,EAAO9B,EAAKo/E,EAAgBS,EAC5C/E,EAAWnoD,EACXktD,GAEJV,GAAa3E,CACf,CAGAxoF,KAAK0zC,cAAc13B,EACrB,CAOAgsE,mBAAAA,GAaU,IAZRhnF,WACEA,EAAahB,KAAKgB,WAAUmE,UAC5BA,EAAYnF,KAAKmF,UAASC,WAC1BA,EAAapF,KAAKoF,WAAU02B,SAC5BA,EAAW97B,KAAK87B,UAMjBx7B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACJwnF,EAAsBxnF,UAAAC,OAAA,EAAAD,kBAAAE,EAEtB,MAAMstF,EACJ9sF,EAAWiQ,SAAS,MACpBjQ,EAAWiQ,SAAS,MACpBjQ,EAAWiQ,SAAS,MACpBu0E,GAAWuI,aAAa98E,SAASjQ,EAAWqE,eACxCrE,EACA,IAAIA,KACV,MAAO,CACLmE,EACAC,EACA,GAAG0iF,EAAe9nF,KAAK8gC,gBAAkBhF,MACzCgyD,GACA3zE,KAAK,IACT,CAMA0J,MAAAA,CAAO7H,GACAhc,KAAK2S,UAIR3S,KAAKmD,QACLnD,KAAKmD,OAAOyb,gBACX5e,KAAK0sC,QACL1sC,KAAKqtC,eAIJrtC,KAAK4kF,kBACP5kF,KAAK0lF,iBAEPtlF,MAAMyjB,OAAO7H,IACf,CAUAwvC,aAAAA,CAAcvnD,GACZ,OAAOunD,GAAcvnD,EACvB,CAOA6hF,mBAAAA,CAAoB74B,GAClB,MAAM84B,EAAQ94B,EAAKzxB,MAAMx7B,KAAK8/B,YAC5B+lD,EAAW,IAAIjkF,MAAgBmkF,EAAMxlF,QACrCytF,EAAU,CAAC,MACb,IAAIC,EAAoB,GACxB,IAAK,IAAIxiF,EAAI,EAAGA,EAAIs6E,EAAMxlF,OAAQkL,IAChCo6E,EAASp6E,GAAKzL,KAAKwrD,cAAcu6B,EAAMt6E,IACvCwiF,EAAUA,EAAQziF,OAAOq6E,EAASp6E,GAAIuiF,GAGxC,OADAC,EAAQn2C,MACD,CACLouC,gBAAiBL,EACjBE,MAAOA,EACPK,aAAc6H,EACdjI,cAAeH,EAEnB,CAOArrE,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAO,IACFF,MAAMoa,SAAS,IAAImlB,MAAoBra,IAC1CoC,OAAQslC,GAAchtD,KAAK0nB,OAAQ1nB,KAAKitD,SACpCjtD,KAAKwiB,KAAO,CAAEA,KAAMxiB,KAAKwiB,KAAKhI,YAAe,CAAA,EAErD,CAEAjV,GAAAA,CAAIhE,EAAmB0C,GACrB,MAAMy7B,qBAAEA,GAAyB1/B,KAAKF,YACtCM,MAAMmF,IAAIhE,EAAK0C,GACf,IAAIiqF,GAAY,EACZC,GAAe,EACnB,GAAmB,iBAAR5sF,EACT,IAAK,MAAMM,KAAQN,EACJ,SAATM,GACF7B,KAAKylF,cAEPyI,EAAYA,GAAaxuD,EAAqBzuB,SAASpP,GACvDssF,EAAeA,GAAyB,SAATtsF,OAGjCqsF,EAAYxuD,EAAqBzuB,SAAS1P,GAC1C4sF,EAAuB,SAAR5sF,EASjB,OAPI4sF,GACFnuF,KAAKylF,cAEHyI,GAAaluF,KAAK6hF,cACpB7hF,KAAK0lF,iBACL1lF,KAAKggB,aAEAhgB,IACT,CAMAoR,UAAAA,GACE,OAAO,CACT,CA+CA,wBAAaghD,CACXt+C,EACA5R,EACAwsD,GAEA,MAAM2tB,EAAmBprB,GACvBn9C,EACA0xE,GAAWlzB,gBACX5D,IAGI0/B,WACJA,EAAarnF,EAAkDsnF,eAC/DA,EAAiB,GAAEtgF,GACnBA,EAAK,EAACC,GACNA,EAAK,EAACoE,IACNA,EAAM,EAACD,KACPA,EAAO,EAAC2pB,SACRA,EAAWl1B,EAAqBy2B,YAChCA,EAAc,KACXixD,GACD,IAAKpsF,KAAYm6E,GAOfpvB,EAAO,IAAIjtD,KALG0uB,GAAY5a,EAAQy6E,aAAe,IAAIhyD,OAKxB,CAC/BpqB,KAAMA,EAAOpE,EACbqE,IAAKA,EAAMpE,EACXkyB,UAAWmuD,EAAep9E,SAAS,aACnCkvB,SAAUkuD,EAAep9E,SAAS,YAClCmvB,YAAaiuD,EAAep9E,SAAS,gBAErCosB,YAAa,EACbvB,cACGwyD,IAELE,EAAwBvhC,EAAKxf,kBAAoBwf,EAAK36C,OAGtDm8E,IADGxhC,EAAK36C,OAAS26C,EAAK5vB,aAAe4vB,EAAK3sB,WAAa2sB,EAAK36C,QAC9Bk8E,EAC9BE,EAAazhC,EAAKxf,kBAAoBghD,EAExC,IAAIE,EAAO,EAoBX,OAdIP,IAAetnF,IACjB6nF,EAAO1hC,EAAK1f,iBAAmB,GAE7B6gD,IAAelnF,IACjBynF,EAAO1hC,EAAK1f,kBAEd0f,EAAK1nD,IAAI,CACP4M,KAAM86C,EAAK96C,KAAOw8E,EAClBv8E,IACE66C,EAAK76C,KACJs8E,EAAazhC,EAAKnxB,UAAY,IAAOmxB,EAAK9rB,oBACzC8rB,EAAK3sB,WACTjD,gBAEK4vB,CACT,CASA,iBAAOr0C,CAGLlJ,GACA,OAAO1P,KAAK04C,YACV,IACKhpC,EACHgY,OAAQ6lC,GAAgB79C,EAAOgY,QAAU,CAAA,EAAIhY,EAAOu9C,OAEtD,CACErU,WAAY,QAGlB,EAvwDA74C,EARWylF,GAAU,uBAamB9lD,IAAoB3/B,EAbjDylF,GAAU,kBAwRI,IAAIliD,MAAoB3D,KAAgB5/B,EAxRtDylF,GAAU,cA0RA3lD,IAAiB9/B,EA1R3BylF,GAAU,OA4RP,QAAMzlF,EA5RTylF,GAAU,eA8oDC,CACpB,QACA,aACA,YACA,UACA,UACA,YACA,WACA,gBACA,eACA,aACA,OACA,QACA,aAKFzlF,EAhqDWylF,GAAU,kBAoqDI93B,GAAkBliD,OACzC,IACA,IACA,KACA,KACA,cACA,aACA,cACA,YACA,iBACA,kBACA,gBAmGJ26C,GAAYq/B,GAAY,CDj4DjB,cAAiCvoD,GACtCkB,MAAAA,GACE,MAAMiD,EAAUphC,KAAK4uF,wBACnBC,EAAY7uF,KAAK8uF,iBAAiB1tD,EAAQ2tD,QAAS3tD,EAAQ4tD,UAC7D,OAAOhvF,KAAKivF,kBAAkBJ,EAChC,CAEAvoE,KAAAA,CAA6C9N,GAC3C,MAAM02E,EAAUlvF,KAAKq+B,qBAAqBr+B,KAAKm+B,SAAU,CACrD3lB,UACAimB,SAAS,EACTC,YAAY,IAEdlc,EAAOxiB,KAAKwiB,KACd,OAAIA,EAEA0sE,EACA1sE,EAAK6b,qBAAqB7b,EAAK2b,SAAU,CACvC3lB,UACAkmB,YAAY,EACZnX,oBAAqBtN,GAAYja,KAAK8qB,mBAIrCokE,CACT,CAEQN,qBAAAA,GACN,MAAO,CACLI,UAAWhvF,KAAKqS,MAAQ,EACxB08E,SAAU/uF,KAAKsS,OAAS,EACxB68E,QAASnvF,KAAKyoF,gBAAgB,GAElC,CAEQwG,iBAAAA,CAAiB/pF,GASvB,IAPAkqF,YACEA,EAAWC,UACXA,GAIDnqF,EAED,MACEmpF,EAAiBruF,KAAKsvF,qBAAqBtvF,MAC7C,MAAO,CACLovF,EAAYj1E,KAAK,IACjB,kCACA,gBAAgBna,KAAKgB,WAAW2tB,QAAQw2D,GAAe,SACvD,cAAcnlF,KAAK87B,aACnB97B,KAAKmF,UAAY,eAAenF,KAAKmF,cAAgB,GACrDnF,KAAKoF,WAAa,gBAAgBpF,KAAKoF,eAAiB,GACxDipF,EAAiB,oBAAoBA,MAAqB,GACvC,QAAnBruF,KAAK6gC,UAAsB,cAAc7gC,KAAK6gC,cAAgB,GAC9D,UACA7gC,KAAKk9B,cAZU,GAaf,IACAl9B,KAAKk/B,gBACL,KACAmwD,EAAUl1E,KAAK,IACf,YAEJ,CAQQ20E,gBAAAA,CAENS,EACAC,GAEA,MAAMH,EAAsB,GAC1BD,EAAwB,GAC1B,IACEK,EADEn9E,EAASi9E,EAIbvvF,KAAKse,iBACH8wE,EAAY1kF,QACP06E,GACDplF,KAAKse,iBACJte,KAAKqS,MAAQ,GACbrS,KAAKsS,OAAS,EACftS,KAAKqS,MACLrS,KAAKsS,SAKX,IAAK,IAAI7G,EAAI,EAAGmY,EAAM5jB,KAAK2jF,WAAWpjF,OAAQkL,EAAImY,EAAKnY,IACrDgkF,EAAazvF,KAAK2oF,mBAAmBl9E,GACd,QAAnBzL,KAAK6gC,YACP4uD,GAAczvF,KAAKqS,QAEjBrS,KAAKugC,qBAAuBvgC,KAAKmjF,SAAS,sBAAuB13E,KACnEzL,KAAK0vF,kBACHN,EACA3jF,EACA+jF,EAAiBC,EACjBn9E,GAGJtS,KAAK2vF,oBACHN,EACA5jF,EACA+jF,EAAiBC,EACjBn9E,GAEFA,GAAUtS,KAAKyoF,gBAAgBh9E,GAGjC,MAAO,CACL4jF,YACAD,cAEJ,CAEQQ,mBAAAA,CAENC,EACAC,EACA39E,EACAC,EACAg3E,GAEA,MAAM2G,EAAmB5vF,EAAO+Z,oBAC1B81E,EAAahwF,KAAKiwF,iBACpBH,EACAD,IAASA,EAAKtzD,UAAYszD,EAAK50D,MAAMiqD,KAEvCgL,EAAaF,EAAa,UAAUA,KAAgB,GACpDhiF,EAAK8hF,EAAUlvD,OACfuvD,EAASniF,EAAK,QAAQ4L,GAAQ5L,EAAI+hF,OAAwB,IAC1DjkF,MAAEA,EAAKu9E,WAAEA,EAAUrgB,UAAEA,EAAS32D,MAAEA,GAAU+2E,EAC5C,IAAIgH,EAAY,GAChB,QAAmB5vF,IAAf6oF,EAA0B,CAC5B,MAAMgH,EAAOh+E,EAAQ,EACrBvG,IACGskF,EAAY,YAAYx2E,GAAQ/E,GAAiB/I,GAAQikF,OAC5D,MAAMvrE,EAAI/N,GAAmB,CAAE3K,MAAO+I,GAAiB/I,KACvD0Y,EAAE,GAAK6kE,EACP7kE,EAAE,GAAKwkD,EACP,MAAMsnB,EAAc,IAAInkF,IAAOkkF,EAAM,GAAGrhF,UAAUwV,GAClDrS,EAAOm+E,EAAYjkF,EACnB+F,EAAMk+E,EAAYlkF,CACpB,CAEA,MAAO,aAAawN,GAAQzH,EAAM49E,UAAyBn2E,GACzDxH,EACA29E,OACII,IAASC,IAAYF,KAAc7kC,GAAUwkC,YACrD,CAEQF,mBAAAA,CAENN,EACArM,EACAwM,EACAD,GAEA,MAAMjvD,EAAatgC,KAAKyoF,gBAAgBzF,GACtCyI,EAAYzrF,KAAKqgC,UAAUpvB,SAASqwB,IACpC2hD,EAAOjjF,KAAK2jF,WAAWX,GACzB,IAAI6I,EACFC,EAEA1C,EACA5tE,EAEAuwE,EAJAE,EAAgB,GAGhBnD,EAAW,EAGbyG,GACGjvD,GAAc,EAAItgC,KAAKmhC,mBAAsBnhC,KAAKsgC,WACrD,IAAK,IAAI70B,EAAI,EAAGmY,EAAMq/D,EAAK1iF,OAAS,EAAGkL,GAAKmY,EAAKnY,IAC/CsgF,EAAetgF,IAAMmY,GAAO5jB,KAAK2gC,aAAe3gC,KAAKwiB,KACrDypE,GAAiBhJ,EAAKx3E,GACtB29E,EAAUppF,KAAKknF,aAAalE,GAAWv3E,GACtB,IAAbq9E,GACF0G,GAAkBpG,EAAQjC,YAAciC,EAAQ/2E,MAChDy2E,GAAYM,EAAQ/2E,OAEpBy2E,GAAYM,EAAQjC,YAElBsE,IAAcM,GACZ/rF,KAAKggC,eAAewvB,KAAKyzB,EAAKx3E,MAChCsgF,GAAe,GAGdA,IAEHF,EACEA,GAAe7rF,KAAK0kF,4BAA4B1B,EAAWv3E,GAC7DqgF,EAAY9rF,KAAK0kF,4BAA4B1B,EAAWv3E,EAAI,GAC5DsgF,EAAep/B,GAAgBk/B,EAAaC,GAAW,IAErDC,IACFvwE,EAAQxb,KAAKokF,qBAAqBpB,EAAWv3E,GAC7C4jF,EAAU3kF,KACR1K,KAAK4vF,oBACH3D,EACAzwE,EACAg0E,EACAD,EACAnG,IAGJ6C,EAAgB,GAChBJ,EAAcC,EACS,QAAnB9rF,KAAK6gC,UACP2uD,GAAkB1G,EAElB0G,GAAkB1G,EAEpBA,EAAW,EAGjB,CAEQ4G,iBAAAA,CAENN,EACA3jF,EACA28E,EACAmH,GAEA,MAAMtM,EAAOjjF,KAAK2jF,WAAWl4E,GAC3B+8E,EAAexoF,KAAKyoF,gBAAgBh9E,GAAKzL,KAAKsgC,WAChD,IAEEuoD,EAFEC,EAAW,EACbC,EAAW,EAEXC,EAAYhpF,KAAKipF,qBAAqBx9E,EAAG,EAAG,uBAC9C,IAAK,IAAI8rC,EAAI,EAAGA,EAAI0rC,EAAK1iF,OAAQg3C,IAAK,CACpC,MAAMplC,KAAEA,EAAIE,MAAEA,EAAK80E,YAAEA,GAAgBnnF,KAAKknF,aAAaz7E,GAAG8rC,GAC1DsxC,EAAe7oF,KAAKipF,qBAAqBx9E,EAAG8rC,EAAG,uBAC3CsxC,IAAiBG,GACnBA,GACEoG,EAAY1kF,QACP06E,GACD4D,EACAZ,EAAaW,EACbwG,EACAzG,EACAN,IAGNO,EAAW52E,EACX22E,EAAWz2E,EACX22E,EAAYH,GAEZC,GAAY3B,CAEhB,CACA0B,GACEuG,EAAY1kF,QACP06E,GACD4D,EACAZ,EAAaW,EACbwG,EACAzG,EACAN,GAGR,CAOAtrD,YAAAA,CAAoDC,GAClD,MAAO,GAAG/8B,MAAM88B,aAAaC,iCAA0CvjB,GAAS5Z,KAAK+sD,wBAA0B/sD,KAAKyxC,mBAAmBrlC,EAAK,GAAIjM,EAAO+Z,0CACzJ,CAQA+1E,gBAAAA,CAEEz0E,EACA+0E,GAEA,MAAMvvF,WACJA,EAAUq8B,YACVA,EAAWQ,OACXA,EAAM9Z,KACNA,EAAI+X,SACJA,EAAQ32B,UACRA,EAASC,WACTA,EAAU2nD,wBACVA,EAAuB3sB,YACvBA,EAAWD,SACXA,EAAQD,UACRA,GACE1kB,EAEE6yE,EAAiBruF,KAAKsvF,qBAAqB,CAC/CpvD,UAAWA,QAAAA,EAAalgC,KAAKkgC,UAC7BC,SAAUA,QAAAA,EAAYngC,KAAKmgC,SAC3BC,YAAaA,QAAAA,EAAepgC,KAAKogC,cAE7BowD,EAAYzjC,GAA2B/sD,KAAK+sD,wBAClD,MAAO,CACLlvB,EAASjB,GAAex0B,EAAQy1B,GAAU,GAC1CR,EAAc,iBAAiBA,MAAkB,GACjDr8B,EACI,gBACGA,EAAWiQ,SAAS,MAASjQ,EAAWiQ,SAAS,KAE9CjQ,EADA,IAAIA,SAGV,GACJ86B,EAAW,cAAcA,QAAiB,GAC1C32B,EAAY,eAAeA,MAAgB,GAC3CC,EAAa,gBAAgBA,MAAiB,GAC9CipF,EACI,oBAAoBA,iCAA8Cz0E,GAAS42E,EAAYxwF,KAAKyxC,mBAAmBrlC,EAAK,GAAIjM,EAAO+Z,0BAC/H,GACJ6J,EAAO6Y,GAAez0B,EAAM4b,GAAQ,GACpCwsE,EAAgB,qBAAuB,IACvCp2E,KAAK,GACT,CAOAm1E,oBAAAA,CAEE9zE,GAEA,MAAQ,CAAC,WAAY,YAAa,gBAC/B1R,OACE2mF,GACCj1E,EACEi1E,EAAW9hE,QAAQ,IAAK,MAM7BxU,KAAK,IACV,KCmiDFxR,GAAcG,SAAS08E,IACvB78E,GAAcQ,YAAYq8E,ICz4DnB,MAAMkL,GAYX5wF,WAAAA,CAAYkK,GAAejK,EAAAC,KAAA,cAAA,GAAAD,6BAVE,GAAKA,2BACP,GAAKA,2BACL,GAAKA,EAAAC,KAAA,4BAAA,GAAAD,EAAAC,KAAA,2BAAA,GAAAD,EAAAC,KAAA,gBAAA,GAS9BA,KAAKgK,OAASA,EACd,MAAMY,EAAY,CAChB5K,KAAKgK,OAAOG,GAAG,YAAanK,KAAK2wF,iBAAiB9pD,KAAK7mC,OACvDA,KAAKgK,OAAOG,GAAG,WAAYnK,KAAK4wF,gBAAgB/pD,KAAK7mC,OACrDA,KAAKgK,OAAOG,GAAG,YAAanK,KAAK6wF,iBAAiBhqD,KAAK7mC,OACvDA,KAAKgK,OAAOG,GAAG,UAAWnK,KAAK8wF,eAAejqD,KAAK7mC,OACnDA,KAAKgK,OAAOG,GAAG,OAAQnK,KAAK+wF,YAAYlqD,KAAK7mC,QAE/CA,KAAKgxF,SAAW,KACdpmF,EAAU7J,QAAS+J,GAAMA,KACzB9K,KAAKgxF,cAAWxwF,EAEpB,CAEAywF,sBAAAA,CAAuB1mE,GACrB,MAAMvgB,EAAShK,KAAKgK,OACdknF,EAAelnF,EAAOmnF,6BAA6B5mE,GACzD,OACEvgB,EAAO+iE,WACPmkB,GAAgBlnF,EAAOs9E,gBACvB4J,GAAgBlnF,EAAOonF,cACvBpnF,EAAOs9E,eAAiBt9E,EAAOonF,YAEnC,CAKA7pD,KAAAA,CAAMhd,GACJ,OAAQvqB,KAAKqxF,mBAAqBrxF,KAAKixF,uBAAuB1mE,EAChE,CAKA+mE,QAAAA,GACE,OAAOtxF,KAAKqxF,kBACd,CAMA/jC,GAAAA,CAAI/iC,GACF,MAAMyjD,EAAShuE,KAAKsxF,WAWpB,OAVItjB,IAAWhuE,KAAKuxF,mBAIlBvxF,KAAKgK,OAAOwnF,iBAAiBjnE,GAC7BvqB,KAAKgK,OAAOynF,mBAAkB,IAEhCzxF,KAAKqxF,oBAAqB,EAC1BrxF,KAAKuxF,kBAAmB,EACxBvxF,KAAK0xF,kBAAmB,EACjB1jB,CACT,CAEA2jB,qBAAAA,GACE,OAAO3xF,KAAK4xF,oBACd,CAMAC,YAAAA,CACEtnE,EAAYrlB,GAQZ,IAAA4sF,EAAA,IAPAxK,eACEA,EAAc8J,aACdA,GAIDlsF,EAED,MAAM8E,EAAShK,KAAKgK,OACd7G,EAAS6G,EAAO7G,OAChB4uF,EAAa,IAAI5lF,GAAMnC,EAAOoN,SAAa,EAAGpN,EAAOqN,OAAQ,EAAK,GAClE26E,EAAahoF,EAAOioF,qBAAqB3K,GAKzC33C,EAJoB,IAAIxjC,GAC5B6lF,EAAW7/E,KAAO6/E,EAAW5J,WAC7B4J,EAAW5/E,IAAM4/E,EAAW7E,WAC5BngF,SAAS+kF,GACmB/iF,UAAUhF,EAAOk0B,uBAEzCkoC,EADUjjE,EAAOknE,cAAc9/C,GAChB3d,SAAS+iC,GACxB1zB,EAAgBjS,EAAO6jC,yBACvBviB,EAAOthB,EAAOojC,kBACdsoB,EAAa/lB,EAAI/iC,SAAS,IAAIT,GAAMmf,EAAKnZ,KAAMmZ,EAAKlZ,MACpDuO,EAAMxd,EAAO8b,kBACb5B,EAASq4C,EAAWppD,IAAI85D,GAAMp3D,UAAU2R,GAAK,GAE7CuxE,EAAMloF,EAAOsU,gBACboJ,EAASwjC,GAAYlhD,EAAO0d,QAClC1d,EAAOsU,gBAAkB,GACzB,MAAM27B,EAAgB,CACpBpc,OAAQ,cACR9Z,KAAM,cACNwc,oBAAqB,eAEvBv2B,EAAO26E,mBAAmB1qC,EAAe,EAAGqtC,GAC5Ct9E,EAAO26E,mBAAmB1qC,EAAem3C,EAAcpnF,EAAOijD,KAAK1sD,QACnEyJ,EAAO65B,OAAQ,EACf,MAAMsuD,EAAYnoF,EAAO2e,gBAAgB,CACvC9J,oBAAqB1b,EAAO0b,oBAC5BI,mBAAmB,IAGrBjV,EAAOsU,gBAAkB4zE,EACzBloF,EAAO0d,OAASA,EAChB1d,EAAO65B,OAAQ,EAEf0gC,GAAS4tB,EAAW,CAClB12E,SAAU,QACVtJ,MAAUggF,EAAU9/E,MAAd,KACN+/E,OAAQjrF,EACRkL,MAAU8/E,EAAU9/E,MAAQ4J,EAArB,KACP3J,OAAW6/E,EAAU7/E,OAAS2J,EAAtB,OAEVjc,KAAKqyF,qBAAuBryF,KAAKqyF,sBACjCryF,KAAKqyF,oBAAsB,KACzBF,EAAU9oF,UAEZyR,GACGyP,EAAEvgB,QAAUhK,KAAKgK,OAAO4lE,gBACzB10D,KAAKo3E,YAAYH,GACL,QAAdL,EAAAvnE,EAAEipD,wBAAYse,GAAdA,EAAgBD,aAAaM,EAAW90E,EAAOhR,EAAGgR,EAAOjR,EAC3D,CAKA25C,WAAAA,CAAYx7B,GACVvqB,KAAKuxF,kBAAmB,EACxB,MAAMvnF,EAAShK,KAAKgK,OACdgkE,EAAShuE,KAAKsxF,WACpB,GAAItjB,GAAUzjD,EAAEipD,aAAc,CAC5B,MAAM1K,EAAa9oE,KAAK4xF,qBAAuB,CAC7CtK,eAAgBt9E,EAAOs9E,eACvB8J,aAAcpnF,EAAOonF,cAEjBntF,EAAQ+F,EAAOm8E,MAClBnsD,MAAM8uC,EAAUwe,eAAgBxe,EAAUsoB,cAC1Cj3E,KAAK,IACF8L,EAAO,CAAEgnC,KAAMjjD,EAAOijD,KAAMhpD,WAAU6kE,GAC5Cv+C,EAAEipD,aAAa+e,QAAQ,aAActuF,GACrCsmB,EAAEipD,aAAa+e,QACb,qBACA9pF,KAAK+pF,UAAU,CACbvuF,MAAOA,EACPyjB,OAAQ1d,EAAOs6E,mBACbxb,EAAUwe,eACVxe,EAAUsoB,cACV,MAIN7mE,EAAEipD,aAAaif,cAAgB,WAC/BzyF,KAAK6xF,aAAatnE,EAAGtE,EACvB,CAEA,OADAjc,EAAO0oF,uBACA1kB,CACT,CAMAhoB,OAAAA,CAAQz7B,GACN,GACEvqB,KAAKgK,OAAO2oF,WACX3yF,KAAKgK,OAAOi5C,qBACZ14B,EAAEqoE,iBACH,CACA,GAAI5yF,KAAKsxF,YAActxF,KAAK4xF,qBAAsB,CAGhD,MAAMtoF,EAAQtJ,KAAKgK,OAAOmnF,6BAA6B5mE,GACjDsoE,EAAqB7yF,KAAK4xF,qBAChC,OACEtoF,EAAQupF,EAAmBvL,gBAC3Bh+E,EAAQupF,EAAmBzB,YAE/B,CACA,OAAO,CACT,CACA,OAAO,CACT,CAKU0B,aAAAA,CAAcvoE,GACtB,OAAOvqB,KAAKgK,OAAOg8C,QAAQz7B,EAC7B,CAEAomE,gBAAAA,CAAgB9lF,GAAuB,IAAtB0f,EAAEA,GAAkB1f,EACnC,MAAMm7C,EAAUhmD,KAAK8yF,cAAcvoE,IAC9BvqB,KAAK0xF,kBAAoB1rC,IAC5BhmD,KAAK0xF,kBAAmB,EAE5B,CAEAd,eAAAA,CAAgBmC,GACd,MAAMxoE,EAAEA,GAAMwoE,EACR/sC,EAAUhmD,KAAK8yF,cAAcvoE,IAC9BvqB,KAAK0xF,kBAAoB1rC,EAC5BhmD,KAAK0xF,kBAAmB,EACf1xF,KAAK0xF,mBAAqB1rC,IAEnChmD,KAAK0xF,kBAAmB,GAEtB1xF,KAAK0xF,mBAEPnnE,EAAEC,iBAEFuoE,EAAG/sC,SAAU,EACb+sC,EAAG1f,WAAarzE,KAAKgK,OAEzB,CAEA6mF,gBAAAA,IACM7wF,KAAK0xF,kBAAoB1xF,KAAKsxF,cAChCtxF,KAAK0xF,kBAAmB,EAE5B,CAOAX,WAAAA,CAAYgC,GAAmB,IAAAC,EAC7B,MAAMzoE,EAAEA,GAAMwoE,EACRxf,EAAUhpD,EAAEqoE,iBAClB5yF,KAAK0xF,kBAAmB,EAExBnnE,EAAEC,iBACF,IAAIyoE,EAAuB,QAAjBD,EAAGzoE,EAAEipD,wBAAYwf,SAAdA,EAAgBE,QAAQ,cACrC,GAAID,IAAW1f,EAAS,CACtB,MAAMvpE,EAAShK,KAAKgK,OACd7G,EAAS6G,EAAO7G,OACtB,IAAI4M,EAAW/F,EAAOmnF,6BAA6B5mE,GACnD,MAAM7C,OAAEA,GACN6C,EAAEipD,aAAc/iE,MAAMQ,SAAS,sBAC3BxI,KAAK4f,MAAMkC,EAAEipD,aAAc0f,QAAQ,uBACnC,CAAA,EAEAC,EAAWF,EAAOruF,KAAKC,IAAI,EAAGouF,EAAO1yF,OAAS,IAC9C6yF,EAAuB,EAE7B,GAAIpzF,KAAK4xF,qBAAsB,CAC7B,MAAMtK,EAAiBtnF,KAAK4xF,qBAAqBtK,eAC3C8J,EAAepxF,KAAK4xF,qBAAqBR,aAC3CrhF,EAAWu3E,GAAkBv3E,GAAYqhF,EAC3CrhF,EAAWu3E,EACFv3E,EAAWqhF,IACpBrhF,GAAYqhF,EAAe9J,GAE7Bt9E,EAAOqpF,YAAY/L,EAAgB8J,UAE5BpxF,KAAK4xF,oBACd,CAGE5nF,EAAO81B,WAAW0vB,KAAK2jC,KACtBnpF,EAAO81B,WAAW0vB,KAAKxlD,EAAOm8E,MAAMp2E,KACnCA,IAAa/F,EAAOm8E,MAAM5lF,UAE5B0yF,EAASA,EAAOK,WAGlBP,EAAGxf,SAAU,EACbwf,EAAG1f,WAAarpE,EAEhBA,EAAOupF,YAAYN,EAAQvrE,EAAQ3X,GAEnC5M,EAAOmrE,gBAAgBtkE,GACvBA,EAAOwpF,aAAajpE,GACpBvgB,EAAOs9E,eAAiB1iF,KAAKiJ,IAC3BkC,EAAWqjF,EACXppF,EAAOm8E,MAAM5lF,QAEfyJ,EAAOonF,aAAexsF,KAAKiJ,IACzB7D,EAAOs9E,eAAiB2L,EAAO1yF,OAC/ByJ,EAAOm8E,MAAM5lF,QAEfyJ,EAAO4lE,eAAgB3rE,MAAQ+F,EAAOijD,KACtCjjD,EAAOypF,kBACPzpF,EAAO4lE,eAAgBC,QACvB7lE,EAAOqB,KAAKxD,EAAS,CACnByB,MAAOyG,EAAWqjF,EAClBrwC,OAAQ,SAEV5/C,EAAOkI,KAAK,eAAgB,CAAErB,WAC9B7G,EAAOqlE,iBAAkB,EACzBrlE,EAAO4c,kBACT,CACF,CAOA+wE,cAAAA,CAAc1lF,GAAuB,IAAtBmf,EAAEA,GAAkBnf,EACjC,GAAIpL,KAAKsxF,YAActxF,KAAKuxF,kBAGtBvxF,KAAK4xF,qBAAsB,CAAA,IAAA8B,EAC7B,MAAM1pF,EAAShK,KAAKgK,OACd7G,EAASnD,KAAKgK,OAAO7G,QACrBmkF,eAAEA,EAAc8J,aAAEA,GAAiBpxF,KAAK4xF,qBACxCne,GAA2B,QAAdigB,EAAAnpE,EAAEipD,oBAAY,IAAAkgB,OAAA,EAAdA,EAAgBjgB,aAActsE,EAC7CssE,IAAetsE,GAEjB6C,EAAOs9E,eAAiBA,EACxBt9E,EAAOonF,aAAeA,EACtBpnF,EAAOypF,kBACPzpF,EAAO4lE,eAAgBC,UAEvB7lE,EAAOw7C,kBACY,SAAfiuB,IACFzpE,EAAOqpF,YAAY/L,EAAgB8J,GACnCpnF,EAAOs9E,eAAiBt9E,EAAOonF,aAAe9J,EAC9Ct9E,EAAO4lE,iBACJ5lE,EAAO4lE,eAAe3rE,MAAQ+F,EAAOijD,MACxCjjD,EAAOypF,kBACPzpF,EAAOqB,KAAKxD,EAAS,CACnByB,MAAOg+E,EACPvkC,OAAQ,YAEV5/C,EAAOkI,KAAK,eAAgB,CAAErB,WAC9B7G,EAAO4c,oBAET/V,EAAOgmE,cAEX,CAGFhwE,KAAKqyF,qBAAuBryF,KAAKqyF,6BAC1BryF,KAAKqyF,2BACLryF,KAAK4xF,qBACZ5xF,KAAK0xF,kBAAmB,CAC1B,CAEAntF,OAAAA,GACEvE,KAAKgxF,UAAYhxF,KAAKgxF,UACxB,ECrWF,MAAM2C,GAAY,iBASX,MAAeC,WAIZpO,GAAqC1lF,WAAAA,GAAAM,SAAAE,WAc7CP,+BASkC,EAAC,CAuCnC8zF,YAAAA,GACE7zF,KAAK8zF,MAAQ9zF,KAAK8zF,MAAMjtD,KAAK7mC,MAC7BA,KAAK+zF,gBAAkB/zF,KAAK+zF,gBAAgBltD,KAAK7mC,MACjDA,KAAKmwE,2BACHnwE,KAAKmwE,2BAA2BtpC,KAAK7mC,KACzC,CAEA0lD,UAAAA,CAAWxjD,GAGT,OAFAlC,KAAK+sE,WAAa/sE,KAAKgwE,cACvBhwE,KAAKk3D,UAAW,EACT92D,MAAMslD,WAAWxjD,EAC1B,CAKA8xF,cAAAA,CAAc9uF,GAUX,IAVY+uF,QACbA,EAAO3tD,SACPA,EAAQC,MACRA,EAAKI,WACLA,GAMDzhC,EACC,OAAO0jC,GAAQ,CACbxC,WAAYpmC,KAAKk0F,sBACjBhtD,SAAU+sD,EACV3tD,WACAC,QACAI,aACA/8B,MAAOA,KACJ5J,KAAKmD,QAENnD,KAAKsnF,iBAAmBtnF,KAAKoxF,aAC/B1qD,SAAWziC,IACTjE,KAAKk0F,sBAAwBjwF,EAC7BjE,KAAKm0F,4BAGX,CAKQL,KAAAA,CAAMvtD,GACZvmC,KAAKo0F,kBAAoBp0F,KAAKg0F,eAAe,CAC3CC,QAAS,EACT3tD,SAAUtmC,KAAKq0F,eAAiB,EAChC9tD,MAAO3hC,KAAKC,IAAI0hC,GAAS,EAAG,KAC5BI,WAAY3mC,KAAK+zF,iBAErB,CAKQA,eAAAA,GAAkB,IAAAO,EACM,QAA9BA,EAAAt0F,KAAKu0F,iCAAyB,IAAAD,GAA9BA,EAAgC1qF,QAChC5J,KAAKu0F,0BAA4Bv0F,KAAKg0F,eAAe,CACnDC,QAAS,EACT3tD,SAAUtmC,KAAKq0F,eACf1tD,WAAY3mC,KAAK8zF,OAErB,CAKArC,iBAAAA,CAAkB+C,GAChBx0F,KAAK0yF,uBACL1yF,KAAK8zF,MAAMU,EAAU,EAAIx0F,KAAKy0F,YAChC,CAKA/B,oBAAAA,GACE,IAAIgC,GAAc,EAClB,CAAC10F,KAAKo0F,kBAAmBp0F,KAAKu0F,2BAA2BxzF,QACtD4zF,IACKA,IAAoBA,EAAgBrtD,WACtCotD,GAAc,EACdC,EAAgB/qF,WAKtB5J,KAAKk0F,sBAAwB,EAGzBQ,GACF10F,KAAKwlD,iBAET,CAMAovC,qBAAAA,GAEI,CAAC50F,KAAKo0F,kBAAmBp0F,KAAKu0F,2BAA2BrjF,KACtDyjF,IAAqBA,GAAmBA,EAAgBrtD,WAG3DtnC,KAAKyxF,mBAET,CAKAoD,SAAAA,GAKE,OAJA70F,KAAKsnF,eAAiB,EACtBtnF,KAAKoxF,aAAepxF,KAAKmmF,MAAM5lF,OAC/BP,KAAK80F,wBACL90F,KAAKyzF,kBACEzzF,IACT,CAKA+0F,MAAAA,GACE/0F,KAAK60F,YACL70F,KAAKm0F,yBACP,CAMAa,eAAAA,GACE,OAAOh1F,KAAKmmF,MAAMnsD,MAAMh6B,KAAKsnF,eAAgBtnF,KAAKoxF,cAAcj3E,KAAK,GACvE,CAOA86E,oBAAAA,CAAqBC,GACnB,IAAI73E,EAAS,EACX/T,EAAQ4rF,EAAY,EAGtB,GAAIl1F,KAAKm1F,SAAS3lC,KAAKxvD,KAAKmmF,MAAM78E,IAChC,KAAOtJ,KAAKm1F,SAAS3lC,KAAKxvD,KAAKmmF,MAAM78E,KACnC+T,IACA/T,IAGJ,KAAO,KAAKkmD,KAAKxvD,KAAKmmF,MAAM78E,KAAWA,MACrC+T,IACA/T,IAGF,OAAO4rF,EAAY73E,CACrB,CAOA+3E,qBAAAA,CAAsBF,GACpB,IAAI73E,EAAS,EACX/T,EAAQ4rF,EAGV,GAAIl1F,KAAKm1F,SAAS3lC,KAAKxvD,KAAKmmF,MAAM78E,IAChC,KAAOtJ,KAAKm1F,SAAS3lC,KAAKxvD,KAAKmmF,MAAM78E,KACnC+T,IACA/T,IAGJ,KAAO,KAAKkmD,KAAKxvD,KAAKmmF,MAAM78E,KAAWA,EAAQtJ,KAAKmmF,MAAM5lF,QACxD8c,IACA/T,IAGF,OAAO4rF,EAAY73E,CACrB,CAOAg4E,oBAAAA,CAAqBH,GACnB,IAAI73E,EAAS,EACX/T,EAAQ4rF,EAAY,EAEtB,MAAQ,KAAK1lC,KAAKxvD,KAAKmmF,MAAM78E,KAAWA,MACtC+T,IACA/T,IAGF,OAAO4rF,EAAY73E,CACrB,CAOAi4E,qBAAAA,CAAsBJ,GACpB,IAAI73E,EAAS,EACX/T,EAAQ4rF,EAEV,MAAQ,KAAK1lC,KAAKxvD,KAAKmmF,MAAM78E,KAAWA,EAAQtJ,KAAKmmF,MAAM5lF,QACzD8c,IACA/T,IAGF,OAAO4rF,EAAY73E,CACrB,CAQAk4E,kBAAAA,CAAmBjO,EAAwBzmD,GACzC,MAAMosB,EAAOjtD,KAAKmmF,MAGlB,IAAI78E,EACAg+E,EAAiB,GACjBtnF,KAAKm1F,SAAS3lC,KAAKvC,EAAKq6B,OACT,IAAdzmD,IAAqBz5B,EAAUooD,KAAKvC,EAAKq6B,EAAiB,KACvDA,EAAiB,EACjBA,EACNiC,EAAQt8B,EAAK3jD,GACf,KAAOA,EAAQ,GAAKA,EAAQ2jD,EAAK1sD,SAAWozF,GAAUnkC,KAAK+5B,IACzDjgF,GAASu3B,EACT0oD,EAAQt8B,EAAK3jD,GAKf,OAHkB,IAAdu3B,GAAoB8yD,GAAUnkC,KAAK+5B,IACrCjgF,IAEKA,CACT,CAMAksF,UAAAA,CAAWlO,GACTA,EAAiBA,QAAAA,EAAkBtnF,KAAKsnF,eAExC,MAAMmO,EAAoBz1F,KAAKu1F,mBAAmBjO,GAAgB,GAEhEoO,EAAkB9wF,KAAKC,IACrB4wF,EACAz1F,KAAKu1F,mBAAmBjO,EAAgB,IAG5CtnF,KAAKsnF,eAAiBmO,EACtBz1F,KAAKoxF,aAAesE,EACpB11F,KAAK80F,wBACL90F,KAAKyzF,kBAELzzF,KAAKm0F,yBACP,CAMAwB,UAAAA,CAAWrO,GACTA,EAAiBA,QAAAA,EAAkBtnF,KAAKsnF,eACxC,MAAMmO,EAAoBz1F,KAAKq1F,qBAAqB/N,GAClDoO,EAAkB11F,KAAKs1F,sBAAsBhO,GAE/CtnF,KAAKsnF,eAAiBmO,EACtBz1F,KAAKoxF,aAAesE,EACpB11F,KAAK80F,wBACL90F,KAAKyzF,iBACP,CAKAD,YAAAA,CAAajpE,IACPvqB,KAAK+sE,WAAc/sE,KAAK2yF,WAG5B3yF,KAAK41F,mBACL51F,KAAKqL,KAAK,kBAAmBkf,EAAI,CAAEA,UAAM/pB,GACzCR,KAAK80F,wBACD90F,KAAKmD,SACPnD,KAAKmD,OAAOkI,KAAK,uBAAwB,CACvCrB,OAAQhK,KACRuqB,MAEFvqB,KAAKmD,OAAO4c,oBAEhB,CAKA61E,gBAAAA,GACM51F,KAAKmD,SACPnD,KAAKmD,OAAOga,aACZnd,KAAKmD,OAAOmzE,mBAAmBvG,mBAGjC/vE,KAAK+sE,WAAY,EAEjB/sE,KAAK61F,qBACL71F,KAAK4vE,eAAgBC,QACrB7vE,KAAK4vE,eAAgB3rE,MAAQjE,KAAKitD,KAClCjtD,KAAKyzF,kBACLzzF,KAAK81F,oBACL91F,KAAK+1F,mBACL/1F,KAAKg2F,gBAAkBh2F,KAAKitD,KAE5BjtD,KAAK8zF,OACP,CAKA3jB,0BAAAA,CAA2B5lD,GACzB,GAAIvqB,KAAKijD,mBACP,OAGF,MAAMvnC,EAAK1b,KAAK4vE,eAEhB90D,GAAuBY,GAAIu6E,gBAAkBv6E,GAAMA,EAAGm0D,QAEtD,MAAM4lB,EAAoBz1F,KAAKmxF,6BAA6B5mE,GAC1D2rE,EAAel2F,KAAKsnF,eACpB6O,EAAan2F,KAAKoxF,cAEjBqE,IAAsBz1F,KAAKo2F,6BAC1BF,IAAiBC,GAClBD,IAAiBT,GAAqBU,IAAeV,KAIpDA,EAAoBz1F,KAAKo2F,6BAC3Bp2F,KAAKsnF,eAAiBtnF,KAAKo2F,4BAC3Bp2F,KAAKoxF,aAAeqE,IAEpBz1F,KAAKsnF,eAAiBmO,EACtBz1F,KAAKoxF,aAAepxF,KAAKo2F,6BAGzBp2F,KAAKsnF,iBAAmB4O,GACxBl2F,KAAKoxF,eAAiB+E,IAEtBn2F,KAAK80F,wBACL90F,KAAKyzF,kBACLzzF,KAAKm0F,2BAET,CAKA4B,gBAAAA,GACE/1F,KAAKsnD,YAAc,OAEftnD,KAAKmD,SACPnD,KAAKmD,OAAOgsE,cAAgBnvE,KAAKmD,OAAOokD,WAAa,QAGvDvnD,KAAKukD,YAAcvkD,KAAKq2F,mBACxBr2F,KAAKsjD,YAActjD,KAAK0S,YAAa,EACrC1S,KAAK4mD,cAAgB5mD,KAAK6mD,eAAgB,CAC5C,CAKAyvC,6BAAAA,CAA8B/uD,EAAe+lB,EAAaL,GACxD,MAAMspC,EAAmBtpC,EAAKjzB,MAAM,EAAGuN,GACrCivD,EAAgBx2F,KAAKwrD,cAAc+qC,GAAkBh2F,OACvD,GAAIgnC,IAAU+lB,EACZ,MAAO,CAAEg6B,eAAgBkP,EAAepF,aAAcoF,GAExD,MAAMC,EAAiBxpC,EAAKjzB,MAAMuN,EAAO+lB,GAEzC,MAAO,CACLg6B,eAAgBkP,EAChBpF,aAAcoF,EAHAx2F,KAAKwrD,cAAcirC,GAAgBl2F,OAKrD,CAKAm2F,6BAAAA,CACEnvD,EACA+lB,EACAtB,GAEA,MACEwqC,EADuBxqC,EAAUhyB,MAAM,EAAGuN,GACTptB,KAAK,IAAI5Z,OAC5C,GAAIgnC,IAAU+lB,EACZ,MAAO,CAAEg6B,eAAgBkP,EAAepF,aAAcoF,GAIxD,MAAO,CACLlP,eAAgBkP,EAChBpF,aAAcoF,EAJOxqC,EAAUhyB,MAAMuN,EAAO+lB,GACfnzC,KAAK,IAAI5Z,OAK1C,CAKAkzF,eAAAA,GAEE,GADAzzF,KAAK22F,kBAAoB,CAAA,EACpB32F,KAAK4vE,eAAV,CAGA,IAAK5vE,KAAK42F,kBAAmB,CAC3B,MAAM1F,EAAelxF,KAAK02F,8BACxB12F,KAAKsnF,eACLtnF,KAAKoxF,aACLpxF,KAAKmmF,OAEPnmF,KAAK4vE,eAAe0X,eAAiB4J,EAAa5J,eAClDtnF,KAAK4vE,eAAewhB,aAAeF,EAAaE,YAClD,CACApxF,KAAK62F,wBAVL,CAWF,CAQAC,kBAAAA,GACE,MAAMlnB,eAAEA,EAAc/uC,UAAEA,EAASR,UAAEA,EAASu2D,kBAAEA,GAAsB52F,KACpE,IAAK4vE,EACH,OAMF,MAAMmnB,EACJ12D,IAAciB,GACTjB,EAAU1R,QAAQ,WAAY,IAC/BkS,IAAcv4B,EACZvB,EACAG,EACF8vF,EAAmBh3F,KAAK0vC,oBAAoBqnD,EAAS,OAC3D/2F,KAAK22F,kBAAoB,CAAA,EACzB32F,KAAKitD,KAAO2iB,EAAe3rE,MAC3BjE,KAAKuF,IAAI,SAAS,GAClBvF,KAAK0lF,iBACL1lF,KAAKgrB,oBAAoBgsE,EAAkBD,EAAS,OACpD/2F,KAAKggB,YACL,MAAMkxE,EAAelxF,KAAKs2F,8BACxB1mB,EAAe0X,eACf1X,EAAewhB,aACfxhB,EAAe3rE,OAEjBjE,KAAKoxF,aAAepxF,KAAKsnF,eAAiB4J,EAAaE,aAClDwF,IACH52F,KAAKsnF,eAAiB4J,EAAa5J,gBAErCtnF,KAAK62F,wBACP,CAKAA,sBAAAA,GACE,GAAI72F,KAAKsnF,iBAAmBtnF,KAAKoxF,aAAc,CAC7C,MAAM51E,EAAQxb,KAAKi3F,wBACnBj3F,KAAK4vE,eAAgBp0D,MAAMrJ,KAAOqJ,EAAMrJ,KACxCnS,KAAK4vE,eAAgBp0D,MAAMpJ,IAAMoJ,EAAMpJ,GACzC,CACF,CAMA6kF,qBAAAA,GACE,IAAKj3F,KAAKmD,OACR,MAAO,CAAEgP,KAAM,MAAOC,IAAK,OAE7B,MAAM8kF,EAAkBl3F,KAAK42F,kBACvB52F,KAAKm3F,iBACLn3F,KAAKsnF,eACT0K,EAAahyF,KAAKiyF,qBAAqBiF,GACvCE,EAAiBp3F,KAAKgkF,oBAAoBkT,GAC1ClU,EAAYoU,EAAepU,UAC3B51B,EAAYgqC,EAAehqC,UAC3BiqC,EACEr3F,KAAKipF,qBAAqBjG,EAAW51B,EAAW,YAChDptD,KAAKsgC,WACP8nD,EAAa4J,EAAW5J,WACxBnsE,EAAgBjc,KAAK6tC,yBACrBypD,EAAct3F,KAAKmD,OAAOyhE,cAC1B2yB,EAAmBD,EAAYjlF,MAAQ4J,EACvCu7E,EAAoBF,EAAYhlF,OAAS2J,EACzCgsE,EAAWsP,EAAmBF,EAC9B/L,EAAYkM,EAAoBH,EAE5BtoF,EAAI,IAAI5C,GACZ6lF,EAAW7/E,KAAOi2E,EAClB4J,EAAW5/E,IAAM4/E,EAAW7E,UAAYkK,GAEvCroF,UAAUhP,KAAKk+B,uBACflvB,UAAUhP,KAAKmD,OAAO8b,mBACtBjS,SACC,IAAIb,GACFmrF,EAAYG,YAAcF,EAC1BD,EAAYI,aAAeF,IAqBjC,OAjBIzoF,EAAE1C,EAAI,IACR0C,EAAE1C,EAAI,GAEJ0C,EAAE1C,EAAI47E,IACRl5E,EAAE1C,EAAI47E,GAEJl5E,EAAE3C,EAAI,IACR2C,EAAE3C,EAAI,GAEJ2C,EAAE3C,EAAIk/E,IACRv8E,EAAE3C,EAAIk/E,GAIRv8E,EAAE1C,GAAKrM,KAAKmD,OAAO+c,QAAQ/N,KAC3BpD,EAAE3C,GAAKpM,KAAKmD,OAAO+c,QAAQ9N,IAEpB,CACLD,KAAM,GAAGpD,EAAE1C,MACX+F,IAAK,GAAGrD,EAAE3C,MACV0vB,SAAU,GAAGu7D,MACbA,WAAYA,EAEhB,CAKAvB,iBAAAA,GACE91F,KAAK23F,YAAc,CACjBr0C,YAAatjD,KAAKsjD,YAClBiB,YAAavkD,KAAKukD,YAClBqC,cAAe5mD,KAAK4mD,cACpBC,cAAe7mD,KAAK6mD,cACpBS,YAAatnD,KAAKsnD,YAClB50C,WAAY1S,KAAK0S,WACjBy8D,cAAenvE,KAAKmD,QAAUnD,KAAKmD,OAAOgsE,cAC1C5nB,WAAYvnD,KAAKmD,QAAUnD,KAAKmD,OAAOokD,WAE3C,CAKAqwC,oBAAAA,GACO53F,KAAK23F,cAIV33F,KAAKsnD,YAActnD,KAAK23F,YAAYrwC,YACpCtnD,KAAKsjD,YAActjD,KAAK23F,YAAYr0C,YACpCtjD,KAAKukD,YAAcvkD,KAAK23F,YAAYpzC,YACpCvkD,KAAK0S,WAAa1S,KAAK23F,YAAYjlF,WACnC1S,KAAK4mD,cAAgB5mD,KAAK23F,YAAY/wC,cACtC5mD,KAAK6mD,cAAgB7mD,KAAK23F,YAAY9wC,cAElC7mD,KAAKmD,SACPnD,KAAKmD,OAAOgsE,cACVnvE,KAAK23F,YAAYxoB,eAAiBnvE,KAAKmD,OAAOgsE,cAChDnvE,KAAKmD,OAAOokD,WACVvnD,KAAK23F,YAAYpwC,YAAcvnD,KAAKmD,OAAOokD,mBAGxCvnD,KAAK23F,YACd,CAMAE,eAAAA,GACE,MAAMjoB,EAAiB5vE,KAAK4vE,eAC5B5vE,KAAKk3D,UAAW,EAChBl3D,KAAK+sE,WAAY,EAEb6C,IACFA,EAAe7sC,MAAQ6sC,EAAe7sC,OACtC6sC,EAAev0D,YACbu0D,EAAev0D,WAAW+pD,YAAYwK,IAE1C5vE,KAAK4vE,eAAiB,KACtB5vE,KAAK0yF,uBACL1yF,KAAKsnF,iBAAmBtnF,KAAKoxF,cAAgBpxF,KAAKwlD,kBAClDxlD,KAAKoxF,aAAepxF,KAAKsnF,eACzBtnF,KAAK43F,uBACD53F,KAAK4kF,mBACP5kF,KAAK0lF,iBACL1lF,KAAKggB,YAET,CAKAgwD,WAAAA,GACE,MAAM8nB,EAAgB93F,KAAKg2F,kBAAoBh2F,KAAKitD,KAYpD,OAXAjtD,KAAK63F,kBAEL73F,KAAKqL,KAAK,kBACVysF,GAAiB93F,KAAKqL,KAAKhD,GACvBrI,KAAKmD,SACPnD,KAAKmD,OAAOkI,KAAK,sBAAuB,CACtCrB,OAAQhK,OAGV83F,GAAiB93F,KAAKmD,OAAOkI,KAAK,kBAAmB,CAAErB,OAAQhK,QAE1DA,IACT,CAKA+3F,uBAAAA,GACE,IAAK,MAAM9kF,KAAQjT,KAAK0nB,OACjB1nB,KAAK2jF,WAAW1wE,WACZjT,KAAK0nB,OAAOzU,EAGzB,CAOA+kF,iBAAAA,CAAkBzwD,EAAe+lB,GAC/B,MAAQ01B,UAAWiV,EAAW7qC,UAAW8qC,GACrCl4F,KAAKgkF,oBAAoBz8C,GAAO,IAChCy7C,UAAWmV,EAAS/qC,UAAWgrC,GAAYp4F,KAAKgkF,oBAChD12B,GACA,GAEJ,GAAI2qC,IAAcE,EAAS,CAEzB,GAAIn4F,KAAK0nB,OAAOuwE,GACd,IACE,IAAIxsF,EAAIysF,EACRzsF,EAAIzL,KAAKimF,oBAAoBgS,GAAW13F,OACxCkL,WAEOzL,KAAK0nB,OAAOuwE,GAAWxsF,GAIlC,GAAIzL,KAAK0nB,OAAOywE,GACd,IACE,IAAI1sF,EAAI2sF,EACR3sF,EAAIzL,KAAKimF,oBAAoBkS,GAAS53F,OACtCkL,IACA,CACA,MAAM4sF,EAAWr4F,KAAK0nB,OAAOywE,GAAS1sF,GAClC4sF,IACFr4F,KAAK0nB,OAAOuwE,KAAej4F,KAAK0nB,OAAOuwE,GAAa,IACpDj4F,KAAK0nB,OAAOuwE,GAAWC,EAAYzsF,EAAI2sF,GAAWC,EAEtD,CAGF,IAAK,IAAI5sF,EAAIwsF,EAAY,EAAGxsF,GAAK0sF,EAAS1sF,WACjCzL,KAAK0nB,OAAOjc,GAGrBzL,KAAKs4F,gBAAgBH,EAASF,EAAYE,EAC5C,MAEE,GAAIn4F,KAAK0nB,OAAOuwE,GAAY,CAC1B,MAAMI,EAAWr4F,KAAK0nB,OAAOuwE,GACvB7xB,EAAOgyB,EAAUF,EACvB,IAAK,IAAIzsF,EAAIysF,EAAWzsF,EAAI2sF,EAAS3sF,WAC5B4sF,EAAS5sF,GAElB,IAAK,MAAMokF,KAAQ7vF,KAAK0nB,OAAOuwE,GAAY,CACzC,MAAMM,EAAc/6E,SAASqyE,EAAM,IAC/B0I,GAAeH,IACjBC,EAASE,EAAcnyB,GAAQiyB,EAASxI,UACjCwI,EAASxI,GAEpB,CACF,CAEJ,CAOAyI,eAAAA,CAAgBtV,EAAmB3lE,GACjC,MAAMm7E,EAAe/3F,OAAOC,OAAO,CAAA,EAAIV,KAAK0nB,QAC5C,IAAK,MAAMu7D,KAAQjjF,KAAK0nB,OAAQ,CAC9B,MAAM+wE,EAAcj7E,SAASylE,EAAM,IAC/BwV,EAAczV,IAChBhjF,KAAK0nB,OAAO+wE,EAAcp7E,GAAUm7E,EAAaC,GAC5CD,EAAaC,EAAcp7E,WACvBrd,KAAK0nB,OAAO+wE,GAGzB,CACF,CAYAC,wBAAAA,CACE1V,EACA51B,EACAurC,EACAC,GAEA,MAAMC,EAA2D,CAAA,EAC3DC,EAAqB94F,KAAKimF,oBAAoBjD,GAAWziF,OACzDw4F,EAAcD,IAAuB1rC,EAE3C,IAAI4rC,GAA0B,EAC9BL,IAAQA,EAAM,GACd34F,KAAKs4F,gBAAgBtV,EAAW2V,GAChC,MAAMM,EAAmBj5F,KAAK0nB,OAAOs7D,GACjChjF,KAAK0nB,OAAOs7D,GAAyB,IAAd51B,EAAkBA,EAAYA,EAAY,QACjE5sD,EAIJ,IAAK,MAAM8I,KAAStJ,KAAK0nB,OAAOs7D,GAAY,CAC1C,MAAMkW,EAAW17E,SAASlU,EAAO,IAC7B4vF,GAAY9rC,IACd4rC,GAA0B,EAC1BH,EAAcK,EAAW9rC,GAAaptD,KAAK0nB,OAAOs7D,GAAW15E,GAEvDyvF,GAA6B,IAAd3rC,UACZptD,KAAK0nB,OAAOs7D,GAAW15E,GAGpC,CACA,IAAI6vF,GAAmB,EAevB,IAdIH,IAA4BD,IAG9B/4F,KAAK0nB,OAAOs7D,EAAY2V,GAAOE,EAC/BM,GAAmB,IAEjBA,GAAoBL,EAAqB1rC,IAI3CurC,IAIKA,EAAM,GACPC,GAAeA,EAAYD,EAAM,GACnC34F,KAAK0nB,OAAOs7D,EAAY2V,GAAO,CAC7B,EAAG,IAAKC,EAAYD,EAAM,KAEnBM,EACTj5F,KAAK0nB,OAAOs7D,EAAY2V,GAAO,CAC7B,EAAG,IAAKM,WAGHj5F,KAAK0nB,OAAOs7D,EAAY2V,GAEjCA,IAEF34F,KAAK4kF,kBAAmB,CAC1B,CASAwU,qBAAAA,CACEpW,EACA51B,EACAisC,EACAT,GAEK54F,KAAK0nB,SACR1nB,KAAK0nB,OAAS,CAAA,GAEhB,MAAM4xE,EAAoBt5F,KAAK0nB,OAAOs7D,GACpCuW,EAA0BD,EACtB,IAAKA,GACL,CAAA,EAEND,IAAaA,EAAW,GAGxB,IAAK,MAAM/vF,KAASiwF,EAAyB,CAC3C,MAAMC,EAAeh8E,SAASlU,EAAO,IACjCkwF,GAAgBpsC,IAClBksC,EAAkBE,EAAeH,GAC/BE,EAAwBC,GAErBD,EAAwBC,EAAeH,WACnCC,EAAkBE,GAG/B,CAEA,GADAx5F,KAAK4kF,kBAAmB,EACpBgU,EAAa,CACf,KAAOS,KACA54F,OAAOU,KAAKy3F,EAAYS,IAAW94F,SAGnCP,KAAK0nB,OAAOs7D,KACfhjF,KAAK0nB,OAAOs7D,GAAa,CAAA,GAE3BhjF,KAAK0nB,OAAOs7D,GAAW51B,EAAYisC,GAAY,IAC1CT,EAAYS,KAGnB,MACF,CACA,IAAKC,EACH,OAEF,MAAMnV,EAAWmV,EAAkBlsC,EAAYA,EAAY,EAAI,GAC/D,KAAO+2B,GAAYkV,KACjBr5F,KAAK0nB,OAAOs7D,GAAW51B,EAAYisC,GAAY,IAAKlV,EAExD,CAQAsV,mBAAAA,CACEC,EACAnyD,EACAqxD,GAEA,MAAMe,EAAY35F,KAAKgkF,oBAAoBz8C,GAAO,GAChDqyD,EAAa,CAAC,GAChB,IA0BInuF,EA1BAouF,EAAc,EAElB,IAAK,IAAIpuF,EAAI,EAAGA,EAAIiuF,EAAan5F,OAAQkL,IACf,OAApBiuF,EAAajuF,IACfouF,IACAD,EAAWC,GAAe,GAE1BD,EAAWC,KAoBf,IAhBID,EAAW,GAAK,IAClB55F,KAAKo5F,sBACHO,EAAU3W,UACV2W,EAAUvsC,UACVwsC,EAAW,GACXhB,GAEFA,EAAcA,GAAeA,EAAY5+D,MAAM4/D,EAAW,GAAK,IAEjEC,GACE75F,KAAK04F,yBACHiB,EAAU3W,UACV2W,EAAUvsC,UAAYwsC,EAAW,GACjCC,GAGCpuF,EAAI,EAAGA,EAAIouF,EAAapuF,IACvBmuF,EAAWnuF,GAAK,EAClBzL,KAAKo5F,sBACHO,EAAU3W,UAAYv3E,EACtB,EACAmuF,EAAWnuF,GACXmtF,GAEOA,GAKL54F,KAAK0nB,OAAOiyE,EAAU3W,UAAYv3E,IAAMmtF,EAAY,KACtD54F,KAAK0nB,OAAOiyE,EAAU3W,UAAYv3E,GAAG,GAAKmtF,EAAY,IAG1DA,EAAcA,GAAeA,EAAY5+D,MAAM4/D,EAAWnuF,GAAK,GAE7DmuF,EAAWnuF,GAAK,GAClBzL,KAAKo5F,sBACHO,EAAU3W,UAAYv3E,EACtB,EACAmuF,EAAWnuF,GACXmtF,EAGN,CASAvF,WAAAA,CAAY9rD,GAAwC,IAAzB+lB,EAAWhtD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGinC,EAAQ,EAC/CvnC,KAAKg4F,kBAAkBzwD,EAAO+lB,GAC9BttD,KAAKmmF,MAAM38E,OAAO+9B,EAAO+lB,EAAM/lB,GAC/BvnC,KAAKitD,KAAOjtD,KAAKmmF,MAAMhsE,KAAK,IAC5Bna,KAAKuF,IAAI,SAAS,GAClBvF,KAAK0lF,iBACL1lF,KAAKggB,YACLhgB,KAAK+3F,yBACP,CAcAxE,WAAAA,CACEtmC,EACAzxC,EACA+rB,GAEA,IADA+lB,EAAWhtD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGinC,EAEV+lB,EAAM/lB,GACRvnC,KAAKg4F,kBAAkBzwD,EAAO+lB,GAEhC,MAAMtB,EAAYhsD,KAAKwrD,cAAcyB,GACrCjtD,KAAKy5F,oBAAoBztC,EAAWzkB,EAAO/rB,GAC3Cxb,KAAKmmF,MAAQ,IACRnmF,KAAKmmF,MAAMnsD,MAAM,EAAGuN,MACpBykB,KACAhsD,KAAKmmF,MAAMnsD,MAAMszB,IAEtBttD,KAAKitD,KAAOjtD,KAAKmmF,MAAMhsE,KAAK,IAC5Bna,KAAKuF,IAAI,SAAS,GAClBvF,KAAK0lF,iBACL1lF,KAAKggB,YACLhgB,KAAK+3F,yBACP,CAMA+B,6BAAAA,CACEvyD,EACA+lB,EACA4jC,GAEIA,GAAgB3pD,GACd+lB,IAAQ/lB,EACVvnC,KAAK+5F,oBAAsBhzF,EAClB/G,KAAK+5F,sBAAwB7yF,IACtClH,KAAK+5F,oBAAsBhzF,EAC3B/G,KAAKoxF,aAAe7pD,GAEtBvnC,KAAKsnF,eAAiB4J,GACbA,EAAe3pD,GAAS2pD,EAAe5jC,EAC5CttD,KAAK+5F,sBAAwB7yF,EAC/BlH,KAAKoxF,aAAeF,EAEpBlxF,KAAKsnF,eAAiB4J,GAIpB5jC,IAAQ/lB,EACVvnC,KAAK+5F,oBAAsB7yF,EAClBlH,KAAK+5F,sBAAwBhzF,IACtC/G,KAAK+5F,oBAAsB7yF,EAC3BlH,KAAKsnF,eAAiBh6B,GAExBttD,KAAKoxF,aAAeF,EAExB,EChlCK,MAAe8I,WAIZpG,GA4CRiC,kBAAAA,GACE,MAAMh7E,EACH7a,KAAKmD,QAAU2X,GAAuB9a,KAAKmD,OAAOie,eACnD5c,IACIy1F,EAAWp/E,EAAI9G,cAAc,YACnCtT,OAAO8J,QAAQ,CACb2vF,eAAgB,MAChBC,YAAa,MACbC,aAAc,MACdC,WAAY,QACZ,cAAe,WACfC,KAAM,MACNvqD,KAAM,mBACLp3B,IAAIzT,IAAA,IAAEk3B,EAAWn4B,GAAMiB,EAAA,OAAK+0F,EAAS/9E,aAAakgB,EAAWn4B,KAChE,MAAMmO,IAAEA,EAAGD,KAAEA,EAAI2pB,SAAEA,GAAa97B,KAAKi3F,wBAGrCgD,EAASz+E,MAAMsB,QAAU,4BAA4B1K,YAAcD,uFAA0F2pB,MAE5J97B,KAAKu6F,yBAA2B1/E,EAAIK,MAAMo3E,YAAY2H,GAEvDx5F,OAAO8J,QAAQ,CACbw4B,KAAM,OACNy3D,QAAS,YACTC,MAAO,UACPC,MAAO,UACPC,KAAM,OACNC,IAAK,OACLC,MAAO,QACPC,iBAAkB,qBAClBC,kBAAmB,sBACnBC,eAAgB,qBACeriF,IAAI9N,IAAA,IAAEL,EAAWH,GAAQQ,EAAA,OACxDovF,EAAS/hF,iBACP1N,EACCxK,KAAKqK,GAA2Bw8B,KAAK7mC,SAG1CA,KAAK4vE,eAAiBqqB,CACxB,CAKAl3D,IAAAA,GACE/iC,KAAK0yF,sBACP,CAOAuI,SAAAA,CAAU1wE,GACR,IAAKvqB,KAAK+sE,UACR,OAEF,MAAMmuB,EAA4B,QAAnBl7F,KAAK6gC,UAAsB7gC,KAAKm7F,WAAan7F,KAAKo7F,QACjE,GAAI7wE,EAAE8wE,WAAWH,EACdl7F,KAAKk7F,EAAO3wE,EAAE8wE,UACb9wE,OAEG,MAAIA,EAAE8wE,WAAWr7F,KAAKs7F,mBAAoB/wE,EAAEgxE,UAAWhxE,EAAEixE,QAO9D,OALEx7F,KAAKA,KAAKs7F,gBAAgB/wE,EAAE8wE,UAG5B9wE,EAGJ,CACAA,EAAEkxE,2BACFlxE,EAAEC,iBACED,EAAE8wE,SAAW,IAAM9wE,EAAE8wE,SAAW,IAElCr7F,KAAK42F,mBAAoB,EACzB52F,KAAKwlD,kBACLxlD,KAAKm0F,2BAELn0F,KAAKmD,QAAUnD,KAAKmD,OAAO4c,kBAE/B,CAQA27E,OAAAA,CAAQnxE,IACDvqB,KAAK+sE,WAAa/sE,KAAK27F,WAAa37F,KAAK42F,kBAC5C52F,KAAK27F,WAAY,EAGfpxE,EAAE8wE,WAAWr7F,KAAK47F,gBAAkBrxE,EAAEgxE,SAAWhxE,EAAEixE,WAEnDx7F,KAAKA,KAAK47F,cAAcrxE,EAAE8wE,UAG1B9wE,GAIJA,EAAEkxE,2BACFlxE,EAAEC,iBACFxqB,KAAKmD,QAAUnD,KAAKmD,OAAO4c,mBAC7B,CAMA87E,OAAAA,CAA8DtxE,GAC5D,MAAMuxE,EAAY97F,KAAK87F,WACjB73F,MAAEA,EAAKqjF,eAAEA,EAAc8J,aAAEA,GAAiBpxF,KAAK4vE,eAGrD,GAFA5vE,KAAK87F,WAAY,EACjBvxE,GAAKA,EAAEE,mBACFzqB,KAAK+sE,UACR,OAEF,MAAMgvB,EAAgBA,KACpB/7F,KAAK82F,qBACL92F,KAAKqL,KAAKxD,GACN7H,KAAKmD,SACPnD,KAAKmD,OAAOkI,KAAK,eAAgB,CAAErB,OAAQhK,OAC3CA,KAAKmD,OAAO4c,qBAGhB,GAAkC,KAA9B/f,KAAK4vE,eAAe3rE,MAGtB,OAFAjE,KAAK0nB,OAAS,CAAA,OACdq0E,IAIF,MAAMC,EAAWh8F,KAAK8lF,oBAAoB7hF,GAAOmiF,aAC/C6V,EAAYj8F,KAAKmmF,MAAM5lF,OACvB27F,EAAgBF,EAASz7F,OACzB47F,EAAkBn8F,KAAKsnF,eACvB8U,EAAgBp8F,KAAKoxF,aACrBtoB,EAAYqzB,IAAoBC,EAClC,IAAIxD,EACFyD,EAEAC,EACAC,EAFAC,EAAWN,EAAgBD,EAI7B,MAAMQ,EAAoBz8F,KAAKs2F,8BAC7BhP,EACA8J,EACAntF,GAEIy4F,EAAaP,EAAkBM,EAAkBnV,eAEnDxe,GACFuzB,EAAcr8F,KAAKmmF,MAAMnsD,MAAMmiE,EAAiBC,GAChDI,GAAYJ,EAAgBD,GACnBD,EAAgBD,IAEvBI,EADEK,EACY18F,KAAKmmF,MAAMnsD,MAAMoiE,EAAgBI,EAAUJ,GAE3Cp8F,KAAKmmF,MAAMnsD,MACvBmiE,EACAA,EAAkBK,IAIxB,MAAM9C,EAAesC,EAAShiE,MAC5ByiE,EAAkBrL,aAAeoL,EACjCC,EAAkBrL,cAiCpB,GA/BIiL,GAAeA,EAAY97F,SACzBm5F,EAAan5F,SAIfq4F,EAAc54F,KAAKskF,mBACjB6X,EACAA,EAAkB,GAClB,GAGFvD,EAAcc,EAAa/gF,IACzB,IAGEigF,EAAa,KAGf9vB,GACFwzB,EAAaH,EACbI,EAAWH,GACFM,GAETJ,EAAaF,EAAgBC,EAAY97F,OACzCg8F,EAAWH,IAEXE,EAAaF,EACbG,EAAWH,EAAgBC,EAAY97F,QAEzCP,KAAKg4F,kBAAkBsE,EAAYC,IAEjC7C,EAAan5F,OAAQ,CACvB,MAAMuD,cAAEA,GAAkBI,IAExB43F,GACApC,EAAav/E,KAAK,MAAQrW,EAAc64F,aACvCx8F,EAAOy8F,wBAERhE,EAAc90F,EAAc+4F,iBAE9B78F,KAAKy5F,oBAAoBC,EAAcyC,EAAiBvD,EAC1D,CACAmD,GACF,CAKAe,kBAAAA,GACE98F,KAAK42F,mBAAoB,CAC3B,CAKAmG,gBAAAA,GACE/8F,KAAK42F,mBAAoB,CAC3B,CAEAoG,mBAAAA,CAAmB5xF,GAA+B,IAA9BpB,OAAEA,GAA0BoB,EAC9C,MAAMk8E,eAAEA,EAAc8J,aAAEA,GAAiBpnF,EACzChK,KAAKm3F,iBAAmB7P,EACxBtnF,KAAKi9F,eAAiB7L,EACtBpxF,KAAK62F,wBACP,CAKA8D,IAAAA,GACE,GAAI36F,KAAKsnF,iBAAmBtnF,KAAKoxF,aAE/B,OAEF,MAAMttF,cAAEA,GAAkBI,IAC1BJ,EAAc64F,WAAa38F,KAAKg1F,kBAC3B70F,EAAOy8F,sBAOV94F,EAAc+4F,qBAAkBr8F,EANhCsD,EAAc+4F,gBAAkB78F,KAAKskF,mBACnCtkF,KAAKsnF,eACLtnF,KAAKoxF,cACL,GAKJpxF,KAAK27F,WAAY,CACnB,CAKAd,KAAAA,GACE76F,KAAK87F,WAAY,CACnB,CASAoB,qBAAAA,CAAsBla,EAAmB51B,GACvC,IACE+vC,EADEC,EAAoBp9F,KAAK2oF,mBAAmB3F,GAOhD,OAJI51B,EAAY,IACd+vC,EAAQn9F,KAAKknF,aAAalE,GAAW51B,EAAY,GACjDgwC,GAAqBD,EAAMhrF,KAAOgrF,EAAM9qF,OAEnC+qF,CACT,CAQAC,mBAAAA,CAAoB9yE,EAAkB+yE,GACpC,MAAMC,EAAgBv9F,KAAKw9F,uBAAuBjzE,EAAG+yE,GACnDlG,EAAiBp3F,KAAKgkF,oBAAoBuZ,GAC1Cva,EAAYoU,EAAepU,UAE7B,GACEA,IAAchjF,KAAK2jF,WAAWpjF,OAAS,GACvCgqB,EAAEixE,SACY,KAAdjxE,EAAE8wE,QAGF,OAAOr7F,KAAKmmF,MAAM5lF,OAASg9F,EAE7B,MAAMnwC,EAAYgqC,EAAehqC,UAC/BgwC,EAAoBp9F,KAAKk9F,sBAAsBla,EAAW51B,GAC1DqwC,EAAmBz9F,KAAK09F,gBAAgB1a,EAAY,EAAGoa,GAEzD,OADoBp9F,KAAK2jF,WAAWX,GAAWhpD,MAAMozB,GAEnC7sD,OAChBk9F,EACA,EACAz9F,KAAKonF,qBAAqBpE,EAE9B,CASAwa,sBAAAA,CAAuBjzE,EAAkB+yE,GACvC,OAAI/yE,EAAEogD,UAAY3qE,KAAKsnF,iBAAmBtnF,KAAKoxF,cAAgBkM,EACtDt9F,KAAKoxF,aAELpxF,KAAKsnF,cAEhB,CAOAqW,iBAAAA,CAAkBpzE,EAAkB+yE,GAClC,MAAMC,EAAgBv9F,KAAKw9F,uBAAuBjzE,EAAG+yE,GACnDlG,EAAiBp3F,KAAKgkF,oBAAoBuZ,GAC1Cva,EAAYoU,EAAepU,UAC7B,GAAkB,IAAdA,GAAmBz4D,EAAEixE,SAAyB,KAAdjxE,EAAE8wE,QAEpC,OAAQkC,EAEV,MAAMnwC,EAAYgqC,EAAehqC,UAC/BgwC,EAAoBp9F,KAAKk9F,sBAAsBla,EAAW51B,GAC1DqwC,EAAmBz9F,KAAK09F,gBAAgB1a,EAAY,EAAGoa,GACvDQ,EAAmB59F,KAAK2jF,WAAWX,GAAWhpD,MAAM,EAAGozB,GACvDg6B,EAAuBpnF,KAAKonF,qBAAqBpE,EAAY,GAE/D,OACGhjF,KAAK2jF,WAAWX,EAAY,GAAGziF,OAChCk9F,EACAG,EAAiBr9F,QAChB,EAAI6mF,EAET,CAMAsW,eAAAA,CAAgB1a,EAAmB3wE,GACjC,MAAM4wE,EAAOjjF,KAAK2jF,WAAWX,GAE7B,IAEE6a,EACAC,EAHEC,EADe/9F,KAAK2oF,mBAAmB3F,GAEzCgb,EAAc,EAIhB,IAAK,IAAIzmD,EAAI,EAAGmkB,EAAOunB,EAAK1iF,OAAQg3C,EAAImkB,EAAMnkB,IAG5C,GAFAsmD,EAAY79F,KAAKknF,aAAalE,GAAWzrC,GAAGllC,MAC5C0rF,GAAsBF,EAClBE,EAAqB1rF,EAAO,CAC9ByrF,GAAa,EACb,MAAMG,EAAWF,EAAqBF,EACpCK,EAAYH,EACZI,EAAqBv5F,KAAKmH,IAAIkyF,EAAW5rF,GAG3C2rF,EAFwBp5F,KAAKmH,IAAImyF,EAAY7rF,GAET8rF,EAAqB5mD,EAAIA,EAAI,EACjE,KACF,CAQF,OAJKumD,IACHE,EAAc/a,EAAK1iF,OAAS,GAGvBy9F,CACT,CAMAI,cAAAA,CAAe7zE,GAEXvqB,KAAKsnF,gBAAkBtnF,KAAKmmF,MAAM5lF,QAClCP,KAAKoxF,cAAgBpxF,KAAKmmF,MAAM5lF,QAIlCP,KAAKq+F,oBAAoB,OAAQ9zE,EACnC,CAMA+zE,YAAAA,CAAa/zE,GACiB,IAAxBvqB,KAAKsnF,gBAA8C,IAAtBtnF,KAAKoxF,cAGtCpxF,KAAKq+F,oBAAoB,KAAM9zE,EACjC,CAOA8zE,mBAAAA,CAAoBx9D,EAA0BtW,GAC5C,MAAMlN,EAASrd,KAAK,MAAM6gC,iBACxBtW,EACAvqB,KAAK+5F,sBAAwB7yF,GAO/B,GALIqjB,EAAEogD,SACJ3qE,KAAKu+F,oBAAoBlhF,GAEzBrd,KAAKw+F,uBAAuBnhF,GAEf,IAAXA,EAAc,CAChB,MAAMxY,EAAM7E,KAAKitD,KAAK1sD,OACtBP,KAAKsnF,eAAiBlkD,GAAS,EAAGpjC,KAAKsnF,eAAgBziF,GACvD7E,KAAKoxF,aAAehuD,GAAS,EAAGpjC,KAAKoxF,aAAcvsF,GAGnD7E,KAAK0yF,uBACL1yF,KAAKyxF,oBACLzxF,KAAK80F,wBACL90F,KAAKyzF,iBACP,CACF,CAMA8K,mBAAAA,CAAoBlhF,GAClB,MAAM6zE,EACJlxF,KAAK+5F,sBAAwBhzF,EACzB/G,KAAKsnF,eAAiBjqE,EACtBrd,KAAKoxF,aAAe/zE,EAM1B,OALArd,KAAK85F,8BACH95F,KAAKsnF,eACLtnF,KAAKoxF,aACLF,GAEgB,IAAX7zE,CACT,CAMAmhF,sBAAAA,CAAuBnhF,GAQrB,OAPIA,EAAS,GACXrd,KAAKsnF,gBAAkBjqE,EACvBrd,KAAKoxF,aAAepxF,KAAKsnF,iBAEzBtnF,KAAKoxF,cAAgB/zE,EACrBrd,KAAKsnF,eAAiBtnF,KAAKoxF,cAEX,IAAX/zE,CACT,CAMAohF,cAAAA,CAAel0E,GACe,IAAxBvqB,KAAKsnF,gBAA8C,IAAtBtnF,KAAKoxF,cAGtCpxF,KAAK0+F,uBAAuB,OAAQn0E,EACtC,CAQAo0E,KAAAA,CACEp0E,EACAtX,EACA4tB,GAEA,IAAI+9D,EACJ,GAAIr0E,EAAEggD,OACJq0B,EAAW5+F,KAAK,mBAAmB6gC,KAAa7gC,KAAKiT,QAChD,KAAIsX,EAAEixE,SAAyB,KAAdjxE,EAAE8wE,SAAgC,KAAd9wE,EAAE8wE,QAI5C,OADAr7F,KAAKiT,IAAuB,SAAd4tB,GAAuB,EAAK,GACnC,EAHP+9D,EAAW5+F,KAAK,mBAAmB6gC,KAAa7gC,KAAKiT,GAIvD,CACA,YAAwB,IAAb2rF,GAA4B5+F,KAAKiT,KAAU2rF,IACpD5+F,KAAKiT,GAAQ2rF,GACN,EAGX,CAKAC,SAAAA,CAAUt0E,EAAkBtX,GAC1B,OAAOjT,KAAK2+F,MAAMp0E,EAAGtX,EAAM,OAC7B,CAKA6rF,UAAAA,CAAWv0E,EAAkBtX,GAC3B,OAAOjT,KAAK2+F,MAAMp0E,EAAGtX,EAAM,QAC7B,CAMA8rF,0BAAAA,CAA2Bx0E,GACzB,IAAIy0E,GAAS,EAYb,OAXAh/F,KAAK+5F,oBAAsBhzF,EAKzB/G,KAAKoxF,eAAiBpxF,KAAKsnF,gBACH,IAAxBtnF,KAAKsnF,iBAEL0X,EAASh/F,KAAK6+F,UAAUt0E,EAAG,mBAE7BvqB,KAAKoxF,aAAepxF,KAAKsnF,eAClB0X,CACT,CAMAC,uBAAAA,CAAwB10E,GACtB,OACEvqB,KAAK+5F,sBAAwB7yF,GAC7BlH,KAAKsnF,iBAAmBtnF,KAAKoxF,aAEtBpxF,KAAK6+F,UAAUt0E,EAAG,gBACQ,IAAxBvqB,KAAKsnF,gBACdtnF,KAAK+5F,oBAAsBhzF,EACpB/G,KAAK6+F,UAAUt0E,EAAG,wBAFpB,CAIT,CAMA20E,eAAAA,CAAgB30E,GAEZvqB,KAAKsnF,gBAAkBtnF,KAAKmmF,MAAM5lF,QAClCP,KAAKoxF,cAAgBpxF,KAAKmmF,MAAM5lF,QAIlCP,KAAK0+F,uBAAuB,QAASn0E,EACvC,CAOAm0E,sBAAAA,CAAuB79D,EAA6BtW,GAClD,MAAMkxB,EAAa,aAAa5a,IAC9BtW,EAAEogD,SAAW,YAAc,iBAE7B3qE,KAAKk0F,sBAAwB,EACzBl0F,KAAKy7C,GAAYlxB,KAGnBvqB,KAAK0yF,uBACL1yF,KAAKyxF,oBACLzxF,KAAK80F,wBACL90F,KAAKyzF,kBAET,CAMA0L,wBAAAA,CAAyB50E,GACvB,OACEvqB,KAAK+5F,sBAAwBhzF,GAC7B/G,KAAKsnF,iBAAmBtnF,KAAKoxF,aAEtBpxF,KAAK8+F,WAAWv0E,EAAG,kBACjBvqB,KAAKoxF,eAAiBpxF,KAAKmmF,MAAM5lF,QAC1CP,KAAK+5F,oBAAsB7yF,EACpBlH,KAAK8+F,WAAWv0E,EAAG,sBAFrB,CAIT,CAMA60E,2BAAAA,CAA4B70E,GAC1B,IAAI42B,GAAU,EASd,OARAnhD,KAAK+5F,oBAAsB7yF,EAEvBlH,KAAKsnF,iBAAmBtnF,KAAKoxF,cAC/BjwC,EAAUnhD,KAAK8+F,WAAWv0E,EAAG,kBAC7BvqB,KAAKoxF,aAAepxF,KAAKsnF,gBAEzBtnF,KAAKsnF,eAAiBtnF,KAAKoxF,aAEtBjwC,CACT,EClqBF,MAAMk+C,GAAiB90E,KAAgBA,EAAiB6qD,OAEjD,MAAekqB,WAIZtF,GAA2Cl6F,WAAAA,GAAAM,SAAAE,WAAAP,EAAAC,KAAA,6BAAA,EAAA,CAGnD6zF,YAAAA,GAEE7zF,KAAKmK,GAAG,YAAanK,KAAKu/F,mBAC1Bv/F,KAAKmK,GAAG,UAAWnK,KAAKq7C,gBACxBr7C,KAAKmK,GAAG,gBAAiBnK,KAAKw/F,oBAC9Bx/F,KAAKmK,GAAG,mBAAoBnK,KAAKy/F,oBAEjCz/F,KAAK0/F,sBAAwB,IAAIhP,GAC/B1wF,MAGFI,MAAMyzF,cACR,CASAhuC,mBAAAA,GACE,OAAO7lD,KAAK0/F,sBAAsBpO,UACpC,CAQAvrC,WAAAA,CAAYx7B,GACV,OAAOvqB,KAAK0/F,sBAAsB35C,YAAYx7B,EAChD,CAKAy7B,OAAAA,CAAQz7B,GACN,OAAOvqB,KAAK0/F,sBAAsB15C,QAAQz7B,EAC5C,CAKAi1E,kBAAAA,CAAmBt9F,GACZlC,KAAK+sE,YAGV/sE,KAAKw1F,WAAWx1F,KAAKmxF,6BAA6BjvF,EAAQqoB,IAC1DvqB,KAAKm0F,0BACP,CAKAsL,kBAAAA,CAAmBv9F,GACZlC,KAAK+sE,YAGV/sE,KAAK21F,WAAW31F,KAAKmxF,6BAA6BjvF,EAAQqoB,IAC1DvqB,KAAKm0F,0BACP,CAUAoL,iBAAAA,CAAiBr6F,GAA2D,IAA1DqlB,EAAEA,EAAC4/C,gBAAEA,GAAmDjlE,EAErElF,KAAKmD,QACLnD,KAAK2yF,WACN0M,GAAc90E,KACdvqB,KAAKijD,qBAKHjjD,KAAK0/F,sBAAsBn4D,MAAMhd,KAIrCvqB,KAAKmD,OAAOmzE,mBAAmB1uC,SAAS5nC,MAEpCmqE,IACFnqE,KAAK42F,mBAAoB,EACzB52F,KAAKwxF,iBAAiBjnE,IAGpBvqB,KAAK+sE,YACP/sE,KAAKo2F,4BAA8Bp2F,KAAKsnF,eACpCtnF,KAAKsnF,iBAAmBtnF,KAAKoxF,cAC/BpxF,KAAK0yF,uBAEP1yF,KAAKm0F,2BAEPn0F,KAAKk3D,WAALl3D,KAAKk3D,SAAaiT,GAAmBnqE,KAAK+sE,YAC5C,CAMA1xB,cAAAA,CAAcxwC,GAAmD,IAAlD0f,EAAEA,EAACvb,UAAEA,GAA2CnE,EAC7D,MAAM80F,EAAU3/F,KAAK0/F,sBAAsBpyC,IAAI/iC,GAE/C,GAAIvqB,KAAKmD,OAAQ,CACfnD,KAAKmD,OAAOmzE,mBAAmBpuC,WAAWloC,MAE1C,MAAMu3D,EAAev3D,KAAKmD,OAAOghD,cACjC,GAAIoT,GAAgBA,IAAiBv3D,KAInC,MAEJ,EAGGA,KAAK2yF,UACL3yF,KAAK0sC,QAAU1sC,KAAK0sC,MAAM+rB,aAC1BzpD,GAAaA,EAAUkqC,iBACxBmmD,GAAc90E,IACdo1E,GAKE3/F,KAAKk3D,WAAal3D,KAAKijD,qBACzBjjD,KAAKwzF,aAAajpE,GACdvqB,KAAKsnF,iBAAmBtnF,KAAKoxF,aAC/BpxF,KAAKyxF,mBAAkB,GAEvBzxF,KAAKm0F,0BAGX,CAMA3C,gBAAAA,CAAiBjnE,GACf,MAAM2mE,EAAelxF,KAAKmxF,6BAA6B5mE,GACrDgd,EAAQvnC,KAAKsnF,eACbh6B,EAAMttD,KAAKoxF,aACT7mE,EAAEogD,SACJ3qE,KAAK85F,8BAA8BvyD,EAAO+lB,EAAK4jC,IAE/ClxF,KAAKsnF,eAAiB4J,EACtBlxF,KAAKoxF,aAAeF,GAElBlxF,KAAK+sE,YACP/sE,KAAK80F,wBACL90F,KAAKyzF,kBAET,CAOAtC,4BAAAA,CAA6B5mE,GAC3B,MAAMq1E,EAAc5/F,KAAKmD,OAAQknE,cAAc9/C,GAC5Cvb,UAAUkG,GAAgBlV,KAAKk+B,wBAC/B5xB,IAAI,IAAIH,IAAOnM,KAAKqoF,kBAAmBroF,KAAKuoF,kBAC/C,IAAIj2E,EAAS,EACX86C,EAAY,EACZ41B,EAAY,EAEd,IAAK,IAAIv3E,EAAI,EAAGA,EAAIzL,KAAK2jF,WAAWpjF,QAC9B+R,GAAUstF,EAAYxzF,EADgBX,IAExC6G,GAAUtS,KAAKyoF,gBAAgBh9E,GAC/Bu3E,EAAYv3E,EACRA,EAAI,IACN2hD,GACEptD,KAAK2jF,WAAWl4E,EAAI,GAAGlL,OAASP,KAAKonF,qBAAqB37E,EAAI,IAOtE,IAAI4G,EADmBzN,KAAKmH,IAAI/L,KAAK2oF,mBAAmB3F,IAExD,MAAM6c,EAAa7/F,KAAK2jF,WAAWX,GAAWziF,OACxC8sD,EAAQrtD,KAAKknF,aAAalE,GAChC,IAAK,IAAIzrC,EAAI,EAAGA,EAAIsoD,EAAYtoD,IAAK,CAEnC,MACMuoD,EAAaztF,EADDg7C,EAAM9V,GAAG4vC,YAE3B,GAAIyY,EAAYvzF,GAAKyzF,EAAY,CAI7Bl7F,KAAKmH,IAAI6zF,EAAYvzF,EAAIyzF,IACzBl7F,KAAKmH,IAAI6zF,EAAYvzF,EAAIgG,IAEzB+6C,IAEF,KACF,CACA/6C,EAAQytF,EACR1yC,GACF,CAEA,OAAOxoD,KAAKiJ,IAEV7N,KAAKoX,MAAQyoF,EAAazyC,EAAYA,EACtCptD,KAAKmmF,MAAM5lF,OAEf,ECjOF,MAAMw/F,GAAwC,eACxCC,GAA0C,iBAC1CC,GAA0C,iBAC1CC,GAA2C,kBAC3CC,GAAsC,cCT/BC,GAAuBA,CAClCpkF,EACA7Y,KAEA,MAAMgZ,EAAQhZ,EAAO8c,mBACrBjE,EAAIm1B,aAAah1B,EAAO,EAAG,EAAGA,EAAO,EAAG,GACxC,MAAMoG,EAAIpf,EAAO8b,kBACjBjD,EAAIhN,UAAUuT,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,KC8BnC89E,GAAuD,CAClE/Y,eAAgB,EAChB8J,aAAc,EACd9lB,eAAgB,uBAChByB,WAAW,EACX4lB,UAAU,EACV0D,mBAAoB,yBACpB9P,YAAa,EACb+Z,YAAa,GACb7L,YAAa,IACbJ,eAAgB,IAChBkM,SAAS,EACThG,wBAAyB,KACzBa,QFpCmC,CACnC,EAAG+E,GACH,GAAIA,GACJ,GAAIJ,GACJ,GAAIC,GACJ,GAAIE,GACJ,GAAID,GACJ,GAAIA,GACJ,GAAIF,GACJ,GAAIG,GACJ,GAAIF,IE2BJ7E,WFxBsC,CACtC,EAAGgF,GACH,GAAIA,GACJ,GAAIJ,GACJ,GAAIC,GACJ,GAAIC,GACJ,GAAIC,GACJ,GAAIA,GACJ,GAAIH,GACJ,GAAIE,GACJ,GAAID,IEeJ1E,gBFA2C,CAC3C,GAAI,UEAJM,cFVyC,CACzC,GAAI,OAEJ,GAAI,OEdJ7B,oBAAqB,KACrB5E,SAAU,WACVyB,mBAAmB,GA8Ed,MAAM4J,WAKHlB,GAgFR,kBAAO7/E,GACL,MAAO,IAAKrf,MAAMqf,iBAAkB+gF,GAAM9gF,YAC5C,CAIA,QAAI1W,GACF,MAAMA,EAAO5I,MAAM4I,KAEnB,MAAgB,UAATA,EAAmB,SAAWA,CACvC,CAOAlJ,WAAAA,CAAYmtD,EAAc/qD,GACxB9B,MAAM6sD,EAAM,IAAKuzC,GAAM9gF,eAAgBxd,IACvClC,KAAK6zF,cACP,CAQA1gF,IAAAA,CAAK5R,EAAa0C,GAChB,OAAIjE,KAAK+sE,WAAa/sE,KAAK23F,aAAep2F,KAAOvB,KAAK23F,aAEpD33F,KAAK23F,YAAYp2F,GAAO0C,EACjBjE,OAEG,WAARuB,IACFvB,KAAKmD,kBAAkB+tE,IACrBlxE,KAAKmD,OAAOmzE,mBAAmBjtE,OAAOrJ,MACxCiE,aAAiBitE,IAAUjtE,EAAMqyE,mBAAmBhqE,IAAItM,OAEnDI,MAAM+S,KAAK5R,EAAK0C,GACzB,CAMAw8F,iBAAAA,CAAkBn3F,GAChBA,EAAQ1E,KAAKC,IAAIyE,EAAO,GACxBtJ,KAAK0gG,eAAe,iBAAkBp3F,EACxC,CAMAq3F,eAAAA,CAAgBr3F,GACdA,EAAQ1E,KAAKiJ,IAAIvE,EAAOtJ,KAAKitD,KAAK1sD,QAClCP,KAAK0gG,eAAe,eAAgBp3F,EACtC,CAOUo3F,cAAAA,CACRrtF,EACA/J,GAEItJ,KAAKqT,KAAc/J,IACrBtJ,KAAK80F,wBACL90F,KAAKqT,GAAY/J,GAEnBtJ,KAAKyzF,iBACP,CAMAqB,qBAAAA,GACE90F,KAAKqL,KAAK,qBACVrL,KAAKmD,QAAUnD,KAAKmD,OAAOkI,KAAK,yBAA0B,CAAErB,OAAQhK,MACtE,CASA0lF,cAAAA,GACE1lF,KAAK+sE,WAAa/sE,KAAKyxF,oBACvBrxF,MAAMslF,gBACR,CAUApB,kBAAAA,GAIE,IAHAC,EAAkBjkF,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKsnF,gBAAkB,EAC5C9C,EAAgBlkF,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKoxF,aACxBvW,EAAkBv6E,UAAAC,OAAA,EAAAD,kBAAAE,EAElB,OAAOJ,MAAMkkF,mBAAmBC,EAAYC,EAAU3J,EACxD,CAQA8J,kBAAAA,CACEj9D,GAGA,IAFA68D,EAAkBjkF,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKsnF,gBAAkB,EAC5C9C,EAAgBlkF,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKoxF,aAExB,OAAOhxF,MAAMukF,mBAAmBj9D,EAAQ68D,EAAYC,EACtD,CAOAR,mBAAAA,GAGE,IAFAsD,EAAchnF,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKsnF,eACtBC,EAAsBjnF,UAAAC,OAAA,EAAAD,kBAAAE,EAEtB,OAAOJ,MAAM4jF,oBAAoBsD,EAAgBC,EACnD,CAMA1jE,MAAAA,CAAO7H,GACL5b,MAAMyjB,OAAO7H,GAGbhc,KAAK22F,kBAAoB,CAAA,EACzB32F,KAAKm0F,yBACP,CAMAxrE,eAAAA,CAAgBzmB,GACd,MAAM6qE,EAAY/sE,KAAK+sE,UACvB/sE,KAAK+sE,WAAY,EACjB,MAAM5pE,EAAS/C,MAAMuoB,gBAAgBzmB,GAErC,OADAlC,KAAK+sE,UAAYA,EACV5pE,CACT,CAMAgxF,uBAAAA,GACE,IAAKn0F,KAAK+sE,YAAc/sE,KAAKmD,OAC3B,OAEF,MAAM6Y,EAAMhc,KAAKwlD,iBAAgB,GACjC,IAAKxpC,EACH,OAEF,MAAMg2E,EAAahyF,KAAKiyF,uBAElBj7C,EAAYh3C,KAAK4gG,4BACjBC,EAA2B7pD,EAAUz2C,OAAS,EACpD,IACIugG,EADAC,EAAuC/kF,EAE3C,GAAI6kF,EAA0B,CAE5BC,EAAgB7sF,GAAuB+H,EAAI7Y,QAC3C49F,EAAaD,EAAc19F,WAAW,MACtCg9F,GAAqBW,EAAY/gG,KAAKmD,QACtC,MAAMqhB,EAAIxkB,KAAKk+B,sBACf6iE,EAAW/xF,UAAUwV,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GACvD,CAQA,GANIxkB,KAAKsnF,iBAAmBtnF,KAAKoxF,cAAiBpxF,KAAK42F,kBAGrD52F,KAAKghG,gBAAgBD,EAAY/O,GAFjChyF,KAAKihG,aAAaF,EAAY/O,GAK5B6O,EAIF,IAAK,MAAMvpD,KAAYN,EAAW,CAChC,MAAMv0B,EAAW60B,EAAS70B,SACpBy+E,EAAiBjtF,GAAuB+H,EAAI7Y,QAC5Cg+F,EAAcD,EAAe99F,WAAW,MAG9C,GAFAg9F,GAAqBe,EAAanhG,KAAKmD,SAElCsf,EAASuc,mBAAoB,CAChC,MAAMxa,EAAI8yB,EAASpZ,sBACnBijE,EAAYnyF,UAAUwV,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GAAIA,EAAE,GACxD,CACA/B,EAASzT,UAAUmyF,GAEnB1+E,EAAS6vB,WAAW6uD,GAAa,EAAM,CAAA,GACvCnhG,KAAK+yC,oBAAoBguD,EAAYt+E,EAAUy+E,EACjD,CAGEL,IACF7kF,EAAIm1B,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GAChCn1B,EAAIwH,UAAUs9E,EAAgB,EAAG,IAGnC9gG,KAAKmD,OAAOqlE,iBAAkB,EAC9BxsD,EAAI6G,SACN,CASA+9E,yBAAAA,GACE,MAAMQ,EAAoC,GAE1C,IAAIjwF,EAAgCnR,KACpC,KAAOmR,GACDA,EAAIsR,UACN2+E,EAAkB12F,KAAKyG,GAEzBA,EAAMA,EAAI2gC,OAGZ,OAAOsvD,CACT,CAUAnP,oBAAAA,GAGoB,IAFlB3oF,EAAahJ,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKsnF,eACrB+Z,EAAqB/gG,UAAAC,OAAA,EAAAD,kBAAAE,EAErB,MAAM2R,EAAOnS,KAAKqoF,iBAChBj2E,EAAMpS,KAAKuoF,gBACXnnD,EAAUphC,KAAKshG,4BAA4Bh4F,EAAO+3F,GACpD,MAAO,CACLlvF,KAAMA,EACNC,IAAKA,EACLg2E,WAAYhnD,EAAQjvB,KACpBg7E,UAAW/rD,EAAQhvB,IAEvB,CAQAkvF,2BAAAA,CACEh4F,EACA+3F,GAEA,OAAIA,EACKrhG,KAAKuhG,6BAA6Bj4F,GAEvCtJ,KAAK22F,mBAAqB,QAAS32F,KAAK22F,kBACnC32F,KAAK22F,kBAEN32F,KAAK22F,kBAAoB32F,KAAKuhG,6BAA6Bj4F,EACrE,CAOAi4F,4BAAAA,CAA6Bj4F,GAC3B,IAAI6jF,EAAY,EACd/E,EAAa,EACf,MAAMh7B,UAAEA,EAAS41B,UAAEA,GAAchjF,KAAKgkF,oBAAoB16E,IACpD+2B,UAAEA,EAASQ,UAAEA,GAAc7gC,KACjC,IAAK,IAAIyL,EAAI,EAAGA,EAAIu3E,EAAWv3E,IAC7B0hF,GAAantF,KAAKyoF,gBAAgBh9E,GAEpC,MAAMi9E,EAAiB1oF,KAAK2oF,mBAAmB3F,GACzCma,EAAQn9F,KAAKknF,aAAalE,GAAW51B,GAC3C+vC,IAAU/U,EAAa+U,EAAMhrF,MAEN,IAArBnS,KAAK2gC,aACLysB,IAAcptD,KAAK2jF,WAAWX,GAAWziF,SAEzC6nF,GAAcpoF,KAAKsqF,0BAErB,IAAIn4E,EAAOu2E,GAAkBN,EAAa,EAAIA,EAAa,GAe3D,OAbIvnD,IAAct4B,IAEd83B,IAAcn5B,GACdm5B,IAAciB,IACdjB,IAAcmB,GAEdrvB,IAAQ,EACCkuB,IAAct5B,GAAQs5B,IAAckB,GAC7CpvB,EAAOu2E,GAAkBN,EAAa,EAAIA,EAAa,GAC9C/nD,IAAcv5B,GAAUu5B,IAAcoB,KAC/CtvB,EAAOu2E,GAAkBN,EAAa,EAAIA,EAAa,KAGpD,CACLh2E,IAAK+6E,EACLh7E,OAEJ,CAOAqvF,cAAAA,CAAela,GACbtnF,KAAKyhG,cACHzhG,KAAKmD,OAAQquC,WACbxxC,KAAKiyF,qBAAqB3K,GAAgB,GAC1CA,EAEJ,CAOA2Z,YAAAA,CAAajlF,EAA+Bg2E,GAC1ChyF,KAAKyhG,cAAczlF,EAAKg2E,EAAYhyF,KAAKsnF,eAC3C,CAQAoa,sBAAAA,GAGuB,IAFrBpa,EAAsBhnF,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKsnF,eAC9B0K,EAA4B1xF,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKiyF,qBAAqB3K,GAEzD,MAAM8P,EAAiBp3F,KAAKgkF,oBAAoBsD,GAC9CtE,EAAYoU,EAAepU,UAC3B51B,EACEgqC,EAAehqC,UAAY,EAAIgqC,EAAehqC,UAAY,EAAI,EAChEiqC,EAAar3F,KAAKipF,qBAAqBjG,EAAW51B,EAAW,YAC7D3kC,EAAazoB,KAAKyxC,mBAAmBplC,EAAIrM,KAAKmD,OAAQsd,UACtD8lE,EAAcvmF,KAAKumF,YAAc99D,EACjCza,EAAKhO,KAAKipF,qBAAqBjG,EAAW51B,EAAW,UACrD+/B,EACE6E,EAAW7E,WACT,EAAIntF,KAAKmhC,mBAAqBnhC,KAAKyoF,gBAAgBzF,GACnDhjF,KAAKsgC,WACP+2D,GAAc,EAAIr3F,KAAKmhC,mBAE3B,MAAO,CACLlI,MACEj5B,KAAKsgG,aACJtgG,KAAKipF,qBAAqBjG,EAAW51B,EAAW,QACnDpwB,QAASh9B,KAAKk0F,sBACd/hF,KAAM6/E,EAAW7/E,KAAO6/E,EAAW5J,WAAa7B,EAAc,EAC9Dn0E,IAAK+6E,EAAY6E,EAAW5/E,IAAMpE,EAClCqE,MAAOk0E,EACPj0E,OAAQ+kF,EAEZ,CAMAoK,aAAAA,CACEzlF,EACAg2E,EACA1K,GAEA,MAAMruD,MAAEA,EAAK+D,QAAEA,EAAO7qB,KAAEA,EAAIC,IAAEA,EAAGC,MAAEA,EAAKC,OAAEA,GACxCtS,KAAK0hG,uBAAuBpa,EAAgB0K,GAC9Ch2E,EAAIsI,UAAY2U,EAChBjd,EAAI23B,YAAc3W,EAClBhhB,EAAIy3B,SAASthC,EAAMC,EAAKC,EAAOC,EACjC,CAOA0uF,eAAAA,CAAgBhlF,EAA+Bg2E,GAC7C,MAAMlpB,EAAY,CAChBwe,eAAgBtnF,KAAK42F,kBACjB52F,KAAK4vE,eAAgB0X,eACrBtnF,KAAKsnF,eACT8J,aAAcpxF,KAAK42F,kBACf52F,KAAK4vE,eAAgBwhB,aACrBpxF,KAAKoxF,cAEXpxF,KAAK2hG,iBAAiB3lF,EAAK8sD,EAAWkpB,EACxC,CAKA/rC,sBAAAA,GACE,MAAM4sC,EACJ7yF,KAAK0/F,sBAAsB/N,wBAC7B3xF,KAAK2hG,iBACH3hG,KAAKmD,OAAQquC,WACbqhD,EACA7yF,KAAKiyF,qBAAqBY,EAAmBvL,gBAAgB,GAEjE,CAEAphC,sBAAAA,CAAuB37B,GACrB,MAAMq3E,EAAgB5hG,KAAKmxF,6BAA6B5mE,GACxDvqB,KAAKwhG,eAAeI,EACtB,CASAD,gBAAAA,CACE3lF,EACA8sD,EACAkpB,GAEA,MAAM3xD,UAAEA,EAASQ,UAAEA,GAAc7gC,KAC3BsnF,EAAiBxe,EAAUwe,eAC/B8J,EAAetoB,EAAUsoB,aACzB3F,EAAYprD,EAAUpvB,SAASqwB,IAC/BiG,EAAQvnC,KAAKgkF,oBAAoBsD,GACjCh6B,EAAMttD,KAAKgkF,oBAAoBoN,GAC/ByQ,EAAYt6D,EAAMy7C,UAClB8e,EAAUx0C,EAAI01B,UACd+e,EAAYx6D,EAAM6lB,UAAY,EAAI,EAAI7lB,EAAM6lB,UAC5C40C,EAAU10C,EAAIF,UAAY,EAAI,EAAIE,EAAIF,UAExC,IAAK,IAAI3hD,EAAIo2F,EAAWp2F,GAAKq2F,EAASr2F,IAAK,CACzC,MAAMgkF,EAAazvF,KAAK2oF,mBAAmBl9E,IAAM,EACjD,IAAI60B,EAAatgC,KAAKyoF,gBAAgBh9E,GACpCw2F,EAAiB,EACjBlZ,EAAW,EACXmZ,EAAS,EAKX,GAHIz2F,IAAMo2F,IACR9Y,EAAW/oF,KAAKknF,aAAa2a,GAAWE,GAAW5vF,MAEjD1G,GAAKo2F,GAAap2F,EAAIq2F,EACxBI,EACEzW,IAAczrF,KAAKgnF,gBAAgBv7E,GAC/BzL,KAAKqS,MACLrS,KAAKinF,aAAax7E,IAAM,OACzB,GAAIA,IAAMq2F,EACf,GAAgB,IAAZE,EACFE,EAASliG,KAAKknF,aAAa4a,GAASE,GAAS7vF,SACxC,CACL,MAAMwuB,EAAc3gC,KAAKsqF,yBACzB4X,EACEliG,KAAKknF,aAAa4a,GAASE,EAAU,GAAG7vF,KACxCnS,KAAKknF,aAAa4a,GAASE,EAAU,GAAG3vF,MACxCsuB,CACJ,CAEFshE,EAAiB3hE,GACbtgC,KAAKsgC,WAAa,GAAM70B,IAAMq2F,GAAW9hG,KAAKsgC,WAAa,KAC7DA,GAActgC,KAAKsgC,YAErB,IAAIsoD,EAAYoJ,EAAW7/E,KAAOs9E,EAAa1G,EAC7CoZ,EAAa7hE,EACb8hE,EAAW,EACb,MAAMC,EAAYH,EAASnZ,EACvB/oF,KAAK42F,mBACP56E,EAAIsI,UAAYtkB,KAAKsiG,kBAAoB,QACzCH,EAAa,EACbC,EAAW9hE,GAEXtkB,EAAIsI,UAAYtkB,KAAKsrE,eAEnBzqC,IAAct4B,IAEd83B,IAAcn5B,GACdm5B,IAAciB,IACdjB,IAAcmB,GAEdonD,EAAY5oF,KAAKqS,MAAQu2E,EAAYyZ,EAC5BhiE,IAAct5B,GAAQs5B,IAAckB,GAC7CqnD,EAAYoJ,EAAW7/E,KAAOs9E,EAAayS,EAClC7hE,IAAcv5B,GAAUu5B,IAAcoB,KAC/CmnD,EAAYoJ,EAAW7/E,KAAOs9E,EAAayS,IAG/ClmF,EAAIy3B,SACFm1C,EACAoJ,EAAW5/E,IAAM4/E,EAAW7E,UAAYiV,EACxCC,EACAF,GAEFnQ,EAAW7E,WAAa8U,CAC1B,CACF,CASAM,sBAAAA,GACE,MAAMC,EAAKxiG,KAAKyiG,uBAChB,OAAOziG,KAAKipF,qBAAqBuZ,EAAGhqE,EAAGgqE,EAAGz+D,EAAG,WAC/C,CAUA2+D,mBAAAA,GACE,MAAMF,EAAKxiG,KAAKyiG,uBAChB,OAAOziG,KAAKipF,qBAAqBuZ,EAAGhqE,EAAGgqE,EAAGz+D,EAAG57B,EAC/C,CAMAs6F,oBAAAA,GACE,MAAME,EAAiB3iG,KAAKgkF,oBAAoBhkF,KAAKsnF,gBAAgB,GACnEl6B,EACEu1C,EAAev1C,UAAY,EAAIu1C,EAAev1C,UAAY,EAAI,EAClE,MAAO,CAAE50B,EAAGmqE,EAAe3f,UAAWj/C,EAAGqpB,EAC3C,CAEA7oD,OAAAA,GACEvE,KAAK63F,kBACL73F,KAAK0/F,sBAAsBn7F,UAC3BnE,MAAMmE,SACR,EAhkBAxE,EA7EWygG,GAAK,cAmFKH,IAAkBtgG,EAnF5BygG,GAAK,OAyFF,SAujBhB73F,GAAcG,SAAS03F,IAEvB73F,GAAcG,SAAS03F,GAAO,UCvtBvB,MAAMoC,WAKHpC,GAqCR,kBAAO/gF,GACL,MAAO,IACFrf,MAAMqf,iBACNmjF,GAAQljF,YAEf,CAOA5f,WAAAA,CAAYmtD,EAAc/qD,GACxB9B,MAAM6sD,EAAM,IAAK21C,GAAQljF,eAAgBxd,GAC3C,CAOA,qBAAOygD,GACL,MAAO,CAAEv0B,SAAUq0B,KACrB,CAQAijC,cAAAA,GACO1lF,KAAK6hF,cAGV7hF,KAAK+sE,WAAa/sE,KAAKyxF,oBACvBzxF,KAAKqmF,cAELrmF,KAAK6iG,gBAAkB,EAEvB7iG,KAAK8iG,UAAY9iG,KAAK+iG,kBAAkB/iG,KAAK4lF,cAEzC5lF,KAAK6iG,gBAAkB7iG,KAAKqS,OAC9BrS,KAAKmT,KAAK,QAASnT,KAAK6iG,iBAEtB7iG,KAAKqgC,UAAUpvB,SAASqwB,KAE1BthC,KAAKymF,gBAGPzmF,KAAKsS,OAAStS,KAAKwmF,iBACrB,CASAuc,iBAAAA,CAAkBC,GAChB,IAAIC,EAAgB,EAClBC,EAAoB,EACpBjH,EAAY,EACd,MAAMtjF,EAAgB,CAAA,EAEtB,IAAK,IAAIlN,EAAI,EAAGA,EAAIu3F,EAAShd,cAAczlF,OAAQkL,IACR,OAArCu3F,EAAS5c,aAAa6V,IAAuBxwF,EAAI,GACnDy3F,EAAoB,EACpBjH,IACAgH,MAECjjG,KAAKmjG,iBACNnjG,KAAKggC,eAAewvB,KAAKwzC,EAAS5c,aAAa6V,KAC/CxwF,EAAI,IAGJy3F,IACAjH,KAGFtjF,EAAIlN,GAAK,CAAEw3E,KAAMggB,EAAe5lF,OAAQ6lF,GAExCjH,GAAa+G,EAAShd,cAAcv6E,GAAGlL,OACvC2iG,GAAqBF,EAAShd,cAAcv6E,GAAGlL,OAGjD,OAAOoY,CACT,CAOAwqE,QAAAA,CAAS9vE,EAAsC2vE,GAC7C,GAAIhjF,KAAK8iG,YAAc9iG,KAAKojG,WAAY,CACtC,MAAMzqF,EAAM3Y,KAAK8iG,UAAU9f,GACvBrqE,IACFqqE,EAAYrqE,EAAIsqE,KAEpB,CACA,OAAO7iF,MAAM+iF,SAAS9vE,EAAU2vE,EAClC,CAOAD,aAAAA,CAAcC,GACZ,IAAKhjF,KAAK0nB,OACR,OAAO,EAET,IAEE27E,EAFEhmF,EAAS,EACXimF,EAAgBtgB,EAAY,EAE5BugB,GAAc,EAChB,MAAM5qF,EAAM3Y,KAAK8iG,UAAU9f,GACzBwgB,EAAcxjG,KAAK8iG,UAAU9f,EAAY,GACvCrqE,IACFqqE,EAAYrqE,EAAIsqE,KAChB5lE,EAAS1E,EAAI0E,QAEXmmF,IACFF,EAAgBE,EAAYvgB,KAC5BsgB,EAAcD,IAAkBtgB,EAChCqgB,EAAaG,EAAYnmF,QAE3B,MAAMlM,OACiB,IAAd6xE,EACHhjF,KAAK0nB,OACL,CAAEu7D,KAAMjjF,KAAK0nB,OAAOs7D,IAC1B,IAAK,MAAM3gB,KAAMlxD,EACf,IAAK,MAAMmxD,KAAMnxD,EAAIkxD,GAAK,CACxB,MAAMohC,EAAWjmF,SAAS8kD,EAAI,IAC9B,GAAImhC,GAAYpmF,KAAYkmF,GAAeE,EAAWJ,GACpD,IAAK,MAAMngB,KAAM/xE,EAAIkxD,GAAIC,GACvB,OAAO,CAGb,CAEF,OAAO,CACT,CAQA8hB,oBAAAA,CACEpB,EACA51B,GAEA,GAAIptD,KAAK8iG,YAAc9iG,KAAKojG,WAAY,CACtC,MAAMzqF,EAAM3Y,KAAK8iG,UAAU9f,GAC3B,IAAKrqE,EACH,MAAO,CAAA,EAETqqE,EAAYrqE,EAAIsqE,KAChB71B,EAAYz0C,EAAI0E,OAAS+vC,CAC3B,CACA,OAAOhtD,MAAMgkF,qBAAqBpB,EAAW51B,EAC/C,CAQUi3B,oBAAAA,CACRrB,EACA51B,EACA5xC,GAEA,MAAM7C,EAAM3Y,KAAK8iG,UAAU9f,GAC3B5iF,MAAMikF,qBAAqB1rE,EAAIsqE,KAAMtqE,EAAI0E,OAAS+vC,EAAW5xC,EAC/D,CAOUwpE,uBAAAA,CAAwBhC,EAAmB51B,GACnD,MAAMz0C,EAAM3Y,KAAK8iG,UAAU9f,GAC3B5iF,MAAM4kF,wBAAwBrsE,EAAIsqE,KAAMtqE,EAAI0E,OAAS+vC,EACvD,CAUU62B,aAAAA,CAAcjB,GACtB,MAAMrqE,EAAM3Y,KAAK8iG,UAAU9f,GAC3B,QAAShjF,KAAK0nB,OAAO/O,EAAIsqE,KAC3B,CAQUiB,aAAAA,CAAclB,GACtB,MAAMrqE,EAAM3Y,KAAK8iG,UAAU9f,GAC3B5iF,MAAM8jF,cAAcvrE,EAAIsqE,KAC1B,CAWAygB,SAAAA,CAAU3d,EAAiB4d,GACzB3jG,KAAKojG,YAAa,EAElB,MAAMn9E,EAAOjmB,KAAK4jG,yBAAyB7d,GACrC8d,EAAsB,GAC5B,IAAK,IAAIp4F,EAAI,EAAGA,EAAIwa,EAAK69E,UAAUvjG,OAAQkL,IACzCo4F,EAAQn5F,QAAQ1K,KAAK+jG,UAAUt4F,EAAGk4F,EAAc19E,IAGlD,OADAjmB,KAAKojG,YAAa,EACXS,CACT,CASAD,wBAAAA,CAAyB7d,GACvB,MAAMod,EAAkBnjG,KAAKmjG,gBAC3Ba,EAAQb,EAAkB,GAAK,IAEjC,IAAIc,EAAmB,EAwBvB,MAAO,CACLH,UAvBW/d,EAAMptE,IAAI,CAACsqE,EAAMD,KAC5B,IAAI3lE,EAAS,EACb,MAAM6mF,EAAmBf,EACrBnjG,KAAKwrD,cAAcy3B,GACnBjjF,KAAKmkG,UAAUlhB,GAEnB,OAAgC,IAA5BihB,EAAiB3jG,OACZ,CAAC,CAAE6jG,KAAM,GAAI/xF,MAAO,IAGtB6xF,EAAiBvrF,IAAKyrF,IAE3B,MAAMC,EAAgBlB,EAClB,CAACiB,GACDpkG,KAAKwrD,cAAc44C,GACjB/xF,EAAQrS,KAAKskG,aAAaD,EAAerhB,EAAW3lE,GAG1D,OAFA4mF,EAAmBr/F,KAAKC,IAAIwN,EAAO4xF,GACnC5mF,GAAUgnF,EAAc9jG,OAASyjG,EAAMzjG,OAChC,CAAE6jG,KAAMC,EAAehyF,aAMhC4xF,mBAEJ,CAcAK,YAAAA,CAAaF,EAAgBphB,GAA2C,IAEpEuH,EAF4Cga,EAAUjkG,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EACvD+R,EAAQ,EAGZ,IAAK,IAAI5G,EAAI,EAAGmY,EAAMwgF,EAAK7jG,OAAQkL,EAAImY,EAAKnY,IAAK,CAQ/C4G,GAPYrS,KAAK4qF,gBACfwZ,EAAK34F,GACLu3E,EACAv3E,EAAI84F,EACJha,EANa,MASFpD,YACboD,EAAe6Z,EAAK34F,EACtB,CACA,OAAO4G,CACT,CAQA8xF,SAAAA,CAAUlgG,GACR,OAAOA,EAAMu3B,MAAMx7B,KAAKwkG,aAC1B,CAaAT,SAAAA,CACE/gB,EACA2gB,EAAoBz+F,GAGR,IAFZ++F,iBAAEA,EAAgBH,UAAEA,GAAyB5+F,EAC7Cu/F,EAAankG,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,EAEhB,MAAMokG,EAAkB1kG,KAAKsqF,yBAC3B6Y,EAAkBnjG,KAAKmjG,gBACvBnd,EAAgB,GAChBge,EAAQb,EAAkB,GAAK,IAEjC,IAAIrvD,EAAY,EACdmvC,EAAiB,GAEjB5lE,EAAS,EACTsnF,EAAa,EACbC,GAAkB,EAEpBjB,GAAgBc,EAEhB,MAAMxc,EAAWrjF,KAAKC,IACpB8+F,EACAM,EACAjkG,KAAK6iG,iBAGD58E,EAAO69E,EAAU9gB,GAEvB,IAAIv3E,EACJ,IAFA4R,EAAS,EAEJ5R,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,IAAK,CAChC,MAAM24F,KAAEA,EAAM/xF,MAAOwyF,GAAc5+E,EAAKxa,GACxC4R,GAAU+mF,EAAK7jG,OAEfuzC,GAAa6wD,EAAaE,EAAYH,EAClC5wD,EAAYm0C,IAAa2c,GAC3B5e,EAAct7E,KAAKu4E,GACnBA,EAAO,GACPnvC,EAAY+wD,EACZD,GAAkB,GAElB9wD,GAAa4wD,EAGVE,GAAoBzB,GACvBlgB,EAAKv4E,KAAKs5F,GAEZ/gB,EAAOA,EAAKz3E,OAAO44F,GAEnBO,EAAaxB,EACT,EACAnjG,KAAKskG,aAAa,CAACN,GAAQhhB,EAAW3lE,GAC1CA,IACAunF,GAAkB,CACpB,CAUA,OARAn5F,GAAKu6E,EAAct7E,KAAKu4E,GAKpBghB,EAAmBQ,EAAgBzkG,KAAK6iG,kBAC1C7iG,KAAK6iG,gBAAkBoB,EAAmBS,EAAkBD,GAEvDze,CACT,CAQAgB,eAAAA,CAAgBhE,GACd,OAAKhjF,KAAK8iG,UAAU9f,EAAY,IAI5BhjF,KAAK8iG,UAAU9f,EAAY,GAAGC,OAASjjF,KAAK8iG,UAAU9f,GAAWC,IAKvE,CASAmE,oBAAAA,CAAqBpE,EAAmBuE,GACtC,OAAIvnF,KAAKmjG,kBAAoB5b,EACpBvnF,KAAKgnF,gBAAgBhE,GAAa,EAAI,EAExC,CACT,CASA8C,mBAAAA,CAAoB74B,GAClB,MAAMghC,EAAU7tF,MAAM0lF,oBAAoB74B,GACxC+4B,EAAgBhmF,KAAK0jG,UAAUzV,EAAQlI,MAAO/lF,KAAKqS,OACnD0zE,EAAQ,IAAInkF,MAAMokF,EAAczlF,QAClC,IAAK,IAAIkL,EAAI,EAAGA,EAAIu6E,EAAczlF,OAAQkL,IACxCs6E,EAAMt6E,GAAKu6E,EAAcv6E,GAAG0O,KAAK,IAInC,OAFA8zE,EAAQlI,MAAQA,EAChBkI,EAAQjI,cAAgBA,EACjBiI,CACT,CAEA6W,WAAAA,GACE,OAAOlgG,KAAKC,IAAI7E,KAAK+kG,SAAU/kG,KAAK6iG,gBACtC,CAEA9K,uBAAAA,GACE,MAAMiN,EAAc,IAAIhgG,IACxB,IAAK,MAAMiO,KAAQjT,KAAK8iG,UAAW,CACjC,MAAMmC,EAAaznF,SAASvK,EAAM,IAClC,GAAIjT,KAAK2jF,WAAWshB,GAAa,CAC/B,MAAMjiB,EAAYhjF,KAAK8iG,UAAU7vF,GAAMgwE,KACvC+hB,EAAYz/F,IAAI,GAAGy9E,KAAa,EAClC,CACF,CACA,IAAK,MAAM/vE,KAAQjT,KAAK0nB,OACjBs9E,EAAY1/F,IAAI2N,WACZjT,KAAK0nB,OAAOzU,EAGzB,CAOAuH,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,OAAOF,MAAMoa,SAAe,CAC1B,WACA,qBACG8K,GAEP,EApfAvlB,EAtBW6iG,GAAO,OAoCJ,WAAS7iG,EApCZ6iG,GAAO,uBAsCY,IAAIpC,GAAM9gE,qBAAsB,UAAQ3/B,EAtC3D6iG,GAAO,cAvCoD,CACtEmC,SAAU,GACVlC,gBAAiB,EACjB37C,iBAAiB,EACjBrE,cAAc,EACd2hD,aAAc,UACdrB,iBAAiB,IA8iBnBx6F,GAAcG,SAAS85F,ICtjBhB,MAAMsC,WAAuB9xC,GAGlCE,mBAAAA,CAAoBlxD,GAClB,QAASA,EAAQ4H,OAAOyY,UAAYriB,MAAMkzD,oBAAoBlxD,EAChE,CAEAsxD,oBAAAA,GACE,OAAO,CACT,CAEAL,gBAAAA,CACEjxD,EACAyN,GAEA,MAAM7F,OAAEA,GAAW5H,GACbqgB,SAAEA,EAAQiqB,MAAEA,GAAU1iC,EAC5B,IAAKyY,IAAaziB,KAAKszD,oBAAoBlxD,GACzC,OAGF,MAAMiQ,MAAEA,EAAKC,OAAEA,GAAWoY,GACxBkoC,GAAgB5oD,EAAQyY,IAEpB3S,EAAO,IAAI3D,GAAMkG,EAAOC,GAC9B,GAAImQ,EAASuc,mBAAoB,CAO/B,MAAO,CACL5Z,OANqBqG,GACrBhJ,EAAS8L,8BACT/tB,EACAksC,EAAQA,EAAMxO,2BAAwB19B,GAItCsP,OAEJ,CAAO,CAEL,MAAMq1F,EAAiB1iF,EACpB8L,yBACAvf,UAAUhF,EAAO8gB,iBAAiB,GACrC,GAAI9qB,KAAKszD,oBAAoBlxD,GAAU,CAGrC,MAAMgjB,OAAEA,EAAS,IAAIjZ,GAAOupD,WAAEA,EAAa,IAAIvpD,IAC7CnM,KAAKuzD,gBAAgB1jD,EAASzN,IAAY,CAAA,EAC5C,MAAO,CACLgjB,OAAQA,EAAO9Y,IAAI64F,GACnBzvC,WAAYA,EAAW9oD,SAASu4F,GAChCr1F,OAEJ,CACE,MAAO,CACLsV,OAAQpb,EAAOukB,yBAAyBjiB,IAAI64F,GAC5Cr1F,OAGN,CACF,EACD/P,EA3DYmlG,GAAc,OACF,aA4DzBv8F,GAAcG,SAASo8F,IC7DhB,MAAME,WAAoBhyC,GAM/BO,cAAAA,CAAczuD,EAAA2F,GAGL,IAFPb,OAAEA,GAA2D9E,GAC7D4K,KAAEA,GAAqDjF,EAEvD,OAAO,IAAIsB,GAAMnC,EAAOqI,OAASvC,EAAKzD,EAAGrC,EAAOsI,QAAUxC,EAAK1D,EACjE,EACDrM,EAZYqlG,GAAW,OACC,SAazBz8F,GAAcG,SAASs8F,ICVhB,MAAMC,WAAqClxC,GAChDkB,gBAAAA,CACEjzD,GAEA,MAAM80E,EAAkB90E,EAAQ4H,OAChB5H,EAAQgzD,QAAQ/zD,OAAO,CAACikG,EAASt7F,KAC/CA,EAAO8nC,QAAUwzD,EAAQh5F,IAAItC,EAAO8nC,QAC7BwzD,GACN,IAAIC,KACCxkG,QAAS+wC,IACfA,EAAOyjB,cAAcF,iBAAiB,CACpCrrD,OAAQ8nC,EACRsjB,QAAS,CAAC8hB,MAGhB,CAKA/hB,kBAAAA,CACE/yD,GAEA,MAAM80E,EAAkB90E,EAAQ4H,OAC1Bw7F,EAAkBtuB,EAAgB3mE,aACxBnO,EAAQgzD,QAAQ/zD,OAAO,CAACikG,EAASt7F,KAC/CA,EAAO8nC,QAAUwzD,EAAQh5F,IAAItC,EAAO8nC,QAC7BwzD,GACN,IAAIC,KACCxkG,QAAS+wC,KACd0zD,EAAgBt0F,KAAMxB,GAAWA,EAAOoiC,SAAWA,IAClDA,EAAOyjB,cAAcJ,mBAAmB,CACtCnrD,OAAQ8nC,EACRsjB,QAAS,CAAC8hB,MAGlB,ECjBK,MAAMuuB,WAAwBxvC,GAKnC,kBAAOx2C,GACL,MAAO,IAAKrf,MAAMqf,iBAAkBgmF,GAAgB/lF,YACtD,CAiBA5f,WAAAA,GAGE,IAFA+P,EAAuBvP,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC1B4B,EAAwC5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE3CF,QACAK,OAAOC,OAAOV,KAAMylG,GAAgB/lF,aACpC1f,KAAKgwC,WAAW9tC,GAChB,MAAMiQ,KAAEA,EAAIC,IAAEA,EAAGmjD,cAAEA,GAAkBrzD,EACrClC,KAAKk2D,UAAUrmD,EAAS,CACtBsC,OACAC,MACAmjD,cAAeA,QAAAA,EAAiB,IAAI8vC,IAExC,CAKAvuC,sBAAAA,GACE,OAAO,CACT,CAMAT,wBAAAA,GACE,CAOFkhB,cAAAA,GAA2C,IAAA,IAAA71E,EAAApB,UAAAC,OAAzB60D,EAAO,IAAAxzD,MAAAF,GAAAG,EAAA,EAAAA,EAAAH,EAAAG,IAAPuzD,EAAOvzD,GAAAvB,UAAAuB,GACa,oBAAhC7B,KAAK0lG,uBACP1lG,KAAKsM,OAAO8oD,GAIZA,EAAQr0D,QAASiJ,IACf,MAAMV,EAAQtJ,KAAKqP,SAASs2F,UAAWx0F,GAAQA,EAAIumC,YAAY1tC,IACzD+F,GACM,IAAVzG,EAEItJ,KAAK8P,OACLxG,EACNtJ,KAAK+P,SAASA,EAAU/F,IAG9B,CAKAwsD,aAAAA,CAAc9mD,GACZ,OACE1P,KAAKuQ,aAAaW,KACfP,GAAMA,EAAEmmC,eAAepnC,IAAWA,EAAOonC,eAAenmC,KAI3DnP,EACE,QACA,sFAEK,GAGFpB,MAAMo2D,cAAc9mD,EAC7B,CASA6mD,UAAAA,CAAW7mD,EAAsBknD,GAI3BlnD,EAAOoiC,QAAUpiC,EAAOoiC,SAAWpiC,EAAOg9B,MAG5Ch9B,EAAOoiC,OAAO0lB,WAAW9nD,GAEhBA,EAAOg9B,OAASh9B,EAAOoiC,SAAWpiC,EAAOg9B,OAElDh9B,EAAOg9B,MAAMrjC,OAAOqG,GAKtB1P,KAAKs3D,YAAY5nD,EAAQknD,EAC3B,CAQAC,SAAAA,CAAUnnD,EAAsBknD,GAC9B52D,KAAKw3D,WAAW9nD,EAAQknD,GAExBlnD,EAAOoiC,QAAUpiC,EAAOoiC,OAAOwlB,YAAY5nD,GAAQ,EACrD,CAOAinD,qBAAAA,CAAsB3tD,EAA2BosD,GAC/Ch1D,MAAMu2D,sBAAsB3tD,EAAMosD,GAClC,MAAMwwC,EAAS,IAAIL,IACnBnwC,EAAQr0D,QAAS2O,IACf,MAAMoiC,OAAEA,GAAWpiC,EACnBoiC,GAAU8zD,EAAOt5F,IAAIwlC,KAEnB9oC,IAAS0pD,GAEXkzC,EAAO7kG,QAAS2rC,IACdA,EAAMiqB,sBAAsBlE,GAAmB2C,KAIjDwwC,EAAO7kG,QAAS2rC,IACdA,EAAMv5B,KAAK,SAAS,IAG1B,CAKAuyC,UAAAA,GAEE,OADA1lD,KAAKg3D,aACE,CACT,CAMA9oD,QAAAA,GACE,MAAO,uBAAuBlO,KAAKoR,gBACrC,CAMA0R,WAAAA,GACE,OAAO,CACT,CAMA+vB,UAAAA,GACE,OAAO,CACT,CAQA6R,eAAAA,CACE1oC,EACAi+B,EACA4rD,GAEA7pF,EAAI2G,OACJ3G,EAAI23B,YAAc3zC,KAAKglD,SAAWhlD,KAAKilD,wBAA0B,EACjE,MAAM/iD,EAAU,CACdohD,aAAa,KACVuiD,EACH1gD,oBAAoB,GAEtB,IAAK,IAAI15C,EAAI,EAAGA,EAAIzL,KAAKqP,SAAS9O,OAAQkL,IACxCzL,KAAKqP,SAAS5D,GAAGi5C,gBAAgB1oC,EAAK9Z,GAExC9B,MAAMskD,gBAAgB1oC,EAAKi+B,GAC3Bj+B,EAAI6G,SACN,EACD9iB,EAvNY0lG,GAAe,OACZ,mBAAiB1lG,EADpB0lG,GAAe,cAf1B,CACEC,uBAAwB,oBAuO5B/8F,GAAcG,SAAS28F,IACvB98F,GAAcG,SAAS28F,GAAiB,mBCvPjC,MAAMK,GAAsBhmG,WAAAA,GACjCC,EAAAC,KAAA,YAOgC,GAAE,CAYlC+lG,YAAAA,CACEC,EACAC,EACAC,EACAC,EACAvjD,GAEA,MAAM5mC,EAAM4mC,EAAax/C,WAAW,KAAM,CACxCwqE,oBAAoB,EACpBw4B,gBAAgB,IAElB,IAAKpqF,EACH,OAEFA,EAAIwH,UAAUyiF,EAAe,EAAG,EAAGC,EAAaC,GAChD,MAEME,EAAkC,CACtCH,cACAC,eACAG,UALgBtqF,EAAI0rC,aAAa,EAAG,EAAGw+C,EAAaC,GAMpDI,WAAYN,EACZO,kBANwBxqF,EAAI0rC,aAAa,EAAG,EAAGw+C,EAAaC,GAO5D/xF,SAAUwuC,EACV5mC,MACAyqF,cAAezmG,MAEjBgmG,EAAQjlG,QAAS+I,IACfA,EAAO48F,QAAQL,KAEjB,MAAQC,UAAWK,GAAwBN,EAS3C,OAPEM,EAAoBt0F,QAAU6zF,GAC9BS,EAAoBr0F,SAAW6zF,IAE/BvjD,EAAavwC,MAAQs0F,EAAoBt0F,MACzCuwC,EAAatwC,OAASq0F,EAAoBr0F,QAE5C0J,EAAI4qF,aAAaD,EAAqB,EAAG,GAClCN,CACT,ECxDK,MAAMQ,GA6CX/mG,WAAAA,GAAoD,IAAxCgnG,SAAEA,EAAW3mG,EAAO0D,aAAavD,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EA1ChDP,EAAAC,KAAA,YAG0B,IAAI+mG,aAAa,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,KA8BjEhnG,EAAAC,KAAA,YAOgC,IAG9BA,KAAK8mG,SAAWA,EAChB9mG,KAAKgnG,eAAeF,EAAUA,GAC9B9mG,KAAKinG,gBACP,CAKAD,cAAAA,CAAe30F,EAAeC,GAC5BtS,KAAKuE,UACLvE,KAAKknG,kBAAkB70F,EAAOC,EAChC,CAMA40F,iBAAAA,CAAkB70F,EAAeC,GAC/B,MAAMnP,EAAS8Q,GAAuB,CAAE5B,QAAOC,WAQ7C9P,EAAKW,EAAOC,WAAW,QAPP,CACd+2B,OAAO,EACPgtE,oBAAoB,EACpBC,OAAO,EACPC,SAAS,EACTC,WAAW,IAIV9kG,IAGLA,EAAG+kG,WAAW,EAAG,EAAG,EAAG,GAEvBvnG,KAAKmD,OAASA,EACdnD,KAAKwC,GAAKA,EACZ,CAcAujG,YAAAA,CACEC,EACAvsF,EACApH,EACAC,EACAswC,EACAl9C,GAEA,MAAMlD,EAAKxC,KAAKwC,GACVwZ,EAAM4mC,EAAax/C,WAAW,MACpC,IAAKZ,IAAOwZ,EACV,OAEF,IAAIwrF,EACA9hG,IACF8hG,EAAgBxnG,KAAKynG,iBAAiB/hG,EAAU+T,IAElD,MAAM4sF,EAAqC,CACzCt9E,cACGtP,EAA4BpH,OAC5BoH,EAA4BqhE,cAC7B,EACF9xD,eACGvP,EAA4BnH,QAC5BmH,EAA4BshE,eAC7B,EACFmrB,YAAa7zF,EACb8zF,aAAc7zF,EACdo1F,iBAAkBr1F,EAClBs1F,kBAAmBr1F,EACnBlQ,QAASI,EACTolG,cAAe5nG,KAAK6nG,cAClBrlG,EACA6P,EACAC,EACCk1F,OAAyBhnG,EAATiZ,GAEnBquF,cAAe9nG,KAAK6nG,cAAcrlG,EAAI6P,EAAOC,GAC7Cy1F,gBACEP,GACAxnG,KAAK6nG,cACHrlG,EACA6P,EACAC,EACCk1F,OAAyBhnG,EAATiZ,GAErBuuF,OAAQhC,EAAQzlG,OAChB0nG,OAAO,EACPC,UAAWloG,KAAKkoG,UAChBC,aAAcnoG,KAAKmoG,aACnBC,KAAM,EACN3B,cAAezmG,KACf4iD,aAAcA,GAEVylD,EAAU7lG,EAAG8lG,oBAYnB,OAXA9lG,EAAG+lG,gBAAgB/lG,EAAGgmG,YAAaH,GACnCrC,EAAQjlG,QAAS+I,IACfA,GAAUA,EAAO48F,QAAQL,KAkP/B,SAA8BA,GAC5B,MAAMzjD,EAAeyjD,EAAczjD,aACjCvwC,EAAQuwC,EAAavwC,MACrBC,EAASswC,EAAatwC,OACtBm2F,EAASpC,EAAcqB,iBACvBgB,EAAUrC,EAAcsB,kBAEtBt1F,IAAUo2F,GAAUn2F,IAAWo2F,IACjC9lD,EAAavwC,MAAQo2F,EACrB7lD,EAAatwC,OAASo2F,EAE1B,CA3PIC,CAAqBtC,GACrBrmG,KAAK4oG,WAAWpmG,EAAI6jG,GACpB7jG,EAAGqmG,YAAYrmG,EAAGsmG,WAAY,MAC9BtmG,EAAGumG,cAAc1C,EAAcuB,eAC/BplG,EAAGumG,cAAc1C,EAAcyB,eAC/BtlG,EAAGwmG,kBAAkBX,GACrBrsF,EAAIm1B,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GACzBk1D,CACT,CAKA9hG,OAAAA,GACMvE,KAAKmD,SAIPnD,KAAKmD,OAAS,KAEdnD,KAAKwC,GAAK,MAEZxC,KAAKipG,kBACP,CAKAA,gBAAAA,GACEjpG,KAAKmoG,aAAe,CAAA,EACpBnoG,KAAKkpG,aAAe,CAAA,CACtB,CAeArB,aAAAA,CACErlG,EACA6P,EACAC,EACA62F,EACAr/F,GAIA,MAAMs/F,QACJA,EAAON,WACPA,EAAUO,KACVA,EAAIC,cACJA,EAAaC,cACbA,EAAaC,mBACbA,EAAkBC,mBAClBA,EAAkBC,eAClBA,EAAcC,eACdA,GACEnnG,EACEonG,EAAUpnG,EAAGqlG,gBA8BnB,OA7BArlG,EAAGqmG,YAAYC,EAAYc,GAC3BpnG,EAAGqnG,cAAcf,EAAYU,EAAoB1/F,GAAUs/F,GAC3D5mG,EAAGqnG,cAAcf,EAAYW,EAAoB3/F,GAAUs/F,GAC3D5mG,EAAGqnG,cAAcf,EAAYY,EAAgBH,GAC7C/mG,EAAGqnG,cAAcf,EAAYa,EAAgBJ,GACzCJ,EACF3mG,EAAGsnG,WACDhB,EACA,EACAO,EACAA,EACAC,EACAH,GAGF3mG,EAAGsnG,WACDhB,EACA,EACAO,EACAh3F,EACAC,EACA,EACA+2F,EACAC,EACA,MAKGM,CACT,CAWAnC,gBAAAA,CACEsC,EACAZ,EACAr/F,GAIA,MAAMo/F,aAAEA,GAAiBlpG,KACzB,GAAIkpG,EAAaa,GACf,OAAOb,EAAaa,GACf,CACL,MAAMH,EAAU5pG,KAAK6nG,cACnB7nG,KAAKwC,GACJ2mG,EAAwC92F,MACxC82F,EAAwC72F,OACzC62F,EACAr/F,GAKF,OAHI8/F,IACFV,EAAaa,GAAYH,GAEpBA,CACT,CACF,CAQAI,iBAAAA,CAAkBtkG,GACZ1F,KAAKkpG,aAAaxjG,KACpB1F,KAAKwC,GAAGumG,cAAc/oG,KAAKkpG,aAAaxjG,WACjC1F,KAAKkpG,aAAaxjG,GAE7B,CAWAkjG,UAAAA,CAAWpmG,EAA2B6jG,GACpC,MAAM4D,EAAWznG,EAAGW,OAClBy/C,EAAeyjD,EAAczjD,aAC7B5mC,EAAM4mC,EAAax/C,WAAW,MAChC,IAAK4Y,EACH,OAEFA,EAAIs1B,UAAU,EAAGsR,EAAatwC,QAC9B0J,EAAIG,MAAM,GAAG,GAEb,MAAM+tF,EAAUD,EAAS33F,OAASswC,EAAatwC,OAC/C0J,EAAIwH,UACFymF,EACA,EACAC,EACAtnD,EAAavwC,MACbuwC,EAAatwC,OACb,EACA,EACAswC,EAAavwC,MACbuwC,EAAatwC,OAEjB,CAUA63F,sBAAAA,CAEE3nG,EACA6jG,GAEA,MACErqF,EADmBqqF,EAAczjD,aACdx/C,WAAW,MAC9BqlG,EAASpC,EAAcqB,iBACvBgB,EAAUrC,EAAcsB,kBACxByC,EAAW3B,EAASC,EAAU,EAChC,IAAK1sF,EACH,OAEF,MAAMquF,EAAK,IAAIC,WAAWtqG,KAAKuqG,YAAa,EAAGH,GACzCI,EAAY,IAAIC,kBAAkBzqG,KAAKuqG,YAAa,EAAGH,GAE7D5nG,EAAGkoG,WAAW,EAAG,EAAGjC,EAAQC,EAASlmG,EAAG6mG,KAAM7mG,EAAG8mG,cAAee,GAChE,MAAMM,EAAU,IAAIC,UAAUJ,EAAW/B,EAAQC,GACjD1sF,EAAI4qF,aAAa+D,EAAS,EAAG,EAC/B,CASA1D,cAAAA,GACE,GAAIjnG,KAAK6qG,QACP,OAAO7qG,KAAK6qG,QAEd,MAAMroG,EAAKxC,KAAKwC,GACdqoG,EAAU,CAAEC,SAAU,GAAIC,OAAQ,IACpC,IAAKvoG,EACH,OAAOqoG,EAET,MAAMG,EAAMxoG,EAAGkB,aAAa,6BAC5B,GAAIsnG,EAAK,CACP,MAAMF,EAAWtoG,EAAGc,aAAa0nG,EAAIC,yBAC/BF,EAASvoG,EAAGc,aAAa0nG,EAAIE,uBAC/BJ,IACFD,EAAQC,SAAWA,EAASzlG,eAE1B0lG,IACFF,EAAQE,OAASA,EAAO1lG,cAE5B,CAEA,OADArF,KAAK6qG,QAAUA,EACRA,CACT,ECzYF,IAAIpE,GAKG,SAAS0E,KACd,MAAM7oG,WAAEA,GAAe4B,IAEvB,OADA5B,EAAWY,WAAW2Q,MAClB1T,EAAOirG,mBAAqB9oG,EAAWsB,YAAYzD,EAAO0D,aACrD,IAAIgjG,GAAmB,CAAEC,SAAU3mG,EAAO0D,cAE1C,IAAIiiG,EAEf,CAOO,SAASuF,KAId,OAHK5E,OADgCnmG,UAAAC,OAAA,QAAAC,IAAAF,UAAA,KAAAA,UAAA,MAEnCmmG,GAAgB0E,MAEX1E,EACT,CAEO,SAAS6E,GAAiBC,GAC/B9E,GAAgB8E,CAClB,CCyBO,MAoBDC,GAAc,CAAC,QAAS,SAKvB,MAAMC,WAKH37D,GAgGR,kBAAOrwB,GACL,MAAO,IACFrf,MAAMqf,iBACNgsF,GAAY/rF,YAEnB,CAYA5f,WAAAA,CAAYsK,EAA4BlI,GACtC9B,QAtGFL,qBAMwB,GAExBA,qBAMwB,GAExBA,yBAK4B,GAE5BA,yBAK4B,GA2E1BC,KAAKgmG,QAAU,GACfvlG,OAAOC,OAAOV,KAAMyrG,GAAY/rF,aAChC1f,KAAKgwC,WAAW9tC,GAChBlC,KAAK0F,SAAW,UAAUkO,OAC1B5T,KAAK0rG,WACa,iBAATthG,GAEApK,KAAKmD,QAAU2X,GAAuB9a,KAAKmD,OAAOie,eACnD5c,KACAmY,eAAevS,GACjBA,EACJlI,EAEJ,CAKAkf,UAAAA,GACE,OAAOphB,KAAK2rG,QACd,CASAD,UAAAA,CAAW53F,GAAiD,IAA3BhE,EAAoBxP,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACtDN,KAAK4rG,cAAc5rG,KAAK0F,UACxB1F,KAAK4rG,cAAc,GAAG5rG,KAAK0F,qBAC3B1F,KAAK2rG,SAAW73F,EAChB9T,KAAK6rG,iBAAmB/3F,EACxB9T,KAAKygF,gBAAgB3wE,GACO,IAAxB9P,KAAKgmG,QAAQzlG,QACfP,KAAK+lG,eAMH/lG,KAAK8rG,cACP9rG,KAAK+rG,oBAET,CAKAH,aAAAA,CAAcrqG,GACZ,MAAMgqG,EAAUF,IAAiB,GAC7BE,aAAmB1E,IACrB0E,EAAQvB,kBAAkBzoG,EAE9B,CAKAgD,OAAAA,GACEnE,MAAMmE,UACNvE,KAAK4rG,cAAc5rG,KAAK0F,UACxB1F,KAAK4rG,cAAc,GAAG5rG,KAAK0F,qBAC3B1F,KAAKkwC,cAAgB,KAEnB,CAAC,mBAAoB,WAAY,cAAe,gBAChDnvC,QAASirG,IACT,MAAMtwF,EAAK1b,KAAKgsG,GAChBtwF,GAAMxX,IAASK,QAAQmX,GAEvB1b,KAAKgsG,QAAcxrG,GAEvB,CAKAyrG,cAAAA,GACE,OACEjsG,KAAK6rG,mBACH7rG,KAAK6rG,iBAAyBj0F,aAAe,KAEnD,CAKAs0F,eAAAA,GACE,MAAMp4F,EAAU9T,KAAKohB,aACrB,OAAKtN,EAME,CACLzB,MAAOyB,EAAQgnE,cAAgBhnE,EAAQzB,MACvCC,OAAQwB,EAAQinE,eAAiBjnE,EAAQxB,QAPlC,CACLD,MAAO,EACPC,OAAQ,EAOd,CAMA65F,OAAAA,CAAQnwF,GACN,IAAKhc,KAAK69B,QAA+B,IAArB79B,KAAKq9B,YACvB,OAEF,MAAMiR,EAAItuC,KAAKqS,MAAQ,EACrBimB,EAAIt4B,KAAKsS,OAAS,EACpB0J,EAAIkI,YACJlI,EAAImI,QAAQmqB,GAAIhW,GAChBtc,EAAIoI,OAAOkqB,GAAIhW,GACftc,EAAIoI,OAAOkqB,EAAGhW,GACdtc,EAAIoI,QAAQkqB,EAAGhW,GACftc,EAAIoI,QAAQkqB,GAAIhW,GAChBtc,EAAIqI,WACN,CAOA7J,QAAAA,GAGsD,IAApD8K,EAAwBhlB,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC3B,MAAM0lG,EAAiC,GAIvC,OAHAhmG,KAAKgmG,QAAQjlG,QAASqrG,IACpBA,GAAapG,EAAQt7F,KAAK0hG,EAAU5xF,cAE/B,IACFpa,MAAMoa,SAAS,IAAIgxF,MAAgBlmF,IACtCrN,IAAKjY,KAAKqsG,SACVz0F,YAAa5X,KAAKisG,iBAClBjG,aACIhmG,KAAK8rG,aACL,CAAEA,aAAc9rG,KAAK8rG,aAAatxF,YAClC,CAAA,EAER,CAMA8xF,OAAAA,GACE,QACItsG,KAAKkjE,SACLljE,KAAKmjE,OACPnjE,KAAKqS,MAAQrS,KAAK2rG,SAASt5F,OAC3BrS,KAAKsS,OAAStS,KAAK2rG,SAASr5F,MAEhC,CAOA6rB,MAAAA,GACE,MAAMouE,EAAwB,GAC5Bz4F,EAAU9T,KAAK2rG,SACft/F,GAAKrM,KAAKqS,MAAQ,EAClBjG,GAAKpM,KAAKsS,OAAS,EACrB,IAAI6lD,EAAsB,GACxBq0C,EAAsB,GACtB/pF,EAAW,GACXgqF,EAAiB,GACnB,IAAK34F,EACH,MAAO,GAET,GAAI9T,KAAKssG,UAAW,CAClB,MAAM5lF,EAAa9S,KACnBukD,EAAUztD,KACR,2BAA6Bgc,EAAa,OAC1C,cACEra,EACA,QACAD,EACA,YACApM,KAAKqS,MACL,aACArS,KAAKsS,OACL,SACF,iBAEFmQ,EAAW,8BAAgCiE,EAAa,KAC1D,CAmBA,GAlBK1mB,KAAK0sG,iBACRD,EAAiB,oCAEnBF,EAAY7hG,KACV,YACA,eACA,eAAe1K,KAAK2sG,WAAU,UAAatgG,EAAIrM,KAAKkjE,aAClD92D,EAAIpM,KAAKmjE,iBAKTrvD,EAAQzB,OAAUyB,EAA6BgnE,yBAE/ChnE,EAAQxB,QAAWwB,EAA6BinE,iBAC9C0xB,IAAiBhqF,gBAGnBziB,KAAK69B,QAAU79B,KAAKs9B,gBAAiB,CACvC,MAAMsvE,EAAW5sG,KAAK+jB,KACtB/jB,KAAK+jB,KAAO,KACZyoF,EAAY,CACV,cAAcngG,SAASD,aAAapM,KAAKqS,kBACvCrS,KAAKsS,kBACKtS,KAAKk9B,wBAEnBl9B,KAAK+jB,KAAO6oF,CACd,CAMA,OAJEz0C,EADEn4D,KAAKm/B,aAAeh3B,EACVgwD,EAAU3sD,OAAOghG,EAAWD,GAE5Bp0C,EAAU3sD,OAAO+gG,EAAaC,GAErCr0C,CACT,CAOAk0C,MAAAA,CAAOQ,GACL,MAAM/4F,EAAU+4F,EAAW7sG,KAAK2rG,SAAW3rG,KAAK6rG,iBAChD,OAAI/3F,EACGA,EAA8BK,UACzBL,EAA8BK,YAGpCnU,KAAK8sG,iBACAh5F,EAAQi6C,aAAa,QAAU,GAE9Bj6C,EAA6BmE,IAGhCjY,KAAKiY,KAAO,EAEvB,CAOA00F,SAAAA,CAAUE,GACR,OAAO7sG,KAAKqsG,OAAOQ,EACrB,CAQAE,MAAAA,CAAO90F,GAA6D,IAAhDL,YAAEA,EAAWD,OAAEA,GAA0BrX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC9D,OAAOmX,GAAUQ,EAAK,CAAEL,cAAaD,WAAUkB,KAAMd,SAC5B,IAAhBH,GAA+B5X,KAAKuF,IAAI,CAAEqS,gBACjD5X,KAAK0rG,WAAW3zF,IAEpB,CAMA7J,QAAAA,GACE,MAAO,oBAAoBlO,KAAKqsG,cAClC,CAEAN,kBAAAA,GACE,MAAMjiG,EAAS9J,KAAK8rG,aAClBkB,EAAehtG,KAAKitG,oBACpBr8D,EAAc5wC,KAAK6wC,wBACnB36B,EAAS06B,EAAYvkC,EACrB8J,EAASy6B,EAAYxkC,EACrB8gG,EAAkBltG,KAAKmtG,aAAentG,KAAK6rG,iBAI7C,GAHI7rG,KAAK0sC,OACP1sC,KAAKuF,IAAI,SAAS,IAEfuE,GAAWoM,EAAS82F,GAAgB72F,EAAS62F,EAMhD,OALAhtG,KAAK2rG,SAAWuB,EAChBltG,KAAKotG,gBAAkB,EACvBptG,KAAKqtG,gBAAkB,EACvBrtG,KAAKstG,YAAcp3F,OACnBlW,KAAKutG,YAAcp3F,GAGrB,MAAM/B,EAAWH,GAAuBi5F,IACtC76F,MAAEA,EAAKC,OAAEA,GAAW46F,EACtBltG,KAAK2rG,SAAWv3F,EAChBpU,KAAKstG,YAAcxjG,EAAOoM,OAASA,EACnClW,KAAKutG,YAAczjG,EAAOqM,OAASA,EACnCk1F,KAAmBtF,aACjB,CAACj8F,GACDojG,EACA76F,EACAC,EACAtS,KAAK2rG,UAEP3rG,KAAKotG,gBAAkBh5F,EAAS/B,MAAQrS,KAAK6rG,iBAAiBx5F,MAC9DrS,KAAKqtG,gBAAkBj5F,EAAS9B,OAAStS,KAAK6rG,iBAAiBv5F,MACjE,CAOAyzF,YAAAA,GAEE,IADAC,EAAkD1lG,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAKgmG,SAAW,GAQrE,GANAA,EAAUA,EAAQl8F,OAAQA,GAAWA,IAAWA,EAAO0jG,kBACvDxtG,KAAKuF,IAAI,SAAS,GAGlBvF,KAAK4rG,cAAc,GAAG5rG,KAAK0F,qBAEJ,IAAnBsgG,EAAQzlG,OAMV,OALAP,KAAK2rG,SAAW3rG,KAAK6rG,iBAErB7rG,KAAKmtG,iBAAc3sG,EACnBR,KAAKotG,gBAAkB,OACvBptG,KAAKqtG,gBAAkB,GAIzB,MAAMI,EAAaztG,KAAK6rG,iBACtB3F,EACGuH,EAAgC3yB,cAAgB2yB,EAAWp7F,MAC9D8zF,EACGsH,EAAgC1yB,eAAiB0yB,EAAWn7F,OAEjE,GAAItS,KAAK2rG,WAAa3rG,KAAK6rG,iBAAkB,CAG3C,MAAMz3F,EAAWH,GAAuB,CACtC5B,MAAO6zF,EACP5zF,OAAQ6zF,IAEVnmG,KAAK2rG,SAAWv3F,EAChBpU,KAAKmtG,YAAc/4F,CACrB,MAAWpU,KAAKmtG,cAKdntG,KAAK2rG,SAAW3rG,KAAKmtG,YACrBntG,KAAKmtG,YACF/pG,WAAW,MACXke,UAAU,EAAG,EAAG4kF,EAAaC,GAEhCnmG,KAAKstG,YAAc,EACnBttG,KAAKutG,YAAc,GAErBlC,KAAmBtF,aACjBC,EACAhmG,KAAK6rG,iBACL3F,EACAC,EACAnmG,KAAK2rG,SACL3rG,KAAK0F,UAGL1F,KAAK6rG,iBAAiBx5F,QAAUrS,KAAK2rG,SAASt5F,OAC9CrS,KAAK6rG,iBAAiBv5F,SAAWtS,KAAK2rG,SAASr5F,SAE/CtS,KAAKotG,gBAAkBptG,KAAK2rG,SAASt5F,MAAQrS,KAAK6rG,iBAAiBx5F,MACnErS,KAAKqtG,gBACHrtG,KAAK2rG,SAASr5F,OAAStS,KAAK6rG,iBAAiBv5F,OAEnD,CAMA8gC,OAAAA,CAAQp3B,GACNA,EAAI8C,sBAAwB9e,KAAK0sG,gBACX,IAAlB1sG,KAAKglD,UAAqBhlD,KAAK8rG,cAAgB9rG,KAAK0tG,gBACtD1tG,KAAK+rG,qBAEP/rG,KAAKmsG,QAAQnwF,GACbhc,KAAKq1C,oBAAoBr5B,EAC3B,CAOAo2B,iBAAAA,CAEEp2B,GAEAA,EAAI8C,sBAAwB9e,KAAK0sG,eACjCtsG,MAAMgyC,kBAAkBp2B,EAC1B,CAaA8G,WAAAA,GACE,OAAO9iB,KAAK2yC,kBACd,CAEA4C,WAAAA,CAAYv5B,GACV,MAAM2xF,EAAgB3tG,KAAK2rG,SAC3B,IAAKgC,EACH,OAEF,MAAMz3F,EAASlW,KAAKotG,gBAClBj3F,EAASnW,KAAKqtG,gBACd/+D,EAAItuC,KAAKqS,MACTimB,EAAIt4B,KAAKsS,OAET4wD,EAAQt+D,KAAKC,IAAI7E,KAAKkjE,MAAO,GAC7BC,EAAQv+D,KAAKC,IAAI7E,KAAKmjE,MAAO,GAC7ByqC,EACGD,EAAmC7yB,cAAgB6yB,EAAct7F,MACpEw7F,EACGF,EAAmC5yB,eACpC4yB,EAAcr7F,OAChBw7F,EAAK5qC,EAAQhtD,EACb63F,EAAK5qC,EAAQhtD,EAEb63F,EAAKppG,KAAKiJ,IAAIygC,EAAIp4B,EAAQ03F,EAAUE,GACpCG,EAAKrpG,KAAKiJ,IAAIyqB,EAAIniB,EAAQ03F,EAAWE,GACrC1hG,GAAKiiC,EAAI,EACTliC,GAAKksB,EAAI,EACT41E,EAAWtpG,KAAKiJ,IAAIygC,EAAGs/D,EAAU13F,EAASgtD,GAC1CirC,EAAWvpG,KAAKiJ,IAAIyqB,EAAGu1E,EAAW13F,EAASgtD,GAE7CwqC,GACE3xF,EAAIwH,UAAUmqF,EAAeG,EAAIC,EAAIC,EAAIC,EAAI5hG,EAAGD,EAAG8hG,EAAUC,EACjE,CAMAT,YAAAA,GACE,MAAMvxF,EAAQnc,KAAK6wC,wBACnB,OAAO10B,EAAM9P,IAAMrM,KAAKstG,aAAenxF,EAAM/P,IAAMpM,KAAKutG,WAC1D,CAMAa,iBAAAA,GACEpuG,KAAKuF,IAAIvF,KAAKksG,kBAChB,CAOAzrB,eAAAA,GAAwD,IAAxCpuE,MAAEA,EAAKC,OAAEA,GAAwBhS,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAClD,MAAMwP,EAAO9P,KAAKksG,kBAClBlsG,KAAKqS,MAAQA,GAASvC,EAAKuC,MAC3BrS,KAAKsS,OAASA,GAAUxC,EAAKwC,MAC/B,CAOA6pB,iCAAAA,GACE,MAAMkyE,EAAMlyE,GACRn8B,KAAKsuG,qBAAuB,IAE9BC,EAASvuG,KAAKqS,MACdm8F,EAAUxuG,KAAKsS,OACf+pE,EAAmB,CAAEhqE,MAAOk8F,EAAQj8F,OAAQk8F,GAC9C,IAQEnxF,EAREoxF,EAASzuG,KAAK2rG,SAASt5F,MACzBq8F,EAAU1uG,KAAK2rG,SAASr5F,OACxB4D,EAAS,EACTC,EAAS,EACTitD,EAAa,EACbC,EAAY,EACZH,EAAQ,EACRC,EAAQ,EA4CV,OAzCIkrC,GAAQA,EAAI7xE,SAAWr1B,GAAQknG,EAAI5xE,SAAWt1B,GAsChD+O,EAASq4F,EAASE,EAClBt4F,EAASq4F,EAAUE,IAtCK,SAApBL,EAAI1xE,cACNzmB,EAASC,EAASuiD,GAAe14D,KAAK2rG,SAAUtvB,GAChDh/D,GAAUkxF,EAASE,EAASv4F,GAAU,EACnB,QAAfm4F,EAAI7xE,SACN4mC,GAAc/lD,GAEG,QAAfgxF,EAAI7xE,SACN4mC,EAAa/lD,GAEfA,GAAUmxF,EAAUE,EAAUv4F,GAAU,EACrB,QAAfk4F,EAAI5xE,SACN4mC,GAAahmD,GAEI,QAAfgxF,EAAI5xE,SACN4mC,EAAYhmD,IAGQ,UAApBgxF,EAAI1xE,cACNzmB,EAASC,EAASyiD,GAAiB54D,KAAK2rG,SAAUtvB,GAClDh/D,EAASoxF,EAASF,EAASr4F,EACR,QAAfm4F,EAAI7xE,SACN0mC,EAAQ7lD,EAAS,GAEA,QAAfgxF,EAAI7xE,SACN0mC,EAAQ7lD,GAEVA,EAASqxF,EAAUF,EAAUr4F,EACV,QAAfk4F,EAAI5xE,SACN0mC,EAAQ9lD,EAAS,GAEA,QAAfgxF,EAAI5xE,SACN0mC,EAAQ9lD,GAEVoxF,EAASF,EAASr4F,EAClBw4F,EAAUF,EAAUr4F,IAMjB,CACL9D,MAAOo8F,EACPn8F,OAAQo8F,EACRx4F,SACAC,SACAitD,aACAC,YACAH,QACAC,QAEJ,CA0BA,iBAAOvqD,CAAU1T,EAEfhD,GACA,IAFE8jG,QAAS2I,EAAG7C,aAAc8C,EAAE32F,IAAEA,EAAGL,YAAEA,EAAW5O,KAAEA,KAAS0G,GAAWxK,EAGtE,OAAOsP,QAAQkE,IAAI,CACjBjB,GAAUQ,EAAM,IAAK/V,EAAS0V,gBAC9B+2F,GAAKp2F,GAAmCo2F,EAAGzsG,GAE3C0sG,EAAKr2F,GAAuB,CAACq2F,GAAK1sG,GAAW,GAC7CiX,GAAwBzJ,EAAQxN,KAC/B2W,KAAKhO,IAA4D,IAA1D6Q,EAAIsqF,EAAU,IAAK8F,GAAe+C,EAAgB,CAAA,GAAGhkG,EAC7D,OAAO,IAAI7K,KAAK0b,EAAI,IACfhM,EAEHuI,MACA+tF,UACA8F,kBACG+C,KAGT,CAQA,cAAOC,CACLp3F,GAGsB,IAFtBE,YAAEA,EAAc,KAAID,OAAEA,GAA0BrX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACnDyuG,EAAgBzuG,UAAAC,OAAA,EAAAD,kBAAAE,EAEhB,OAAOiX,GAAUC,EAAK,CAAEE,cAAaD,WAAUkB,KAC5Cd,GAAQ,IAAI/X,KAAK+X,EAAKg3F,GAE3B,CASA,wBAAa38C,CACXt+C,GAGA,IAFA5R,EAAkB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EACrBouD,EAAmBpuD,UAAAC,OAAA,EAAAD,kBAAAE,EAEnB,MAAM67E,EAAmBprB,GACvBn9C,EACA9T,KAAKsyD,gBACL5D,GAEF,OAAO1uD,KAAK8uG,QACVzyB,EAAiB,eAAiBA,EAAuB,KACzDn6E,EACAm6E,GACAtjE,MAAOf,IACPxW,EAAI,MAAO,wBAAyBwW,GAC7B,MAEX,ECh0BK,SAASg3F,GACdl7F,GAEA,IAAKyuB,GAAwBitB,KAAK17C,EAAQ+5C,UACxC,MAAO,CAAA,EAET,MAAMohD,EAA6Bn7F,EAAQi6C,aAAa,WACxD,IAIIz2C,EACAoE,EALAxF,EAAS,EACTC,EAAS,EACT+0D,EAAO,EACPC,EAAO,EAGX,MAAM+jC,EAAYp7F,EAAQi6C,aAAa,SACjCohD,EAAar7F,EAAQi6C,aAAa,UAClC1hD,EAAIyH,EAAQi6C,aAAa,MAAQ,EACjC3hD,EAAI0H,EAAQi6C,aAAa,MAAQ,EAEjCqhD,IADcH,GAAexsE,GAAmB+sB,KAAKy/C,IAErDI,GACHH,IAAcC,GAA4B,SAAdD,GAAuC,SAAfC,EAEvD,IAAIG,EAAkB,GAClBC,EAAY,EACZC,EAAa,EAiBjB,GAfIJ,IAEC/iG,GAAKD,IACN0H,EAAQuH,YACwB,cAAhCvH,EAAQuH,WAAWwyC,WAEnByhD,EACE,cAAgBzzE,GAAUxvB,GAAK,KAAO,IAAMwvB,GAAUzvB,GAAK,KAAO,KACpEkL,GAAUxD,EAAQi6C,aAAa,cAAgB,IAAMuhD,EACrDx7F,EAAQoI,aAAa,YAAa5E,GAClCxD,EAAQmJ,gBAAgB,KACxBnJ,EAAQmJ,gBAAgB,MAIxBmyF,GAAkBC,EACpB,MAAO,CACLh9F,MAAO,EACPC,OAAQ,GAIZ,MAAMm9F,EAAoC,CACxCp9F,MAAO,EACPC,OAAQ,GAGV,GAAI88F,EAIF,OAHAK,EAAUp9F,MAAQwpB,GAAUqzE,GAC5BO,EAAUn9F,OAASupB,GAAUszE,GAEtBM,EAGT,MAAMC,EAAeT,EAAYh0E,MAAMwH,IACvCyoC,GAAQnxD,WAAW21F,EAAa,IAChCvkC,GAAQpxD,WAAW21F,EAAa,IAChC,MAAMn1B,EAAexgE,WAAW21F,EAAa,IACvCl1B,EAAgBzgE,WAAW21F,EAAa,IAC9CD,EAAUvkC,KAAOA,EACjBukC,EAAUtkC,KAAOA,EACjBskC,EAAUl1B,aAAeA,EACzBk1B,EAAUj1B,cAAgBA,EACrB60B,GAMHI,EAAUp9F,MAAQkoE,EAClBk1B,EAAUn9F,OAASkoE,IANnBi1B,EAAUp9F,MAAQwpB,GAAUqzE,GAC5BO,EAAUn9F,OAASupB,GAAUszE,GAC7Bj5F,EAASu5F,EAAUp9F,MAAQkoE,EAC3BpkE,EAASs5F,EAAUn9F,OAASkoE,GAO9B,MAAM8zB,EAAsBnyE,GAC1BroB,EAAQi6C,aAAa,wBAA0B,IA4BjD,GA1BIugD,EAAoB9xE,SAAWr1B,IAEO,SAApCmnG,EAAoB3xE,cACtBxmB,EAASD,EAASA,EAASC,EAASA,EAASD,GAGP,UAApCo4F,EAAoB3xE,cACtBxmB,EAASD,EAASA,EAASC,EAASD,EAASC,GAG/Co5F,EAAYE,EAAUp9F,MAAQkoE,EAAerkE,EAC7Cs5F,EAAaC,EAAUn9F,OAASkoE,EAAgBtkE,EACb,QAA/Bo4F,EAAoB9xE,SACtB+yE,GAAa,GAEoB,QAA/BjB,EAAoB7xE,SACtB+yE,GAAc,GAEmB,QAA/BlB,EAAoB9xE,SACtB+yE,EAAY,GAEqB,QAA/BjB,EAAoB7xE,SACtB+yE,EAAa,IAKJ,IAAXt5F,GACW,IAAXC,GACS,IAAT+0D,GACS,IAATC,GACM,IAAN9+D,GACM,IAAND,EAEA,OAAOqjG,EAqBT,IAnBKpjG,GAAKD,IAAuC,cAAjC0H,EAAQuH,WAAYwyC,WAClCyhD,EACE,cAAgBzzE,GAAUxvB,GAAK,KAAO,IAAMwvB,GAAUzvB,GAAK,KAAO,MAGtEkL,EACEg4F,EACA,WACAp5F,EAFAo5F,QAKAn5F,EACA,KACC+0D,EAAOh1D,EAASq5F,GACjB,KACCpkC,EAAOh1D,EAASq5F,GACjB,KAGuB,QAArB17F,EAAQ+5C,SAAoB,CAG9B,IAFAnyC,EAAK5H,EAAQ6H,cAAcg0F,gBAAgB7tE,GAAO,KAE3ChuB,EAAQ87F,YACbl0F,EAAG42E,YAAYx+E,EAAQ87F,YAEzB97F,EAAQw+E,YAAY52E,EACtB,MACEA,EAAK5H,EACL4H,EAAGuB,gBAAgB,KACnBvB,EAAGuB,gBAAgB,KACnB3F,EAASoE,EAAGqyC,aAAa,aAAez2C,EAG1C,OADAoE,EAAGQ,aAAa,YAAa5E,GACtBm4F,CACT,CDwqBC1vG,EA9vBY0rG,GAAW,OA+FR,SAAO1rG,EA/FV0rG,GAAW,kBAiGG,IAAInoE,MAAoBkoE,KAAYzrG,EAjGlD0rG,GAAW,cAzBkD,CACxEpuE,YAAa,EACbyvE,kBAAkB,EAClBG,oBAAqB,GACrB/pC,MAAO,EACPC,MAAO,EACPupC,gBAAgB,IAsHuB3sG,EAnG5B0rG,GAAW,kBA0qBG,IACpB/9C,GACH,IACA,IACA,QACA,SACA,sBACA,aACA,OACA,cACA,oBA4EJ/kD,GAAcG,SAAS2iG,IACvB9iG,GAAcQ,YAAYsiG,IEx1BnB,MAAMoE,GAAcC,GAAkBA,EAAKC,QAAQphF,QAAQ,OAAQ,ICIpEqhF,GAA2B5wE,GpH2BT,CACpB,UACA,OACA,SACA,WACA,WACA,OACA,SqHtCG,SAAS6wE,GACdp1F,EACAq1F,GAEA,IAAIriD,EAEFsiD,EACA1kG,EACAmY,EAHAwsF,EAAuB,GAIzB,IAAK3kG,EAAI,EAAGmY,EAAMssF,EAAU3vG,OAAQkL,EAAImY,EAAKnY,IAC3CoiD,EAAWqiD,EAAUzkG,GACrB0kG,EAAWt1F,EAAIw1F,uBACb,6BACAxiD,GAEFuiD,EAAYA,EAAU5kG,OAAO5J,MAAM4pB,KAAK2kF,IAE1C,OAAOC,CACT,CClBA,MAAME,GAAiB,CACrB,oBACA,KACA,KACA,KACA,KACA,gBACA,KACA,KACA,IACA,KACA,MAEIC,GAAY,aAEX,SAASC,GACd31F,EACAs/D,GACA,IAAAs2B,EACA,MAAMC,GAAwC,QAAhCD,EAAAt2B,EAASpsB,aAAawiD,eAAUE,SAAhCA,EAAkCz2E,MAAM,KAAM,GAC1D22E,EAAqB91F,EAAI8B,eAAe+zF,GAI1C,GAHIC,GAAsBA,EAAmB5iD,aAAawiD,KACxDC,GAA+B31F,EAAK81F,GAElCA,IACFL,GAAevvG,QAAS8tD,IACtB,MAAM5qD,EAAQ0sG,EAAmB5iD,aAAac,IACzCsrB,EAASv9D,aAAaiyC,IAAS5qD,GAClCk2E,EAASj+D,aAAa2yC,EAAM5qD,MAG3Bk2E,EAASy2B,SAASrwG,QAAQ,CAC7B,MAAMswG,EAAiBF,EAAmBG,WAAU,GACpD,KAAOD,EAAejB,YACpBz1B,EAASmY,YAAYue,EAAejB,WAExC,CAEFz1B,EAASl9D,gBAAgBszF,GAC3B,CCpCA,MAAMQ,GAAW,CACf,iBACA,iBACA,qBACA,sBCeF,MAAMC,GAAWt1F,GACf/S,GAAcM,YAAY4mG,GAAWn0F,GAAIrW,eAepC,MAAM4rG,GAUXnxG,WAAAA,CACEwf,EACApd,EACAsW,EACAqC,EACAq2F,GAEAlxG,KAAKsf,SAAWA,EAChBtf,KAAKkC,QAAUA,EACflC,KAAKwY,QAAUA,EACfxY,KAAKmxG,SAAW,+BAChBnxG,KAAK6a,IAAMA,EACX7a,KAAKkxG,UAAYA,EACjBlxG,KAAKoxG,aD9CF,SACLv2F,GAEA,MAAMw2F,EAASpB,GAAiBp1F,EAAKk2F,IAC/BK,EAAmD,CAAA,EACzD,IAAI75D,EAAI85D,EAAO9wG,OACf,KAAOg3C,KAAK,CACV,MAAM77B,EAAK21F,EAAO95D,GACd77B,EAAGqyC,aAAa,eAClByiD,GAA+B31F,EAAKa,GAEtC,MAAM/H,EAAK+H,EAAGqyC,aAAa,MACvBp6C,IACFy9F,EAAaz9F,GAAM+H,EAEvB,CACA,OAAO01F,CACT,CC6BwBE,CAAgBz2F,GACpC7a,KAAK0uD,SCvDF,SAAqB7zC,GAC1B,MAAM6M,EAAS7M,EAAIi+D,qBAAqB,SAClCy4B,EAAqB,CAAA,EAG3B,IAAK,IAAI9lG,EAAI,EAAGA,EAAIic,EAAOnnB,OAAQkL,IAAK,CACtC,MAAM+lG,GAAiB9pF,EAAOjc,GAAG8iF,aAAe,IAAI5/D,QAElD,oBACA,IAG2B,KAAzB6iF,EAAcj1E,QAKlBi1E,EACGh2E,MAAM,KAEN1xB,OAAO,CAAC6kD,EAAMrlD,EAAOqC,IAAUA,EAAMpL,OAAS,GAAKouD,EAAKpyB,QAExDx7B,QAAS4tD,IAIR,IACGA,EAAK1zB,MAAM,OAAS,IAAI16B,OAAS,GAClCouD,EAAKpyB,OAAOymB,WAAW,KAEvB,OAGF,MAAM/nB,EAAQ0zB,EAAKnzB,MAAM,KACvBi2E,EAAkC,CAAA,EAElCC,EADcz2E,EAAM,GAAGsB,OACUf,MAAM,KAAK1xB,OAAO,SAAU6nG,GAC3D,OAAOA,EAAKp1E,MACd,GAEF,IAAK,IAAIgb,EAAI,EAAGA,EAAIm6D,EAAmBnxG,OAAQg3C,IAAK,CAClD,MAAMo6D,EAAOD,EAAmBn6D,GAAG/b,MAAM,KACvCnoB,EAAWs+F,EAAK,GAAGp1E,OACnBt4B,EAAQ0tG,EAAK,GAAGp1E,OAClBk1E,EAAQp+F,GAAYpP,CACtB,EACA0qD,EAAO1zB,EAAM,GAAGsB,QACXf,MAAM,KAAKz6B,QAAS6wG,IAET,MADdA,EAAQA,EAAMjjF,QAAQ,QAAS,IAAI4N,UAInCg1E,EAASK,GAAS,IACZL,EAASK,IAAU,MACpBH,OAIb,CACA,OAAOF,CACT,CDLoBM,CAAYh3F,EAC9B,CAEAwN,KAAAA,GACE,OAAO7T,QAAQkE,IACb1Y,KAAKsf,SAAS3G,IAAK7E,GAAY9T,KAAK8xG,aAAah+F,IAErD,CAEA,kBAAMg+F,CAAap2F,GACjB,MAAMi8D,EAAQq5B,GAAQt1F,GACtB,GAAIi8D,EAAO,CACT,MAAMxmE,QAAmCwmE,EAAMvlB,YAC7C12C,EACA1b,KAAKkC,QACLlC,KAAK0uD,UAcP,OAZA1uD,KAAK+xG,gBAAgB5gG,EAAKuK,EAAIvT,GAC9BnI,KAAK+xG,gBAAgB5gG,EAAKuK,EAAItT,GAC1B+I,aAAes6F,IAAet6F,EAAI06F,iBACpC9oC,GACE5xD,EACAA,EAAIgrB,qCAGN4mC,GAAmC5xD,SAE/BnR,KAAKgyG,gBAAgB7gG,EAAKuK,GAChC1b,KAAKwY,SAAWxY,KAAKwY,QAAQkD,EAAIvK,GAC1BA,CACT,CACA,OAAO,IACT,CAEA8gG,yBAAAA,CACE9gG,EACAkC,EACA6+F,GAEA,MAAMjuG,EAAQkN,EAAIkC,GAChB07C,EAAQ/uD,KAAKmxG,SACf,IAAKpiD,EAAMS,KAAKvrD,GACd,OAGF8qD,EAAMiT,UAAY,EAElB,MAAMruD,EAAKo7C,EAAM/yB,KAAK/3B,GAAQ,GAG9B,OAFA8qD,EAAMiT,UAAY,EAEXkwC,EAAQv+F,EACjB,CAEAo+F,eAAAA,CACE5gG,EACAuK,EACArI,GAEA,MAAM8+F,EAAcnyG,KAAKiyG,0BACvB9gG,EACAkC,EACArT,KAAKoxG,cAEP,GAAIe,EAAa,CACf,MAAMx5B,EAAcj9D,EAAGqyC,aAAa16C,EAAW,YACzC8mE,EAAWT,GAAStnB,YAAY+/C,EAAahhG,EAAK,IACnDnR,KAAKkC,QACR86B,QAAS27C,IAEXxnE,EAAI5L,IAAI8N,EAAU8mE,EACpB,CACF,CAIA,qBAAM63B,CACJ7gG,EACAihG,EACAC,GAEA,MAAMC,EAAmBtyG,KAAKiyG,0BAC5B9gG,EACA,WACAnR,KAAKkxG,WAEP,GAAIoB,EAAkB,CACpB,MAAMC,EAAkBr9F,GAAgB/D,EAAI+sB,uBACtCs0E,EAAcF,EAAiB,GAAG/jD,cACxC,IAAIkkD,EAAgBL,EACpB,MACGC,GACDI,EAAclkD,eACdkkD,EAAc1kD,aAAa,eAAiB58C,EAAIsR,UAEhDgwF,EAAgBA,EAAclkD,cAGhCkkD,EAAclkD,cAAe+jC,YAAYkgB,GAMzC,MAAMtuC,EAAiB7U,GACrB,GAAGojD,EAAc1kD,aAAa,cAAgB,MAC5CykD,EAAYzkD,aAAa,sBAAwB,MAIrDykD,EAAYt2F,aACV,YACA,UAAUgoD,EAAe/pD,KAAK,SAGhC,MAAM6qD,QAAkBxwD,QAAQkE,IAC9B45F,EAAiB35F,IAAK+5F,GACb1B,GAAQ0B,GACZtgD,YAAYsgD,EAAiB1yG,KAAKkC,QAASlC,KAAK0uD,UAChD71C,KAAM85F,IACL5vC,GAAmC4vC,GACnCA,EAAgBv1E,SAAWu1E,EAAgBC,gBACpCD,EAAgBC,SAChBD,MAITlwF,EACiB,IAArBuiD,EAAUzkE,OAAeykE,EAAU,GAAK,IAAI/O,GAAM+O,GAC9C6tC,EAAax9F,GACjBk9F,EACA9vF,EAASyb,uBAEPzb,EAASA,gBACLziB,KAAKgyG,gBACTvvF,EACAgwF,EAIAD,EAAYzkD,aAAa,aAAe0kD,OAAgBjyG,GAG5D,MAAM0V,OAAEA,EAAMC,OAAEA,EAAMrK,MAAEA,EAAKsK,MAAEA,EAAKE,WAAEA,EAAUC,WAAEA,GAChDR,GAAY88F,GACdpwF,EAASld,IAAI,CACX6R,OAAO,EACPC,OAAO,IAEToL,EAASld,IAAI,CACX2Q,SACAC,SACArK,QACAsK,QACAC,MAAO,IAEToM,EAASuI,oBACP,IAAI7e,GAAMmK,EAAYC,GACtBzP,EACAA,GAEFqK,EAAIsR,SAAWA,CACjB,aAEStR,EAAIsR,QAGf,EE1NF,MAAMqwF,GAAiBp3F,GACrB4mB,GAAsBktB,KAAKqgD,GAAWn0F,IAuBjCq3F,eAAeC,GACpBn4F,EACArC,GAE2B,IAD3BZ,YAAEA,EAAWD,OAAEA,GAA0BrX,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE5C,GAAIqX,GAAUA,EAAOG,QAGnB,OAFAtW,EAAI,MAAO,IAAIW,EAAmB,qBA3BH8wG,CACjCpjG,QAAS,GACTyP,SAAU,GACVpd,QAAS,CAAA,EACTgxG,YAAa,IA2Bb,MAAMj4F,EAAkBJ,EAAII,iBCvCvB,SAA4BJ,GACjC,MAAMs4F,EAAWlD,GAAiBp1F,EAAK,CAAC,MAAO,YACzCu4F,EAAiB,CAAC,IAAK,IAAK,aAAc,OAAQ,aAExD,IAAK,MAAMC,KAAcF,EAAU,CACjC,MAAMG,EAA8BD,EAAWniD,WAEzCqiD,EAAqC,CAAA,EAC3C,IAAK,MAAM1kD,KAAQykD,EACjBzkD,EAAK5qD,QAAUsvG,EAAW1kD,EAAK9e,MAAQ8e,EAAK5qD,OAG9C,MAAMuvG,GAASD,EAAW,eAAiBA,EAAWE,MAAQ,IAAIz5E,MAAM,GAExE,GAAc,KAAVw5E,EACF,OAEF,MAAME,EAAoB74F,EAAI8B,eAAe62F,GAC7C,GAA0B,OAAtBE,EAEF,OAEF,IAAIC,EAAiBD,EAAkB5C,WAAU,GAEjD,MAAM8C,EAAmCD,EAAeziD,WAElD2iD,EAA0C,CAAA,EAChD,IAAK,MAAMhlD,KAAQ+kD,EACjB/kD,EAAK5qD,QAAU4vG,EAAgBhlD,EAAK9e,MAAQ8e,EAAK5qD,OAInD,MAAMoI,EAAEA,EAAI,EAACD,EAAEA,EAAI,EAAC4C,UAAEA,EAAY,IAAOukG,EACnCO,EAAe,GAAG9kG,KACtB6kG,EAAgB7kG,WAAa,gBACjB3C,MAAMD,KAIpB,GAFA4iG,GAAsB2E,GAElB,SAASnkD,KAAKmkD,EAAe9lD,UAAW,CAE1C,MAAMkmD,EAAMJ,EAAeh4F,cAAcg0F,gBAAgB7tE,GAAO,KAChErhC,OAAO8J,QAAQspG,GAAiB9yG,QAAQmE,IAAA,IAAE6qC,EAAM9rC,GAAMiB,EAAA,OACpD6uG,EAAIC,eAAelyE,GAAOiO,EAAM9rC,KAElC8vG,EAAI9qE,UAAU0qE,EAAeM,YAC7BN,EAAiBI,CACnB,CAEA,IAAK,MAAMllD,KAAQykD,EAAe,CAChC,IAAKzkD,EACH,SAEF,MAAM9e,KAAEA,EAAI9rC,MAAEA,GAAU4qD,EACxB,IAAIukD,EAAeniG,SAAS8+B,GAI5B,GAAa,UAATA,EAAkB,CAIpB,MAAMmkE,EAAmC,CAAA,EACzCvjD,GAAiB1sD,EAAOiwG,GAExBzzG,OAAO8J,QAAQspG,GAAiB9yG,QAAQ8J,IAAmB,IAAjBklC,EAAM9rC,GAAM4G,EACpDqpG,EAAYnkE,GAAQ9rC,IAGtB0sD,GAAiBkjD,EAAgBr4F,OAAS,GAAI04F,GAC9C,MAAMC,EAAe1zG,OAAO8J,QAAQ2pG,GACjCv7F,IAAKy7F,GAAUA,EAAMj6F,KAAK,MAC1BA,KAAK,KACRw5F,EAAez3F,aAAa6zB,EAAMokE,EACpC,MAEGN,EAAgB9jE,IAAS4jE,EAAez3F,aAAa6zB,EAAM9rC,EAEhE,CAEA0vG,EAAez3F,aAAa,YAAa43F,GACzCH,EAAez3F,aAAa,sBAAuB,KACnDy3F,EAAe12F,gBAAgB,MAC/Bo2F,EAAWh4F,WAAY6pD,aAAayuC,EAAgBN,EACtD,CACF,CD7CEgB,CAAmBx5F,GAEnB,MAAMy5F,EAAc1yG,MAAM4pB,KAAKvQ,EAAgB69D,qBAAqB,MAClE52E,EAAU,IACL8sG,GAAsB/zF,GACzBrD,cACAD,UAEE2H,EAAWg1F,EAAYxqG,OAAQ4R,IACnCszF,GAAsBtzF,GACfo3F,GAAcp3F,KNjDlB,SAA4B5H,GACjC,IAAI63F,EAA2B73F,EAC/B,KAAO63F,IAAaA,EAAWA,EAASp9C,gBACtC,GACEo9C,GACAA,EAAS99C,UACTmiD,GAAyBxgD,KAAKqgD,GAAWlE,MACxCA,EAAS59C,aAAa,uBAEvB,OAAO,EAGX,OAAO,CACT,CMoCiCwmD,CAAmB74F,KAElD,IAAK4D,GAAaA,IAAaA,EAAS/e,OACtC,MAAO,CA5CTsP,QAAS,GACTyP,SAAU,GACVpd,QAAS,CAAA,EACTgxG,YAAa,GA2CThxG,UACAgxG,YAAaoB,GAGjB,MAAME,EAA4C,CAAA,EAClDF,EACGxqG,OAAQ4R,GAA0B,aAAnBm0F,GAAWn0F,IAC1B3a,QAAS2a,IACRA,EAAGQ,aAAa,oBAAqBR,EAAGqyC,aAAa,cAAgB,IACrE,MAAMp6C,EAAK+H,EAAGqyC,aAAa,MAC3BymD,EAAe7gG,GAAM/R,MAAM4pB,KAAK9P,EAAGo9D,qBAAqB,MAAMhvE,OAC3D4R,GAAOo3F,GAAcp3F,MAK5B,MAAM+4F,EAAgB,IAAIxD,GACxB3xF,EACApd,EACAsW,EACAqC,EACA25F,GAKF,MAAO,CACL3kG,cAHsB4kG,EAAcpsF,QAIpC/I,WACApd,UACAgxG,YAAaoB,EAEjB,CE1EO,SAASI,GACdppD,EACA9yC,EACAtW,GAKA,OAAO8wG,IAHQ,IAAKvuG,IAA2B,YAEhCkwG,gBAAgBrpD,EAAO/uB,OAAQ,YACjB/jB,EAAStW,EACxC,CCPO,SAAS0yG,GACdl9F,EACAc,GAE2B,IAD3BtW,EAAyB5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAE5B,OAAOu0G,MAAMn9F,EAAIiX,QAAQ,SAAU,IAAI4N,OAAQ,CAC7C5kB,OAAQzV,EAAQyV,SAEfkB,KAAMi8F,IACL,IAAKA,EAASC,GACZ,MAAM,IAAIhzG,EAAY,uBAAuB+yG,EAAS9rE,UAExD,OAAO8rE,EAAS7nD,SAEjBp0C,KAAMm8F,GACEN,GAAkBM,EAASx8F,EAAStW,IAE5C6W,MAAM,KHxBwBk6F,CACjCpjG,QAAS,GACTyP,SAAU,GACVpd,QAAS,CAAA,EACTgxG,YAAa,KGwBf,CCpCO,MAAM+B,GACX/yG,QAEkD1B,IAA1C0B,EAAgC+lG,MAS7BiN,GAAmBA,CAAC7iG,EAAeC,KAC9C,MAAMswC,EAAe3uC,GAAuB,CAAE5B,QAAOC,WAE/C9P,EADeqR,KACGzQ,WAAW,SAI7B+xG,EAAc,CAClB5K,YAHkB,IAAI6K,YAAY/iG,EAAQC,EAAS,IAK/C+iG,EAAoB,CACxB3N,iBAAkBr1F,EAClBs1F,kBAAmBr1F,EACnBswC,aAAcA,GAEhB,IAAIlb,EAEJA,EAAYjjC,IAAkB6wG,YAAYC,MAC1C1O,GAAmBrgD,UAAUoiD,WAAW39F,KACtCkqG,EACA3yG,EACA6yG,GAEF,MAAMG,EAAgB/wG,IAAkB6wG,YAAYC,MAAQ7tE,EAE5DA,EAAYjjC,IAAkB6wG,YAAYC,MAC1C1O,GAAmBrgD,UAAU2jD,uBAAuBl/F,KAClDkqG,EACA3yG,EACA6yG,GAIF,OAAOG,EAFkB/wG,IAAkB6wG,YAAYC,MAAQ7tE,GChDpD+tE,GAAkB,wBAElBC,GAAyB,SAChCD,oJCeA1mD,GAAQ,IAAIzvB,OAAOm2E,GAAiB,KAEnC,MAAME,GAQX,QAAI3sG,GACF,OAAQhJ,KAAKF,YAAkCkJ,IACjD,CAwBAlJ,WAAAA,GAGoE,IAHxDkJ,KACVA,KACG9G,GACwD5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC9DG,OAAOC,OACLV,KACCA,KAAKF,YAAkCsB,SACxCc,EAEJ,CAEU0zG,iBAAAA,GACR,OAAOF,EACT,CAEAG,eAAAA,GACE,MD5DwB,kLC6D1B,CASAC,aAAAA,CACEtzG,GAGA,IAFAE,EAAsBpC,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAK41G,oBAC9BG,EAAoBz1G,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAGN,KAAK61G,kBAE5B,MACEvzG,YAAYkB,YAAEA,EAAc,UAC1BU,IACgB,UAAhBV,IACFd,EAAiBA,EAAeisB,QAC9BogC,GACA0mD,GAAgB9mF,QAAQ,QAASnrB,KAGrC,MAAMwyG,EAAexzG,EAAGI,aAAaJ,EAAGyzG,eAClCtzG,EAAiBH,EAAGI,aAAaJ,EAAGK,iBACpCqzG,EAAU1zG,EAAGszG,gBAEnB,IAAKE,IAAiBrzG,IAAmBuzG,EACvC,MAAM,IAAIn0G,EACR,qDAKJ,GAFAS,EAAGM,aAAakzG,EAAcD,GAC9BvzG,EAAGO,cAAcizG,IACZxzG,EAAGQ,mBAAmBgzG,EAAcxzG,EAAGS,gBAC1C,MAAM,IAAIlB,EACR,mCAAmC/B,KAAKgJ,SAASxG,EAAG2zG,iBAClDH,MAON,GAFAxzG,EAAGM,aAAaH,EAAgBD,GAChCF,EAAGO,cAAcJ,IACZH,EAAGQ,mBAAmBL,EAAgBH,EAAGS,gBAC5C,MAAM,IAAIlB,EACR,qCAAqC/B,KAAKgJ,SAASxG,EAAG2zG,iBACpDxzG,MAQN,GAHAH,EAAG4zG,aAAaF,EAASF,GACzBxzG,EAAG4zG,aAAaF,EAASvzG,GACzBH,EAAG6zG,YAAYH,IACV1zG,EAAG8zG,oBAAoBJ,EAAS1zG,EAAG+zG,aACtC,MAAM,IAAIx0G,EACR,0BAA0B/B,KAAKgJ,SAASxG,EAAGg0G,kBAAkBN,MAIjE,MAAMO,EAAmBz2G,KAAK02G,oBAAoBl0G,EAAI0zG,IAAY,CAAA,EAIlE,OAHAO,EAAiBE,OAASn0G,EAAGo0G,mBAAmBV,EAAS,UACzDO,EAAiBI,OAASr0G,EAAGo0G,mBAAmBV,EAAS,UAElD,CACLA,UACAY,mBAAoB92G,KAAK+2G,sBAAsBv0G,EAAI0zG,GACnDO,mBAEJ,CASAM,qBAAAA,CACEv0G,EACA0zG,GAEA,MAAO,CACLhO,UAAW1lG,EAAGw0G,kBAAkBd,EAAS,aAE7C,CASAQ,mBAAAA,CACEl0G,EACA0zG,GAEA,MAAMe,EAAaj3G,KAAKF,YACrB22G,iBAEGA,EAAgE,CAAA,EACtE,IAAK,IAAIhrG,EAAI,EAAGA,EAAIwrG,EAAU12G,OAAQkL,IACpCgrG,EAAiBQ,EAAUxrG,IAAMjJ,EAAGo0G,mBAClCV,EACAe,EAAUxrG,IAGd,OAAOgrG,CACT,CAQAS,iBAAAA,CACE10G,EACAs0G,EACAK,GAEA,MAAMC,EAAoBN,EAAmB5O,UACvCmP,EAAS70G,EAAG80G,eAClB90G,EAAG+0G,WAAW/0G,EAAGg1G,aAAcH,GAC/B70G,EAAGi1G,wBAAwBL,GAC3B50G,EAAGk1G,oBAAoBN,EAAmB,EAAG50G,EAAGm1G,OAAO,EAAO,EAAG,GACjEn1G,EAAGo1G,WAAWp1G,EAAGg1G,aAAcL,EAAe30G,EAAGq1G,YACnD,CAEAC,iBAAAA,CAAkB51G,GAChB,MAAMM,EAAKN,EAAQE,QACnB,GAAIF,EAAQ8lG,OAAS,EAAG,CACtB,MAAM31F,EAAQnQ,EAAQwlG,iBAChBp1F,EAASpQ,EAAQylG,kBACnBzlG,EAAQgkG,cAAgB7zF,GAASnQ,EAAQikG,eAAiB7zF,IAC5D9P,EAAGumG,cAAc7mG,EAAQ4lG,eACzB5lG,EAAQ4lG,cAAgB5lG,EAAQukG,cAAcoB,cAC5CrlG,EACA6P,EACAC,IAGJ9P,EAAGu1G,qBACDv1G,EAAGgmG,YACHhmG,EAAGw1G,kBACHx1G,EAAGsmG,WACH5mG,EAAQ4lG,cACR,EAEJ,MAEEtlG,EAAG+lG,gBAAgB/lG,EAAGgmG,YAAa,MACnChmG,EAAGy1G,QAEP,CAEAC,aAAAA,CAAch2G,GACZA,EAAQ8lG,SACR9lG,EAAQkmG,OACR,MAAM+P,EAAOj2G,EAAQ4lG,cACrB5lG,EAAQ4lG,cAAgB5lG,EAAQ0lG,cAChC1lG,EAAQ0lG,cAAgBuQ,CAC1B,CAUA3K,cAAAA,CAAetrG,GACb,OAAO,CACT,CAeAwkG,OAAAA,CAAQxkG,GACF+yG,GAAqB/yG,IACvBlC,KAAK83G,kBAAkB51G,GACvBlC,KAAKo4G,aAAal2G,GAClBlC,KAAKk4G,cAAch2G,IAEnBlC,KAAKq4G,UAAUn2G,EAEnB,CAEAm2G,SAAAA,CAAU1yD,GACR,CAQF2yD,WAAAA,GACE,OAAOt4G,KAAKgJ,IACd,CASAuvG,cAAAA,CAAer2G,GACb,MAAMX,EAAMvB,KAAKs4G,cAIjB,OAHKp2G,EAAQimG,aAAa5mG,KACxBW,EAAQimG,aAAa5mG,GAAOvB,KAAK81G,cAAc5zG,EAAQE,UAElDF,EAAQimG,aAAa5mG,EAC9B,CAcA62G,YAAAA,CAAal2G,GACX,MAAMM,EAAKN,EAAQE,QACbo2G,EAASx4G,KAAKu4G,eAAer2G,GACd,IAAjBA,EAAQkmG,MAAclmG,EAAQ6lG,gBAChCvlG,EAAGqmG,YAAYrmG,EAAGsmG,WAAY5mG,EAAQ6lG,iBAEtCvlG,EAAGqmG,YAAYrmG,EAAGsmG,WAAY5mG,EAAQ0lG,eAExCplG,EAAGi2G,WAAWD,EAAOtC,SACrBl2G,KAAKk3G,kBAAkB10G,EAAIg2G,EAAO1B,mBAAoB50G,EAAQgmG,WAE9D1lG,EAAGk2G,UAAUF,EAAO/B,iBAAiBE,OAAQ,EAAIz0G,EAAQgkG,aACzD1jG,EAAGk2G,UAAUF,EAAO/B,iBAAiBI,OAAQ,EAAI30G,EAAQikG,cAEzDnmG,KAAK24G,gBAAgBn2G,EAAIg2G,EAAO/B,kBAChCj0G,EAAGo2G,SAAS,EAAG,EAAG12G,EAAQwlG,iBAAkBxlG,EAAQylG,mBACpDnlG,EAAGq2G,WAAWr2G,EAAGs2G,eAAgB,EAAG,EACtC,CAEAC,qBAAAA,CACEv2G,EACAonG,EACAoP,GAEAx2G,EAAGy2G,cAAcD,GACjBx2G,EAAGqmG,YAAYrmG,EAAGsmG,WAAYc,GAE9BpnG,EAAGy2G,cAAcz2G,EAAG02G,SACtB,CAEAC,uBAAAA,CAAwB32G,EAA2Bw2G,GACjDx2G,EAAGy2G,cAAcD,GACjBx2G,EAAGqmG,YAAYrmG,EAAGsmG,WAAY,MAC9BtmG,EAAGy2G,cAAcz2G,EAAG02G,SACtB,CAUAP,eAAAA,CACES,EACAC,GAEA,CAOFC,eAAAA,CAAgBp3G,GACd,IAAKA,EAAQq3G,UAAW,CACtB,MAAMrT,YAAEA,EAAWC,aAAEA,GAAiBjkG,EAChCq3G,EAAYtlG,GAAuB,CACvC5B,MAAO6zF,EACP5zF,OAAQ6zF,IAEVjkG,EAAQq3G,UAAYA,CACtB,CACF,CAQA/+F,QAAAA,GACE,MAAMg/F,EAAc/4G,OAAOU,KACxBnB,KAAKF,YAAkCsB,UAAY,IAGtD,MAAO,CACL4H,KAAMhJ,KAAKgJ,QACRwwG,EAAYn4G,OAAwB,CAACC,EAAKC,KAC3CD,EAAIC,GAAOvB,KACTuB,GAEKD,GACN,CAAA,GAEP,CAMAmkB,MAAAA,GAEE,OAAOzlB,KAAKwa,UACd,CAEA,uBAAa5B,CAAU1T,EAErBygD,GAC6B,IAF7B38C,KAAEA,KAASywG,GAAoCv0G,EAG/C,OAAO,IAAIlF,KAAKy5G,EAClB,EACD15G,EA3YY41G,GAAU,OAmBP,cAEd51G,EArBW41G,GAAU,mBA0Be,IC9C/B,MAAM+D,GAA2B,CACtC1sG,SAAU,oCACV2sG,OACE,4EACFrtG,IAAK,oCACLstG,WAAY,2DACZhtG,SAAU,oCACVitG,QAAS,0DACTC,OAAQ,0DACRC,UACE,4EACF1zF,QAAS,igBAiBT2zF,KAAM,0FCkBD,MAAMC,WAAmBtE,GA0B9B2C,WAAAA,GACE,MAAO,GAAGt4G,KAAKgJ,QAAQhJ,KAAKk6G,MAC9B,CAEUtE,iBAAAA,GACR,MAAO,mRASC8D,GAAyB15G,KAAKk6G,mCAIxC,CAQA7B,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAMuU,EAAS,IAAIuf,GAAMh5B,KAAKi5B,OAAOQ,YAC/BU,EAAQn6B,KAAKm6B,MACbhY,EAAK1I,EAAO,GAAK0gB,EACjBggF,EAAK1gG,EAAO,GAAK0gB,EACjBogC,EAAK9gD,EAAO,GAAK0gB,EACjBigF,EAAS,EAAIjgF,EAEnB,IAAK,IAAI1uB,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GACnB,IAAI4uG,EAAIC,EAAIC,EACZ,OAAQv6G,KAAKk6G,MACX,IAAK,WACHG,EAAMjlG,EAAI+M,EAAM,IAChBm4F,EAAMniF,EAAIgiF,EAAM,IAChBI,EAAMjlG,EAAIilD,EAAM,IAChB,MACF,IAAK,SACH8/C,EAAK,KAAQ,IAAMjlG,IAAM,IAAM+M,GAAO,IACtCm4F,EAAK,KAAQ,IAAMniF,IAAM,IAAMgiF,GAAO,IACtCI,EAAK,KAAQ,IAAMjlG,IAAM,IAAMilD,GAAO,IACtC,MACF,IAAK,MACH8/C,EAAKjlG,EAAI+M,EACTm4F,EAAKniF,EAAIgiF,EACTI,EAAKjlG,EAAIilD,EACT,MACF,IAAK,aACH8/C,EAAKz1G,KAAKmH,IAAIqJ,EAAI+M,GAClBm4F,EAAK11G,KAAKmH,IAAIosB,EAAIgiF,GAClBI,EAAK31G,KAAKmH,IAAIuJ,EAAIilD,GAClB,MACF,IAAK,WACH8/C,EAAKjlG,EAAI+M,EACTm4F,EAAKniF,EAAIgiF,EACTI,EAAKjlG,EAAIilD,EACT,MACF,IAAK,SACH8/C,EAAKz1G,KAAKiJ,IAAIuH,EAAG+M,GACjBm4F,EAAK11G,KAAKiJ,IAAIsqB,EAAGgiF,GACjBI,EAAK31G,KAAKiJ,IAAIyH,EAAGilD,GACjB,MACF,IAAK,UACH8/C,EAAKz1G,KAAKC,IAAIuQ,EAAG+M,GACjBm4F,EAAK11G,KAAKC,IAAIszB,EAAGgiF,GACjBI,EAAK31G,KAAKC,IAAIyQ,EAAGilD,GACjB,MACF,IAAK,UACH8/C,EACEl4F,EAAK,IACA,EAAI/M,EAAI+M,EAAM,IACf,IAAO,GAAK,IAAM/M,IAAM,IAAM+M,GAAO,IAC3Cm4F,EACEH,EAAK,IACA,EAAIhiF,EAAIgiF,EAAM,IACf,IAAO,GAAK,IAAMhiF,IAAM,IAAMgiF,GAAO,IAC3CI,EACEhgD,EAAK,IACA,EAAIjlD,EAAIilD,EAAM,IACf,IAAO,GAAK,IAAMjlD,IAAM,IAAMilD,GAAO,IAC3C,MACF,IAAK,YACH8/C,EAAKl4F,EAAK/M,EAAK,EAAI+M,EAAK/M,EAAK,IAC7BklG,EAAKH,EAAKhiF,EAAK,EAAIgiF,EAAKhiF,EAAK,IAC7BoiF,EAAKhgD,EAAKjlD,EAAK,EAAIilD,EAAKjlD,EAAK,IAC7B,MACF,IAAK,OACH+kG,EAAKl4F,EAAK/M,EAAIglG,EACdE,EAAKH,EAAKhiF,EAAIiiF,EACdG,EAAKhgD,EAAKjlD,EAAI8kG,EAElBn0F,EAAKxa,GAAK4uG,EACVp0F,EAAKxa,EAAI,GAAK6uG,EACdr0F,EAAKxa,EAAI,GAAK8uG,CAChB,CACF,CAQA5B,eAAAA,CACEn2G,EACAi0G,GAEA,MAAMh9F,EAAS,IAAIuf,GAAMh5B,KAAKi5B,OAAOQ,YACrChgB,EAAO,GAAMzZ,KAAKm6B,MAAQ1gB,EAAO,GAAM,IACvCA,EAAO,GAAMzZ,KAAKm6B,MAAQ1gB,EAAO,GAAM,IACvCA,EAAO,GAAMzZ,KAAKm6B,MAAQ1gB,EAAO,GAAM,IACvCA,EAAO,GAAKzZ,KAAKm6B,MACjB33B,EAAGg4G,WAAW/D,EAAiBgE,OAAQhhG,EACzC,EArIA1Z,EAdWk6G,GAAU,WAtBoC,CACzDhhF,MAAO,UACPihF,KAAM,WACN//E,MAAO,IAuCkCp6B,EApB9Bk6G,GAAU,OAsBP,cAAYl6G,EAtBfk6G,GAAU,mBAwBK,CAAC,WA8H7BtxG,GAAcG,SAASmxG,IClMhB,MAAMv3G,GAAkD,CAC7DsK,SAAU,2XAcV0tG,KAAM,qXCuBD,MAAMC,WAAmBhF,GA4B9B2C,WAAAA,GACE,MAAO,GAAGt4G,KAAKgJ,QAAQhJ,KAAKk6G,MAC9B,CAEAtE,iBAAAA,GACE,OAAOlzG,GAAe1C,KAAKk6G,KAC7B,CAEArE,eAAAA,GACE,MD5CwB,4TC6C1B,CAEAuC,YAAAA,CAAal2G,GACX,MAAMM,EAAKN,EAAQE,QACjBwnG,EAAU5pG,KAAK6nG,cAAc3lG,EAAQukG,cAAezmG,KAAK46G,OAC3D56G,KAAK+4G,sBAAsBv2G,EAAIonG,EAAUpnG,EAAGq4G,UAC5Cz6G,MAAMg4G,aAAal2G,GACnBlC,KAAKm5G,wBAAwB32G,EAAIA,EAAGq4G,SACtC,CAEAhT,aAAAA,CAAc0D,EAA6BqP,GACzC,OAAOrP,EAAQ9D,iBAAiBmT,EAAMl1G,SAAUk1G,EAAMx5F,aACxD,CAQA05F,eAAAA,GACE,MAAMF,EAAQ56G,KAAK46G,OACjBvoG,MAAEA,EAAKC,OAAEA,GAAWsoG,EAAMx5F,aAC5B,MAAO,CACL,EAAIw5F,EAAM1kG,OACV,EACA,EACA,EACA,EAAI0kG,EAAMzkG,OACV,GACCykG,EAAMzoG,KAAOE,GACbuoG,EAAMxoG,IAAME,EACb,EAEJ,CAQA+lG,SAAAA,CAASnzG,GAGY,IAFnBohG,WAAWrgF,KAAEA,EAAI5T,MAAEA,EAAKC,OAAEA,GAC1Bm0F,eAAesU,UAAEA,IACA71G,EACjB,MAAM01G,EAAQ56G,KAAK46G,MACdG,EAAUC,aACbD,EAAUC,WAAannG,MAEzB,MAAMonG,EAAUF,EAAUC,WACpB54G,EAAU64G,EAAQ73G,WAAW,MAC/B63G,EAAQ5oG,QAAUA,GAAS4oG,EAAQ3oG,SAAWA,GAChD2oG,EAAQ5oG,MAAQA,EAChB4oG,EAAQ3oG,OAASA,GAEjBlQ,EAAQkf,UAAU,EAAG,EAAGjP,EAAOC,GAEjClQ,EAAQ+uC,aACNypE,EAAM1kG,OACN,EACA,EACA0kG,EAAMzkG,OACNykG,EAAMzoG,KACNyoG,EAAMxoG,KAERhQ,EAAQohB,UAAUo3F,EAAMx5F,aAAc,EAAG,EAAG/O,EAAOC,GACnD,MAAM4oG,EAAY94G,EAAQslD,aAAa,EAAG,EAAGr1C,EAAOC,GAAQ2T,KAC5D,IAAK,IAAIxa,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GACb0J,EAAI8Q,EAAKxa,EAAI,GAEb0W,EAAK+4F,EAAUzvG,GACf0uG,EAAKe,EAAUzvG,EAAI,GACnB8uD,EAAK2gD,EAAUzvG,EAAI,GACnB6uD,EAAK4gD,EAAUzvG,EAAI,GAEzB,OAAQzL,KAAKk6G,MACX,IAAK,WACHj0F,EAAKxa,GAAM2J,EAAI+M,EAAM,IACrB8D,EAAKxa,EAAI,GAAM0sB,EAAIgiF,EAAM,IACzBl0F,EAAKxa,EAAI,GAAM6J,EAAIilD,EAAM,IACzBt0C,EAAKxa,EAAI,GAAM0J,EAAImlD,EAAM,IACzB,MACF,IAAK,OACHr0C,EAAKxa,EAAI,GAAK6uD,EAGpB,CACF,CAQAq+C,eAAAA,CACEn2G,EACAi0G,GAEA,MAAMn/F,EAAStX,KAAK86G,kBACpBt4G,EAAG24G,UAAU1E,EAAiB2E,OAAQ,GACtC54G,EAAG64G,iBAAiB5E,EAAiB6E,kBAAkB,EAAOhkG,EAChE,CAQAkD,QAAAA,GAIE,MAAO,IACFpa,MAAMoa,WACTogG,MAAO56G,KAAK46G,OAAS56G,KAAK46G,MAAMpgG,WAEpC,CASA,uBAAa5B,CAAU/N,EAErB3I,GACuD,IAFvD8G,KAAEA,EAAI4xG,MAAEA,KAAUnB,GAAoC5uG,EAGtD,OAAO4gG,GAAY7yF,WAAWgiG,EAAO14G,GAAS2W,KAC3C0iG,GAAiB,IAAIv7G,KAAK,IAAKy5G,EAAemB,MAAOW,IAE1D,EAhKAx7G,EAhBW46G,GAAU,OAsBP,cAAY56G,EAtBf46G,GAAU,WArBoC,CACzDT,KAAM,WACN//E,MAAO,IA2CkCp6B,EAxB9B46G,GAAU,mBA0BK,CAAC,mBAAoB,WAyJjDhyG,GAAcG,SAAS6xG,IC/LhB,MAAMa,WAAa7F,GAkBxBC,iBAAAA,GACE,MC/C0B,qgCDgD5B,CAEAlP,OAAAA,CAAQxkG,GACF+yG,GAAqB/yG,IAEvBlC,KAAKy7G,YAAcv5G,EAAQgkG,YAAchkG,EAAQikG,aACjDjkG,EAAQ8lG,SACRhoG,KAAK83G,kBAAkB51G,GACvBlC,KAAK07G,YAAa,EAClB17G,KAAKo4G,aAAal2G,GAClBlC,KAAKk4G,cAAch2G,GACnBlC,KAAK83G,kBAAkB51G,GACvBlC,KAAK07G,YAAa,EAClB17G,KAAKo4G,aAAal2G,GAClBlC,KAAKk4G,cAAch2G,IAEnBlC,KAAKq4G,UAAUn2G,EAEnB,CAEAm2G,SAAAA,CAASnzG,GAA2D,IAAxDohG,WAAWrgF,KAAEA,EAAI5T,MAAEA,EAAKC,OAAEA,IAA4BpN,EAGhElF,KAAKy7G,YAAcppG,EAAQC,EAC3BtS,KAAK07G,YAAa,EAClB,IAAIC,EAAY37G,KAAK47G,eAAiBvpG,EACtC,MAAMi0F,EAAY,IAAImE,kBAAkBxkF,GAClC41F,EAAU,GACVC,EAAa,EAAIzpG,EACvB,IAAK,IAAI5G,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,IAAI2J,EAAI,EACN+iB,EAAI,EACJ7iB,EAAI,EACJH,EAAI,EACJ4mG,EAAS,EACX,MAAMC,EAAUvwG,EAAKA,EAAIqwG,EACnBG,EAAUD,EAAUF,EAS1B,IAAK,IAAIvkE,GAAI,GAAcA,EAAIskE,EAAStkE,IAAK,CAC3C,MAAM2kE,EAAU3kE,EAAIskE,EACd58D,EAA6C,EAAlCr6C,KAAKsB,MAAMy1G,EAAYO,GAClCC,EAAS,EAAIv3G,KAAKmH,IAAImwG,GAC5B,IAAIE,EAAe3wG,EAAIwzC,EAEnBm9D,EAAeJ,EACjBI,EAAeJ,EACNI,EAAeH,IACxBG,EAAeH,GAEjB,MAAMI,EAAap2F,EAAKm2F,EAAe,GAAKD,EAC5C/mG,GAAK6Q,EAAKm2F,GAAgBC,EAC1BlkF,GAAKlS,EAAKm2F,EAAe,GAAKC,EAC9B/mG,GAAK2Q,EAAKm2F,EAAe,GAAKC,EAC9BlnG,GAAKknG,EACLN,GAAUI,CACZ,CACA7V,EAAU76F,GAAK2J,EAAID,EACnBmxF,EAAU76F,EAAI,GAAK0sB,EAAIhjB,EACvBmxF,EAAU76F,EAAI,GAAK6J,EAAIH,EACvBmxF,EAAU76F,EAAI,GAAK0J,EAAI4mG,CACzB,CACA/7G,KAAK07G,YAAa,EAClBC,EAAY37G,KAAK47G,eAAiBtpG,EAClC,IAAK,IAAI7G,EAAI,EAAGA,EAAI66F,EAAU/lG,OAAQkL,GAAK,EAAG,CAC5C,IAAI2J,EAAI,EACN+iB,EAAI,EACJ7iB,EAAI,EACJH,EAAI,EACJ4mG,EAAS,EACX,MAAMC,EAAUvwG,EAAIqwG,EACdG,EAAU3V,EAAU/lG,OAASu7G,EAAaE,EAShD,IAAK,IAAIzkE,GAAI,GAAcA,EAAIskE,EAAStkE,IAAK,CAC3C,MAAM2kE,EAAU3kE,EAAIskE,EACd58D,EAAWr6C,KAAKsB,MAAMy1G,EAAYO,GAAWJ,EAC7CK,EAAS,EAAIv3G,KAAKmH,IAAImwG,GAC5B,IAAIE,EAAe3wG,EAAIwzC,EAEnBm9D,EAAeJ,EACjBI,EAAeJ,EACNI,EAAeH,IACxBG,EAAeH,GAEjB,MAAMI,EAAa/V,EAAU8V,EAAe,GAAKD,EACjD/mG,GAAKkxF,EAAU8V,GAAgBC,EAC/BlkF,GAAKmuE,EAAU8V,EAAe,GAAKC,EACnC/mG,GAAKgxF,EAAU8V,EAAe,GAAKC,EACnClnG,GAAKknG,EACLN,GAAUI,CACZ,CACAl2F,EAAKxa,GAAK2J,EAAID,EACd8Q,EAAKxa,EAAI,GAAK0sB,EAAIhjB,EAClB8Q,EAAKxa,EAAI,GAAK6J,EAAIH,EAClB8Q,EAAKxa,EAAI,GAAK0J,EAAI4mG,CACpB,CACF,CAQApD,eAAAA,CACEn2G,EACAi0G,GAEA,MAAM6F,EAAQt8G,KAAKu8G,mBACnB/5G,EAAGg6G,WAAW/F,EAAiBgG,OAAQH,EACzC,CAEA9O,cAAAA,GACE,OAAqB,IAAdxtG,KAAK+iC,IACd,CAEA64E,YAAAA,GACE,IAAIc,EAAY,EAChB,MAAMhB,WAAEA,EAAUD,YAAEA,GAAgBz7G,KAYpC,OAXI07G,EACED,EAAc,IAEhBiB,EAAY,EAAIjB,GAGdA,EAAc,IAEhBiB,EAAYjB,GAGTiB,EAAY18G,KAAK+iC,KAAO,GACjC,CAMAw5E,gBAAAA,GACE,MAAMx5E,EAAO/iC,KAAK47G,eAClB,OAAO57G,KAAK07G,WAAa,CAAC34E,EAAM,GAAK,CAAC,EAAGA,EAC3C,EA5KAhjC,EADWy7G,GAAI,OAYD,QAAMz7G,EAZTy7G,GAAI,WAd8B,CAC7Cz4E,KAAM,IA2B6BhjC,EAdxBy7G,GAAI,mBAgBW,CAAC,WAgK7B7yG,GAAcG,SAAS0yG,IEtLhB,MAAMmB,WAAmBhH,GAe9BC,iBAAAA,GACE,MCtC0B,wPDuC5B,CAQAyC,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAM03G,EAAah4G,KAAKopB,MAAwB,IAAlBhuB,KAAK48G,YACnC,IAAK,IAAInxG,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EACpCwa,EAAKxa,IAAMmxG,EACX32F,EAAKxa,EAAI,IAAMmxG,EACf32F,EAAKxa,EAAI,IAAMmxG,CAEnB,CAEApP,cAAAA,GACE,OAA2B,IAApBxtG,KAAK48G,UACd,CAQAjE,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiBoG,YAAa78G,KAAK48G,WAClD,EAhDA78G,EADW48G,GAAU,OASP,cAAY58G,EATf48G,GAAU,WAboC,CACzDC,WAAY,IAuB6B78G,EAX9B48G,GAAU,mBAaK,CAAC,gBAuC7Bh0G,GAAcG,SAAS6zG,IE1EhB,MCcMG,GAAgD,CAC3DxlG,OAAQ,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAClEylG,YAAY,GAmBP,MAAMC,WAIHrH,GAwBRC,iBAAAA,GACE,MDhE0B,ySCiE5B,CAQAyC,SAAAA,CAAUn2G,GACR,MACE+jB,EADgB/jB,EAAQokG,UACPrgF,KACjBzB,EAAIxkB,KAAKsX,OACTylG,EAAa/8G,KAAK+8G,WAEpB,IAAK,IAAItxG,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GAKnB,GAHAwa,EAAKxa,GAAK2J,EAAIoP,EAAE,GAAK2T,EAAI3T,EAAE,GAAKlP,EAAIkP,EAAE,GAAY,IAAPA,EAAE,GAC7CyB,EAAKxa,EAAI,GAAK2J,EAAIoP,EAAE,GAAK2T,EAAI3T,EAAE,GAAKlP,EAAIkP,EAAE,GAAY,IAAPA,EAAE,GACjDyB,EAAKxa,EAAI,GAAK2J,EAAIoP,EAAE,IAAM2T,EAAI3T,EAAE,IAAMlP,EAAIkP,EAAE,IAAc,IAARA,EAAE,KAC/Cu4F,EAAY,CACf,MAAM5nG,EAAI8Q,EAAKxa,EAAI,GACnBwa,EAAKxa,IAAM0J,EAAIqP,EAAE,GACjByB,EAAKxa,EAAI,IAAM0J,EAAIqP,EAAE,GACrByB,EAAKxa,EAAI,IAAM0J,EAAIqP,EAAE,IACrByB,EAAKxa,EAAI,GACP2J,EAAIoP,EAAE,IAAM2T,EAAI3T,EAAE,IAAMlP,EAAIkP,EAAE,IAAMrP,EAAIqP,EAAE,IAAc,IAARA,EAAE,GACtD,CACF,CACF,CAQAm0F,eAAAA,CACEn2G,EACAi0G,GAEA,MAAMjyF,EAAIxkB,KAAKsX,OACbA,EAAS,CACPkN,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,GACFA,EAAE,IACFA,EAAE,IACFA,EAAE,IACFA,EAAE,IACFA,EAAE,IACFA,EAAE,IACFA,EAAE,IACFA,EAAE,KAEJy4F,EAAY,CAACz4F,EAAE,GAAIA,EAAE,GAAIA,EAAE,IAAKA,EAAE,KACpChiB,EAAG06G,iBAAiBzG,EAAiB0G,cAAc,EAAO7lG,GAC1D9U,EAAGg4G,WAAW/D,EAAiB2G,WAAYH,EAC7C,CAEAziG,QAAAA,GACE,MAAO,IACFpa,MAAMoa,WACTlD,OAAQ,IAAItX,KAAKsX,QAErB,ECjIK,SAAS+lG,GAAwB97G,EAAa+V,GAAyB,IAAAgmG,EAC5E,MAAMC,GAeLx9G,EAfau9G,EAAG,cAAcN,GAY7BxiG,QAAAA,GACE,MAAO,CAAExR,KAAMhJ,KAAKgJ,KAAM+zG,WAAY/8G,KAAK+8G,WAC7C,GACD,OAVex7G,GAAGxB,EAAAu9G,EAAA,WAEC,CAChBP,YAAY,EACZzlG,WACDgmG,GAOH,OADA30G,GAAcG,SAASy0G,EAAUh8G,GAC1Bg8G,CACT,CDsBEx9G,EAdWi9G,GAAW,OAsBR,eAAaj9G,EAtBhBi9G,GAAW,WAwBJF,IAAwB/8G,EAxB/Bi9G,GAAW,mBA0BI,CAAC,eAAgB,eA+E7Cr0G,GAAcG,SAASk0G,IC/GhB,MAAMQ,GAAUH,GACrB,UACA,CACE,MAAQ,QAAS,OAAU,EAAG,MAAO,MAAS,OAAS,OAAS,GAAG,MACnE,eAAmB,OAAS,GAAG,OAAU,EAAG,EAAG,EAAG,EAAG,IAI5CI,GAAUJ,GACrB,UACA,CACE,OAAS,QAAS,OAAU,EAAG,OAAS,OAAS,OAAS,OAAS,EACnE,OAAS,cAAkB,OAAS,EAAG,OAAS,EAAG,EAAG,EAAG,EAAG,IAInDK,GAAaL,GACxB,aACA,CACE,SAAS,QAAU,OAAU,EAAG,QAAS,OAAU,SAAS,OAAU,EACtE,QAAS,eAAoB,QAAS,EAAG,OAAS,EAAG,EAAG,EAAG,EAAG,IAIrDM,GAAcN,GACzB,cACA,CACE,SAAS,QAAU,OAAU,EAAG,QAAS,OAAU,SAAS,OAAU,GACtE,QAAU,cAAmB,QAAS,EAAG,OAAS,EAAG,EAAG,EAAG,EAAG,IAIrDO,GAAWP,GACtB,WACA,CACE,OAAO,MAAQ,KAAQ,EAAG,GAAG,KAAQ,OAAO,KAAQ,EAAG,GAAG,WAC1D,MAAO,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAIhBQ,GAAQR,GACnB,QACA,CACE,KAAO,KAAO,KAAO,EAAG,EAAG,KAAO,KAAO,KAAO,EAAG,EAAG,KAAO,KAAO,KACpE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAITS,GAAaT,GACxB,aACA,CACE,IAAK,IAAK,IAAK,GAAG,EAAI,IAAK,IAAK,IAAK,GAAG,EAAI,IAAK,IAAK,IAAK,GAAG,EAAI,EAAG,EAAG,EACxE,EAAG,ICjEA,MAAMU,WAAiBpI,GAY5B71G,WAAAA,GAEE,IADAoC,EAAoE5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAEvEF,MAAM8B,GACNlC,KAAKg+G,WAAa97G,EAAQ87G,YAAc,EAC1C,CAQAtX,OAAAA,CAAQxkG,GACF+yG,GAAqB/yG,KACvBA,EAAQ8lG,QAAUhoG,KAAKg+G,WAAWz9G,OAAS,GAE7CP,KAAKg+G,WAAWj9G,QAAS+I,IACvBA,EAAO48F,QAAQxkG,IAEnB,CAMAsY,QAAAA,GACE,MAAO,CACLxR,KAAMhJ,KAAKgJ,KACXg1G,WAAYh+G,KAAKg+G,WAAWrlG,IAAK7O,GAAWA,EAAO0Q,YAEvD,CAEAgzF,cAAAA,GACE,OAAQxtG,KAAKg+G,WAAW9sG,KAAMpH,IAAYA,EAAO0jG,iBACnD,CASA,iBAAO50F,CACLlJ,EACAxN,GAEA,OAAOsS,QAAQkE,KACXhJ,EAAOsuG,YAAc,IAA6BrlG,IAAK7O,GACvDnB,GACGE,SAA4BiB,EAAOd,MACnC4P,WAAW9O,EAAQ5H,KAExB2W,KAAMolG,GAAmB,IAAIj+G,KAAK,CAAEg+G,WAAYC,IACpD,EA9DAl+G,EALWg+G,GAAQ,OAUL,YA4DhBp1G,GAAcG,SAASi1G,IChEhB,MAAMG,WAAiBvI,GAc5BC,iBAAAA,GACE,MCrC0B,2VDsC5B,CAEApI,cAAAA,GACE,OAAyB,IAAlBxtG,KAAKm+G,QACd,CAQA9F,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAMi5G,EAAWv5G,KAAKsB,MAAsB,IAAhBlG,KAAKm+G,UAC/BC,EAAa,KAAOD,EAAW,MAAS,KAAO,IAAMA,IAEvD,IAAK,IAAI1yG,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EACpCwa,EAAKxa,GAAK2yG,GAAan4F,EAAKxa,GAAK,KAAO,IACxCwa,EAAKxa,EAAI,GAAK2yG,GAAan4F,EAAKxa,EAAI,GAAK,KAAO,IAChDwa,EAAKxa,EAAI,GAAK2yG,GAAan4F,EAAKxa,EAAI,GAAK,KAAO,GAEpD,CAQAktG,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiB4H,UAAWr+G,KAAKm+G,SAChD,EAjDAp+G,EADWm+G,GAAQ,OAQL,YAAUn+G,EARbm+G,GAAQ,WAbkC,CACrDC,SAAU,IAsB6Bp+G,EAV5Bm+G,GAAQ,mBAYO,CAAC,cAyC7Bv1G,GAAcG,SAASo1G,IE3EhB,MAAMx7G,GAAiB,CAC5B47G,cAAe,yiBAkBfC,cAAe,2oBAoBfC,cAAe,8iBAkBfC,cAAe,4oBAoBfC,cAAe,8iBAkBfC,cAAe,4oBAoBfC,cAAe,8iBAkBfC,cAAe,6oBC9EV,MAAMC,WAAkBnJ,GAiB7B2C,WAAAA,GACE,MAAO,GAAGt4G,KAAKgJ,QAAQpE,KAAKqB,KAAKjG,KAAKsX,OAAO/W,WAC3CP,KAAK++G,OAAS,EAAI,GAEtB,CAEAnJ,iBAAAA,GACE,OAAOlzG,GAAe1C,KAAKs4G,cAC7B,CAQAD,SAAAA,CAAUn2G,GACR,MAAMokG,EAAYpkG,EAAQokG,UACxBrgF,EAAOqgF,EAAUrgF,KACjB+4F,EAAUh/G,KAAKsX,OACf2nG,EAAOr6G,KAAKopB,MAAMppB,KAAKqB,KAAK+4G,EAAQz+G,SACpC2+G,EAAWt6G,KAAKsB,MAAM+4G,EAAO,GAC7BE,EAAK7Y,EAAUj0F,MACf+sG,EAAK9Y,EAAUh0F,OACfiwE,EAASrgF,EAAQ8Z,IAAIqjG,gBAAgBF,EAAIC,GACzCE,EAAM/8B,EAAOt8D,KAEbs5F,EAAWv/G,KAAK++G,OAAS,EAAI,EAC/B,IAAI3pG,EAAG+iB,EAAG7iB,EAAGH,EAAGqqG,EAAQC,EAAKC,EAAKC,EAAQC,EAAIvzG,EAAGD,EAAG61B,EAAIC,EAExD,IAAK91B,EAAI,EAAGA,EAAIgzG,EAAIhzG,IAClB,IAAKC,EAAI,EAAGA,EAAI8yG,EAAI9yG,IAAK,CASvB,IARAmzG,EAAwB,GAAdpzG,EAAI+yG,EAAK9yG,GAGnB+I,EAAI,EACJ+iB,EAAI,EACJ7iB,EAAI,EACJH,EAAI,EAEC+sB,EAAK,EAAGA,EAAK+8E,EAAM/8E,IACtB,IAAKD,EAAK,EAAGA,EAAKg9E,EAAMh9E,IACtBy9E,EAAMtzG,EAAI81B,EAAKg9E,EACfO,EAAMpzG,EAAI41B,EAAKi9E,EAGXQ,EAAM,GAAKA,GAAON,GAAMK,EAAM,GAAKA,GAAON,IAI9CQ,EAA4B,GAAlBD,EAAMP,EAAKM,GACrBG,EAAKZ,EAAQ98E,EAAK+8E,EAAOh9E,GAEzB7sB,GAAK6Q,EAAK05F,GAAUC,EACpBznF,GAAKlS,EAAK05F,EAAS,GAAKC,EACxBtqG,GAAK2Q,EAAK05F,EAAS,GAAKC,EAEnBL,IACHpqG,GAAK8Q,EAAK05F,EAAS,GAAKC,IAI9BN,EAAIE,GAAUpqG,EACdkqG,EAAIE,EAAS,GAAKrnF,EAClBmnF,EAAIE,EAAS,GAAKlqG,EAIhBgqG,EAAIE,EAAS,GAHVD,EAGet5F,EAAKu5F,EAAS,GAFdrqG,CAItB,CAEFjT,EAAQokG,UAAY/jB,CACtB,CAQAo2B,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGq9G,WAAWpJ,EAAiBqJ,QAAS9/G,KAAKsX,OAC/C,CAMAkD,QAAAA,GACE,MAAO,IACFpa,MAAMoa,WACTukG,OAAQ/+G,KAAK++G,OACbznG,OAAQ,IAAItX,KAAKsX,QAErB,EA7GAvX,EANW++G,GAAS,OAWN,aAAW/+G,EAXd++G,GAAS,WA7CmC,CACvDC,QAAQ,EACRznG,OAAQ,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,KAwDOvX,EAb7B++G,GAAS,mBAeM,CAAC,UAAW,UAAW,YAAa,UAuGhEn2G,GAAcG,SAASg2G,IC7KhB,MCKDiB,GAAQ,QAqBP,MAAMC,WAAcrK,GAkBzBC,iBAAAA,GACE,MD7C0B,6ZC8C5B,CAEA91G,WAAAA,GAAkD,IAAtCoC,EAA+B5B,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,CAAA,EAC5CF,MAAM8B,GACNlC,KAAKigH,MACH/9G,EAAQ+9G,OAENjgH,KAAKF,YACLsB,SAAS6+G,MAAMz0G,QACrB,CAQA6sG,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAM+6G,EAAQjgH,KAAKigH,MACjBC,EAAO,EAAID,EAAM,GACjBE,EAAO,EAAIF,EAAM,GACjBG,EAAO,EAAIH,EAAM,GAEdjgH,KAAKqgH,YACRrgH,KAAKqgH,UAAY,CACfjrG,EAAG,IAAIk1F,WAAW,KAClBnyE,EAAG,IAAImyE,WAAW,KAClBh1F,EAAG,IAAIg1F,WAAW,OAMtB,MAAMgW,EAAMtgH,KAAKqgH,UACjB,IAAK,IAAI50G,EAAI,EAAGA,EAAI,IAAKA,IACvB60G,EAAIlrG,EAAE3J,GAA+B,IAA1B7G,KAAKqR,IAAIxK,EAAI,IAAKy0G,GAC7BI,EAAInoF,EAAE1sB,GAA+B,IAA1B7G,KAAKqR,IAAIxK,EAAI,IAAK00G,GAC7BG,EAAIhrG,EAAE7J,GAA+B,IAA1B7G,KAAKqR,IAAIxK,EAAI,IAAK20G,GAE/B,IAAK,IAAI30G,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EACpCwa,EAAKxa,GAAK60G,EAAIlrG,EAAE6Q,EAAKxa,IACrBwa,EAAKxa,EAAI,GAAK60G,EAAInoF,EAAElS,EAAKxa,EAAI,IAC7Bwa,EAAKxa,EAAI,GAAK60G,EAAIhrG,EAAE2Q,EAAKxa,EAAI,GAEjC,CAQAktG,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAG+9G,WAAW9J,EAAiB+J,OAAQxgH,KAAKigH,MAC9C,CAEAzS,cAAAA,GACE,MAAMyS,MAAEA,GAAUjgH,KAClB,OAAoB,IAAbigH,EAAM,IAAyB,IAAbA,EAAM,IAAyB,IAAbA,EAAM,EACnD,CAEAzlG,QAAAA,GACE,MAAO,CACLxR,KAAM+2G,GACNE,MAAOjgH,KAAKigH,MAAMz0G,SAEtB,EAxFAzL,EADWigH,GAAK,OAYFD,IAAKhgH,EAZRigH,GAAK,WAb+B,CAC/CC,MAAO,CAAC,EAAG,EAAG,KA0BsBlgH,EAdzBigH,GAAK,mBAgBU,CAAC,WA4E7Br3G,GAAcG,SAASk3G,ICpHhB,MAAMt9G,GAAiD,CAC5D63B,QAAS,6SAUTkmF,UAAW,iWAWXC,WAAY,yUCFP,MAAMC,WAAkBhL,GAe7B0C,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,IAAK,IAAWjB,EAAPwH,EAAI,EAAkBA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACtD,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GACnB,OAAQzL,KAAKk6G,MACX,IAAK,UACHj2G,GAASmR,EAAI+iB,EAAI7iB,GAAK,EACtB,MACF,IAAK,YACHrR,GAASW,KAAKiJ,IAAIuH,EAAG+iB,EAAG7iB,GAAK1Q,KAAKC,IAAIuQ,EAAG+iB,EAAG7iB,IAAM,EAClD,MACF,IAAK,aACHrR,EAAQ,IAAOmR,EAAI,IAAO+iB,EAAI,IAAO7iB,EAIzC2Q,EAAKxa,EAAI,GAAKwa,EAAKxa,EAAI,GAAKwa,EAAKxa,GAAKxH,CACxC,CACF,CAEAq0G,WAAAA,GACE,MAAO,GAAGt4G,KAAKgJ,QAAQhJ,KAAKk6G,MAC9B,CAEAtE,iBAAAA,GACE,OAAOlzG,GAAe1C,KAAKk6G,KAC7B,CAQAvB,eAAAA,CACEn2G,EACAi0G,GAGAj0G,EAAG24G,UAAU1E,EAAiBmK,MADjB,EAEf,CAOApT,cAAAA,GACE,OAAO,CACT,EACDztG,EAlEY4gH,GAAS,OAGN,aAAW5gH,EAHd4gH,GAAS,WAXmC,CACvDzG,KAAM,YAekCn6G,EAL7B4gH,GAAS,mBAOM,CAAC,UA6D7Bh4G,GAAcG,SAAS63G,ICxEhB,MAAME,GAAgD,IACxD/D,GACHgE,SAAU,GAYL,MAAMC,WAAoB/D,GAc/BlC,eAAAA,GACE,MAAMl3C,EAAM5jE,KAAK8gH,SAAWl8G,KAAK0B,GAC/B06G,EAASn1G,GAAI+3D,GACbq9C,EAAOj1G,GAAI43D,GACXs9C,EAAS,EAAI,EACbC,EAAev8G,KAAKqB,KAAKi7G,GAAUD,EACnCG,EAAc,EAAIJ,EACpBhhH,KAAKsX,OAAS,CACZ0pG,EAASI,EAAc,EACvBF,EAASE,EAAcD,EACvBD,EAASE,EAAcD,EACvB,EACA,EACAD,EAASE,EAAcD,EACvBH,EAASE,EAASE,EAClBF,EAASE,EAAcD,EACvB,EACA,EACAD,EAASE,EAAcD,EACvBD,EAASE,EAAcD,EACvBH,EAASE,EAASE,EAClB,EACA,EACA,EACA,EACA,EACA,EACA,EAEJ,CAEA5T,cAAAA,GACE,OAAyB,IAAlBxtG,KAAK8gH,QACd,CAEApa,OAAAA,CAAQxkG,GACNlC,KAAK86G,kBACL16G,MAAMsmG,QAAQxkG,EAChB,CAEAsY,QAAAA,GACE,MAAO,CACLxR,KAAMhJ,KAAKgJ,KACX83G,SAAU9gH,KAAK8gH,SAEnB,EAtDA/gH,EALWghH,GAAW,OAUR,eAAahhH,EAVhBghH,GAAW,WAYJF,IAkDpBl4G,GAAcG,SAASi4G,ICzEhB,MAAMM,WAAe1L,GAyB1B0C,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,IAAK,IAAIuG,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EACpCwa,EAAKxa,GAAK,IAAMwa,EAAKxa,GACrBwa,EAAKxa,EAAI,GAAK,IAAMwa,EAAKxa,EAAI,GAC7Bwa,EAAKxa,EAAI,GAAK,IAAMwa,EAAKxa,EAAI,GAEzBzL,KAAKm6B,QACPlU,EAAKxa,EAAI,GAAK,IAAMwa,EAAKxa,EAAI,GAGnC,CAEUmqG,iBAAAA,GACR,MC3D0B,gfD4D5B,CAQApI,cAAAA,GACE,OAAQxtG,KAAKshH,MACf,CAQA3I,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAG24G,UAAU1E,EAAiB8K,QAASvnG,OAAOha,KAAKshH,SACnD9+G,EAAG24G,UAAU1E,EAAiB+K,OAAQxnG,OAAOha,KAAKm6B,OACpD,EAxDAp6B,EAPWshH,GAAM,OAaH,UAAQthH,EAbXshH,GAAM,WAXgC,CACjDlnF,OAAO,EACPmnF,QAAQ,IAwB6BvhH,EAf1BshH,GAAM,mBAiBS,CAAC,UAAW,WAiDxC14G,GAAcG,SAASu4G,IEhEhB,MAAMI,WAAc9L,GAazBC,iBAAAA,GACE,MCrC0B,8eDsC5B,CAQAyC,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAMw8G,EAAQ1hH,KAAK0hH,MACnB,IAAK,IAAIj2G,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAMk2G,GAAQ,GAAM/8G,KAAKk+D,UAAY4+C,EACrCz7F,EAAKxa,IAAMk2G,EACX17F,EAAKxa,EAAI,IAAMk2G,EACf17F,EAAKxa,EAAI,IAAMk2G,CACjB,CACF,CAQAhJ,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiBmL,OAAQ5hH,KAAK0hH,MAAQ,KACnDl/G,EAAGk2G,UAAUjC,EAAiBoL,MAAOj9G,KAAKk+D,SAC5C,CAEA0qC,cAAAA,GACE,OAAsB,IAAfxtG,KAAK0hH,KACd,EAhDA3hH,EADW0hH,GAAK,OAOF,SAAO1hH,EAPV0hH,GAAK,WAd+B,CAC/CC,MAAO,IAsB6B3hH,EATzB0hH,GAAK,mBAWU,CAAC,SAAU,UAyCvC94G,GAAcG,SAAS24G,IErDhB,MAAMK,WAAiBnM,GAe5B0C,SAAAA,CAASnzG,GAA2D,IAAxDohG,WAAWrgF,KAAEA,EAAI5T,MAAEA,EAAKC,OAAEA,IAA4BpN,EAChE,IAAK,IAAIuG,EAAI,EAAGA,EAAI6G,EAAQ7G,GAAKzL,KAAK+hH,UACpC,IAAK,IAAIxqE,EAAI,EAAGA,EAAIllC,EAAOklC,GAAKv3C,KAAK+hH,UAAW,CAC9C,MAAMz4G,EAAY,EAAJmC,EAAQ4G,EAAY,EAAJklC,EACxBniC,EAAI6Q,EAAK3c,GACT6uB,EAAIlS,EAAK3c,EAAQ,GACjBgM,EAAI2Q,EAAK3c,EAAQ,GACjB6L,EAAI8Q,EAAK3c,EAAQ,GAEvB,IAAK,IAAI04G,EAAKv2G,EAAGu2G,EAAKp9G,KAAKiJ,IAAIpC,EAAIzL,KAAK+hH,UAAWzvG,GAAS0vG,IAC1D,IAAK,IAAIC,EAAK1qE,EAAG0qE,EAAKr9G,KAAKiJ,IAAI0pC,EAAIv3C,KAAK+hH,UAAW1vG,GAAQ4vG,IAAM,CAC/D,MAAM34G,EAAa,EAAL04G,EAAS3vG,EAAa,EAAL4vG,EAC/Bh8F,EAAK3c,GAAS8L,EACd6Q,EAAK3c,EAAQ,GAAK6uB,EAClBlS,EAAK3c,EAAQ,GAAKgM,EAClB2Q,EAAK3c,EAAQ,GAAK6L,CACpB,CAEJ,CAEJ,CAKAq4F,cAAAA,GACE,OAA0B,IAAnBxtG,KAAK+hH,SACd,CAEUnM,iBAAAA,GACR,MCnE0B,ojBDoE5B,CAQA+C,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiByL,WAAYliH,KAAK+hH,UACjD,EACDhiH,EA5DY+hH,GAAQ,OAGL,YAAU/hH,EAHb+hH,GAAQ,WAbkC,CACrDC,UAAW,IAiB4BhiH,EAL5B+hH,GAAQ,mBAOO,CAAC,eAuD7Bn5G,GAAcG,SAASg5G,IExDhB,MAAMK,WAAoBxM,GA2B/BC,iBAAAA,GACE,MCxD0B,oUDyD5B,CAMAyC,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAM+5C,EAA2B,IAAhBj/C,KAAKi/C,SACpBxlC,EAAS,IAAIuf,GAAMh5B,KAAKi5B,OAAOQ,YAC/B2oF,EAAO,CAAC3oG,EAAO,GAAKwlC,EAAUxlC,EAAO,GAAKwlC,EAAUxlC,EAAO,GAAKwlC,GAChEojE,EAAQ,CACN5oG,EAAO,GAAKwlC,EACZxlC,EAAO,GAAKwlC,EACZxlC,EAAO,GAAKwlC,GAGhB,IAAK,IAAIxzC,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GAGjB2J,EAAIgtG,EAAK,IACTjqF,EAAIiqF,EAAK,IACT9sG,EAAI8sG,EAAK,IACThtG,EAAIitG,EAAM,IACVlqF,EAAIkqF,EAAM,IACV/sG,EAAI+sG,EAAM,KAEVp8F,EAAKxa,EAAI,GAAK,EAElB,CACF,CAQAktG,eAAAA,CACEn2G,EACAi0G,GAEA,MAAMh9F,EAAS,IAAIuf,GAAMh5B,KAAKi5B,OAAOQ,YACnCwlB,EAAWj/C,KAAKi/C,SAChBmjE,EAAO,CACL,EAAI3oG,EAAO,GAAK,IAAMwlC,EACtB,EAAIxlC,EAAO,GAAK,IAAMwlC,EACtB,EAAIxlC,EAAO,GAAK,IAAMwlC,EACtB,GAEFojE,EAAQ,CACN5oG,EAAO,GAAK,IAAMwlC,EAClBxlC,EAAO,GAAK,IAAMwlC,EAClBxlC,EAAO,GAAK,IAAMwlC,EAClB,GAEJz8C,EAAGg4G,WAAW/D,EAAiB6L,KAAMF,GACrC5/G,EAAGg4G,WAAW/D,EAAiB8L,MAAOF,EACxC,EA1EAtiH,EAfWoiH,GAAW,OAqBR,eAAapiH,EArBhBoiH,GAAW,WAhBqC,CAC3DlpF,MAAO,UACPgmB,SAAU,IACVujE,UAAU,IAoCgCziH,EAvB/BoiH,GAAW,mBAyBI,CAAC,OAAQ,UAmErCx5G,GAAcG,SAASq5G,IEnEhB,MAAMM,WAAe9M,GAsC1BgD,eAAAA,CAEEn2G,EACAi0G,GAEAj0G,EAAGg6G,WACD/F,EAAiBgG,OACjBz8G,KAAK07G,WAAa,CAAC,EAAI17G,KAAKqS,MAAO,GAAK,CAAC,EAAG,EAAIrS,KAAKsS,SAEvD9P,EAAGq9G,WAAWpJ,EAAiBiM,MAAO1iH,KAAK2iH,KAC7C,CAEAC,eAAAA,GACE,MAAMzmG,EAAQnc,KAAK6iH,UACnB,OAAOj+G,KAAKosC,KAAKhxC,KAAK8iH,aAAe3mG,EACvC,CAEAm8F,WAAAA,GACE,MAAMyK,EAAe/iH,KAAK4iH,kBAC1B,MAAO,GAAG5iH,KAAKgJ,QAAQ+5G,GACzB,CAEAnN,iBAAAA,GACE,MAAMmN,EAAe/iH,KAAK4iH,kBAC1B,OAAO5iH,KAAKgjH,eAAeD,EAC7B,CAEAE,OAAAA,GACE,MAAMC,EAAeljH,KAAKmjH,cAAcnjH,KAAK8iH,cAC3C3mG,EAAQnc,KAAK6iH,UACbE,EAAe/iH,KAAK4iH,kBACpBD,EAAO,IAAI/gH,MAAMmhH,GACnB,IAAK,IAAIt3G,EAAI,EAAGA,GAAKs3G,EAAct3G,IACjCk3G,EAAKl3G,EAAI,GAAKy3G,EAAaz3G,EAAI0Q,GAEjC,OAAOwmG,CACT,CAMAK,cAAAA,CAAeD,GACb,MAAM3hF,EAAU,IAAIx/B,MAAMmhH,GAC1B,IAAK,IAAIt3G,EAAI,EAAGA,GAAKs3G,EAAct3G,IACjC21B,EAAQ31B,EAAI,GAAK,GAAGA,eAEtB,MAAO,2JAKiBs3G,qHAIlB3hF,EACCzoB,IACC,CAAC0E,EAAQ5R,IAAM,4DAC8B4R,cAAmB5R,wCAAwC4R,cAAmB5R,yCACpGA,qBAGxB0O,KAAK,2DAId,CAEAipG,eAAAA,CAA+ClhH,GAC7CA,EAAQ8lG,SACRhoG,KAAKqS,MAAQnQ,EAAQgkG,YACrBlmG,KAAK07G,YAAa,EAClB17G,KAAKqjH,GAAKz+G,KAAKopB,MAAMhuB,KAAKqS,MAAQrS,KAAKkW,QACvClW,KAAKsjH,GAAKphH,EAAQikG,aAClBnmG,KAAK6iH,UAAY7iH,KAAKqjH,GAAKrjH,KAAKqS,MAChCrS,KAAK2iH,KAAO3iH,KAAKijH,UACjB/gH,EAAQwlG,iBAAmB1nG,KAAKqjH,GAChCjjH,MAAMsmG,QAAQxkG,GACdA,EAAQgkG,YAAchkG,EAAQwlG,iBAE9B1nG,KAAKsS,OAASpQ,EAAQikG,aACtBnmG,KAAK07G,YAAa,EAClB17G,KAAKsjH,GAAK1+G,KAAKopB,MAAMhuB,KAAKsS,OAAStS,KAAKmW,QACxCnW,KAAK6iH,UAAY7iH,KAAKsjH,GAAKtjH,KAAKsS,OAChCtS,KAAK2iH,KAAO3iH,KAAKijH,UACjB/gH,EAAQylG,kBAAoB3nG,KAAKsjH,GACjCljH,MAAMsmG,QAAQxkG,GACdA,EAAQikG,aAAejkG,EAAQylG,iBACjC,CAcAjB,OAAAA,CAAQxkG,GACF+yG,GAAqB/yG,GACtBlC,KAA4CojH,gBAAgBlhH,GAE5DlC,KAAyCq4G,UAAUn2G,EAExD,CAEAsrG,cAAAA,GACE,OAAuB,IAAhBxtG,KAAKkW,QAAgC,IAAhBlW,KAAKmW,MACnC,CAEAgtG,aAAAA,CAAcI,GACZ,OAAQl3G,IACN,GAAIA,GAAKk3G,GAASl3G,IAAMk3G,EACtB,OAAO,EAET,GAAIl3G,EAAI,cAAgBA,gBACtB,OAAO,EAGT,MAAMm3G,GADNn3G,GAAKzH,KAAK0B,IACKi9G,EACf,OAAS3+G,KAAKoH,IAAIK,GAAKA,EAAKzH,KAAKoH,IAAIw3G,GAAOA,EAEhD,CAEAnL,SAAAA,CAAsCn2G,GACpC,MAAMokG,EAAYpkG,EAAQokG,UACxBpwF,EAASlW,KAAKkW,OACdC,EAASnW,KAAKmW,OAEhBnW,KAAKyjH,UAAY,EAAIvtG,EACrBlW,KAAK0jH,UAAY,EAAIvtG,EAErB,MAAMwtG,EAAKrd,EAAUj0F,MACfuxG,EAAKtd,EAAUh0F,OACf+wG,EAAKz+G,KAAKopB,MAAM21F,EAAKztG,GACrBotG,EAAK1+G,KAAKopB,MAAM41F,EAAKztG,GAC3B,IAAI0tG,EAGFA,EADsB,cAApB7jH,KAAK8jH,WACG9jH,KAAK+jH,WAAW7hH,EAASyhH,EAAIC,EAAIP,EAAIC,GAClB,YAApBtjH,KAAK8jH,WACJ9jH,KAAKgkH,kBAAkB9hH,EAASyhH,EAAIC,EAAIP,EAAIC,GACzB,aAApBtjH,KAAK8jH,WACJ9jH,KAAKikH,kBAAkB/hH,EAASyhH,EAAIC,EAAIP,EAAIC,GACzB,YAApBtjH,KAAK8jH,WACJ9jH,KAAKkkH,cAAchiH,EAASyhH,EAAIC,EAAIP,EAAIC,GAGxC,IAAI1Y,UAAUyY,EAAIC,GAE9BphH,EAAQokG,UAAYud,CACtB,CAWAE,UAAAA,CACE7hH,EACAyhH,EACAC,EACAP,EACAC,GAEA,MAAMhd,EAAYpkG,EAAQokG,UACpB6d,EAAO,GACb,IAAIC,GAAQ,EACRC,GAAQ,EACRC,EAAQX,EAAKQ,EACbI,EAAQX,EAAKO,EACjB,MAAMpJ,EAAY74G,EAAQukG,cAAcsU,UACxC,IAAIjN,EAAK,EACLC,EAAK,EACT,MAAMyW,EAAKb,EACX,IAAIc,EAAK,EACJ1J,EAAUgJ,aACbhJ,EAAUgJ,WAAalwG,MAEzB,MAAM6wG,EAAY3J,EAAUgJ,YACxBW,EAAUryG,MAAa,IAALsxG,GAAYe,EAAUpyG,OAASsxG,KACnDc,EAAUryG,MAAa,IAALsxG,EAClBe,EAAUpyG,OAASsxG,GAErB,MAAM5nG,EAAM0oG,EAAUthH,WAAW,MAOjC,IANA4Y,EAAIsF,UAAU,EAAG,EAAQ,IAALqiG,EAAUC,GAC9B5nG,EAAI4qF,aAAaN,EAAW,EAAG,GAE/B+c,EAAKz+G,KAAKsB,MAAMm9G,GAChBC,EAAK1+G,KAAKsB,MAAMo9G,IAERc,IAAUC,GAChBV,EAAKW,EACLV,EAAKW,EACDlB,EAAKz+G,KAAKsB,MAAMo+G,EAAQH,GAC1BG,EAAQ1/G,KAAKsB,MAAMo+G,EAAQH,IAE3BG,EAAQjB,EACRe,GAAQ,GAENd,EAAK1+G,KAAKsB,MAAMq+G,EAAQJ,GAC1BI,EAAQ3/G,KAAKsB,MAAMq+G,EAAQJ,IAE3BI,EAAQjB,EACRe,GAAQ,GAEVroG,EAAIwH,UAAUkhG,EAAW5W,EAAIC,EAAI4V,EAAIC,EAAIY,EAAIC,EAAIH,EAAOC,GACxDzW,EAAK0W,EACLzW,EAAK0W,EACLA,GAAMF,EAER,OAAOvoG,EAAI0rC,aAAaomD,EAAIC,EAAIsV,EAAIC,EACtC,CAWAY,aAAAA,CAEEhiH,EACAyhH,EACAC,EACAP,EACAC,GA2DA,MAAMqB,EAAUziH,EAAQokG,UAAUrgF,KAChC2+F,EAAU1iH,EAAQ8Z,IAAIqjG,gBAAgBgE,EAAIC,GAC1CuB,EAAWD,EAAQ3+F,KACnB6+F,EAAU9kH,KAAKmjH,cAAcnjH,KAAK8iH,cAClCiC,EAAS/kH,KAAKyjH,UACduB,EAAShlH,KAAK0jH,UACduB,EAAY,EAAIjlH,KAAKyjH,UACrByB,EAAY,EAAIllH,KAAK0jH,UACrByB,EAAUvgH,KAAKosC,KAAM+zE,EAAS/kH,KAAK8iH,aAAgB,GACnDsC,EAAUxgH,KAAKosC,KAAMg0E,EAAShlH,KAAK8iH,aAAgB,GACnDuC,EAAoD,CAAA,EACpDjgG,EAAa,CAAE/Y,EAAG,EAAGD,EAAG,GACxBk5G,EAAc,CAAEj5G,EAAG,EAAGD,EAAG,GAE3B,OAvEA,SAASm5G,EAAQC,GACf,IAAIjjG,EAAG9W,EAAG0wG,EAAQvwG,EAAKuJ,EAAGkhB,EAAKjE,EAAO9C,EAAM6K,EAAOsrF,EAAIC,EAGvD,IAFAtgG,EAAO/Y,GAAKm5G,EAAI,IAAOT,EACvBO,EAAQj5G,EAAIzH,KAAKsB,MAAMkf,EAAO/Y,GACzBkW,EAAI,EAAGA,EAAI+gG,EAAI/gG,IAAK,CAQvB,IAPA6C,EAAOhZ,GAAKmW,EAAI,IAAOyiG,EACvBM,EAAQl5G,EAAIxH,KAAKsB,MAAMkf,EAAOhZ,GAC9B+I,EAAI,EACJkhB,EAAM,EACNjE,EAAQ,EACR9C,EAAO,EACP6K,EAAQ,EACH1uB,EAAI65G,EAAQj5G,EAAI84G,EAAS15G,GAAK65G,EAAQj5G,EAAI84G,EAAS15G,IACtD,KAAIA,EAAI,GAAKA,GAAKk4G,GAAlB,CAGA8B,EAAK7gH,KAAKsB,MAAM,IAAOtB,KAAKmH,IAAIN,EAAI2Z,EAAO/Y,IACtCg5G,EAAUI,KACbJ,EAAUI,GAAM,CAAA,GAElB,IAAK,IAAIluE,EAAI+tE,EAAQl5G,EAAIg5G,EAAS7tE,GAAK+tE,EAAQl5G,EAAIg5G,EAAS7tE,IACtDA,EAAI,GAAKA,GAAKqsE,IAGlB8B,EAAK9gH,KAAKsB,MAAM,IAAOtB,KAAKmH,IAAIwrC,EAAInyB,EAAOhZ,IACtCi5G,EAAUI,GAAIC,KACjBL,EAAUI,GAAIC,GAAMZ,EAClBlgH,KAAKqB,KACHrB,KAAKqR,IAAIwvG,EAAKR,EAAW,GAAKrgH,KAAKqR,IAAIyvG,EAAKR,EAAW,IACrD,MAGR/I,EAASkJ,EAAUI,GAAIC,GACnBvJ,EAAS,IACXvwG,EAAqB,GAAd2rC,EAAIosE,EAAKl4G,GAChB0J,GAAKgnG,EACL9lF,GAAO8lF,EAASwI,EAAQ/4G,GACxBwmB,GAAS+pF,EAASwI,EAAQ/4G,EAAM,GAChC0jB,GAAQ6sF,EAASwI,EAAQ/4G,EAAM,GAC/BuuB,GAASgiF,EAASwI,EAAQ/4G,EAAM,IAxBpC,CA4BFA,EAAqB,GAAd2W,EAAI8gG,EAAKmC,GAChBX,EAASj5G,GAAOyqB,EAAMlhB,EACtB0vG,EAASj5G,EAAM,GAAKwmB,EAAQjd,EAC5B0vG,EAASj5G,EAAM,GAAK0jB,EAAOna,EAC3B0vG,EAASj5G,EAAM,GAAKuuB,EAAQhlB,CAC9B,CAEA,QAAMqwG,EAAInC,EACDkC,EAAQC,GAERZ,CAEX,CAgBOW,CAAQ,EACjB,CAWAtB,iBAAAA,CAEE/hH,EACAyhH,EACAC,EACAP,EACAC,GAEA,IAAInuG,EACAG,EACAyuB,EACAj5B,EACAuB,EACAD,EACAX,EACA8rC,EACAouE,EACAC,EACAC,EACA5sF,EAEA6sF,EADAzoG,EAAS,EAEb,MAAM0nG,EAAS/kH,KAAKyjH,UACduB,EAAShlH,KAAK0jH,UACdqC,EAAK,GAAKpC,EAAK,GAEfqC,EADM9jH,EAAQokG,UACDrgF,KACbggG,EAAY/jH,EAAQ8Z,IAAIqjG,gBAAgBgE,EAAIC,GAC5C4C,EAAaD,EAAUhgG,KAC7B,IAAKxa,EAAI,EAAGA,EAAI63G,EAAI73G,IAClB,IAAK8rC,EAAI,EAAGA,EAAI8rE,EAAI9rE,IAOlB,IANAlrC,EAAIzH,KAAKsB,MAAM6+G,EAASxtE,GACxBnrC,EAAIxH,KAAKsB,MAAM8+G,EAASv5G,GACxBk6G,EAAQZ,EAASxtE,EAAIlrC,EACrBu5G,EAAQZ,EAASv5G,EAAIW,EACrB05G,EAAU,GAAK15G,EAAIu3G,EAAKt3G,GAEnBw5G,EAAO,EAAGA,EAAO,EAAGA,IACvB1wG,EAAI6wG,EAAOF,EAAUD,GACrBvwG,EAAI0wG,EAAOF,EAAU,EAAID,GACzB9hF,EAAIiiF,EAAOF,EAAUC,EAAKF,GAC1B/6G,EAAIk7G,EAAOF,EAAUC,EAAK,EAAIF,GAC9B5sF,EACE9jB,GAAK,EAAIwwG,IAAU,EAAIC,GACvBtwG,EAAIqwG,GAAS,EAAIC,GACjB7hF,EAAI6hF,GAAS,EAAID,GACjB76G,EAAI66G,EAAQC,EACdM,EAAW7oG,KAAY4b,EAI7B,OAAOgtF,CACT,CAWAjC,iBAAAA,CAEE9hH,EACAyhH,EACAC,EACAP,EACAC,GAEA,MAAM6C,EAASnmH,KAAKyjH,UAClB2C,EAASpmH,KAAK0jH,UACd2C,EAAazhH,KAAKosC,KAAKm1E,EAAS,GAChCG,EAAa1hH,KAAKosC,KAAKo1E,EAAS,GAEhCngG,EADM/jB,EAAQokG,UACHrgF,KACXsgG,EAAOrkH,EAAQ8Z,IAAIqjG,gBAAgBgE,EAAIC,GACvCkD,EAAQD,EAAKtgG,KACf,IAAK,IAAIsxB,EAAI,EAAGA,EAAI+rE,EAAI/rE,IACtB,IAAK,IAAI9rC,EAAI,EAAGA,EAAI43G,EAAI53G,IAAK,CAC3B,MAAMwyD,EAAoB,GAAdxyD,EAAI8rC,EAAI8rE,GACpB,IAAIlH,EAAS,EACT6C,EAAU,EACVyH,EAAe,EACfC,EAAM,EACNC,EAAM,EACNC,EAAM,EACNC,EAAM,EACV,MAAMzqE,GAAW7E,EAAI,IAAO6uE,EAC5B,IAAK,IAAIU,EAAKliH,KAAKsB,MAAMqxC,EAAI6uE,GAASU,GAAMvvE,EAAI,GAAK6uE,EAAQU,IAAM,CACjE,MAAM94G,EAAKpJ,KAAKmH,IAAIqwC,GAAW0qE,EAAK,KAAQR,EAC1CnqE,GAAW1wC,EAAI,IAAO06G,EACtBY,EAAK/4G,EAAKA,EACZ,IAAK,IAAIw1G,EAAK5+G,KAAKsB,MAAMuF,EAAI06G,GAAS3C,GAAM/3G,EAAI,GAAK06G,EAAQ3C,IAAM,CACjE,IAAIz1G,EAAKnJ,KAAKmH,IAAIowC,GAAWqnE,EAAK,KAAQ6C,EAC1C,MAAM/3E,EAAI1pC,KAAKqB,KAAK8gH,EAAKh5G,EAAKA,GAE1BugC,EAAI,GAAKA,OAIb6tE,EAAS,EAAI7tE,EAAIA,EAAIA,EAAI,EAAIA,EAAIA,EAAI,EACjC6tE,EAAS,IACXpuG,EAAK,GAAKy1G,EAAKsD,EAAKnD,GAEpBkD,GAAO1K,EAASl2F,EAAKlY,EAAK,GAC1B04G,GAAgBtK,EAEZl2F,EAAKlY,EAAK,GAAK,MACjBouG,EAAUA,EAASl2F,EAAKlY,EAAK,GAAM,KAErC24G,GAAOvK,EAASl2F,EAAKlY,GACrB44G,GAAOxK,EAASl2F,EAAKlY,EAAK,GAC1B64G,GAAOzK,EAASl2F,EAAKlY,EAAK,GAC1BixG,GAAW7C,GAGf,CACF,CACAqK,EAAMvoD,GAAMyoD,EAAM1H,EAClBwH,EAAMvoD,EAAK,GAAK0oD,EAAM3H,EACtBwH,EAAMvoD,EAAK,GAAK2oD,EAAM5H,EACtBwH,EAAMvoD,EAAK,GAAK4oD,EAAMJ,CACxB,CAEF,OAAOF,CACT,EApdAxmH,EApBW0iH,GAAM,OA0BH,UAAQ1iH,EA1BX0iH,GAAM,WA/BgC,CACjDqB,WAAY,UACZ5tG,OAAQ,EACRC,OAAQ,EACR2sG,aAAc,IAuDuB/iH,EA5B1B0iH,GAAM,mBA8BS,CAAC,SAAU,UA6cvC95G,GAAcG,SAAS25G,IC1gBhB,MAAMuE,WAAmBrR,GAgB9BC,iBAAAA,GACE,MCvC0B,mhBDwC5B,CAQAyC,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAM+hH,GAAUjnH,KAAKknH,WACrB,IAAK,IAAIz7G,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GACb5G,EAAMD,KAAKC,IAAIuQ,EAAG+iB,EAAG7iB,GAC3B2Q,EAAKxa,IAAM5G,IAAQuQ,GAAKvQ,EAAMuQ,GAAK6xG,EAAS,EAC5ChhG,EAAKxa,EAAI,IAAM5G,IAAQszB,GAAKtzB,EAAMszB,GAAK8uF,EAAS,EAChDhhG,EAAKxa,EAAI,IAAM5G,IAAQyQ,GAAKzQ,EAAMyQ,GAAK2xG,EAAS,CAClD,CACF,CAQAtO,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiB0Q,aAAcnnH,KAAKknH,WACnD,CAEA1Z,cAAAA,GACE,OAA2B,IAApBxtG,KAAKknH,UACd,EArDAnnH,EADWinH,GAAU,OAUP,cAAYjnH,EAVfinH,GAAU,WAboC,CACzDE,WAAY,IAwB6BnnH,EAZ9BinH,GAAU,mBAcK,CAAC,gBA2C7Br+G,GAAcG,SAASk+G,IEzDhB,MAAMI,WAAiBzR,GAgB5BC,iBAAAA,GACE,MCvC0B,qjBDwC5B,CAQAyC,SAAAA,CAASnzG,GAA4C,IAAzCohG,WAAWrgF,KAAEA,IAA0B/gB,EACjD,MAAM+hH,GAAUjnH,KAAKqnH,SACrB,IAAK,IAAI57G,EAAI,EAAGA,EAAIwa,EAAK1lB,OAAQkL,GAAK,EAAG,CACvC,MAAM2J,EAAI6Q,EAAKxa,GACT0sB,EAAIlS,EAAKxa,EAAI,GACb6J,EAAI2Q,EAAKxa,EAAI,GACb5G,EAAMD,KAAKC,IAAIuQ,EAAG+iB,EAAG7iB,GACrByjB,GAAO3jB,EAAI+iB,EAAI7iB,GAAK,EACpBgyG,EAA8B,EAAtB1iH,KAAKmH,IAAIlH,EAAMk0B,GAAY,IAAOkuF,EAChDhhG,EAAKxa,IAAM5G,IAAQuQ,GAAKvQ,EAAMuQ,GAAKkyG,EAAM,EACzCrhG,EAAKxa,EAAI,IAAM5G,IAAQszB,GAAKtzB,EAAMszB,GAAKmvF,EAAM,EAC7CrhG,EAAKxa,EAAI,IAAM5G,IAAQyQ,GAAKzQ,EAAMyQ,GAAKgyG,EAAM,CAC/C,CACF,CAQA3O,eAAAA,CACEn2G,EACAi0G,GAEAj0G,EAAGk2G,UAAUjC,EAAiB8Q,WAAYvnH,KAAKqnH,SACjD,CAEA7Z,cAAAA,GACE,OAAyB,IAAlBxtG,KAAKqnH,QACd,EAvDAtnH,EADWqnH,GAAQ,OAUL,YAAUrnH,EAVbqnH,GAAQ,WAbkC,CACrDC,SAAU,IAwB6BtnH,EAZ5BqnH,GAAQ,mBAcO,CAAC,cA6C7Bz+G,GAAcG,SAASs+G"}