@@ -7,8 +7,12 @@ import { toFixed } from '../../util/misc/toFixed';
77import { FabricObjectSVGExportMixin } from '../Object/FabricObjectSVGExportMixin' ;
88import { type TextStyleDeclaration } from './StyledText' ;
99import { JUSTIFY } from '../Text/constants' ;
10- import type { FabricText } from './Text' ;
10+ import type { FabricText , GraphemeBBox } from './Text' ;
1111import { STROKE , FILL } from '../../constants' ;
12+ import { createRotateMatrix } from '../../util/misc/matrix' ;
13+ import { radiansToDegrees } from '../../util/misc/radiansDegreesConversion' ;
14+ import { Point } from '../../Point' ;
15+ import { matrixToSVG } from '../../util/misc/svgExport' ;
1216
1317const multipleSpacesRegex = / + / g;
1418const dblQuoteRegex = / " / g;
@@ -31,11 +35,23 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
3135 }
3236
3337 toSVG ( this : TextSVGExportMixin & FabricText , reviver ?: TSVGReviver ) : string {
34- return this . _createBaseSVGMarkup ( this . _toSVG ( ) , {
35- reviver,
36- noStyle : true ,
37- withShadow : true ,
38- } ) ;
38+ const textSvg = this . _createBaseSVGMarkup ( this . _toSVG ( ) , {
39+ reviver,
40+ noStyle : true ,
41+ withShadow : true ,
42+ } ) ,
43+ path = this . path ;
44+ if ( path ) {
45+ return (
46+ textSvg +
47+ path . _createBaseSVGMarkup ( path . _toSVG ( ) , {
48+ reviver,
49+ withShadow : true ,
50+ additionalTransform : matrixToSVG ( this . calcOwnMatrix ( ) ) ,
51+ } )
52+ ) ;
53+ }
54+ return textSvg ;
3955 }
4056
4157 private _getSVGLeftTopOffsets ( this : TextSVGExportMixin & FabricText ) {
@@ -142,22 +158,34 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
142158 styleDecl : TextStyleDeclaration ,
143159 left : number ,
144160 top : number ,
161+ charBox : GraphemeBBox ,
145162 ) {
163+ const numFractionDigit = config . NUM_FRACTION_DIGITS ;
146164 const styleProps = this . getSvgSpanStyles (
147165 styleDecl ,
148166 char !== char . trim ( ) || ! ! char . match ( multipleSpacesRegex ) ,
149167 ) ,
150168 fillStyles = styleProps ? `style="${ styleProps } "` : '' ,
151169 dy = styleDecl . deltaY ,
152- dySpan = dy ? ` dy="${ toFixed ( dy , config . NUM_FRACTION_DIGITS ) } " ` : '' ;
170+ dySpan = dy ? ` dy="${ toFixed ( dy , numFractionDigit ) } " ` : '' ,
171+ { angle, renderLeft, renderTop, width } = charBox ;
172+ let angleAttr = '' ;
173+ if ( renderLeft !== undefined ) {
174+ const wBy2 = width / 2 ;
175+ angle &&
176+ ( angleAttr = ` rotate="${ toFixed ( radiansToDegrees ( angle ) , numFractionDigit ) } "` ) ;
177+ const m = createRotateMatrix ( { angle : radiansToDegrees ( angle ! ) } ) ;
178+ m [ 4 ] = renderLeft ! ;
179+ m [ 5 ] = renderTop ! ;
180+ const renderPoint = new Point ( - wBy2 , 0 ) . transform ( m ) ;
181+ left = renderPoint . x ;
182+ top = renderPoint . y ;
183+ }
153184
154- return `<tspan x="${ toFixed (
155- left ,
156- config . NUM_FRACTION_DIGITS ,
157- ) } " y="${ toFixed (
185+ return `<tspan x="${ toFixed ( left , numFractionDigit ) } " y="${ toFixed (
158186 top ,
159- config . NUM_FRACTION_DIGITS ,
160- ) } " ${ dySpan } ${ fillStyles } >${ escapeXml ( char ) } </tspan>`;
187+ numFractionDigit ,
188+ ) } " ${ dySpan } ${ angleAttr } ${ fillStyles } >${ escapeXml ( char ) } </tspan>`;
161189 }
162190
163191 private _setSVGTextLineText (
@@ -181,7 +209,7 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
181209 textTopOffset +=
182210 ( lineHeight * ( 1 - this . _fontSizeFraction ) ) / this . lineHeight ;
183211 for ( let i = 0 , len = line . length - 1 ; i <= len ; i ++ ) {
184- timeToRender = i === len || this . charSpacing ;
212+ timeToRender = i === len || this . charSpacing || this . path ;
185213 charsToRender += line [ i ] ;
186214 charBox = this . __charBounds [ lineIndex ] [ i ] ;
187215 if ( boxWidth === 0 ) {
@@ -196,7 +224,7 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
196224 }
197225 }
198226 if ( ! timeToRender ) {
199- // if we have charSpacing, we render char by char
227+ // if we have charSpacing or a path , we render char by char
200228 actualStyle =
201229 actualStyle || this . getCompleteStyleDeclaration ( lineIndex , i ) ;
202230 nextStyle = this . getCompleteStyleDeclaration ( lineIndex , i + 1 ) ;
@@ -210,6 +238,7 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
210238 style ,
211239 textLeftOffset ,
212240 textTopOffset ,
241+ charBox ,
213242 ) ,
214243 ) ;
215244 charsToRender = '' ;
0 commit comments