{"version":3,"file":"StaticCanvas.mjs","names":[],"sources":["../../../src/canvas/StaticCanvas.ts"],"sourcesContent":["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';\nimport { escapeXml } from '../util/lang_string';\n\n/**\n * Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset\n * Better try to restrict with types to avoid confusion.\n */\nexport type TCanvasSizeOptions =\n  | {\n      backstoreOnly?: true;\n      cssOnly?: false;\n    }\n  | {\n      backstoreOnly?: false;\n      cssOnly?: true;\n    };\n\nexport type TSVGExportOptions = {\n  suppressPreamble?: boolean;\n  viewBox?: {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n  };\n  encoding?: 'UTF-8'; // test Encoding type and see what happens\n  width?: string;\n  height?: string;\n  reviver?: TSVGReviver;\n};\n\nexport type PatternQuality = 'fast' | 'good' | 'best' | 'nearest' | 'bilinear';\n\n/**\n * Static canvas class\n * @see {@link http://fabric5.fabricjs.com/static_canvas|StaticCanvas demo}\n * @fires before:render\n * @fires after:render\n * @fires canvas:cleared\n * @fires object:added\n * @fires object:removed\n */\n// TODO: fix `EventSpec` inheritance https://github.com/microsoft/TypeScript/issues/26154#issuecomment-1366616260\nexport class StaticCanvas<\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  EventSpec extends StaticCanvasEvents = StaticCanvasEvents,\n>\n  extends createCollectionMixin(CommonMethods<CanvasEvents>)\n  implements StaticCanvasOptions\n{\n  declare width: number;\n  declare height: number;\n\n  // background\n  declare backgroundVpt: boolean;\n  declare backgroundColor: TFiller | string;\n  declare backgroundImage?: FabricObject;\n  // overlay\n  declare overlayVpt: boolean;\n  declare overlayColor: TFiller | string;\n  declare overlayImage?: FabricObject;\n\n  declare clipPath?: FabricObject;\n\n  declare includeDefaultValues: boolean;\n\n  // rendering config\n  declare renderOnAddRemove: boolean;\n  declare skipOffscreen: boolean;\n  declare enableRetinaScaling: boolean;\n  declare imageSmoothingEnabled: boolean;\n\n  /**\n   * @todo move to Canvas\n   */\n  declare controlsAboveOverlay: boolean;\n\n  /**\n   * @todo move to Canvas\n   */\n  declare allowTouchScrolling: boolean;\n\n  declare viewportTransform: TMat2D;\n\n  /**\n   * The viewport bounding box in scene plane coordinates, see {@link calcViewportBoundaries}\n   */\n  declare vptCoords: TCornerPoint;\n\n  /**\n   * A reference to the canvas actual HTMLCanvasElement.\n   * Can be use to read the raw pixels, but never write or manipulate\n   * @type HTMLCanvasElement\n   */\n  get lowerCanvasEl() {\n    return this.elements.lower?.el;\n  }\n\n  get contextContainer() {\n    return this.elements.lower?.ctx;\n  }\n\n  /**\n   * If true the Canvas is in the process or has been disposed/destroyed.\n   * No more rendering operation will be executed on this canvas.\n   * @type boolean\n   */\n  declare destroyed?: boolean;\n\n  /**\n   * Started the process of disposing but not done yet.\n   * WIll likely complete the render cycle already scheduled but stopping adding more.\n   * @type boolean\n   */\n  declare disposed?: boolean;\n\n  declare _offset: { left: number; top: number };\n  declare protected hasLostContext: boolean;\n  declare protected nextRenderHandle: number;\n\n  declare elements: StaticCanvasDOMManager;\n\n  /**\n   * When true control drawing is skipped.\n   * This boolean is used to avoid toDataURL to export controls.\n   * Usage of this boolean to build up other flows and features is not supported\n   * @type Boolean\n   * @default false\n   */\n  declare protected skipControlsDrawing: boolean;\n\n  /**\n   * Controls the rendering of images under node-canvas.\n   * Has no effects on the browser context.\n   */\n  declare patternQuality: PatternQuality;\n\n  static ownDefaults = staticCanvasDefaults;\n\n  // reference to\n  declare protected __cleanupTask?: {\n    (): void;\n    kill: (reason?: any) => void;\n  };\n\n  static getDefaults(): Record<string, any> {\n    return StaticCanvas.ownDefaults;\n  }\n\n  constructor(\n    el?: string | HTMLCanvasElement,\n    options: TOptions<StaticCanvasOptions> = {},\n  ) {\n    super();\n    Object.assign(\n      this,\n      (this.constructor as typeof StaticCanvas).getDefaults(),\n    );\n    this.set(options);\n    this.initElements(el);\n    this._setDimensionsImpl({\n      width: this.width || this.elements.lower.el.width || 0,\n      height: this.height || this.elements.lower.el.height || 0,\n    });\n    this.skipControlsDrawing = false;\n    this.viewportTransform = [...this.viewportTransform];\n    this.calcViewportBoundaries();\n  }\n\n  protected initElements(el?: string | HTMLCanvasElement) {\n    this.elements = new StaticCanvasDOMManager(el);\n  }\n\n  add(...objects: FabricObject[]) {\n    const size = super.add(...objects);\n    objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n    return size;\n  }\n\n  insertAt(index: number, ...objects: FabricObject[]) {\n    const size = super.insertAt(index, ...objects);\n    objects.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n    return size;\n  }\n\n  remove(...objects: FabricObject[]) {\n    const removed = super.remove(...objects);\n    removed.length > 0 && this.renderOnAddRemove && this.requestRenderAll();\n    return removed;\n  }\n\n  _onObjectAdded(obj: FabricObject) {\n    if (obj.canvas && (obj.canvas as StaticCanvas) !== this) {\n      log(\n        'warn',\n        'Canvas is trying to add an object that belongs to a different canvas.\\n' +\n          'Resulting to default behavior: removing object from previous canvas and adding to new canvas',\n      );\n      obj.canvas.remove(obj);\n    }\n    obj._set('canvas', this);\n    obj.setCoords();\n    this.fire('object:added', { target: obj });\n    obj.fire('added', { target: this });\n  }\n\n  _onObjectRemoved(obj: FabricObject) {\n    obj._set('canvas', undefined);\n    this.fire('object:removed', { target: obj });\n    obj.fire('removed', { target: this });\n  }\n\n  _onStackOrderChanged() {\n    this.renderOnAddRemove && this.requestRenderAll();\n  }\n\n  /**\n   * @private\n   * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html\n   * @return {Number} retinaScaling if applied, otherwise 1;\n   */\n  getRetinaScaling() {\n    return this.enableRetinaScaling ? getDevicePixelRatio() : 1;\n  }\n\n  /**\n   * Calculates canvas element offset relative to the document\n   * This method is also attached as \"resize\" event handler of window\n   */\n  calcOffset() {\n    return (this._offset = this.elements.calcOffset());\n  }\n\n  /**\n   * Returns canvas width (in px)\n   * @return {Number}\n   */\n  getWidth(): number {\n    return this.width;\n  }\n\n  /**\n   * Returns canvas height (in px)\n   * @return {Number}\n   */\n  getHeight(): number {\n    return this.height;\n  }\n\n  /**\n   * Internal use only\n   * @protected\n   */\n  protected _setDimensionsImpl(\n    dimensions: Partial<TSize | CSSDimensions>,\n    { cssOnly = false, backstoreOnly = false }: TCanvasSizeOptions = {},\n  ) {\n    if (!cssOnly) {\n      const size = {\n        width: this.width,\n        height: this.height,\n        ...(dimensions as Partial<TSize>),\n      };\n      this.elements.setDimensions(size, this.getRetinaScaling());\n      this.hasLostContext = true;\n      this.width = size.width;\n      this.height = size.height;\n    }\n    if (!backstoreOnly) {\n      this.elements.setCSSDimensions(dimensions);\n    }\n\n    this.calcOffset();\n  }\n\n  /**\n   * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)\n   * @param {Object}        dimensions                    Object with width/height properties\n   * @param {Number|String} [dimensions.width]            Width of canvas element\n   * @param {Number|String} [dimensions.height]           Height of canvas element\n   * @param {Object}        [options]                     Options object\n   * @param {Boolean}       [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions\n   * @param {Boolean}       [options.cssOnly=false]       Set the given dimensions only as css dimensions\n   */\n  setDimensions(\n    dimensions: Partial<CSSDimensions>,\n    options?: { cssOnly?: true; backstoreOnly?: false },\n  ): void;\n  setDimensions(\n    dimensions: Partial<TSize>,\n    options?: { backstoreOnly?: true; cssOnly?: false },\n  ): void;\n  setDimensions(dimensions: Partial<TSize>, options?: never): void;\n  setDimensions(\n    dimensions: Partial<TSize | CSSDimensions>,\n    options?: TCanvasSizeOptions,\n  ) {\n    this._setDimensionsImpl(dimensions, options);\n    if (!options || !options.cssOnly) {\n      this.requestRenderAll();\n    }\n  }\n\n  /**\n   * Returns canvas zoom level\n   * @return {Number}\n   */\n  getZoom() {\n    return this.viewportTransform[0];\n  }\n\n  /**\n   * Sets viewport transformation of this canvas instance\n   * @param {Array} vpt a Canvas 2D API transform matrix\n   */\n  setViewportTransform(vpt: TMat2D) {\n    this.viewportTransform = vpt;\n    this.calcViewportBoundaries();\n    this.renderOnAddRemove && this.requestRenderAll();\n  }\n\n  /**\n   * Sets zoom level of this canvas instance, the zoom centered around point\n   * meaning that following zoom to point with the same point will have the visual\n   * effect of the zoom originating from that point. The point won't move.\n   * It has nothing to do with canvas center or visual center of the viewport.\n   * @param {Point} point to zoom with respect to\n   * @param {Number} value to set zoom to, less than 1 zooms out\n   */\n  zoomToPoint(point: Point, value: number) {\n    // TODO: just change the scale, preserve other transformations\n    const before = point,\n      vpt: TMat2D = [...this.viewportTransform];\n    const newPoint = transformPoint(point, invertTransform(vpt));\n    vpt[0] = value;\n    vpt[3] = value;\n    const after = transformPoint(newPoint, vpt);\n    vpt[4] += before.x - after.x;\n    vpt[5] += before.y - after.y;\n    this.setViewportTransform(vpt);\n  }\n\n  /**\n   * Sets zoom level of this canvas instance\n   * @param {Number} value to set zoom to, less than 1 zooms out\n   */\n  setZoom(value: number) {\n    this.zoomToPoint(new Point(0, 0), value);\n  }\n\n  /**\n   * Pan viewport so as to place point at top left corner of canvas\n   * @param {Point} point to move to\n   */\n  absolutePan(point: Point) {\n    const vpt: TMat2D = [...this.viewportTransform];\n    vpt[4] = -point.x;\n    vpt[5] = -point.y;\n    return this.setViewportTransform(vpt);\n  }\n\n  /**\n   * Pans viewpoint relatively\n   * @param {Point} point (position vector) to move by\n   */\n  relativePan(point: Point) {\n    return this.absolutePan(\n      new Point(\n        -point.x - this.viewportTransform[4],\n        -point.y - this.viewportTransform[5],\n      ),\n    );\n  }\n\n  /**\n   * Returns &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 = this.patternQuality;\n    this.fire('before:render', { ctx });\n    this._renderBackground(ctx);\n\n    ctx.save();\n    //apply viewport transform once for all rendering process\n    ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n    this._renderObjects(ctx, objects);\n    ctx.restore();\n    if (!this.controlsAboveOverlay && !this.skipControlsDrawing) {\n      this.drawControls(ctx);\n    }\n    if (path) {\n      path._set('canvas', this);\n      // needed to setup a couple of variables\n      // todo migrate to the newer one\n      path.shouldCache();\n      path._transformDone = true;\n      (path as TCachedFabricObject).renderCache({ forClipping: true });\n      this.drawClipPathOnCanvas(ctx, path as TCachedFabricObject);\n    }\n    this._renderOverlay(ctx);\n    if (this.controlsAboveOverlay && !this.skipControlsDrawing) {\n      this.drawControls(ctx);\n    }\n    this.fire('after:render', { ctx });\n\n    if (this.__cleanupTask) {\n      this.__cleanupTask();\n      this.__cleanupTask = undefined;\n    }\n  }\n\n  /**\n   * Paint the cached clipPath on the lowerCanvasEl\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  drawClipPathOnCanvas(\n    ctx: CanvasRenderingContext2D,\n    clipPath: TCachedFabricObject,\n  ) {\n    const v = this.viewportTransform;\n    ctx.save();\n    ctx.transform(...v);\n    // DEBUG: uncomment this line, comment the following\n    // ctx.globalAlpha = 0.4;\n    ctx.globalCompositeOperation = 'destination-in';\n    clipPath.transform(ctx);\n    ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);\n    ctx.drawImage(\n      clipPath._cacheCanvas,\n      -clipPath.cacheTranslationX,\n      -clipPath.cacheTranslationY,\n    );\n    ctx.restore();\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   * @param {Array} objects to render\n   */\n  _renderObjects(ctx: CanvasRenderingContext2D, objects: FabricObject[]) {\n    for (let i = 0, len = objects.length; i < len; ++i) {\n      objects[i] && objects[i].render(ctx);\n    }\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   * @param {string} property 'background' or 'overlay'\n   */\n  _renderBackgroundOrOverlay(\n    ctx: CanvasRenderingContext2D,\n    property: 'background' | 'overlay',\n  ) {\n    const fill = this[`${property}Color`],\n      object = this[`${property}Image`],\n      v = this.viewportTransform,\n      needsVpt = this[`${property}Vpt`];\n    if (!fill && !object) {\n      return;\n    }\n    const isAFiller = isFiller(fill);\n    if (fill) {\n      ctx.save();\n      ctx.beginPath();\n      ctx.moveTo(0, 0);\n      ctx.lineTo(this.width, 0);\n      ctx.lineTo(this.width, this.height);\n      ctx.lineTo(0, this.height);\n      ctx.closePath();\n      ctx.fillStyle = isAFiller ? fill.toLive(ctx /* this */)! : fill;\n      if (needsVpt) {\n        ctx.transform(...v);\n      }\n      if (isAFiller) {\n        ctx.transform(1, 0, 0, 1, fill.offsetX || 0, fill.offsetY || 0);\n        const m = ((fill as Gradient<'linear'>).gradientTransform ||\n          (fill as Pattern).patternTransform) as TMat2D;\n        m && ctx.transform(...m);\n      }\n      ctx.fill();\n      ctx.restore();\n    }\n    if (object) {\n      ctx.save();\n      const { skipOffscreen } = this;\n      // if the object doesn't move with the viewport,\n      // the offscreen concept does not apply;\n      this.skipOffscreen = needsVpt;\n      if (needsVpt) {\n        ctx.transform(...v);\n      }\n      object.render(ctx);\n      this.skipOffscreen = skipOffscreen;\n      ctx.restore();\n    }\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  _renderBackground(ctx: CanvasRenderingContext2D) {\n    this._renderBackgroundOrOverlay(ctx, 'background');\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  _renderOverlay(ctx: CanvasRenderingContext2D) {\n    this._renderBackgroundOrOverlay(ctx, 'overlay');\n  }\n\n  /**\n   * Returns coordinates of a center of canvas.\n   * @return {Point}\n   */\n  getCenterPoint() {\n    return new Point(this.width / 2, this.height / 2);\n  }\n\n  /**\n   * Centers object horizontally in the canvas\n   */\n  centerObjectH(object: FabricObject) {\n    return this._centerObject(\n      object,\n      new Point(this.getCenterPoint().x, object.getCenterPoint().y),\n    );\n  }\n\n  /**\n   * Centers object vertically in the canvas\n   * @param {FabricObject} object Object to center vertically\n   */\n  centerObjectV(object: FabricObject) {\n    return this._centerObject(\n      object,\n      new Point(object.getCenterPoint().x, this.getCenterPoint().y),\n    );\n  }\n\n  /**\n   * Centers object vertically and horizontally in the canvas\n   * @param {FabricObject} object Object to center vertically and horizontally\n   */\n  centerObject(object: FabricObject) {\n    return this._centerObject(object, this.getCenterPoint());\n  }\n\n  /**\n   * Centers object vertically and horizontally in the viewport\n   * @param {FabricObject} object Object to center vertically and horizontally\n   */\n  viewportCenterObject(object: FabricObject) {\n    return this._centerObject(object, this.getVpCenter());\n  }\n\n  /**\n   * Centers object horizontally in the viewport, object.top is unchanged\n   * @param {FabricObject} object Object to center vertically and horizontally\n   */\n  viewportCenterObjectH(object: FabricObject) {\n    return this._centerObject(\n      object,\n      new Point(this.getVpCenter().x, object.getCenterPoint().y),\n    );\n  }\n\n  /**\n   * Centers object Vertically in the viewport, object.top is unchanged\n   * @param {FabricObject} object Object to center vertically and horizontally\n   */\n  viewportCenterObjectV(object: FabricObject) {\n    return this._centerObject(\n      object,\n      new Point(object.getCenterPoint().x, this.getVpCenter().y),\n    );\n  }\n\n  /**\n   * Calculate the point in canvas that correspond to the center of actual viewport.\n   * @return {Point} vpCenter, viewport center\n   */\n  getVpCenter(): Point {\n    return transformPoint(\n      this.getCenterPoint(),\n      invertTransform(this.viewportTransform),\n    );\n  }\n\n  /**\n   * @private\n   * @param {FabricObject} object Object to center\n   * @param {Point} center Center point\n   */\n  _centerObject(object: FabricObject, center: Point) {\n    object.setXY(center, CENTER, CENTER);\n    object.setCoords();\n    this.renderOnAddRemove && this.requestRenderAll();\n  }\n\n  /**\n   * Returns dataless JSON representation of canvas\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {String} json string\n   */\n  toDatalessJSON(propertiesToInclude?: string[]) {\n    return this.toDatalessObject(propertiesToInclude);\n  }\n\n  /**\n   * Returns object representation of canvas\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toObject(propertiesToInclude?: string[]) {\n    return this._toObjectMethod('toObject', propertiesToInclude);\n  }\n\n  /**\n   * Returns Object representation of canvas\n   * this alias is provided because if you call JSON.stringify on an instance,\n   * the toJSON object will be invoked if it exists.\n   * Having a toJSON method means you can do JSON.stringify(myCanvas)\n   * JSON does not support additional properties because toJSON has its own signature\n   * @return {Object} JSON compatible object\n   * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#serialization}\n   * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo}\n   * @example <caption>JSON representation of canvas </caption>\n   * const json = canvas.toJSON();\n   * @example <caption>JSON representation of canvas </caption>\n   * const json = JSON.stringify(canvas);\n   */\n  toJSON() {\n    return this.toObject();\n  }\n\n  /**\n   * Returns dataless object representation of canvas\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} object representation of an instance\n   */\n  toDatalessObject(propertiesToInclude?: string[]) {\n    return this._toObjectMethod('toDatalessObject', propertiesToInclude);\n  }\n\n  /**\n   * @private\n   */\n  _toObjectMethod(\n    methodName: TValidToObjectMethod,\n    propertiesToInclude?: string[],\n  ) {\n    const clipPath = this.clipPath;\n    const clipPathData =\n      clipPath && !clipPath.excludeFromExport\n        ? this._toObject(clipPath, methodName, propertiesToInclude)\n        : null;\n    return {\n      version: VERSION,\n      ...pick(this, propertiesToInclude as (keyof this)[]),\n      objects: this._objects\n        .filter((object) => !object.excludeFromExport)\n        .map((instance) =>\n          this._toObject(instance, methodName, propertiesToInclude),\n        ),\n      ...this.__serializeBgOverlay(methodName, propertiesToInclude),\n      ...(clipPathData ? { clipPath: clipPathData } : null),\n    };\n  }\n\n  /**\n   * @private\n   */\n  protected _toObject(\n    instance: FabricObject,\n    methodName: TValidToObjectMethod,\n    propertiesToInclude?: string[],\n  ) {\n    let originalValue;\n\n    if (!this.includeDefaultValues) {\n      originalValue = instance.includeDefaultValues;\n      instance.includeDefaultValues = false;\n    }\n\n    const object = instance[methodName](propertiesToInclude);\n    if (!this.includeDefaultValues) {\n      instance.includeDefaultValues = !!originalValue;\n    }\n    return object;\n  }\n\n  /**\n   * @private\n   */\n  __serializeBgOverlay(\n    methodName: TValidToObjectMethod,\n    propertiesToInclude?: string[],\n  ) {\n    const data: any = {},\n      bgImage = this.backgroundImage,\n      overlayImage = this.overlayImage,\n      bgColor = this.backgroundColor,\n      overlayColor = this.overlayColor;\n\n    if (isFiller(bgColor)) {\n      if (!bgColor.excludeFromExport) {\n        data.background = bgColor.toObject(propertiesToInclude);\n      }\n    } else if (bgColor) {\n      data.background = bgColor;\n    }\n\n    if (isFiller(overlayColor)) {\n      if (!overlayColor.excludeFromExport) {\n        data.overlay = overlayColor.toObject(propertiesToInclude);\n      }\n    } else if (overlayColor) {\n      data.overlay = overlayColor;\n    }\n\n    if (bgImage && !bgImage.excludeFromExport) {\n      data.backgroundImage = this._toObject(\n        bgImage,\n        methodName,\n        propertiesToInclude,\n      );\n    }\n    if (overlayImage && !overlayImage.excludeFromExport) {\n      data.overlayImage = this._toObject(\n        overlayImage,\n        methodName,\n        propertiesToInclude,\n      );\n    }\n\n    return data;\n  }\n\n  /* _TO_SVG_START_ */\n\n  declare svgViewportTransformation: boolean;\n\n  /**\n   * Returns SVG representation of canvas\n   * @param {Object} [options] Options object for SVG output\n   * @param {Boolean} [options.suppressPreamble=false] If true xml tag is not included\n   * @param {Object} [options.viewBox] SVG viewbox object\n   * @param {Number} [options.viewBox.x] x-coordinate of viewbox\n   * @param {Number} [options.viewBox.y] y-coordinate of viewbox\n   * @param {Number} [options.viewBox.width] Width of viewbox\n   * @param {Number} [options.viewBox.height] Height of viewbox\n   * @param {String} [options.encoding=UTF-8] Encoding of SVG output\n   * @param {String} [options.width] desired width of svg with or without units\n   * @param {String} [options.height] desired height of svg with or without units\n   * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.\n   * @return {String} SVG string\n   * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#serialization}\n   * @see {@link http://jsfiddle.net/fabricjs/jQ3ZZ/|jsFiddle demo}\n   * @example <caption>Normal SVG output</caption>\n   * var svg = canvas.toSVG();\n   * @example <caption>SVG output without preamble (without &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(\n        `<g clip-path=\"url(#${escapeXml(this.clipPath.clipPathId ?? '')})\" >\\n`,\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 {Promise<FabricObject> | Promise<void> | void} [reviver] Method for further parsing of JSON elements, called after each fabric object created with the instance\n   * if creation was successfully or with defined error if not. If a FabricObject is returned in the reviver, and an error occurred, this instance will be used in place of that one witch generated error.\n   * @param {Object} [options] options\n   * @param {AbortSignal} [options.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n   * @return {Promise<Canvas | StaticCanvas>} instance\n   * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#deserialization}\n   * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n   * @example <caption>loadFromJSON</caption>\n   * canvas.loadFromJSON(json).then((canvas) => canvas.requestRenderAll());\n   * @example <caption>loadFromJSON with reviver</caption>\n   * canvas.loadFromJSON(json, function(o, object, error) {\n   *   // `o` = json object\n   *   // `object` = fabric.Object instance or undefined\n   *   // `error` = FabricError or undefined\n   *   // ... do some stuff ...\n   *   if(error){\n   *      return new FabricText('placeholder-object');\n   *   }\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"],"mappings":"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"}