{"version":3,"file":"Image.min.mjs","sources":["../../../src/shapes/Image.ts"],"sourcesContent":["import { getFabricDocument, getEnv } from '../env';\nimport type { BaseFilter } from '../filters/BaseFilter';\nimport { getFilterBackend } from '../filters/FilterBackend';\nimport { SHARED_ATTRIBUTES } from '../parser/attributes';\nimport { parseAttributes } from '../parser/parseAttributes';\nimport type {\n  TClassProperties,\n  TCrossOrigin,\n  TSize,\n  Abortable,\n  TOptions,\n} from '../typedefs';\nimport { uid } from '../util/internals/uid';\nimport { createCanvasElement } from '../util/misc/dom';\nimport { findScaleToCover, findScaleToFit } from '../util/misc/findScaleTo';\nimport type { LoadImageOptions } from '../util/misc/objectEnlive';\nimport {\n  enlivenObjectEnlivables,\n  enlivenObjects,\n  loadImage,\n} from '../util/misc/objectEnlive';\nimport { parsePreserveAspectRatioAttribute } from '../util/misc/svgParsing';\nimport { classRegistry } from '../ClassRegistry';\nimport { FabricObject, cacheProperties } from './Object/FabricObject';\nimport type { FabricObjectProps, SerializedObjectProps } from './Object/types';\nimport type { ObjectEvents } from '../EventTypeDefs';\nimport { WebGLFilterBackend } from '../filters/WebGLFilterBackend';\nimport { NONE } from '../constants';\nimport { getDocumentFromElement } from '../util/dom_misc';\nimport type { CSSRules } from '../parser/typedefs';\nimport type { Resize } from '../filters/Resize';\nimport type { TCachedFabricObject } from './Object/Object';\nimport { log } from '../util/internals/console';\n\n// @todo Would be nice to have filtering code not imported directly.\n\nexport type ImageSource =\n  | HTMLImageElement\n  | HTMLVideoElement\n  | HTMLCanvasElement;\n\ninterface UniqueImageProps {\n  srcFromAttribute: boolean;\n  minimumScaleTrigger: number;\n  cropX: number;\n  cropY: number;\n  imageSmoothing: boolean;\n  filters: BaseFilter[];\n  resizeFilter?: Resize;\n}\n\nexport const imageDefaultValues: Partial<TClassProperties<FabricImage>> = {\n  strokeWidth: 0,\n  srcFromAttribute: false,\n  minimumScaleTrigger: 0.5,\n  cropX: 0,\n  cropY: 0,\n  imageSmoothing: true,\n};\n\nexport interface SerializedImageProps extends SerializedObjectProps {\n  src: string;\n  crossOrigin: TCrossOrigin;\n  filters: any[];\n  resizeFilter?: any;\n  cropX: number;\n  cropY: number;\n}\n\nexport interface ImageProps extends FabricObjectProps, UniqueImageProps {}\n\nconst IMAGE_PROPS = ['cropX', 'cropY'] as const;\n\n/**\n * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}\n */\nexport class FabricImage<\n    Props extends TOptions<ImageProps> = Partial<ImageProps>,\n    SProps extends SerializedImageProps = SerializedImageProps,\n    EventSpec extends ObjectEvents = ObjectEvents\n  >\n  extends FabricObject<Props, SProps, EventSpec>\n  implements ImageProps\n{\n  /**\n   * When calling {@link FabricImage.getSrc}, return value from element src with `element.getAttribute('src')`.\n   * This allows for relative urls as image src.\n   * @since 2.7.0\n   * @type Boolean\n   * @default false\n   */\n  declare srcFromAttribute: boolean;\n\n  /**\n   * private\n   * contains last value of scaleX to detect\n   * if the Image got resized after the last Render\n   * @type Number\n   */\n  protected _lastScaleX = 1;\n\n  /**\n   * private\n   * contains last value of scaleY to detect\n   * if the Image got resized after the last Render\n   * @type Number\n   */\n  protected _lastScaleY = 1;\n\n  /**\n   * private\n   * contains last value of scaling applied by the apply filter chain\n   * @type Number\n   */\n  protected _filterScalingX = 1;\n\n  /**\n   * private\n   * contains last value of scaling applied by the apply filter chain\n   * @type Number\n   */\n  protected _filterScalingY = 1;\n\n  /**\n   * minimum scale factor under which any resizeFilter is triggered to resize the image\n   * 0 will disable the automatic resize. 1 will trigger automatically always.\n   * number bigger than 1 are not implemented yet.\n   * @type Number\n   */\n  declare minimumScaleTrigger: number;\n\n  /**\n   * key used to retrieve the texture representing this image\n   * @since 2.0.0\n   * @type String\n   * @default\n   */\n  declare cacheKey: string;\n\n  /**\n   * Image crop in pixels from original image size.\n   * @since 2.0.0\n   * @type Number\n   * @default\n   */\n  declare cropX: number;\n\n  /**\n   * Image crop in pixels from original image size.\n   * @since 2.0.0\n   * @type Number\n   * @default\n   */\n  declare cropY: number;\n\n  /**\n   * Indicates whether this canvas will use image smoothing when painting this image.\n   * Also influence if the cacheCanvas for this image uses imageSmoothing\n   * @since 4.0.0-beta.11\n   * @type Boolean\n   * @default\n   */\n  declare imageSmoothing: boolean;\n\n  declare preserveAspectRatio: string;\n\n  protected declare src: string;\n\n  declare filters: BaseFilter[];\n  declare resizeFilter: Resize;\n\n  declare _element: ImageSource;\n  declare _filteredEl?: HTMLCanvasElement;\n  declare _originalElement: ImageSource;\n\n  static type = 'Image';\n\n  static cacheProperties = [...cacheProperties, ...IMAGE_PROPS];\n\n  static ownDefaults = imageDefaultValues;\n\n  static getDefaults(): Record<string, any> {\n    return {\n      ...super.getDefaults(),\n      ...FabricImage.ownDefaults,\n    };\n  }\n  /**\n   * Constructor\n   * Image can be initialized with any canvas drawable or a string.\n   * The string should be a url and will be loaded as an image.\n   * Canvas and Image element work out of the box, while videos require extra code to work.\n   * Please check video element events for seeking.\n   * @param {ImageSource | string} element Image element\n   * @param {Object} [options] Options object\n   */\n  constructor(elementId: string, options?: Props);\n  constructor(element: ImageSource, options?: Props);\n  constructor(arg0: ImageSource | string, options: Props = {} as Props) {\n    super({ filters: [], ...options });\n    this.cacheKey = `texture${uid()}`;\n    this.setElement(\n      typeof arg0 === 'string'\n        ? ((\n            (this.canvas && getDocumentFromElement(this.canvas.getElement())) ||\n            getFabricDocument()\n          ).getElementById(arg0) as ImageSource)\n        : arg0,\n      options\n    );\n  }\n\n  /**\n   * Returns image element which this instance if based on\n   */\n  getElement() {\n    return this._element;\n  }\n\n  /**\n   * Sets image element for this instance to a specified one.\n   * If filters defined they are applied to new image.\n   * You might need to call `canvas.renderAll` and `object.setCoords` after replacing, to render new image and update controls area.\n   * @param {HTMLImageElement} element\n   * @param {Partial<TSize>} [size] Options object\n   */\n  setElement(element: ImageSource, size: Partial<TSize> = {}) {\n    this.removeTexture(this.cacheKey);\n    this.removeTexture(`${this.cacheKey}_filtered`);\n    this._element = element;\n    this._originalElement = element;\n    this._setWidthHeight(size);\n    // element.classList.add(FabricImage.CSS_CANVAS);\n    if (this.filters.length !== 0) {\n      this.applyFilters();\n    }\n    // resizeFilters work on the already filtered copy.\n    // we need to apply resizeFilters AFTER normal filters.\n    // applyResizeFilters is run more often than normal filters\n    // and is triggered by user interactions rather than dev code\n    if (this.resizeFilter) {\n      this.applyResizeFilters();\n    }\n  }\n\n  /**\n   * Delete a single texture if in webgl mode\n   */\n  removeTexture(key: string) {\n    const backend = getFilterBackend(false);\n    if (backend instanceof WebGLFilterBackend) {\n      backend.evictCachesForKey(key);\n    }\n  }\n\n  /**\n   * Delete textures, reference to elements and eventually JSDOM cleanup\n   */\n  dispose() {\n    super.dispose();\n    this.removeTexture(this.cacheKey);\n    this.removeTexture(`${this.cacheKey}_filtered`);\n    this._cacheContext = null;\n    (\n      ['_originalElement', '_element', '_filteredEl', '_cacheCanvas'] as const\n    ).forEach((elementKey) => {\n      const el = this[elementKey];\n      el && getEnv().dispose(el);\n      // @ts-expect-error disposing\n      this[elementKey] = undefined;\n    });\n  }\n\n  /**\n   * Get the crossOrigin value (of the corresponding image element)\n   */\n  getCrossOrigin(): string | null {\n    return (\n      this._originalElement &&\n      ((this._originalElement as any).crossOrigin || null)\n    );\n  }\n\n  /**\n   * Returns original size of an image\n   */\n  getOriginalSize() {\n    const element = this.getElement() as any;\n    if (!element) {\n      return {\n        width: 0,\n        height: 0,\n      };\n    }\n    return {\n      width: element.naturalWidth || element.width,\n      height: element.naturalHeight || element.height,\n    };\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  _stroke(ctx: CanvasRenderingContext2D) {\n    if (!this.stroke || this.strokeWidth === 0) {\n      return;\n    }\n    const w = this.width / 2,\n      h = this.height / 2;\n    ctx.beginPath();\n    ctx.moveTo(-w, -h);\n    ctx.lineTo(w, -h);\n    ctx.lineTo(w, h);\n    ctx.lineTo(-w, h);\n    ctx.lineTo(-w, -h);\n    ctx.closePath();\n  }\n\n  /**\n   * Returns object representation of an instance\n   * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n   * @return {Object} Object representation of an instance\n   */\n  toObject<\n    T extends Omit<Props & TClassProperties<this>, keyof SProps>,\n    K extends keyof T = never\n  >(propertiesToInclude: K[] = []): Pick<T, K> & SProps {\n    const filters: Record<string, any>[] = [];\n    this.filters.forEach((filterObj) => {\n      filterObj && filters.push(filterObj.toObject());\n    });\n    return {\n      ...super.toObject([...IMAGE_PROPS, ...propertiesToInclude]),\n      src: this.getSrc(),\n      crossOrigin: this.getCrossOrigin(),\n      filters,\n      ...(this.resizeFilter\n        ? { resizeFilter: this.resizeFilter.toObject() }\n        : {}),\n    };\n  }\n\n  /**\n   * Returns true if an image has crop applied, inspecting values of cropX,cropY,width,height.\n   * @return {Boolean}\n   */\n  hasCrop() {\n    return (\n      !!this.cropX ||\n      !!this.cropY ||\n      this.width < this._element.width ||\n      this.height < this._element.height\n    );\n  }\n\n  /**\n   * Returns svg representation of an instance\n   * @return {string[]} an array of strings with the specific svg representation\n   * of the instance\n   */\n  _toSVG() {\n    const imageMarkup: string[] = [],\n      element = this._element,\n      x = -this.width / 2,\n      y = -this.height / 2;\n    let svgString: string[] = [],\n      strokeSvg: string[] = [],\n      clipPath = '',\n      imageRendering = '';\n    if (!element) {\n      return [];\n    }\n    if (this.hasCrop()) {\n      const clipPathId = uid();\n      svgString.push(\n        '<clipPath id=\"imageCrop_' + clipPathId + '\">\\n',\n        '\\t<rect x=\"' +\n          x +\n          '\" y=\"' +\n          y +\n          '\" width=\"' +\n          this.width +\n          '\" height=\"' +\n          this.height +\n          '\" />\\n',\n        '</clipPath>\\n'\n      );\n      clipPath = ' clip-path=\"url(#imageCrop_' + clipPathId + ')\" ';\n    }\n    if (!this.imageSmoothing) {\n      imageRendering = ' image-rendering=\"optimizeSpeed\"';\n    }\n    imageMarkup.push(\n      '\\t<image ',\n      'COMMON_PARTS',\n      `xlink:href=\"${this.getSvgSrc(true)}\" x=\"${x - this.cropX}\" y=\"${\n        y - this.cropY\n        // we're essentially moving origin of transformation from top/left corner to the center of the shape\n        // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left\n        // so that object's center aligns with container's left/top\n      }\" width=\"${\n        element.width || (element as HTMLImageElement).naturalWidth\n      }\" height=\"${\n        element.height || (element as HTMLImageElement).naturalHeight\n      }\"${imageRendering}${clipPath}></image>\\n`\n    );\n\n    if (this.stroke || this.strokeDashArray) {\n      const origFill = this.fill;\n      this.fill = null;\n      strokeSvg = [\n        `\\t<rect x=\"${x}\" y=\"${y}\" width=\"${this.width}\" height=\"${\n          this.height\n        }\" style=\"${this.getSvgStyles()}\" />\\n`,\n      ];\n      this.fill = origFill;\n    }\n    if (this.paintFirst !== 'fill') {\n      svgString = svgString.concat(strokeSvg, imageMarkup);\n    } else {\n      svgString = svgString.concat(imageMarkup, strokeSvg);\n    }\n    return svgString;\n  }\n\n  /**\n   * Returns source of an image\n   * @param {Boolean} filtered indicates if the src is needed for svg\n   * @return {String} Source of an image\n   */\n  getSrc(filtered?: boolean): string {\n    const element = filtered ? this._element : this._originalElement;\n    if (element) {\n      if ((element as HTMLCanvasElement).toDataURL) {\n        return (element as HTMLCanvasElement).toDataURL();\n      }\n\n      if (this.srcFromAttribute) {\n        return element.getAttribute('src') || '';\n      } else {\n        return (element as HTMLImageElement).src;\n      }\n    } else {\n      return this.src || '';\n    }\n  }\n\n  /**\n   * Alias for getSrc\n   * @param filtered\n   * @deprecated\n   */\n  getSvgSrc(filtered?: boolean) {\n    return this.getSrc(filtered);\n  }\n\n  /**\n   * Loads and sets source of an image\\\n   * **IMPORTANT**: It is recommended to abort loading tasks before calling this method to prevent race conditions and unnecessary networking\n   * @param {String} src Source string (URL)\n   * @param {LoadImageOptions} [options] Options object\n   */\n  setSrc(src: string, { crossOrigin, signal }: LoadImageOptions = {}) {\n    return loadImage(src, { crossOrigin, signal }).then((img) => {\n      typeof crossOrigin !== 'undefined' && this.set({ crossOrigin });\n      this.setElement(img);\n    });\n  }\n\n  /**\n   * Returns string representation of an instance\n   * @return {String} String representation of an instance\n   */\n  toString() {\n    return `#<Image: { src: \"${this.getSrc()}\" }>`;\n  }\n\n  applyResizeFilters() {\n    const filter = this.resizeFilter,\n      minimumScale = this.minimumScaleTrigger,\n      objectScale = this.getTotalObjectScaling(),\n      scaleX = objectScale.x,\n      scaleY = objectScale.y,\n      elementToFilter = this._filteredEl || this._originalElement;\n    if (this.group) {\n      this.set('dirty', true);\n    }\n    if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {\n      this._element = elementToFilter;\n      this._filterScalingX = 1;\n      this._filterScalingY = 1;\n      this._lastScaleX = scaleX;\n      this._lastScaleY = scaleY;\n      return;\n    }\n    const canvasEl = createCanvasElement(),\n      sourceWidth = elementToFilter.width,\n      sourceHeight = elementToFilter.height;\n    canvasEl.width = sourceWidth;\n    canvasEl.height = sourceHeight;\n    this._element = canvasEl;\n    this._lastScaleX = filter.scaleX = scaleX;\n    this._lastScaleY = filter.scaleY = scaleY;\n    getFilterBackend().applyFilters(\n      [filter as BaseFilter],\n      elementToFilter,\n      sourceWidth,\n      sourceHeight,\n      this._element\n    );\n    this._filterScalingX = canvasEl.width / this._originalElement.width;\n    this._filterScalingY = canvasEl.height / this._originalElement.height;\n  }\n\n  /**\n   * Applies filters assigned to this image (from \"filters\" array) or from filter param\n   * @method applyFilters\n   * @param {Array} filters to be applied\n   * @param {Boolean} forResizing specify if the filter operation is a resize operation\n   */\n  applyFilters(filters: BaseFilter[] = this.filters || []) {\n    filters = filters.filter((filter) => filter && !filter.isNeutralState());\n    this.set('dirty', true);\n\n    // needs to clear out or WEBGL will not resize correctly\n    this.removeTexture(`${this.cacheKey}_filtered`);\n\n    if (filters.length === 0) {\n      this._element = this._originalElement;\n      // this is unsafe and needs to be rethinkend\n      this._filteredEl = undefined;\n      this._filterScalingX = 1;\n      this._filterScalingY = 1;\n      return;\n    }\n\n    const imgElement = this._originalElement,\n      sourceWidth =\n        (imgElement as HTMLImageElement).naturalWidth || imgElement.width,\n      sourceHeight =\n        (imgElement as HTMLImageElement).naturalHeight || imgElement.height;\n\n    if (this._element === this._originalElement) {\n      // if the _element a reference to _originalElement\n      // we need to create a new element to host the filtered pixels\n      const canvasEl = createCanvasElement();\n      canvasEl.width = sourceWidth;\n      canvasEl.height = sourceHeight;\n      this._element = canvasEl;\n      this._filteredEl = canvasEl;\n    } else if (this._filteredEl) {\n      // if the _element is it own element,\n      // and we also have a _filteredEl, then we clean up _filteredEl\n      // and we assign it to _element.\n      // in this way we invalidate the eventual old resize filtered element\n      this._element = this._filteredEl;\n      this._filteredEl\n        .getContext('2d')!\n        .clearRect(0, 0, sourceWidth, sourceHeight);\n      // we also need to resize again at next renderAll, so remove saved _lastScaleX/Y\n      this._lastScaleX = 1;\n      this._lastScaleY = 1;\n    }\n    getFilterBackend().applyFilters(\n      filters,\n      this._originalElement,\n      sourceWidth,\n      sourceHeight,\n      this._element as HTMLCanvasElement\n    );\n    if (\n      this._originalElement.width !== this._element.width ||\n      this._originalElement.height !== this._element.height\n    ) {\n      this._filterScalingX = this._element.width / this._originalElement.width;\n      this._filterScalingY =\n        this._element.height / this._originalElement.height;\n    }\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  _render(ctx: CanvasRenderingContext2D) {\n    ctx.imageSmoothingEnabled = this.imageSmoothing;\n    if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {\n      this.applyResizeFilters();\n    }\n    this._stroke(ctx);\n    this._renderPaintInOrder(ctx);\n  }\n\n  /**\n   * Paint the cached copy of the object on the target context.\n   * it will set the imageSmoothing for the draw operation\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   */\n  drawCacheOnCanvas(\n    this: TCachedFabricObject<FabricImage>,\n    ctx: CanvasRenderingContext2D\n  ) {\n    ctx.imageSmoothingEnabled = this.imageSmoothing;\n    // cant use ts-expect-error because of ts 5.3 cross check\n    // @ts-ignore TS doesn't respect this type casting\n    super.drawCacheOnCanvas(ctx);\n  }\n\n  /**\n   * Decide if the object should cache or not. Create its own cache level\n   * needsItsOwnCache should be used when the object drawing method requires\n   * a cache step. None of the fabric classes requires it.\n   * Generally you do not cache objects in groups because the group outside is cached.\n   * This is the special image version where we would like to avoid caching where possible.\n   * Essentially images do not benefit from caching. They may require caching, and in that\n   * case we do it. Also caching an image usually ends in a loss of details.\n   * A full performance audit should be done.\n   * @return {Boolean}\n   */\n  shouldCache() {\n    return this.needsItsOwnCache();\n  }\n\n  _renderFill(ctx: CanvasRenderingContext2D) {\n    const elementToDraw = this._element;\n    if (!elementToDraw) {\n      return;\n    }\n    const scaleX = this._filterScalingX,\n      scaleY = this._filterScalingY,\n      w = this.width,\n      h = this.height,\n      // crop values cannot be lesser than 0.\n      cropX = Math.max(this.cropX, 0),\n      cropY = Math.max(this.cropY, 0),\n      elWidth =\n        (elementToDraw as HTMLImageElement).naturalWidth || elementToDraw.width,\n      elHeight =\n        (elementToDraw as HTMLImageElement).naturalHeight ||\n        elementToDraw.height,\n      sX = cropX * scaleX,\n      sY = cropY * scaleY,\n      // the width height cannot exceed element width/height, starting from the crop offset.\n      sW = Math.min(w * scaleX, elWidth - sX),\n      sH = Math.min(h * scaleY, elHeight - sY),\n      x = -w / 2,\n      y = -h / 2,\n      maxDestW = Math.min(w, elWidth / scaleX - cropX),\n      maxDestH = Math.min(h, elHeight / scaleY - cropY);\n\n    elementToDraw &&\n      ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, maxDestW, maxDestH);\n  }\n\n  /**\n   * needed to check if image needs resize\n   * @private\n   */\n  _needsResize() {\n    const scale = this.getTotalObjectScaling();\n    return scale.x !== this._lastScaleX || scale.y !== this._lastScaleY;\n  }\n\n  /**\n   * @private\n   * @deprecated unused\n   */\n  _resetWidthHeight() {\n    this.set(this.getOriginalSize());\n  }\n\n  /**\n   * @private\n   * Set the width and the height of the image object, using the element or the\n   * options.\n   */\n  _setWidthHeight({ width, height }: Partial<TSize> = {}) {\n    const size = this.getOriginalSize();\n    this.width = width || size.width;\n    this.height = height || size.height;\n  }\n\n  /**\n   * Calculate offset for center and scale factor for the image in order to respect\n   * the preserveAspectRatio attribute\n   * @private\n   */\n  parsePreserveAspectRatioAttribute() {\n    const pAR = parsePreserveAspectRatioAttribute(\n        this.preserveAspectRatio || ''\n      ),\n      pWidth = this.width,\n      pHeight = this.height,\n      parsedAttributes = { width: pWidth, height: pHeight };\n    let rWidth = this._element.width,\n      rHeight = this._element.height,\n      scaleX = 1,\n      scaleY = 1,\n      offsetLeft = 0,\n      offsetTop = 0,\n      cropX = 0,\n      cropY = 0,\n      offset;\n\n    if (pAR && (pAR.alignX !== NONE || pAR.alignY !== NONE)) {\n      if (pAR.meetOrSlice === 'meet') {\n        scaleX = scaleY = findScaleToFit(this._element, parsedAttributes);\n        offset = (pWidth - rWidth * scaleX) / 2;\n        if (pAR.alignX === 'Min') {\n          offsetLeft = -offset;\n        }\n        if (pAR.alignX === 'Max') {\n          offsetLeft = offset;\n        }\n        offset = (pHeight - rHeight * scaleY) / 2;\n        if (pAR.alignY === 'Min') {\n          offsetTop = -offset;\n        }\n        if (pAR.alignY === 'Max') {\n          offsetTop = offset;\n        }\n      }\n      if (pAR.meetOrSlice === 'slice') {\n        scaleX = scaleY = findScaleToCover(this._element, parsedAttributes);\n        offset = rWidth - pWidth / scaleX;\n        if (pAR.alignX === 'Mid') {\n          cropX = offset / 2;\n        }\n        if (pAR.alignX === 'Max') {\n          cropX = offset;\n        }\n        offset = rHeight - pHeight / scaleY;\n        if (pAR.alignY === 'Mid') {\n          cropY = offset / 2;\n        }\n        if (pAR.alignY === 'Max') {\n          cropY = offset;\n        }\n        rWidth = pWidth / scaleX;\n        rHeight = pHeight / scaleY;\n      }\n    } else {\n      scaleX = pWidth / rWidth;\n      scaleY = pHeight / rHeight;\n    }\n    return {\n      width: rWidth,\n      height: rHeight,\n      scaleX,\n      scaleY,\n      offsetLeft,\n      offsetTop,\n      cropX,\n      cropY,\n    };\n  }\n\n  /**\n   * Default CSS class name for canvas\n   * @static\n   * @type String\n   * @default\n   */\n  static CSS_CANVAS = 'canvas-img';\n\n  /**\n   * List of attribute names to account for when parsing SVG element (used by {@link FabricImage.fromElement})\n   * @static\n   * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}\n   */\n  static ATTRIBUTE_NAMES = [\n    ...SHARED_ATTRIBUTES,\n    'x',\n    'y',\n    'width',\n    'height',\n    'preserveAspectRatio',\n    'xlink:href',\n    'crossOrigin',\n    'image-rendering',\n  ];\n\n  /**\n   * Creates an instance of FabricImage from its object representation\n   * @static\n   * @param {Object} object Object to create an instance from\n   * @param {object} [options] Options object\n   * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n   * @returns {Promise<FabricImage>}\n   */\n  static fromObject<T extends TOptions<SerializedImageProps>>(\n    { filters: f, resizeFilter: rf, src, crossOrigin, type, ...object }: T,\n    options?: Abortable\n  ) {\n    return Promise.all([\n      loadImage(src!, { ...options, crossOrigin }),\n      f && enlivenObjects<BaseFilter>(f, options),\n      // TODO: redundant - handled by enlivenObjectEnlivables\n      rf && enlivenObjects<BaseFilter>([rf], options),\n      enlivenObjectEnlivables(object, options),\n    ]).then(([el, filters = [], [resizeFilter] = [], hydratedProps = {}]) => {\n      return new this(el, {\n        ...object,\n        // TODO: this creates a difference between image creation and restoring from JSON\n        src,\n        filters,\n        resizeFilter,\n        ...hydratedProps,\n      });\n    });\n  }\n\n  /**\n   * Creates an instance of Image from an URL string\n   * @static\n   * @param {String} url URL to create an image from\n   * @param {LoadImageOptions} [options] Options object\n   * @returns {Promise<FabricImage>}\n   */\n  static fromURL<T extends TOptions<ImageProps>>(\n    url: string,\n    { crossOrigin = null, signal }: LoadImageOptions = {},\n    imageOptions?: T\n  ): Promise<FabricImage> {\n    return loadImage(url, { crossOrigin, signal }).then(\n      (img) => new this(img, imageOptions)\n    );\n  }\n\n  /**\n   * Returns {@link FabricImage} instance from an SVG element\n   * @static\n   * @param {HTMLElement} element Element to parse\n   * @param {Object} [options] Options object\n   * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n   * @param {Function} callback Callback to execute when Image object is created\n   */\n  static async fromElement(\n    element: HTMLElement,\n    options: Abortable = {},\n    cssRules?: CSSRules\n  ) {\n    const parsedAttributes = parseAttributes(\n      element,\n      this.ATTRIBUTE_NAMES,\n      cssRules\n    );\n    return this.fromURL(\n      parsedAttributes['xlink:href'],\n      options,\n      parsedAttributes\n    ).catch((err) => {\n      log('log', 'Unable to parse Image', err);\n      return null;\n    });\n  }\n}\n\nclassRegistry.setClass(FabricImage);\nclassRegistry.setSVGClass(FabricImage);\n"],"names":["imageDefaultValues","strokeWidth","srcFromAttribute","minimumScaleTrigger","cropX","cropY","imageSmoothing","IMAGE_PROPS","FabricImage","FabricObject","getDefaults","_objectSpread","super","ownDefaults","constructor","arg0","options","arguments","length","undefined","filters","_defineProperty","this","cacheKey","concat","uid","setElement","canvas","getDocumentFromElement","getElement","getFabricDocument","getElementById","_element","element","size","removeTexture","_originalElement","_setWidthHeight","applyFilters","resizeFilter","applyResizeFilters","key","backend","getFilterBackend","WebGLFilterBackend","evictCachesForKey","dispose","_cacheContext","forEach","elementKey","el","getEnv","getCrossOrigin","crossOrigin","getOriginalSize","width","naturalWidth","height","naturalHeight","_stroke","ctx","stroke","w","h","beginPath","moveTo","lineTo","closePath","toObject","propertiesToInclude","filterObj","push","src","getSrc","hasCrop","_toSVG","imageMarkup","x","y","svgString","strokeSvg","clipPath","imageRendering","clipPathId","getSvgSrc","strokeDashArray","origFill","fill","getSvgStyles","paintFirst","filtered","toDataURL","getAttribute","setSrc","signal","loadImage","then","img","set","toString","filter","minimumScale","objectScale","getTotalObjectScaling","scaleX","scaleY","elementToFilter","_filteredEl","group","_filterScalingX","_filterScalingY","_lastScaleX","_lastScaleY","canvasEl","createCanvasElement","sourceWidth","sourceHeight","isNeutralState","imgElement","getContext","clearRect","_render","imageSmoothingEnabled","isMoving","_needsResize","_renderPaintInOrder","drawCacheOnCanvas","shouldCache","needsItsOwnCache","_renderFill","elementToDraw","Math","max","elWidth","elHeight","sX","sY","sW","min","sH","maxDestW","maxDestH","drawImage","scale","_resetWidthHeight","parsePreserveAspectRatioAttribute","pAR","preserveAspectRatio","pWidth","pHeight","parsedAttributes","offset","rWidth","rHeight","offsetLeft","offsetTop","alignX","NONE","alignY","meetOrSlice","findScaleToFit","findScaleToCover","fromObject","_ref","f","rf","type","object","_objectWithoutProperties","_excluded","Promise","all","enlivenObjects","enlivenObjectEnlivables","_ref2","hydratedProps","fromURL","url","imageOptions","fromElement","cssRules","parseAttributes","ATTRIBUTE_NAMES","catch","err","log","cacheProperties","SHARED_ATTRIBUTES","classRegistry","setClass","setSVGClass"],"mappings":"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"}