{"version":3,"file":"FabricObjectSVGExportMixin.min.mjs","sources":["../../../../src/shapes/Object/FabricObjectSVGExportMixin.ts"],"sourcesContent":["import type { TSVGReviver } from '../../typedefs';\nimport { uid } from '../../util/internals/uid';\nimport { colorPropToSVG, matrixToSVG } from '../../util/misc/svgParsing';\nimport { FILL, NONE, STROKE } from '../../constants';\nimport type { FabricObject } from './FabricObject';\nimport { isFiller } from '../../util/typeAssertions';\n\nexport class FabricObjectSVGExportMixin {\n  /**\n   * When an object is being exported as SVG as a clippath, a reference inside the SVG is needed.\n   * This reference is a UID in the fabric namespace and is temporary stored here.\n   * @type {String}\n   */\n  declare clipPathId?: string;\n\n  /**\n   * Returns styles-string for svg-export\n   * @param {Boolean} skipShadow a boolean to skip shadow filter output\n   * @return {String}\n   */\n  getSvgStyles(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    skipShadow?: boolean\n  ) {\n    const fillRule = this.fillRule ? this.fillRule : 'nonzero',\n      strokeWidth = this.strokeWidth ? this.strokeWidth : '0',\n      strokeDashArray = this.strokeDashArray\n        ? this.strokeDashArray.join(' ')\n        : NONE,\n      strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',\n      strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',\n      strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',\n      strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',\n      opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',\n      visibility = this.visible ? '' : ' visibility: hidden;',\n      filter = skipShadow ? '' : this.getSvgFilter(),\n      fill = colorPropToSVG(FILL, this.fill),\n      stroke = colorPropToSVG(STROKE, this.stroke);\n\n    return [\n      stroke,\n      'stroke-width: ',\n      strokeWidth,\n      '; ',\n      'stroke-dasharray: ',\n      strokeDashArray,\n      '; ',\n      'stroke-linecap: ',\n      strokeLineCap,\n      '; ',\n      'stroke-dashoffset: ',\n      strokeDashOffset,\n      '; ',\n      'stroke-linejoin: ',\n      strokeLineJoin,\n      '; ',\n      'stroke-miterlimit: ',\n      strokeMiterLimit,\n      '; ',\n      fill,\n      'fill-rule: ',\n      fillRule,\n      '; ',\n      'opacity: ',\n      opacity,\n      ';',\n      filter,\n      visibility,\n    ].join('');\n  }\n\n  /**\n   * Returns filter for svg shadow\n   * @return {String}\n   */\n  getSvgFilter(this: FabricObjectSVGExportMixin & FabricObject) {\n    return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';\n  }\n\n  /**\n   * Returns id attribute for svg output\n   * @return {String}\n   */\n  getSvgCommons(\n    this: FabricObjectSVGExportMixin & FabricObject & { id?: string }\n  ) {\n    return [\n      this.id ? `id=\"${this.id}\" ` : '',\n      this.clipPath\n        ? `clip-path=\"url(#${\n            (this.clipPath as FabricObjectSVGExportMixin & FabricObject)\n              .clipPathId\n          })\" `\n        : '',\n    ].join('');\n  }\n\n  /**\n   * Returns transform-string for svg-export\n   * @param {Boolean} use the full transform or the single object one.\n   * @return {String}\n   */\n  getSvgTransform(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    full?: boolean,\n    additionalTransform = ''\n  ) {\n    const transform = full ? this.calcTransformMatrix() : this.calcOwnMatrix(),\n      svgTransform = `transform=\"${matrixToSVG(transform)}`;\n    return `${svgTransform}${additionalTransform}\" `;\n  }\n\n  /**\n   * Returns svg representation of an instance\n   * This function is implemented in each subclass\n   * This is just because typescript otherwise cryies all the time\n   * @return {Array} an array of strings with the specific svg representation\n   * of the instance\n   */\n  _toSVG(reviver?: TSVGReviver): string[] {\n    return [''];\n  }\n\n  /**\n   * Returns svg representation of an instance\n   * @param {TSVGReviver} [reviver] Method for further parsing of svg representation.\n   * @return {String} svg representation of an instance\n   */\n  toSVG(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    reviver?: TSVGReviver\n  ) {\n    return this._createBaseSVGMarkup(this._toSVG(reviver), {\n      reviver,\n    });\n  }\n\n  /**\n   * Returns svg clipPath representation of an instance\n   * @param {TSVGReviver} [reviver] Method for further parsing of svg representation.\n   * @return {String} svg representation of an instance\n   */\n  toClipPathSVG(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    reviver?: TSVGReviver\n  ) {\n    return (\n      '\\t' +\n      this._createBaseClipPathSVGMarkup(this._toSVG(reviver), {\n        reviver,\n      })\n    );\n  }\n\n  /**\n   * @private\n   */\n  _createBaseClipPathSVGMarkup(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    objectMarkup: string[],\n    {\n      reviver,\n      additionalTransform = '',\n    }: { reviver?: TSVGReviver; additionalTransform?: string } = {}\n  ) {\n    const commonPieces = [\n        this.getSvgTransform(true, additionalTransform),\n        this.getSvgCommons(),\n      ].join(''),\n      // insert commons in the markup, style and svgCommons\n      index = objectMarkup.indexOf('COMMON_PARTS');\n    objectMarkup[index] = commonPieces;\n    return reviver ? reviver(objectMarkup.join('')) : objectMarkup.join('');\n  }\n\n  /**\n   * @private\n   */\n  _createBaseSVGMarkup(\n    this: FabricObjectSVGExportMixin & FabricObject,\n    objectMarkup: string[],\n    {\n      noStyle,\n      reviver,\n      withShadow,\n      additionalTransform,\n    }: {\n      noStyle?: boolean;\n      reviver?: TSVGReviver;\n      withShadow?: boolean;\n      additionalTransform?: string;\n    } = {}\n  ): string {\n    const styleInfo = noStyle ? '' : `style=\"${this.getSvgStyles()}\" `,\n      shadowInfo = withShadow ? `style=\"${this.getSvgFilter()}\" ` : '',\n      clipPath = this.clipPath as FabricObjectSVGExportMixin & FabricObject,\n      vectorEffect = this.strokeUniform\n        ? 'vector-effect=\"non-scaling-stroke\" '\n        : '',\n      absoluteClipPath = clipPath && clipPath.absolutePositioned,\n      stroke = this.stroke,\n      fill = this.fill,\n      shadow = this.shadow,\n      markup = [],\n      // insert commons in the markup, style and svgCommons\n      index = objectMarkup.indexOf('COMMON_PARTS');\n    let clipPathMarkup;\n    if (clipPath) {\n      clipPath.clipPathId = `CLIPPATH_${uid()}`;\n      clipPathMarkup = `<clipPath id=\"${\n        clipPath.clipPathId\n      }\" >\\n${clipPath.toClipPathSVG(reviver)}</clipPath>\\n`;\n    }\n    if (absoluteClipPath) {\n      markup.push('<g ', shadowInfo, this.getSvgCommons(), ' >\\n');\n    }\n    markup.push(\n      '<g ',\n      this.getSvgTransform(false),\n      !absoluteClipPath ? shadowInfo + this.getSvgCommons() : '',\n      ' >\\n'\n    );\n    const commonPieces = [\n      styleInfo,\n      vectorEffect,\n      noStyle ? '' : this.addPaintOrder(),\n      ' ',\n      additionalTransform ? `transform=\"${additionalTransform}\" ` : '',\n    ].join('');\n    objectMarkup[index] = commonPieces;\n    if (isFiller(fill)) {\n      markup.push(fill.toSVG(this));\n    }\n    if (isFiller(stroke)) {\n      markup.push(stroke.toSVG(this));\n    }\n    if (shadow) {\n      markup.push(shadow.toSVG(this));\n    }\n    if (clipPath) {\n      markup.push(clipPathMarkup);\n    }\n    markup.push(objectMarkup.join(''));\n    markup.push('</g>\\n');\n    absoluteClipPath && markup.push('</g>\\n');\n    return reviver ? reviver(markup.join('')) : markup.join('');\n  }\n\n  addPaintOrder(this: FabricObjectSVGExportMixin & FabricObject) {\n    return this.paintFirst !== FILL ? ` paint-order=\"${this.paintFirst}\" ` : '';\n  }\n}\n"],"names":["FabricObjectSVGExportMixin","getSvgStyles","skipShadow","fillRule","this","strokeWidth","strokeDashArray","join","NONE","strokeDashOffset","strokeLineCap","strokeLineJoin","strokeMiterLimit","opacity","visibility","visible","filter","getSvgFilter","fill","colorPropToSVG","FILL","STROKE","stroke","shadow","concat","id","getSvgCommons","clipPath","clipPathId","getSvgTransform","full","additionalTransform","arguments","length","undefined","transform","calcTransformMatrix","calcOwnMatrix","svgTransform","matrixToSVG","_toSVG","reviver","toSVG","_createBaseSVGMarkup","toClipPathSVG","_createBaseClipPathSVGMarkup","objectMarkup","commonPieces","index","indexOf","noStyle","withShadow","styleInfo","shadowInfo","vectorEffect","strokeUniform","absoluteClipPath","absolutePositioned","markup","clipPathMarkup","uid","push","addPaintOrder","isFiller","paintFirst"],"mappings":"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"}