fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
3 lines (2 loc) • 4.88 kB
JavaScript
import{config as t}from"../../config.min.mjs";import{escapeXml as e}from"../../util/lang_string.min.mjs";import{colorPropToSVG as i,createSVGRect as n}from"../../util/misc/svgParsing.min.mjs";import{hasStyleChanged as s}from"../../util/misc/textStyles.min.mjs";import{toFixed as o}from"../../util/misc/toFixed.min.mjs";import{FabricObjectSVGExportMixin as r}from"../Object/FabricObjectSVGExportMixin.min.mjs";import{JUSTIFY as h}from"./constants.min.mjs";import{STROKE as l,FILL as a}from"../../constants.min.mjs";import{createRotateMatrix as g}from"../../util/misc/matrix.min.mjs";import{radiansToDegrees as c}from"../../util/misc/radiansDegreesConversion.min.mjs";import{Point as m}from"../../Point.min.mjs";import{matrixToSVG as f}from"../../util/misc/svgExport.min.mjs";const d=/ +/g,p=/"/g;function S(t,e,i,s,o){return`\t\t${n(t,{left:e,top:i,width:s,height:o})}\n`}class x extends r{_toSVG(){const t=this._getSVGLeftTopOffsets(),e=this._getSVGTextAndBg(t.textTop,t.textLeft);return this._wrapSVGTextAndBg(e)}toSVG(t){const e=this._createBaseSVGMarkup(this._toSVG(),{reviver:t,noStyle:!0,withShadow:!0}),i=this.path;return i?e+i._createBaseSVGMarkup(i._toSVG(),{reviver:t,withShadow:!0,additionalTransform:f(this.calcOwnMatrix())}):e}_getSVGLeftTopOffsets(){return{textLeft:-this.width/2,textTop:-this.height/2,lineTop:this.getHeightOfLine(0)}}_wrapSVGTextAndBg(t){let{textBgRects:i,textSpans:n}=t;const s=this.getSvgTextDecoration(this);return[i.join(""),'\t\t<text xml:space="preserve" ',`font-family="${e(this.fontFamily.replace(p,"'"))}" `,`font-size="${e(this.fontSize)}" `,this.fontStyle?`font-style="${e(this.fontStyle)}" `:"",this.fontWeight?`font-weight="${e(this.fontWeight)}" `:"",s?`text-decoration="${s}" `:"","rtl"===this.direction?'direction="rtl" ':"",'style="',this.getSvgStyles(!0),'"',this.addPaintOrder()," >",n.join(""),"</text>\n"]}_getSVGTextAndBg(t,e){const i=[],n=[];let s,o=t;this.backgroundColor&&n.push(S(this.backgroundColor,-this.width/2,-this.height/2,this.width,this.height));for(let t=0,r=this._textLines.length;t<r;t++)s=this._getLineLeftOffset(t),"rtl"===this.direction&&(s+=this.width),(this.textBackgroundColor||this.styleHas("textBackgroundColor",t))&&this._setSVGTextLineBg(n,t,e+s,o),this._setSVGTextLineText(i,t,e+s,o),o+=this.getHeightOfLine(t);return{textSpans:i,textBgRects:n}}_createTextCharSpan(i,n,s,r,h){const l=t.NUM_FRACTION_DIGITS,a=this.getSvgSpanStyles(n,i!==i.trim()||!!i.match(d)),f=a?`style="${a}"`:"",p=n.deltaY,S=p?` dy="${o(p,l)}" `:"",{angle:x,renderLeft:u,renderTop:_,width:T}=h;let y="";if(void 0!==u){const t=T/2;x&&(y=` rotate="${o(c(x),l)}"`);const e=g({angle:c(x)});e[4]=u,e[5]=_;const i=new m(-t,0).transform(e);s=i.x,r=i.y}return`<tspan x="${o(s,l)}" y="${o(r,l)}" ${S}${y}${f}>${e(i)}</tspan>`}_setSVGTextLineText(t,e,i,n){const o=this.getHeightOfLine(e),r=this.textAlign.includes(h),l=this._textLines[e];let a,g,c,m,f,d="",p=0;n+=o*(1-this._fontSizeFraction)/this.lineHeight;for(let o=0,h=l.length-1;o<=h;o++)f=o===h||this.charSpacing||this.path,d+=l[o],c=this.__charBounds[e][o],0===p?(i+=c.kernedWidth-c.width,p+=c.width):p+=c.kernedWidth,r&&!f&&this._reSpaceAndTab.test(l[o])&&(f=!0),f||(a=a||this.getCompleteStyleDeclaration(e,o),g=this.getCompleteStyleDeclaration(e,o+1),f=s(a,g,!0)),f&&(m=this._getStyleDeclaration(e,o),t.push(this._createTextCharSpan(d,m,i,n,c)),d="",a=g,"rtl"===this.direction?i-=p:i+=p,p=0)}_setSVGTextLineBg(t,e,i,n){const s=this._textLines[e],o=this.getHeightOfLine(e)/this.lineHeight;let r,h=0,l=0,a=this.getValueOfPropertyAt(e,0,"textBackgroundColor");for(let g=0;g<s.length;g++){const{left:s,width:c,kernedWidth:m}=this.__charBounds[e][g];r=this.getValueOfPropertyAt(e,g,"textBackgroundColor"),r!==a?(a&&t.push(S(a,i+l,n,h,o)),l=s,h=c,a=r):h+=m}r&&t.push(S(a,i+l,n,h,o))}getSvgStyles(e){return`${super.getSvgStyles(e)} text-decoration-thickness: ${o(this.textDecorationThickness*this.getObjectScaling().y/10,t.NUM_FRACTION_DIGITS)}%; white-space: pre;`}getSvgSpanStyles(n,s){const{fontFamily:r,strokeWidth:h,stroke:g,fill:c,fontSize:m,fontStyle:f,fontWeight:d,textDecorationThickness:p,linethrough:S,overline:x,underline:u}=n,_=this.getSvgTextDecoration({underline:null!=u?u:this.underline,overline:null!=x?x:this.overline,linethrough:null!=S?S:this.linethrough}),T=p||this.textDecorationThickness;return[g?i(l,g):"",h?`stroke-width: ${e(h)}; `:"",r?`font-family: ${r.includes("'")||r.includes('"')?e(r):`'${e(r)}'`}; `:"",m?`font-size: ${e(m)}px; `:"",f?`font-style: ${e(f)}; `:"",d?`font-weight: ${e(d)}; `:"",_?`text-decoration: ${_}; text-decoration-thickness: ${o(T*this.getObjectScaling().y/10,t.NUM_FRACTION_DIGITS)}%; `:"",c?i(a,c):"",s?"white-space: pre; ":""].join("")}getSvgTextDecoration(t){return["overline","underline","line-through"].filter(e=>t[e.replace("-","")]).join(" ")}}export{x as TextSVGExportMixin};
//# sourceMappingURL=TextSVGExportMixin.min.mjs.map