{"version":3,"file":"TextSVGExportMixin.mjs","names":[],"sources":["../../../../src/shapes/Text/TextSVGExportMixin.ts"],"sourcesContent":["import { config } from '../../config';\nimport type { TSVGReviver } from '../../typedefs';\nimport { escapeXml } from '../../util/lang_string';\nimport { colorPropToSVG, createSVGRect } from '../../util/misc/svgParsing';\nimport { hasStyleChanged } from '../../util/misc/textStyles';\nimport { toFixed } from '../../util/misc/toFixed';\nimport { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin';\nimport { type TextStyleDeclaration } from './StyledText';\nimport {\n  JUSTIFY,\n  TEXT_DECORATION_COLOR,\n  TEXT_DECORATION_THICKNESS,\n} from '../Text/constants';\nimport type { FabricText, GraphemeBBox } from './Text';\nimport { STROKE, FILL } from '../../constants';\nimport { createRotateMatrix } from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport { Point } from '../../Point';\nimport { matrixToSVG } from '../../util/misc/svgExport';\n\nconst multipleSpacesRegex = /  +/g;\nconst dblQuoteRegex = /\"/g;\n\nfunction createSVGInlineRect(\n  color: string,\n  left: number,\n  top: number,\n  width: number,\n  height: number,\n) {\n  return `\\t\\t${createSVGRect(color, { left, top, width, height })}\\n`;\n}\n\nexport class TextSVGExportMixin extends FabricObjectSVGExportMixin {\n  _toSVG(this: TextSVGExportMixin & FabricText): string[] {\n    const offsets = this._getSVGLeftTopOffsets(),\n      textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);\n    return this._wrapSVGTextAndBg(textAndBg);\n  }\n\n  toSVG(this: TextSVGExportMixin & FabricText, reviver?: TSVGReviver): string {\n    const textSvg = this._createBaseSVGMarkup(this._toSVG(), {\n        reviver,\n        noStyle: true,\n        withShadow: true,\n      }),\n      path = this.path;\n    if (path) {\n      return (\n        textSvg +\n        path._createBaseSVGMarkup(path._toSVG(), {\n          reviver,\n          withShadow: true,\n          additionalTransform: matrixToSVG(this.calcOwnMatrix()),\n        })\n      );\n    }\n    return textSvg;\n  }\n\n  private _getSVGLeftTopOffsets(this: TextSVGExportMixin & FabricText) {\n    return {\n      textLeft: -this.width / 2,\n      textTop: -this.height / 2,\n      lineTop: this.getHeightOfLine(0),\n    };\n  }\n\n  private _wrapSVGTextAndBg(\n    this: TextSVGExportMixin & FabricText,\n    {\n      textBgRects,\n      textSpans,\n    }: {\n      textSpans: string[];\n      textBgRects: string[];\n    },\n  ) {\n    const noShadow = true,\n      textDecoration = this.getSvgTextDecoration(this);\n    return [\n      textBgRects.join(''),\n      '\\t\\t<text xml:space=\"preserve\" ',\n      `font-family=\"${escapeXml(this.fontFamily.replace(dblQuoteRegex, \"'\"))}\" `,\n      `font-size=\"${escapeXml(this.fontSize)}\" `,\n      this.fontStyle ? `font-style=\"${escapeXml(this.fontStyle)}\" ` : '',\n      this.fontWeight ? `font-weight=\"${escapeXml(this.fontWeight)}\" ` : '',\n      textDecoration ? `text-decoration=\"${textDecoration}\" ` : '',\n      this.direction === 'rtl' ? `direction=\"rtl\" ` : '',\n      'style=\"',\n      this.getSvgStyles(noShadow),\n      '\"',\n      this.addPaintOrder(),\n      ' >',\n      textSpans.join(''),\n      '</text>\\n',\n    ];\n  }\n\n  /**\n   * @private\n   * @param {Number} textTopOffset Text top offset\n   * @param {Number} textLeftOffset Text left offset\n   * @return {Object}\n   */\n  private _getSVGTextAndBg(\n    this: TextSVGExportMixin & FabricText,\n    textTopOffset: number,\n    textLeftOffset: number,\n  ) {\n    const textSpans: string[] = [],\n      textBgRects: string[] = [];\n    let height = textTopOffset,\n      lineOffset;\n\n    // bounding-box background\n    this.backgroundColor &&\n      textBgRects.push(\n        createSVGInlineRect(\n          this.backgroundColor,\n          -this.width / 2,\n          -this.height / 2,\n          this.width,\n          this.height,\n        ),\n      );\n\n    // text and text-background\n    for (let i = 0, len = this._textLines.length; i < len; i++) {\n      lineOffset = this._getLineLeftOffset(i);\n      if (this.direction === 'rtl') {\n        lineOffset += this.width;\n      }\n      if (this.textBackgroundColor || this.styleHas('textBackgroundColor', i)) {\n        this._setSVGTextLineBg(\n          textBgRects,\n          i,\n          textLeftOffset + lineOffset,\n          height,\n        );\n      }\n      this._setSVGTextLineText(\n        textSpans,\n        i,\n        textLeftOffset + lineOffset,\n        height,\n      );\n      height += this.getHeightOfLine(i);\n    }\n\n    return {\n      textSpans,\n      textBgRects,\n    };\n  }\n\n  private _createTextCharSpan(\n    this: TextSVGExportMixin & FabricText,\n    char: string,\n    styleDecl: TextStyleDeclaration,\n    left: number,\n    top: number,\n    charBox: GraphemeBBox,\n  ) {\n    const numFractionDigit = config.NUM_FRACTION_DIGITS;\n    const styleProps = this.getSvgSpanStyles(\n        styleDecl,\n        char !== char.trim() || !!char.match(multipleSpacesRegex),\n      ),\n      fillStyles = styleProps ? `style=\"${styleProps}\"` : '',\n      dy = styleDecl.deltaY,\n      dySpan = dy ? ` dy=\"${toFixed(dy, numFractionDigit)}\" ` : '',\n      { angle, renderLeft, renderTop, width } = charBox;\n    let angleAttr = '';\n    if (renderLeft !== undefined) {\n      const wBy2 = width / 2;\n      angle &&\n        (angleAttr = ` rotate=\"${toFixed(radiansToDegrees(angle), numFractionDigit)}\"`);\n      const m = createRotateMatrix({ angle: radiansToDegrees(angle!) });\n      m[4] = renderLeft!;\n      m[5] = renderTop!;\n      const renderPoint = new Point(-wBy2, 0).transform(m);\n      left = renderPoint.x;\n      top = renderPoint.y;\n    }\n\n    return `<tspan x=\"${toFixed(left, numFractionDigit)}\" y=\"${toFixed(\n      top,\n      numFractionDigit,\n    )}\" ${dySpan}${angleAttr}${fillStyles}>${escapeXml(char)}</tspan>`;\n  }\n\n  private _setSVGTextLineText(\n    this: TextSVGExportMixin & FabricText,\n    textSpans: string[],\n    lineIndex: number,\n    textLeftOffset: number,\n    textTopOffset: number,\n  ) {\n    const lineHeight = this.getHeightOfLine(lineIndex),\n      isJustify = this.textAlign.includes(JUSTIFY),\n      line = this._textLines[lineIndex];\n    let actualStyle,\n      nextStyle,\n      charsToRender = '',\n      charBox,\n      style,\n      boxWidth = 0,\n      timeToRender;\n\n    textTopOffset +=\n      (lineHeight * (1 - this._fontSizeFraction)) / this.lineHeight;\n    for (let i = 0, len = line.length - 1; i <= len; i++) {\n      timeToRender = i === len || this.charSpacing || this.path;\n      charsToRender += line[i];\n      charBox = this.__charBounds[lineIndex][i];\n      if (boxWidth === 0) {\n        textLeftOffset += charBox.kernedWidth - charBox.width;\n        boxWidth += charBox.width;\n      } else {\n        boxWidth += charBox.kernedWidth;\n      }\n      if (isJustify && !timeToRender) {\n        if (this._reSpaceAndTab.test(line[i])) {\n          timeToRender = true;\n        }\n      }\n      if (!timeToRender) {\n        // if we have charSpacing or a path, we render char by char\n        actualStyle =\n          actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);\n        nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);\n        timeToRender = hasStyleChanged(actualStyle, nextStyle, true);\n      }\n      if (timeToRender) {\n        style = this._getStyleDeclaration(lineIndex, i);\n        textSpans.push(\n          this._createTextCharSpan(\n            charsToRender,\n            style,\n            textLeftOffset,\n            textTopOffset,\n            charBox,\n          ),\n        );\n        charsToRender = '';\n        actualStyle = nextStyle;\n        if (this.direction === 'rtl') {\n          textLeftOffset -= boxWidth;\n        } else {\n          textLeftOffset += boxWidth;\n        }\n        boxWidth = 0;\n      }\n    }\n  }\n\n  private _setSVGTextLineBg(\n    this: TextSVGExportMixin & FabricText,\n    textBgRects: (string | number)[],\n    i: number,\n    leftOffset: number,\n    textTopOffset: number,\n  ) {\n    const line = this._textLines[i],\n      heightOfLine = this.getHeightOfLine(i) / this.lineHeight;\n    let boxWidth = 0,\n      boxStart = 0,\n      currentColor,\n      lastColor = this.getValueOfPropertyAt(i, 0, 'textBackgroundColor');\n    for (let j = 0; j < line.length; j++) {\n      const { left, width, kernedWidth } = this.__charBounds[i][j];\n      currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');\n      if (currentColor !== lastColor) {\n        lastColor &&\n          textBgRects.push(\n            createSVGInlineRect(\n              lastColor,\n              leftOffset + boxStart,\n              textTopOffset,\n              boxWidth,\n              heightOfLine,\n            ),\n          );\n        boxStart = left;\n        boxWidth = width;\n        lastColor = currentColor;\n      } else {\n        boxWidth += kernedWidth;\n      }\n    }\n    currentColor &&\n      textBgRects.push(\n        createSVGInlineRect(\n          lastColor,\n          leftOffset + boxStart,\n          textTopOffset,\n          boxWidth,\n          heightOfLine,\n        ),\n      );\n  }\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(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {\n    const objectLevelTextDecorationColor = this[TEXT_DECORATION_COLOR]\n      ? ` text-decoration-color: ${escapeXml(this[TEXT_DECORATION_COLOR])};`\n      : '';\n    return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%;${objectLevelTextDecorationColor} white-space: pre;`;\n  }\n\n  /**\n   * Returns styles-string for svg-export\n   * @param {Object} style the object from which to retrieve style properties\n   * @param {Boolean} useWhiteSpace a boolean to include an additional attribute in the style.\n   * @return {String}\n   */\n  getSvgSpanStyles(\n    this: TextSVGExportMixin & FabricText,\n    style: TextStyleDeclaration,\n    useWhiteSpace?: boolean,\n  ) {\n    const {\n      fontFamily,\n      strokeWidth,\n      stroke,\n      fill,\n      fontSize,\n      fontStyle,\n      fontWeight,\n      textDecorationThickness,\n      textDecorationColor,\n      linethrough,\n      overline,\n      underline,\n    } = style;\n\n    const textDecoration = this.getSvgTextDecoration({\n      underline: underline ?? this.underline,\n      overline: overline ?? this.overline,\n      linethrough: linethrough ?? this.linethrough,\n    });\n    const thickness =\n      textDecorationThickness || this[TEXT_DECORATION_THICKNESS];\n    const decorationColor = textDecorationColor || this[TEXT_DECORATION_COLOR];\n    return [\n      stroke ? colorPropToSVG(STROKE, stroke) : '',\n      strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '',\n      fontFamily\n        ? `font-family: ${\n            !fontFamily.includes(\"'\") && !fontFamily.includes('\"')\n              ? `'${escapeXml(fontFamily)}'`\n              : escapeXml(fontFamily)\n          }; `\n        : '',\n      fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '',\n      fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '',\n      fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '',\n      textDecoration\n        ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%;${\n            decorationColor\n              ? ` text-decoration-color: ${escapeXml(decorationColor)};`\n              : ''\n          } `\n        : '',\n      fill ? colorPropToSVG(FILL, fill) : '',\n      useWhiteSpace ? 'white-space: pre; ' : '',\n    ].join('');\n  }\n\n  /**\n   * Returns text-decoration property for svg-export\n   * @param {Object} style the object from which to retrieve style properties\n   * @return {String}\n   */\n  getSvgTextDecoration(\n    this: TextSVGExportMixin & FabricText,\n    style: TextStyleDeclaration,\n  ) {\n    return (['overline', 'underline', 'line-through'] as const)\n      .filter(\n        (decoration) =>\n          style[\n            decoration.replace('-', '') as\n              | 'overline'\n              | 'underline'\n              | 'linethrough'\n          ],\n      )\n      .join(' ');\n  }\n}\n"],"mappings":"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"}