{"version":3,"file":"StaticCanvas.min.mjs","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 {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.\n   * @param {Object} [options] options\n   * @param {AbortSignal} [options.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n   * @return {Promise<Canvas | StaticCanvas>} instance\n   * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-3#deserialization}\n   * @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}\n   * @example <caption>loadFromJSON</caption>\n   * canvas.loadFromJSON(json).then((canvas) => canvas.requestRenderAll());\n   * @example <caption>loadFromJSON with reviver</caption>\n   * canvas.loadFromJSON(json, function(o, object) {\n   *   // `o` = json object\n   *   // `object` = fabric.Object instance\n   *   // ... do some stuff ...\n   * }).then((canvas) => {\n   *   ... canvas is restored, add your code.\n   * });\n   *\n   */\n  loadFromJSON(\n    json: string | Record<string, any>,\n    reviver?: EnlivenObjectOptions['reviver'],\n    { signal }: Abortable = {},\n  ): Promise<this> {\n    if (!json) {\n      return Promise.reject(new FabricError('`json` is undefined'));\n    }\n\n    // parse json if it wasn't already\n    const { objects = [], ...serialized } =\n      typeof json === 'string' ? JSON.parse(json) : json;\n    const { backgroundImage, background, overlayImage, overlay, clipPath } =\n      serialized;\n    const renderOnAddRemove = this.renderOnAddRemove;\n    this.renderOnAddRemove = false;\n\n    return Promise.all([\n      enlivenObjects<FabricObject>(objects, {\n        reviver,\n        signal,\n      }),\n      enlivenObjectEnlivables(\n        {\n          backgroundImage,\n          backgroundColor: background,\n          overlayImage,\n          overlayColor: overlay,\n          clipPath,\n        },\n        { signal },\n      ),\n    ]).then(([enlived, enlivedMap]) => {\n      this.clear();\n      this.add(...enlived);\n      this.set(serialized);\n      this.set(enlivedMap);\n      this.renderOnAddRemove = renderOnAddRemove;\n      return this;\n    });\n  }\n\n  /**\n   * Clones canvas instance\n   * @param {string[]} [properties] Array of properties to include in the cloned canvas and children\n   */\n  clone(properties: string[]) {\n    const data = this.toObject(properties);\n    const canvas = this.cloneWithoutData();\n    return canvas.loadFromJSON(data);\n  }\n\n  /**\n   * Clones canvas instance without cloning existing data.\n   * This essentially copies canvas dimensions since loadFromJSON does not affect canvas size.\n   */\n  cloneWithoutData() {\n    const el = createCanvasElementFor(this);\n    return new (this.constructor as Constructor<this>)(el);\n  }\n\n  /**\n   * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately\n   * @param {Object} [options] Options object\n   * @param {String} [options.format=png] The format of the output image. Either \"jpeg\" or \"png\"\n   * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.\n   * @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent\n   * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14\n   * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14\n   * @param {Number} [options.width] Cropping width. Introduced in v1.2.14\n   * @param {Number} [options.height] Cropping height. Introduced in v1.2.14\n   * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0\n   * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.\n   * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format\n   * @see {@link https://jsfiddle.net/xsjua1rd/ demo}\n   * @example <caption>Generate jpeg dataURL with lower quality</caption>\n   * var dataURL = canvas.toDataURL({\n   *   format: 'jpeg',\n   *   quality: 0.8\n   * });\n   * @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>\n   * var dataURL = canvas.toDataURL({\n   *   format: 'png',\n   *   left: 100,\n   *   top: 100,\n   *   width: 200,\n   *   height: 200\n   * });\n   * @example <caption>Generate double scaled png dataURL</caption>\n   * var dataURL = canvas.toDataURL({\n   *   format: 'png',\n   *   multiplier: 2\n   * });\n   * @example <caption>Generate dataURL with objects that overlap a specified object</caption>\n   * var myObject;\n   * var dataURL = canvas.toDataURL({\n   *   filter: (object) => object.isContainedWithinObject(myObject) || object.intersectsWithObject(myObject)\n   * });\n   */\n  toDataURL(options = {} as TDataUrlOptions): string {\n    const {\n      format = 'png',\n      quality = 1,\n      multiplier = 1,\n      enableRetinaScaling = false,\n    } = options;\n    const finalMultiplier =\n      multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);\n\n    return toDataURL(\n      this.toCanvasElement(finalMultiplier, options),\n      format,\n      quality,\n    );\n  }\n  toBlob(options = {} as TDataUrlOptions): Promise<Blob | null> {\n    const {\n      format = 'png',\n      quality = 1,\n      multiplier = 1,\n      enableRetinaScaling = false,\n    } = options;\n    const finalMultiplier =\n      multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);\n\n    return toBlob(\n      this.toCanvasElement(finalMultiplier, options),\n      format,\n      quality,\n    );\n  }\n\n  /**\n   * Create a new HTMLCanvas element painted with the current canvas content.\n   * No need to resize the actual one or repaint it.\n   * Will transfer object ownership to a new canvas, paint it, and set everything back.\n   * This is an intermediary step used to get to a dataUrl but also it is useful to\n   * create quick image copies of a canvas without passing for the dataUrl string\n   * @param {Number} [multiplier] a zoom factor.\n   * @param {Object} [options] Cropping informations\n   * @param {Number} [options.left] Cropping left offset.\n   * @param {Number} [options.top] Cropping top offset.\n   * @param {Number} [options.width] Cropping width.\n   * @param {Number} [options.height] Cropping height.\n   * @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.\n   */\n  toCanvasElement(\n    multiplier = 1,\n    { width, height, left, top, filter } = {} as TToCanvasElementOptions,\n  ): HTMLCanvasElement {\n    const scaledWidth = (width || this.width) * multiplier,\n      scaledHeight = (height || this.height) * multiplier,\n      zoom = this.getZoom(),\n      originalWidth = this.width,\n      originalHeight = this.height,\n      originalSkipControlsDrawing = this.skipControlsDrawing,\n      newZoom = zoom * multiplier,\n      vp = this.viewportTransform,\n      translateX = (vp[4] - (left || 0)) * multiplier,\n      translateY = (vp[5] - (top || 0)) * multiplier,\n      newVp = [newZoom, 0, 0, newZoom, translateX, translateY] as TMat2D,\n      originalRetina = this.enableRetinaScaling,\n      canvasEl = createCanvasElementFor({\n        width: scaledWidth,\n        height: scaledHeight,\n      }),\n      objectsToRender = filter\n        ? this._objects.filter((obj) => filter(obj))\n        : this._objects;\n    this.enableRetinaScaling = false;\n    this.viewportTransform = newVp;\n    this.width = scaledWidth;\n    this.height = scaledHeight;\n    this.skipControlsDrawing = true;\n    this.calcViewportBoundaries();\n    this.renderCanvas(canvasEl.getContext('2d')!, objectsToRender);\n    this.viewportTransform = vp;\n    this.width = originalWidth;\n    this.height = originalHeight;\n    this.calcViewportBoundaries();\n    this.enableRetinaScaling = originalRetina;\n    this.skipControlsDrawing = originalSkipControlsDrawing;\n    return canvasEl;\n  }\n\n  /**\n   * Waits until rendering has settled to destroy the canvas\n   * @returns {Promise<boolean>} a promise resolving to `true` once the canvas has been destroyed or to `false` if the canvas has was already destroyed\n   * @throws if aborted by a consequent call\n   */\n  dispose() {\n    !this.disposed &&\n      this.elements.cleanupDOM({ width: this.width, height: this.height });\n    runningAnimations.cancelByCanvas(this);\n    this.disposed = true;\n    return new Promise<boolean>((resolve, reject) => {\n      const task = () => {\n        this.destroy();\n        resolve(true);\n      };\n      task.kill = reject;\n      if (this.__cleanupTask) {\n        this.__cleanupTask.kill('aborted');\n      }\n\n      if (this.destroyed) {\n        resolve(false);\n      } else if (this.nextRenderHandle) {\n        this.__cleanupTask = task;\n      } else {\n        task();\n      }\n    });\n  }\n\n  /**\n   * Clears the canvas element, disposes objects and frees resources.\n   *\n   * Invoked as part of the **async** operation of {@link dispose}.\n   *\n   * **CAUTION**:\n   *\n   * This method is **UNSAFE**.\n   * You may encounter a race condition using it if there's a requested render.\n   * Call this method only if you are sure rendering has settled.\n   * Consider using {@link dispose} as it is **SAFE**\n   *\n   * @private\n   */\n  destroy() {\n    this.destroyed = true;\n    this.cancelRequestedRender();\n    this.forEachObject((object) => object.dispose());\n    this._objects = [];\n    if (this.backgroundImage) {\n      this.backgroundImage.dispose();\n    }\n    this.backgroundImage = undefined;\n    if (this.overlayImage) {\n      this.overlayImage.dispose();\n    }\n    this.overlayImage = undefined;\n    this.elements.dispose();\n  }\n\n  /**\n   * Returns a string representation of an instance\n   * @return {String} string representation of an instance\n   */\n  toString() {\n    return `#<Canvas (${this.complexity()}): { objects: ${\n      this._objects.length\n    } }>`;\n  }\n}\n"],"names":["StaticCanvas","createCollectionMixin","CommonMethods","lowerCanvasEl","_this$elements$lower","this","elements","lower","el","contextContainer","_this$elements$lower2","ctx","getDefaults","ownDefaults","constructor","options","arguments","length","undefined","super","Object","assign","set","initElements","_setDimensionsImpl","width","height","skipControlsDrawing","viewportTransform","calcViewportBoundaries","StaticCanvasDOMManager","add","size","renderOnAddRemove","requestRenderAll","insertAt","index","_len","objects","Array","_key","remove","removed","_onObjectAdded","obj","canvas","log","_set","setCoords","fire","target","_onObjectRemoved","_onStackOrderChanged","getRetinaScaling","enableRetinaScaling","getDevicePixelRatio","calcOffset","_offset","getWidth","getHeight","dimensions","cssOnly","backstoreOnly","setDimensions","hasLostContext","setCSSDimensions","getZoom","setViewportTransform","vpt","zoomToPoint","point","value","before","newPoint","transformPoint","invertTransform","after","x","y","setZoom","Point","absolutePan","relativePan","getElement","clearContext","clearRect","getContext","clear","getObjects","backgroundImage","overlayImage","backgroundColor","overlayColor","renderAll","cancelRequestedRender","destroyed","renderCanvas","_objects","renderAndReset","nextRenderHandle","disposed","requestAnimFrame","iVpt","a","b","min","max","vptCoords","tl","tr","bl","br","cancelAnimFrame","drawControls","_ctx","v","path","clipPath","imageSmoothingEnabled","patternQuality","_renderBackground","save","transform","_renderObjects","restore","controlsAboveOverlay","shouldCache","_transformDone","renderCache","forClipping","drawClipPathOnCanvas","_renderOverlay","__cleanupTask","globalCompositeOperation","scale","zoomX","zoomY","drawImage","_cacheCanvas","cacheTranslationX","cacheTranslationY","i","len","render","_renderBackgroundOrOverlay","property","fill","object","needsVpt","isAFiller","isFiller","beginPath","moveTo","lineTo","closePath","fillStyle","toLive","offsetX","offsetY","m","gradientTransform","patternTransform","skipOffscreen","getCenterPoint","centerObjectH","_centerObject","centerObjectV","centerObject","viewportCenterObject","getVpCenter","viewportCenterObjectH","viewportCenterObjectV","center","setXY","CENTER","toDatalessJSON","propertiesToInclude","toDatalessObject","toObject","_toObjectMethod","toJSON","methodName","clipPathData","excludeFromExport","_toObject","version","VERSION","pick","filter","map","instance","__serializeBgOverlay","originalValue","includeDefaultValues","data","bgImage","bgColor","background","overlay","toSVG","reviver","markup","_this$clipPath$clipPa","_setSVGPreamble","_setSVGHeader","push","escapeXml","clipPathId","_setSVGBgOverlayColor","_setSVGBgOverlayImage","_setSVGObjects","join","suppressPreamble","encoding","NUM_FRACTION_DIGITS","config","optViewBox","viewBox","svgViewportTransformation","toFixed","createSVGFontFacesMarkup","createSVGRefElementsMarkup","createSVGClipPathMarkup","uid","toClipPathSVG","prop","shouldTransform","isType","additionalTransform","matrixToSVG","fontList","fontPaths","forEach","isCollection","isTextObject","styles","fontFamily","values","styleRow","_ref","fontListMarkup","keys","forEachObject","fabricObject","_setSVGObject","bgOrOverlay","filler","repeat","finalWidth","finalHeight","isPattern","source","id","loadFromJSON","json","signal","Promise","reject","FabricError","serialized","JSON","parse","all","enlivenObjects","enlivenObjectEnlivables","then","_ref2","enlived","enlivedMap","clone","properties","cloneWithoutData","createCanvasElementFor","toDataURL","format","quality","multiplier","finalMultiplier","toCanvasElement","toBlob","left","top","scaledWidth","scaledHeight","zoom","originalWidth","originalHeight","originalSkipControlsDrawing","newZoom","vp","newVp","originalRetina","canvasEl","objectsToRender","dispose","cleanupDOM","runningAnimations","cancelByCanvas","resolve","task","destroy","kill","toString","complexity","_defineProperty","staticCanvasDefaults"],"mappings":"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"}