{"version":3,"file":"FabricObjectSVGExportMixin.mjs","names":[],"sources":["../../../../src/shapes/Object/FabricObjectSVGExportMixin.ts"],"sourcesContent":["import type { TSVGReviver } from '../../typedefs';\nimport { uid } from '../../util/internals/uid';\nimport { colorPropToSVG } from '../../util/misc/svgParsing';\nimport { FILL, NONE, STROKE } from '../../constants';\nimport type { FabricObject } from './FabricObject';\nimport { isFiller } from '../../util/typeAssertions';\nimport { matrixToSVG } from '../../util/misc/svgExport';\nimport { escapeXml } from '../../util/lang_string';\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    ]\n      .map((v) => escapeXml(v))\n      .join('');\n  }\n\n  /**\n   * Returns filter for svg shadow\n   * @return {String}\n   */\n  getSvgFilter(this: FabricObjectSVGExportMixin & FabricObject) {\n    return this.shadow\n      ? `filter: url(#SVGID_${escapeXml(this.shadow.id)});`\n      : '';\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=\"${escapeXml(String(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\n      ? ` paint-order=\"${escapeXml(this.paintFirst)}\" `\n      : '';\n  }\n}\n"],"mappings":"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"}