{"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/controls/fireEvent.ts","../src/util/misc/resolveOrigin.ts","../src/controls/util.ts","../src/controls/drag.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/util/misc/vectors.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/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/normalizeAttr.ts","../src/util/internals/cleanupSvgAttribute.ts","../src/parser/parseTransformAttribute.ts","../src/parser/normalizeValue.ts","../src/parser/parseFontDeclaration.ts","../src/parser/parseStyleString.ts","../src/parser/parseStyleAttribute.ts","../src/parser/parseStyleObject.ts","../src/parser/setStrokeFillOpacity.ts","../src/parser/parseAttributes.ts","../src/parser/getGlobalStylesForElement.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/dom_style.ts","../src/util/misc/mergeClipPaths.ts","../src/util/internals/getRandomInt.ts","../src/util/internals/dom_request.ts","../src/util/transform_matrix_removal.ts","../src/util/misc/rotatePoint.ts","../src/canvas/DOMManagers/CanvasDOMManager.ts","../src/canvas/SelectableCanvas.ts","../src/canvas/CanvasOptions.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/parser/parsePointsAttribute.ts","../src/shapes/Polyline.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/getCSSRules.ts","../src/parser/elements_parser.ts","../src/parser/parseSVGDocument.ts","../src/parser/parseUseDirectives.ts","../src/parser/loadSVGFromString.ts","../src/parser/loadSVGFromURL.ts","../src/controls/polyControl.ts","../src/controls/pathControl.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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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 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';\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","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 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#events}\n * @see {@link http://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 another one\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @chainable\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   * @static\n   * @memberOf fabric.util\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   * @static\n   * @memberOf fabric.util\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 as typeof Collection & TBase;\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) =>\n  new Promise((resolve, _) => {\n    canvasEl.toBlob(resolve, `image/${format}`, quality);\n  }) as Promise<Blob | null>;\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 {@link TMat2D} 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   * @default\n   */\n  backgroundVpt: boolean;\n\n  /**\n   * Background color of canvas instance.\n   * @type {(String|TFiller)}\n   * @default\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   * @default\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   * @default\n   */\n  overlayVpt: boolean;\n\n  /**\n   * Overlay color of canvas instance.\n   * @since 1.3.9\n   * @type {(String|TFiller)}\n   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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};\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\n/**\n * Static canvas class\n * @see {@link http://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  protected declare hasLostContext: boolean;\n  protected declare 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  protected declare skipControlsDrawing: boolean;\n\n  static ownDefaults = staticCanvasDefaults;\n\n  // reference to\n  protected declare __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   * Sets width of this canvas instance\n   * @param {Number|String} value                         Value to set width to\n   * @param {Object}        [options]                     Options object\n   * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n   * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n   * @deprecated will be removed in 7.0\n   */\n  setWidth(\n    value: TSize['width'],\n    options?: { backstoreOnly?: true; cssOnly?: false },\n  ): void;\n  setWidth(\n    value: CSSDimensions['width'],\n    options?: { cssOnly?: true; backstoreOnly?: false },\n  ): void;\n  setWidth(value: number, options?: never) {\n    return this.setDimensions({ width: value }, options);\n  }\n\n  /**s\n   * Sets height of this canvas instance\n   * @param {Number|String} value                         Value to set height to\n   * @param {Object}        [options]                     Options object\n   * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n   * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n   * @deprecated will be removed in 7.0\n   */\n  setHeight(\n    value: TSize['height'],\n    options?: { backstoreOnly?: true; cssOnly?: false },\n  ): void;\n  setHeight(\n    value: CSSDimensions['height'],\n    options?: { cssOnly?: true; backstoreOnly?: false },\n  ): void;\n  setHeight(value: CSSDimensions['height'], options?: never) {\n    return this.setDimensions({ height: value }, options);\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 &lt;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 = 'best';\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   * Returned value is an object with top and left properties\n   * @return {Object} object with \"top\" and \"left\" number values\n   * @deprecated migrate to `getCenterPoint`\n   */\n  getCenter() {\n    return {\n      top: this.height / 2,\n      left: this.width / 2,\n    };\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   * @return {Object} JSON compatible object\n   * @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization}\n   * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n   * @example <caption>JSON without additional properties</caption>\n   * var json = canvas.toJSON();\n   * @example <caption>JSON with additional properties included</caption>\n   * var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY']);\n   * @example <caption>JSON without default values</caption>\n   * var json = canvas.toJSON();\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   * @function\n   * @param {Object} [options] Options object for SVG output\n   * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n   * @param {Object} [options.viewBox] SVG viewbox object\n   * @param {Number} [options.viewBox.x] x-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   * @tutorial {@link http://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 &lt;?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   * @tutorial {@link http://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 {\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 { 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 {\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 {\n  degreesToRadians,\n  radiansToDegrees,\n} from '../util/misc/radiansDegreesConversion';\nimport type { Control } from './Control';\nimport { CENTER } from '../constants';\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): number {\n  //  angle is relative to canvas plane\n  const angle = fabricObject.getTotalAngle(),\n    cornerAngle =\n      angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;\n  return Math.round((cornerAngle % 360) / 45);\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","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","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 * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors colors}\n */\nexport class Color {\n  private declare _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   * @memberOf Color\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   * @static\n   * @function\n   * @memberOf Color\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   * @memberOf Color\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   * @memberOf Color\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   * @static\n   * @function\n   * @memberOf Color\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   * @memberOf Color\n   * @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)\n   * @return {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   * @static\n   * @memberOf Color\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   * @static\n   * @memberOf Color\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   * @static\n   * @memberOf Color\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, 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 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 { 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   * @default\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   * @default\n   */\n  declare offsetX: number;\n\n  /**\n   * Shadow vertical offset\n   * @type Number\n   * @default\n   */\n  declare offsetY: number;\n\n  /**\n   * Whether the shadow should affect stroke operations\n   * @type Boolean\n   * @default\n   */\n  declare affectStroke: boolean;\n\n  /**\n   * Indicates whether toObject should include default values\n   * @type Boolean\n   * @default\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   * @default\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://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} 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: LEFT,\n  originY: TOP,\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  protected declare readonly byValue: T;\n  protected declare readonly easing: TEasingFunction<T>;\n\n  private declare readonly _onStart: VoidFunction;\n  private declare readonly _onChange: TOnAnimationChangeCallback<T, void>;\n  private declare readonly _onComplete: TOnAnimationChangeCallback<T, void>;\n  private declare 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  private declare 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   * @chainable\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 {@link Point} is in the polygon defined by [points]{@link Point}\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   * @static\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   * @static\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   * @static\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   * @static\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   * @static\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   * @static\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   * @static\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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#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 {@link FabricObject#originX} {@link FabricObject#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 {@link FabricObject#originX} and {@link FabricObject#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 {@link FabricObject#originX} {@link FabricObject#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 {@link FabricObject#originX} {@link FabricObject#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   * In this case the rect is meant aligned with the axis of the canvas.\n   * TL is the TOP LEFT point while br is the BOTTOM RIGHT point\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://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 === key) {\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   * Returns the position of the object as if it has a different 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.\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  getPointByOrigin(originX: TOriginX, originY: TOriginY): Point {\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.translateToOriginPoint(\n      this.getRelativeCenterPoint(),\n      LEFT,\n      TOP,\n    );\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 * @tutorial {@link http://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   * @param {Object} dims\n   * @param {Object} dims.width width of canvas\n   * @param {Object} dims.height height of canvas\n   * @param {Object} dims.zoomX zoomX zoom value to unscale the canvas before drawing cache\n   * @param {Object} dims.zoomY zoomY zoom value to unscale the canvas before drawing cache\n   * @return {Object}.width width of canvas\n   * @return {Object}.height height of canvas\n   * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache\n   * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache\n   */\n  _limitCacheSize(\n    dims: TSize & { zoomX: number; zoomY: number; capped: boolean } & any,\n  ) {\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 {Object}.x width of object to be cached\n   * @return {Object}.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 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   * @private\n   * return if the object would be visible in rendering\n   * @memberOf FabricObject.prototype\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() {\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() {\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   * @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   * Returns true if any of the specified types is identical to the type of an instance\n   * @param {String} type Type to check against\n   * @return {Boolean}\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.translateToOriginPoint(\n        this.getRelativeCenterPoint(),\n        originX,\n        originY,\n      );\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   * @tutorial {@link http://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  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      centerPoint = target.getRelativeCenterPoint(),\n      constraint = target.translateToOriginPoint(centerPoint, 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 { CENTER, LEFT, RESIZING, RIGHT } from '../constants';\nimport { resolveOrigin } from '../util/misc/resolveOrigin';\nimport { getLocalPoint, isTransformCentered } from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\n\n/**\n * Action handler to change object's width\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 changeObjectWidth: TransformActionHandler = (\n  eventData,\n  transform,\n  x,\n  y,\n) => {\n  const localPoint = getLocalPoint(\n    transform,\n    transform.originX,\n    transform.originY,\n    x,\n    y,\n  );\n  //  make sure the control changes width ONLY from it's side of target\n  if (\n    resolveOrigin(transform.originX) === resolveOrigin(CENTER) ||\n    (resolveOrigin(transform.originX) === resolveOrigin(RIGHT) &&\n      localPoint.x < 0) ||\n    (resolveOrigin(transform.originX) === resolveOrigin(LEFT) &&\n      localPoint.x > 0)\n  ) {\n    const { target } = transform,\n      strokePadding =\n        target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),\n      multiplier = isTransformCentered(transform) ? 2 : 1,\n      oldWidth = target.width,\n      newWidth =\n        Math.abs((localPoint.x * multiplier) / target.scaleX) - strokePadding;\n    target.set('width', Math.max(newWidth, 1));\n    //  check against actual target width in case `newWidth` was rejected\n    return oldWidth !== target.width;\n  }\n  return false;\n};\n\nexport const changeWidth = wrapWithFireEvent(\n  RESIZING,\n  wrapWithFixedAnchor(changeObjectWidth),\n);\n","import { FILL, STROKE, twoMathPi } from '../constants';\nimport type { InteractiveFabricObject } from '../shapes/Object/InteractiveObject';\nimport { degreesToRadians } from '../util/misc/radiansDegreesConversion';\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  styleOverride = styleOverride || {};\n  const xSize =\n      this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n    ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\n    transparentCorners =\n      typeof styleOverride.transparentCorners !== 'undefined'\n        ? styleOverride.transparentCorners\n        : fabricObject.transparentCorners,\n    methodName = transparentCorners ? STROKE : FILL,\n    stroke =\n      !transparentCorners &&\n      (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);\n  let myLeft = left,\n    myTop = top,\n    size;\n  ctx.save();\n  ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';\n  ctx.strokeStyle =\n    styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';\n  // TODO: use proper ellipse code.\n  if (xSize > ySize) {\n    size = xSize;\n    ctx.scale(1.0, ySize / xSize);\n    myTop = (top * xSize) / ySize;\n  } else if (ySize > xSize) {\n    size = ySize;\n    ctx.scale(xSize / ySize, 1.0);\n    myLeft = (left * ySize) / xSize;\n  } else {\n    size = xSize;\n  }\n  ctx.beginPath();\n  ctx.arc(myLeft, myTop, size / 2, 0, twoMathPi, false);\n  ctx[methodName]();\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  styleOverride = styleOverride || {};\n  const xSize =\n      this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,\n    ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,\n    transparentCorners =\n      typeof styleOverride.transparentCorners !== 'undefined'\n        ? styleOverride.transparentCorners\n        : fabricObject.transparentCorners,\n    methodName = transparentCorners ? STROKE : FILL,\n    stroke =\n      !transparentCorners &&\n      (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),\n    xSizeBy2 = xSize / 2,\n    ySizeBy2 = ySize / 2;\n  ctx.save();\n  ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';\n  ctx.strokeStyle =\n    styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';\n  ctx.translate(left, top);\n  //  angle is relative to canvas plane\n  const angle = fabricObject.getTotalAngle();\n  ctx.rotate(degreesToRadians(angle));\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[`${methodName}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 { SCALE } from '../constants';\nimport type { InteractiveFabricObject } 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 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  ) {\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   * 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.translateToOriginPoint(\n    target.getRelativeCenterPoint(),\n    originX,\n    originY,\n  );\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) => {\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);\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) => {\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) % 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) => {\n  return isAltAction(eventData, fabricObject)\n    ? skewCursorStyleHandler(eventData, control, fabricObject)\n    : scaleCursorStyleHandler(eventData, control, fabricObject);\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 is return 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 http://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 * 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, '&amp;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&apos;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\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 as string);\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(element: HTMLElement, selector: string) {\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(element: HTMLElement, selectors: string[]) {\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(element: HTMLElement, selectors: string[]) {\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 { 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 * @static\n * @function\n * @memberOf fabric\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","import { 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 * @static\n * @function\n * @memberOf fabric\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","/**\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 * @static\n * @memberOf fabric\n * @param {SVGElement} element Element to parse\n * @return {Object} Objects with values parsed from style attribute of an element\n */\nexport function parseStyleAttribute(element: HTMLElement): 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 | 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 { elementMatchesRule } from './elementMatchesRule';\nimport type { CSSRules } from './typedefs';\n\n/**\n * @private\n */\n\nexport function getGlobalStylesForElement(\n  element: HTMLElement,\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 { 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   * @default\n   */\n  declare rx: number;\n\n  /**\n   * Vertical border radius\n   * @type Number\n   * @default\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   * @static\n   * @memberOf Rect\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   * @static\n   * @memberOf Rect\n   * @param {HTMLElement} element Element to parse\n   * @param {Object} [options] Options object\n   */\n  static async fromElement(\n    element: HTMLElement,\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  private declare _prevLayoutStrategy?: LayoutStrategy;\n  protected declare _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   * @default\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   * @default\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   * @static\n   * @memberOf Group\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 * @static\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","// 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\n * @param {Object | string} styles\n */\nexport function setStyle(\n  element: HTMLElement,\n  styles: string | Record<string, string>,\n) {\n  const elementStyle = element.style;\n  if (!elementStyle || !styles) {\n    return;\n  } else if (typeof styles === 'string') {\n    elementStyle.cssText += ';' + styles;\n  } else {\n    Object.entries(styles).forEach(([property, value]) =>\n      elementStyle.setProperty(property, value),\n    );\n  }\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 * @memberOf fabric.util\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","/**\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 { getFabricWindow } from '../../env';\nimport { noop } from '../../constants';\nimport type { Abortable } from '../../typedefs';\nimport { SignalAbortedError } from './console';\n\ntype requestOptions = Abortable & {\n  onComplete?: (xhr: XMLHttpRequest) => void;\n};\n\n/**\n * Cross-browser abstraction for sending XMLHttpRequest\n * @deprecated this has to go away, we can use a modern browser method to do the same.\n * @param {String} url URL to send XMLHttpRequest to\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} options.onComplete Callback to invoke when request is completed\n * @return {XMLHttpRequest} request\n */\n\nexport function request(url: string, options: requestOptions = {}) {\n  const onComplete = options.onComplete || noop,\n    xhr = new (getFabricWindow().XMLHttpRequest)(),\n    signal = options.signal,\n    abort = function () {\n      xhr.abort();\n    },\n    removeListener = function () {\n      signal && signal.removeEventListener('abort', abort);\n      xhr.onerror = xhr.ontimeout = noop;\n    };\n\n  if (signal && signal.aborted) {\n    throw new SignalAbortedError('request');\n  } else if (signal) {\n    signal.addEventListener('abort', abort, { once: true });\n  }\n\n  /** @ignore */\n  xhr.onreadystatechange = function () {\n    if (xhr.readyState === 4) {\n      removeListener();\n      onComplete(xhr);\n      xhr.onreadystatechange = noop;\n    }\n  };\n\n  xhr.onerror = xhr.ontimeout = removeListener;\n\n  xhr.open('get', url, true);\n\n  xhr.send();\n  return xhr;\n}\n","import { CENTER, SCALE_X, SCALE_Y } from '../constants';\nimport type { FabricImage } 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?: any,\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 { Point } from '../../Point';\nimport type { TRadian } from '../../typedefs';\n/**\n * Rotates `point` around `origin` with `radians`\n * @deprecated use the Point.rotate\n * @param {Point} origin The origin of the rotation\n * @param {Point} 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 */\nexport const rotatePoint = (\n  point: Point,\n  origin: Point,\n  radians: TRadian,\n): Point => point.rotate(radians, origin);\n","import { getEnv, getFabricDocument } from '../../env';\nimport type { TSize } from '../../typedefs';\nimport { createCanvasElement, setStyle } from '../../util';\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 { dragHandler } from '../controls/drag';\nimport { 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';\n\n/**\n * Canvas class\n * @class Canvas\n * @extends StaticCanvas\n * @tutorial {@link http://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   * @tutorial {@link http://fabricjs.com/fabric-intro-part-4#free_drawing}\n   * @type Boolean\n   * @default\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 subTargets for Mouse Events, ordered bottom up from innermost nested subTarget\n   * @type FabricObject[]\n   */\n  targets: FabricObject[] = [];\n\n  /**\n   * Keep track of the hovered target\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   * _absolutePointer 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  protected declare _absolutePointer?: Point;\n\n  /**\n   * During a mouse event we may need the pointer multiple times in multiple functions.\n   * _pointer 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  protected declare _pointer?: Point;\n\n  /**\n   * During a mouse event we may need the target multiple times in multiple functions.\n   * _target holds a reference to the target that is valid for the event\n   * lifespan. Every fabricJS mouse event create and delete the cache every time\n   * @type {FabricObject}\n   */\n  protected declare _target?: FabricObject;\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  private declare pixelFindCanvasEl: HTMLCanvasElement;\n  private declare pixelFindContext: CanvasRenderingContext2D;\n\n  protected declare _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       * relative to target's containing coordinate plane\n       * both agree on every point\n       **/\n      transform: Transform = {\n        target: target,\n        action,\n        actionHandler,\n        actionPerformed: false,\n        corner,\n        scaleX: target.scaleX,\n        scaleY: target.scaleY,\n        skewX: target.skewX,\n        skewY: target.skewY,\n        offsetX: pointer.x - target.left,\n        offsetY: pointer.y - target.top,\n        originX: origin.x,\n        originY: origin.y,\n        ex: pointer.x,\n        ey: pointer.y,\n        lastX: pointer.x,\n        lastY: pointer.y,\n        theta: degreesToRadians(target.angle),\n        width: target.width,\n        height: target.height,\n        shiftKey: e.shiftKey,\n        altKey,\n        original: {\n          ...saveObjectTransform(target),\n          originX: origin.x,\n          originY: origin.y,\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   * Method that determines what object we are clicking on\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 {FabricObject | null} the target found\n   */\n  findTarget(e: TPointerEvent): FabricObject | undefined {\n    if (this.skipTargetFind) {\n      return undefined;\n    }\n\n    const pointer = this.getViewportPoint(e),\n      activeObject = this._activeObject,\n      aObjects = this.getActiveObjects();\n\n    this.targets = [];\n\n    if (activeObject && aObjects.length >= 1) {\n      if (activeObject.findControl(pointer, isTouchEvent(e))) {\n        // if we hit the corner of the active object, let's return that.\n        return activeObject;\n      } else if (\n        aObjects.length > 1 &&\n        // check pointer is over active selection and possibly perform `subTargetCheck`\n        this.searchPossibleTargets([activeObject], pointer)\n      ) {\n        // active selection does not select sub targets like normal groups\n        return activeObject;\n      } else if (\n        activeObject === this.searchPossibleTargets([activeObject], pointer)\n      ) {\n        // active object is not an active selection\n        if (!this.preserveObjectStacking) {\n          return activeObject;\n        } else {\n          const subTargets = this.targets;\n          this.targets = [];\n          const target = this.searchPossibleTargets(this._objects, pointer);\n          if (\n            e[this.altSelectionKey as ModifierKey] &&\n            target &&\n            target !== activeObject\n          ) {\n            // alt selection: select active object even though it is not the top most target\n            // restore targets\n            this.targets = subTargets;\n            return activeObject;\n          }\n          return target;\n        }\n      }\n    }\n\n    return this.searchPossibleTargets(this._objects, pointer);\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 {Object} [pointer] point from viewport.\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(\n        obj,\n        sendPointToPlane(pointer, undefined, this.viewportTransform),\n      )\n    ) {\n      if (\n        (this.perPixelTargetFind || obj.perPixelTargetFind) &&\n        !(obj as unknown as IText).isEditing\n      ) {\n        if (!this.isTargetTransparent(obj, pointer.x, pointer.y)) {\n          return true;\n        }\n      } else {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Internal Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\n   * @param {Array} [objects] objects array to look into\n   * @param {Object} [pointer] x,y object of point coordinates we want to check.\n   * @return {FabricObject} **top most object from given `objects`** that contains pointer\n   * @private\n   */\n  _searchPossibleTargets(\n    objects: FabricObject[],\n    pointer: Point,\n  ): FabricObject | undefined {\n    // Cache all targets where their bounding box contains point.\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 subTarget = this._searchPossibleTargets(\n            target._objects as FabricObject[],\n            pointer,\n          );\n          subTarget && this.targets.push(subTarget);\n        }\n        return target;\n      }\n    }\n  }\n\n  /**\n   * Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted\n   * @see {@link _searchPossibleTargets}\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  ): FabricObject | undefined {\n    const target = this._searchPossibleTargets(objects, pointer);\n\n    // if we found something in this.targets, and the group is interactive, return the innermost subTarget\n    // that is still interactive\n    // TODO: reverify why interactive. the target should be returned always, but selected only\n    // if interactive.\n    if (\n      target &&\n      isCollection(target) &&\n      target.interactive &&\n      this.targets[0]\n    ) {\n      /** targets[0] is the innermost nested target, but it could be inside non interactive groups and so not a selection target */\n      const targets = this.targets;\n      for (let i = targets.length - 1; i > 0; i--) {\n        const t = targets[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          return t;\n        }\n      }\n      return targets[0];\n    }\n\n    return target;\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._pointer) {\n      return this._pointer;\n    }\n    return this.getPointer(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._absolutePointer) {\n      return this._absolutePointer;\n    }\n    return this.getPointer(e);\n  }\n\n  /**\n   * Returns pointer relative to canvas.\n   *\n   * @deprecated This method is deprecated since v6 to protect you from misuse.\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  getPointer(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 &lt;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 { 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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\n   */\n  altActionKey: TOptionalModifierKey;\n}\n\nexport interface CanvasSelectionOptions {\n  /**\n   * Indicates whether group selection should be enabled\n   * @type Boolean\n   * @default\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   * @default\n   */\n  selectionKey: TOptionalModifierKey | ModifierKey[];\n\n  /**\n   * Indicates which key enable alternative selection\n   * in case of target overlapping with active object\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   * @default\n   */\n  altSelectionKey: TOptionalModifierKey;\n\n  /**\n   * Color of selection\n   * @type String\n   * @default\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   * @default\n   */\n  selectionBorderColor: string;\n\n  /**\n   * Width of a line used in object/group selection\n   * @type Number\n   * @default\n   */\n  selectionLineWidth: number;\n\n  /**\n   * Select only shapes that are fully contained in the dragged selection rectangle.\n   * @type Boolean\n   * @default\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   * @default\n   */\n  perPixelTargetFind: boolean;\n\n  /**\n   * Number of pixels around target pixel to tolerate (consider active) during object detection\n   * @type Number\n   * @default\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   * @default\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   * @type Boolean\n   * @since 1.6.5\n   * @default\n   */\n  stopContextMenu: boolean;\n\n  /**\n   * Indicates if the canvas can fire right click events\n   * @type Boolean\n   * @since 1.6.5\n   * @default\n   */\n  fireRightClick: boolean;\n\n  /**\n   * Indicates if the canvas can fire middle click events\n   * @type Boolean\n   * @since 1.7.8\n   * @default\n   */\n  fireMiddleClick: boolean;\n\n  /**\n   * When the option is enabled, PointerEvent is used instead of TPointerEvent.\n   * @type Boolean\n   * @default\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   * @default\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\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: false,\n  fireRightClick: false,\n  fireMiddleClick: false,\n  enablePointerEvents: false,\n\n  containerClass: 'canvas-container',\n  // turn to true for fabric 7.0\n  preserveObjectStacking: false,\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  private declare 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    pointer: viewportPoint,\n    absolutePointer: 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  private declare _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  private declare _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  private declare _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  private declare _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, 'add');\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, _eventjsFunctor: 'add' | 'remove') {\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    functor(canvasElement, 'click', this._onClick);\n    // decide if to remove in fabric 7.0\n    functor(canvasElement, 'dblclick', this._onClick);\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    // if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {\n    //   eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);\n    //   eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);\n    //   eventjs[eventjsFunctor](\n    //     canvasElement,\n    //     'orientation',\n    //     this._onOrientationChange\n    //   );\n    //   eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);\n    //   eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);\n    // }\n  }\n\n  /**\n   * Removes all event listeners, used when disposing the instance\n   */\n  removeListeners() {\n    this.addOrRemove(removeListener, 'remove');\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.__onMouseWheel(e);\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   * @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    if (!this._currentTransform && !this.findTarget(e)) {\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 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: this.targets,\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 as FabricObject | undefined,\n      dragSource: this._dragSource as FabricObject | undefined,\n      dropTarget: this._draggedoverTarget as FabricObject,\n    };\n    this.fire('drag', options);\n    this._dragSource && this._dragSource.fire('drag', options);\n  }\n\n  /**\n   * As opposed to {@link findTarget} we want the top most object to be returned w/o the active object cutting in line.\n   * Override at will\n   */\n  protected findDragTargets(e: DragEvent) {\n    this.targets = [];\n    const target = this._searchPossibleTargets(\n      this._objects,\n      this.getViewportPoint(e),\n    );\n    return {\n      target,\n      targets: [...this.targets],\n    };\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 { target, targets } = this.findDragTargets(e);\n    const dragSource = this._dragSource as FabricObject;\n    const options = {\n      e,\n      target,\n      subTargets: targets,\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(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 < targets.length; i++) {\n      const subTarget = targets[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 { target, targets } = this.findDragTargets(e);\n    const options = {\n      e,\n      target,\n      subTargets: targets,\n      dragSource: this._dragSource,\n    };\n    this.fire('dragenter', options);\n    //  fire dragenter on targets\n    this._fireEnterLeaveEvents(target, 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 options = {\n      e,\n      target: this._draggedoverTarget,\n      subTargets: this.targets,\n      dragSource: this._dragSource,\n    };\n    this.fire('dragleave', options);\n\n    //  fire dragleave on targets\n    this._fireEnterLeaveEvents(undefined, options);\n    this._renderDragEffects(e, this._dragSource);\n    this._dropTarget = undefined;\n    //  clear targets\n    this.targets = [];\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 { target, targets } = this.findDragTargets(e);\n    const options = this._basicEventHandler('drop:before', {\n      e,\n      target,\n      subTargets: targets,\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 = this.findTarget(e),\n      subTargets = this.targets || [];\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   * 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    // 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    // 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 && this._target === currentActiveObject)\n    ) {\n      shouldPreventScrolling = true;\n    }\n    // prevent default, will block scrolling from start\n    shouldPreventScrolling && e.preventDefault();\n    this._resetTransformEventData();\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  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  _onMouseDown(e: TPointerEvent) {\n    this.__onMouseDown(e);\n    this._resetTransformEventData();\n    const canvasElement = this.upperCanvasEl,\n      eventTypePrefix = this._getEventPrefix();\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  }\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.__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.__onMouseUp(e);\n    this._resetTransformEventData();\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  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousemove\n   */\n  _onMouseMove(e: TPointerEvent) {\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  }\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._cacheTransformEventData(e);\n    this._handleEvent(e, 'up:before');\n\n    const transform = this._currentTransform;\n    const isClick = this._isClick;\n    const target = this._target;\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      this._resetTransformEventData();\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 = this._target,\n      targets = this.targets || [],\n      options: CanvasEvents[`mouse:${T}`] = {\n        e,\n        target,\n        subTargets: targets,\n        ...getEventPoints(this, e),\n        transform: this._currentTransform,\n        ...(eventType === 'up:before' || eventType === 'up'\n          ? {\n              isClick: this._isClick,\n              currentTarget: this.findTarget(e),\n              // set by the preceding `findTarget` call\n              currentSubTargets: this.targets,\n            }\n          : {}),\n        ...(eventType === 'down:before' || eventType === 'down'\n          ? extraData\n          : {}),\n      } as CanvasEvents[`mouse:${T}`];\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 < targets.length; i++) {\n      targets[i] !== target && targets[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._cacheTransformEventData(e);\n    this._handleEvent(e, 'down:before');\n\n    let target: FabricObject | undefined = this._target;\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      this._resetTransformEventData();\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._target = this._pointer = this._absolutePointer = 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._pointer = this.getViewportPoint(e);\n    this._absolutePointer = sendPointToPlane(\n      this._pointer,\n      undefined,\n      this.viewportTransform,\n    );\n    this._target = this._currentTransform\n      ? this._currentTransform.target\n      : this.findTarget(e);\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._cacheTransformEventData(e);\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    this._resetTransformEventData();\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 = this._hoveredTarget,\n      _hoveredTargets = this._hoveredTargets,\n      targets = this.targets,\n      length = Math.max(_hoveredTargets.length, targets.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        targets[i] === target ||\n        (_hoveredTargets[i] && _hoveredTargets[i] === _hoveredTarget)\n      ) {\n        continue;\n      }\n      this.fireSyntheticInOutEvents('mouse', {\n        e,\n        target: targets[i],\n        oldTarget: _hoveredTargets[i],\n      });\n    }\n    this._hoveredTarget = target;\n    this._hoveredTargets = this.targets.concat();\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(target: FabricObject | undefined, data: DragEventData) {\n    const draggedoverTarget = this._draggedoverTarget,\n      _hoveredTargets = this._hoveredTargets,\n      targets = this.targets,\n      length = Math.max(_hoveredTargets.length, targets.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: targets[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   * Method that defines actions when an Event Mouse Wheel\n   * @param {Event} e Event object fired on mouseup\n   */\n  __onMouseWheel(e: TPointerEvent) {\n    this._cacheTransformEventData(e);\n    this._handleEvent(e, 'wheel');\n    this._resetTransformEventData();\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        this.targets\n          .concat()\n          .reverse()\n          .map((_target) => {\n            hoverCursor = _target.hoverCursor || hoverCursor;\n          });\n      }\n      this.setCursor(hoverCursor);\n    } else {\n      const control = corner.control;\n      this.setCursor(control.cursorStyleHandler(e, control, target));\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   * @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        if (target === activeObject) {\n          const pointer = this.getViewportPoint(e);\n          target =\n            // first search active objects for a target to remove\n            this.searchPossibleTargets(prevActiveObjects, pointer) ||\n            //  if not found, search under active selection for a target to add\n            // `prevActiveObjects` will be searched but we already know they will not be found\n            this.searchPossibleTargets(this._objects, pointer);\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 = [...this.targets];\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 = [...this.targets];\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, multiplier: number) {\n  let colorValue, opacity;\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        opacity = value;\n      }\n    }\n  }\n\n  const color = new Color(\n    colorValue || el.getAttribute('stop-color') || 'rgb(0,0,0)',\n  );\n\n  return {\n    offset: parsePercent(el.getAttribute('offset'), 0),\n    color: color.toRgb(),\n    opacity:\n      ifNaN(parseFloat(opacity || el.getAttribute('stop-opacity') || ''), 1) *\n      color.getAlpha() *\n      multiplier,\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 { Color } from '../color/Color';\nimport { 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} from './typedefs';\nimport { classRegistry } from '../ClassRegistry';\nimport { isPath } from '../util/typeAssertions';\n\n/**\n * Gradient class\n * @class Gradient\n * @tutorial {@link http://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      const color = new Color(colorStops[position]);\n      this.colorStops.push({\n        offset: parseFloat(position),\n        color: color.toRgb(),\n        opacity: color.getAlpha(),\n      });\n    }\n    return this;\n  }\n\n  /**\n   * Returns object representation of a gradient\n   * @param {string[]} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {object}\n   */\n  toObject(propertiesToInclude?: (keyof this | string)[]) {\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, opacity }) => {\n      markup.push(\n        '<stop ',\n        'offset=\"',\n        offset * 100 + '%',\n        '\" style=\"stop-color:',\n        color,\n        typeof opacity !== 'undefined' ? ';stop-opacity: ' + opacity : ';',\n        '\"/>\\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, opacity, offset }) => {\n      gradient.addColorStop(\n        offset,\n        typeof opacity !== 'undefined'\n          ? new Color(color).setAlpha(opacity).toRgba()\n          : color,\n      );\n    });\n\n    return gradient;\n  }\n\n  static async fromObject(\n    options: GradientOptions<'linear'>,\n  ): Promise<Gradient<'radial'>>;\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   * @static\n   * @memberOf Gradient\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://fabricjs.com/patterns demo}\n * @see {@link http://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   * @default\n   */\n  offsetX = 0;\n\n  /**\n   * Pattern vertical offset from object's left/top corner\n   * @type Number\n   * @default\n   */\n  offsetY = 0;\n\n  /**\n   * @type TCrossOrigin\n   * @default\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   * @default\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(\n              ((patternSource as HTMLImageElement).width as number) / width,\n              0,\n            ),\n      patternHeight =\n        repeat === 'repeat-x' || repeat === 'no-repeat'\n          ? 1 + Math.abs(patternOffsetY || 0)\n          : ifNaN(\n              ((patternSource as HTMLImageElement).height as number) / height,\n              0,\n            );\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://fabricjs.com/freedrawing|Freedrawing demo}\n */\nexport abstract class BaseBrush {\n  /**\n   * Color of a brush\n   * @type String\n   * @default\n   */\n  color = 'rgb(0, 0, 0)';\n\n  /**\n   * Width of a brush, has to be a Number, no string literals\n   * @type Number\n   * @default\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   * @default\n   */\n  shadow: Shadow | null = null;\n\n  /**\n   * Line endings style of a brush (one of \"butt\", \"round\", \"square\")\n   * @type String\n   * @default\n   */\n  strokeLineCap: CanvasLineCap = 'round';\n\n  /**\n   * Corner style of a brush (one of \"bevel\", \"round\", \"miter\")\n   * @type String\n   * @default\n   */\n  strokeLineJoin: CanvasLineJoin = 'round';\n\n  /**\n   * Maximum miter length (used for strokeLineJoin = \"miter\") of a brush's\n   * @type Number\n   * @default\n   */\n  strokeMiterLimit = 10;\n\n  /**\n   * Stroke Dash Array.\n   * @type Array\n   * @default\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   * @default\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   * @static\n   * @memberOf Path\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   * @static\n   * @memberOf Path\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   * @static\n   * @memberOf Path\n   * @param {HTMLElement} element to parse\n   * @param {Partial<PathProps>} [options] Options object\n   */\n  static async fromElement(\n    element: HTMLElement,\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  protected declare _points: Point[];\n  protected declare _hasStraightLine: boolean;\n  protected declare 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    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    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   * @static\n   * @memberOf Circle\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   * @static\n   * @memberOf Circle\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   * @default\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   * @default\n   */\n  width = 10;\n\n  /**\n   * Density of a spray (number of dots per chunk)\n   * @type Number\n   * @default\n   */\n  density = 20;\n\n  /**\n   * Width of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidth = 1;\n\n  /**\n   * Width variance of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidthVariance = 1;\n\n  /**\n   * Whether opacity of a dot should be random\n   * @type Boolean\n   * @default\n   */\n  randomOpacity = false;\n\n  /**\n   * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n   * @type Boolean\n   * @default\n   */\n  optimizeOverlapping = true;\n\n  private declare sprayChunks: SprayBrushPoint[][];\n\n  private declare 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\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   * @default\n   */\n  declare x1: number;\n\n  /**\n   * y value or first line edge\n   * @type number\n   * @default\n   */\n  declare y1: number;\n\n  /**\n   * x value or second line edge\n   * @type number\n   * @default\n   */\n  declare x2: number;\n\n  /**\n   * y value or second line edge\n   * @type number\n   * @default\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   * @method toObject\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toObject<\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   * @static\n   * @memberOf Line\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   * @static\n   * @memberOf Line\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   * @static\n   * @memberOf Line\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   * @default\n   */\n  declare rx: number;\n\n  /**\n   * Vertical radius\n   * @type Number\n   * @default\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   * @static\n   * @memberOf Ellipse\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   * @static\n   * @memberOf Ellipse\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 type { XY } from '../Point';\n\n/**\n * Parses \"points\" attribute, returning an array of values\n * @static\n * @memberOf fabric\n * @param {String} points points attribute string\n * @return {Array} array of points\n */\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 { 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   * @default\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  private declare 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   * @static\n   * @memberOf Polyline\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   * @static\n   * @memberOf Polyline\n   * @param {HTMLElement} element Element to parser\n   * @param {Object} [options] Options object\n   */\n  static async fromElement(\n    element: HTMLElement,\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      // eslint-disable-next-line @typescript-eslint/no-unused-vars\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   * @static\n   * @memberOf Polyline\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 { 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  protected declare abstract _textLines: string[][];\n  protected declare _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        // eslint-disable-next-line no-unused-vars\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    // eslint-disable-next-line\n    for (const p1 in obj) {\n      // eslint-disable-next-line\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   * @deprecated unused\n   */\n  _getSVGLineTopOffset(\n    this: TextSVGExportMixin & FabricText,\n    lineIndex: number,\n  ) {\n    let lineTopOffset = 0,\n      j;\n    for (j = 0; j < lineIndex; j++) {\n      lineTopOffset += this.getHeightOfLine(j);\n    }\n    const lastHeight = this.getHeightOfLine(j);\n    return {\n      lineTop: lineTopOffset,\n      offset:\n        ((this._fontSizeMult - this._fontSizeFraction) * lastHeight) /\n        (this.lineHeight * this._fontSizeMult),\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      deltaY,\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      deltaY ? `baseline-shift: ${-deltaY}; ` : '',\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 { DEFAULT_SVG_FONT_SIZE, FILL, 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\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: string;\n  pathSide: TPathSide;\n  pathAlign: TPathAlign;\n  underline: boolean;\n  overline: boolean;\n  linethrough: boolean;\n  textAlign: string;\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 * @tutorial {@link http://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   * @default\n   */\n  declare fontSize: number;\n\n  /**\n   * Font weight (e.g. bold, normal, 400, 600, 800)\n   * @type {(Number|String)}\n   * @default\n   */\n  declare fontWeight: string | number;\n\n  /**\n   * Font family\n   * @type String\n   * @default\n   */\n  declare fontFamily: string;\n\n  /**\n   * Text decoration underline.\n   * @type Boolean\n   * @default\n   */\n  declare underline: boolean;\n\n  /**\n   * Text decoration overline.\n   * @type Boolean\n   * @default\n   */\n  declare overline: boolean;\n\n  /**\n   * Text decoration linethrough.\n   * @type Boolean\n   * @default\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 String\n   * @default\n   */\n  declare textAlign: string;\n\n  /**\n   * Font style . Possible values: \"\", \"normal\", \"italic\" or \"oblique\".\n   * @type String\n   * @default\n   */\n  declare fontStyle: string;\n\n  /**\n   * Line height\n   * @type Number\n   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\n   */\n  declare _fontSizeMult: number;\n\n  /**\n   * additional space between characters\n   * expressed in thousands of em unit\n   * @type Number\n   * @default\n   */\n  declare charSpacing: number;\n\n  /**\n   * Baseline shift, styles only, keep at 0 for the main text object\n   * @type {Number}\n   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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   * @default\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 (\n        textAlign === RIGHT ||\n        textAlign === JUSTIFY ||\n        textAlign === JUSTIFY_RIGHT\n      ) {\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   * @static\n   * @memberOf Text\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   * @static\n   * @memberOf Text\n   * @param {HTMLElement} element Element to parse\n   * @param {Object} [options] Options object\n   */\n  static async fromElement(\n    element: HTMLElement,\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/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 } from '../../typedefs';\nimport { getDocumentFromElement } from '../../util/dom_misc';\nimport { LEFT, MODIFIED, RIGHT, reNewline } from '../../constants';\nimport type { IText } from './IText';\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  protected declare inCompositionMode: boolean;\n\n  protected declare _reSpace: RegExp;\n  private declare _currentTickState?: ValueAnimation;\n  private declare _currentTickCompleteState?: ValueAnimation;\n  protected _currentCursorOpacity = 1;\n  private declare _textBeforeEdit: string;\n  protected declare __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  protected declare selected: boolean;\n  protected declare cursorOffsetCache: { left?: number; top?: number };\n  protected declare _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  protected declare _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, void>;\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   * @private\n   */\n  updateFromTextArea() {\n    if (!this.hiddenTextarea) {\n      return;\n    }\n    this.cursorOffsetCache = {};\n    const textarea = this.hiddenTextarea;\n    this.text = textarea.value;\n    this.set('dirty', true);\n    this.initDimensions();\n    this.setCoords();\n    const newSelection = this.fromStringToGraphemeSelection(\n      textarea.selectionStart,\n      textarea.selectionEnd,\n      textarea.value,\n    );\n    this.selectionEnd = this.selectionStart = newSelection.selectionEnd;\n    if (!this.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   * Please use exitEditingImpl, this function was kept to avoid breaking changes.\n   * Will be removed in fabric 7.0\n   * @deprecated use \"exitEditingImpl\"\n   */\n  protected _exitEditing() {\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  }\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    this._exitEditing();\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   * @default\n   */\n  declare hiddenTextareaContainer?: HTMLElement | null;\n\n  private declare _clickHandlerInitialized: boolean;\n  private declare _copyDone: boolean;\n  private declare 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 } 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   * @default\n   */\n  declare selectionStart: number;\n\n  /**\n   * Index where text selection ends\n   * @type Number\n   * @default\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   * @default\n   */\n  declare selectionColor: string;\n\n  /**\n   * Indicates whether text is in editing mode\n   * @type Boolean\n   * @default\n   */\n  declare isEditing: boolean;\n\n  /**\n   * Indicates whether a text can be edited\n   * @type Boolean\n   * @default\n   */\n  declare editable: boolean;\n\n  /**\n   * Border color of text object while it's in editing mode\n   * @type String\n   * @default\n   */\n  declare editingBorderColor: string;\n\n  /**\n   * Width of cursor (in px)\n   * @type Number\n   * @default\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   * @default\n   */\n  declare cursorColor: string;\n\n  /**\n   * Delay between cursor blink (in ms)\n   * @type Number\n   * @default\n   */\n  declare cursorDelay: number;\n\n  /**\n   * Duration of cursor fade in (in ms)\n   * @type Number\n   * @default\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   * @default\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\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    const boundaries = {\n      top: topOffset,\n      left: lineLeftOffset + (leftOffset > 0 ? leftOffset : 0),\n    };\n    if (this.direction === 'rtl') {\n      if (\n        this.textAlign === RIGHT ||\n        this.textAlign === JUSTIFY ||\n        this.textAlign === JUSTIFY_RIGHT\n      ) {\n        boundaries.left *= -1;\n      } else if (this.textAlign === LEFT || this.textAlign === JUSTIFY_LEFT) {\n        boundaries.left = lineLeftOffset - (leftOffset > 0 ? leftOffset : 0);\n      } else if (\n        this.textAlign === CENTER ||\n        this.textAlign === JUSTIFY_CENTER\n      ) {\n        boundaries.left = lineLeftOffset - (leftOffset > 0 ? leftOffset : 0);\n      }\n    }\n    return boundaries;\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 selectionStart = selection.selectionStart,\n      selectionEnd = selection.selectionEnd,\n      isJustify = this.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 (this.direction === 'rtl') {\n        if (\n          this.textAlign === RIGHT ||\n          this.textAlign === JUSTIFY ||\n          this.textAlign === JUSTIFY_RIGHT\n        ) {\n          drawStart = this.width - drawStart - drawWidth;\n        } else if (this.textAlign === LEFT || this.textAlign === JUSTIFY_LEFT) {\n          drawStart = boundaries.left + lineOffset - boxEnd;\n        } else if (\n          this.textAlign === CENTER ||\n          this.textAlign === JUSTIFY_CENTER\n        ) {\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   * @default\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   * @default\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          // eslint-disable-next-line no-unused-vars\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   * @method toObject\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toObject<\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[]) as Pick<T, K> & SProps;\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    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  ) {\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    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 } 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\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?: any;\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 * @tutorial {@link http://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   * @default\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   * @default\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   * @default\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   * @default\n   */\n  declare imageSmoothing: boolean;\n\n  declare preserveAspectRatio: string;\n\n  protected declare 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    element.classList?.add(FabricImage.CSS_CANVAS);\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   * @method applyFilters\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() {\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   * Default CSS class name for canvas\n   * Will be removed from fabric 7\n   * @static\n   * @deprecated\n   * @type String\n   * @default\n   */\n  static CSS_CANVAS = 'canvas-img';\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link FabricImage.fromElement})\n   * @static\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   * @static\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      // TODO: redundant - handled by enlivenObjectEnlivables\n      rf && enlivenObjects<BaseFilter<'Resize'>>([rf], options),\n      enlivenObjectEnlivables(object, options),\n    ]).then(([el, filters = [], [resizeFilter] = [], hydratedProps = {}]) => {\n      return new this(el, {\n        ...object,\n        // TODO: this 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   * @static\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   * @static\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 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 { 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 { 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 * @static\n * @function\n * @memberOf fabric\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 * @memberOf fabric\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 { request } from '../util/internals/dom_request';\nimport { parseSVGDocument, createEmptyResponse } from './parseSVGDocument';\nimport type { SVGParsingOutput, TSvgReviverCallback } from './typedefs';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\n\n/**\n * Takes url corresponding to an SVG document, and parses it into a set of fabric objects.\n * Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)\n * @memberOf fabric\n * @param {string} url 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  // need to handle error properly\n  return new Promise<Document>((resolve, reject) => {\n    const onComplete = (r: XMLHttpRequest) => {\n      const xml = r.responseXML;\n      if (xml) {\n        resolve(xml);\n      }\n      reject();\n    };\n\n    request(url.replace(/^\\n\\s*/, '').trim(), {\n      onComplete,\n      signal: options.signal,\n    });\n  })\n    .then((parsedDoc) => parseSVGDocument(parsedDoc, reviver, options))\n    .catch(() => {\n      // this is an unhappy path, we dont care about speed\n      return createEmptyResponse();\n    });\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 { 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   * @param {String} type\n   * @default\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, object>> {\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   * @default\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   * @default\n   **/\n  declare mode: BlendColorOwnProps['mode'];\n  /**\n   * alpha value. represent the strength of the blend color operation.\n   * @type Number\n   * @default\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   * @default\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   * @static\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) =>\n        new this({ ...filterOptions, image: enlivedImage }) as BlendImage,\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   * @default\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   * @default\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://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   * @default\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, object>[] } & Record<\n      string,\n      any\n    > = {},\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   * @static\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, object>[]).map(\n        (filter) =>\n          classRegistry\n            .getClass<typeof BaseFilter>(filter.type)\n            .fromObject(filter, options),\n      ),\n    ).then(\n      (enlivedFilters) => new this({ subFilters: enlivedFilters }) as Composed,\n    );\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   * @default\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   * @default\n   **/\n  declare alpha: InvertOwnProps['alpha'];\n\n  /**\n   * Filter invert. if false, does nothing\n   * @param {Boolean} invert\n   * @default\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   * @default\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   * @param {String} type\n   * @default\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 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   * @default\n   */\n  declare resizeType: ResizeOwnProps['resizeType'];\n\n  /**\n   * Scale factor for resizing, x axis\n   * @param {Number} scaleX\n   * @default\n   */\n  declare scaleX: ResizeOwnProps['scaleX'];\n\n  /**\n   * Scale factor for resizing, y axis\n   * @param {Number} scaleY\n   * @default\n   */\n  declare scaleY: ResizeOwnProps['scaleY'];\n\n  /**\n   * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n   * @param {Number} lanczosLobes\n   * @default\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   * @default\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   * @default\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","_objectSpread","removeFonts","forEach","fontFamily","clearFonts","restoreDefaults","keys","defaults","reduce","acc","key","log","severity","_len","optionalParams","Array","_key","console","FabricError","Error","message","options","concat","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","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","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","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","StaticCanvas","lowerCanvasEl","_this$elements$lower","elements","contextContainer","_this$elements$lower2","getDefaults","ownDefaults","initElements","_setDimensionsImpl","skipControlsDrawing","calcViewportBoundaries","requestRenderAll","setCoords","getRetinaScaling","_offset","getWidth","getHeight","setWidth","setHeight","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","patternQuality","_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","getCenter","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","parse","serialized","_objectWithoutProperties","_excluded","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","_qrDecompose","otherOptions","setPositionByOrigin","resetObjectTransform","saveObjectTransform","sizeAfterTransform","dimX","dimY","bbox","calcPlaneChangeMatrix","from","sendPointToPlane","to","sendVectorToPlane","sendObjectToPlane","fireEvent","_target$canvas","originOffset","bottom","right","resolveOrigin","originValue","NOT_ALLOWED_CURSOR","isTransformCentered","originX","originY","invertOrigin","isLocked","lockingKey","commonEventInfo","eventData","pointer","findCornerQuadrant","control","cornerAngle","getTotalAngle","round","getLocalPoint","corner","controls","padding","localPoint","getRelativeCenterPoint","translateToGivenOrigin","normalizePoint","dragHandler","newLeft","newTop","moveX","moveY","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","svgTransform","_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","_templateObject","_taggedTemplateLiteral","viewportSeparator","_templateObject2","svgNS","reFontDeclaration","attributesMap","cx","cy","display","fSize","cPath","svgValidTagNamesRegEx","svgViewBoxElementsRegEx","svgValidParentsRegEx","reViewBoxAttrValue","_templateObject3","unitVectorX","zero","rotateVector","vector","createVector","magnitude","calcAngleBetweenVectors","crossProduct","dotProduct","calcVectorRotation","getUnitVector","getOrthonormalVector","counterClockwise","isBetweenVectors","AxB","AxT","BxT","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","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","pos","_getLeftTopCoords","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","_ref4","extraParam","_excluded2","enlivedObjectOptions","wrapWithFireEvent","actionHandler","extraEventInfo","actionPerformed","wrapWithFixedAnchor","centerPoint","constraint","changeWidth","changeObjectWidth","strokePadding","oldWidth","newWidth","renderCircleControl","styleOverride","xSize","sizeX","cornerSize","ySize","sizeY","transparentCorners","cornerStrokeColor","myLeft","myTop","cornerColor","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","touchSizeY","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","coord","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","normalizeAttr","attr","_attributesMap","regex","cleanupSvgAttribute","attributeValue","_templateObject4","_templateObject5","_templateObject6","transforms","transformList","_templateObject7","reTransformList","reTransform","reTransformAll","parseTransformAttribute","test","matchAll","transformMatch","matchedParams","operation","rawArgs","arg1","arg2","arg3","arg4","arg5","arg","normalizeValue","parentAttributes","parsed","ouputValue","transformMatrix","fillIndex","strokeIndex","parseFontDeclaration","oStyle","parseStyleString","chunk","parseStyleAttribute","parseStyleObject","colorAttributesMap","parseAttributes","attributes","cssRules","parentFontSize","ownAttributes","rule","getGlobalStylesForElement","normalizedStyle","normalizedAttr","normalizedValue","font","mergedAttrs","colorAttr","setStrokeFillOpacity","RECT_PROPS","Rect","_initRxRy","rx","ry","isRounded","bezierCurveTo","fromElement","_parseAttributes","ATTRIBUTE_NAMES","restOfparsedAttributes","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","setStyle","elementStyle","setProperty","getRandomInt","random","request","xhr","removeListener","ontimeout","onreadystatechange","readyState","open","send","removeTransformMatrixForSvgParsing","preserveAspectRatioOptions","_assignTransformMatrixProps","cropX","cropY","offsetLeft","offsetTop","_newCanvas$getContext","getRegularPolygonPath","numVertexes","radius","interiorAngle","rotationAdjustment","rad","commonAttributes","groupSVGElements","mergeClipPaths","_b$group","removeTransformFromObject","finalTransform","rotatePoint","transformPath","pathOffset","pathSegment","newSegment","CanvasDOMManager","containerClass","upperCanvasEl","createUpperCanvas","upper","applyCanvasStyle","container","createContainerElement","replaceChild","className","removeChild","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","skipTargetFind","getViewportPoint","aObjects","searchPossibleTargets","subTargets","altSelectionKey","_pointIsInObjectSelectionArea","viewportZoom","angleRadians","cosP","sinP","cosPSinP","cosPMinusSinP","_checkTarget","isEditing","_searchPossibleTargets","subTarget","_pointer","_absolutePointer","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","viewportPoint","scenePoint","absolutePointer","addListener","syntheticEventConfig","mouse","in","targetIn","targetOut","canvasIn","canvasOut","drag","Canvas","eventHandler","addOrRemove","_getEventPrefix","functor","_eventjsFunctor","canvasElement","eventTypePrefix","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onClick","_onDragStart","_onDragEnd","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","removeListeners","_onMouseUp","_onTouchEnd","clearTimeout","_willAddMouseDown","__onMouseWheel","shared","nestedTarget","_isClick","_dragSource","_onDragProgress","_renderDragEffects","dropTarget","_dropTarget","didDrop","dataTransfer","dropEffect","dragSource","_draggedoverTarget","findDragTargets","eventType","_fireEnterLeaveEvents","_basicEventHandler","clicks","detail","_cacheTransformEventData","_handleEvent","getPointerId","evt","identifier","pointerId","_isMainEvent","isPrimary","touches","mainTouchId","shouldPreventScrolling","currentActiveObject","__onMouseDown","_target","__onMouseUp","__onMouseMove","_shouldRender","_this$_activeObject","isClick","button","_onMouseUpInDrawingMode","shouldRender","targetWasActive","handleSelection","found","originalControl","originalMouseUpHandler","_setCursorFromEvent","extraData","currentTarget","currentSubTargets","_onMouseDownInDrawingMode","onMouseDown","_onMouseMoveInDrawingMode","onMouseUp","grouped","handleMultiSelection","groupSelector","_transformObject","_fireOverOutEvents","textEditingManager","fireSyntheticInOutEvents","oldTarget","fireCanvas","draggedoverTarget","targetChanged","outOpt","nextTarget","inOpt","previousTarget","localPointer","_performTransformAction","activeSelection","reverse","isAS","prevActiveObjects","multiSelectAdd","newActiveSelection","point1","point2","collectedObjects","klass","htmlElement","linearDefaultCoords","radialDefaultCoords","ifNaN","valueIfNaN","isPercent","isFinite","parsePercent","NaN","RE_KEY_VALUE_PAIRS","RE_KEY_VALUE","parseColorStop","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","patternWidth","patternHeight","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","largeFlag","sweepFlag","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","parsePointsAttribute","pointsSplit","parsedPoints","polylineDefaultValues","exactBoundingBox","Polyline","initialized","isOpen","_projectStrokeOnPoints","strokeDiff","bboxNoStroke","layoutProperties","_options$width","_options$height","_options$width2","_options$height2","output","diffX","diffY","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","_options$parsedAttrib","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","_getSVGLineTopOffset","lastHeight","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","diff","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","_selectionStart","newSelectionStart","newSelectionEnd","selectLine","_selectionStart2","enterEditingImpl","initHiddenTextarea","_saveEditingProps","_setEditingProps","_textBeforeEdit","activeElement","currentStart","currentEnd","__selectionStartOnMouseDown","editingBorderColor","fromStringToGraphemeSelection","smallerTextStart","graphemeStart","smallerTextEnd","fromGraphemeToStringSelection","cursorOffsetCache","inCompositionMode","updateTextareaPosition","updateFromTextArea","textarea","_calcTextareaPosition","desiredPosition","compositionStart","cursorLocation","charHeight","upperCanvas","upperCanvasWidth","upperCanvasHeight","clientWidth","clientHeight","_savedProps","_restoreEditingProps","_exitEditing","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","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","_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","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","_element$classList","removeTexture","_originalElement","CSS_CANVAS","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","getCSSRules","allRules","styleContents","ruleObj","propertyValuePairs","pair","_rule","findTag","ElementsParser","clipPaths","regexUrl","gradientDefs","elList","getGradientDefs","createObject","resolveGradient","resolveClipPath","extractPropertyDefinition","storage","gradientDef","usingElement","exactOwner","clipPathElements","objTransformInv","clipPathTag","clipPathOwner","clipPathElement","enlivedClippath","clipRule","gTransform","isValidSvgTag","createEmptyResponse","allElements","async","parseSVGDocument","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","xml","responseXML","parsedDoc","ACTION_NAME","createPolyPositionHandler","pointIndex","polyObject","polyActionHandler","poly","mouseLocalPosition","factoryPolyActionHandler","anchorPoint","anchorPointInParentPlane","createPolyActionHandler","calcPathPointPosition","pathObject","commandIndex","pathPositionHandler","pathActionHandler","movePathPoint","anchorCommand","PathPointControl","controlFill","controlStroke","PathControlPointControl","connectToCommandIndex","connectToPointIndex","connectionDashArray","commandType","createControl","commandIndexPos","pointIndexPos","isControlPoint","controlPointStyle","pointStyle","previousCommandType","indexFromPrevCommand","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","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","filterOptions","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":"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"}