modern-text 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class u{static get defaultStyle(){return{width:"auto",height:"auto",color:"#000000",fontSize:14,fontWeight:"normal",fontFamily:"sans-serif",fontStyle:"normal",fontKerning:"normal",textWrap:"wrap",textAlign:"start",verticalAlign:"baseline",textDecoration:null,textStrokeWidth:0,textStrokeColor:"#000000",direction:"inherit",lineHeight:1,letterSpacing:0,shadowColor:"#000000",shadowOffsetX:0,shadowOffsetY:0,shadowBlur:0}}constructor(i={}){const{view:t=document.createElement("canvas"),pixelRatio:l=window.devicePixelRatio||1,content:o="",style:h}=i;this.view=t,this.context=t.getContext("2d"),this.pixelRatio=l,this.content=o,this.style={...u.defaultStyle,...h},this.update()}measure(i=0,t=0){let l=this._createParagraphs(this.content);l=this._createWrapedParagraphs(l,i);const o=this.context;let h=0;for(let c=l.length,x=0;x<c;x++){const e=l[x];e.contentBox.top=h;let s=0,d=null;for(const n of e.fragments){this._setContextStyle({...n.style,textAlign:"left",verticalAlign:"baseline"});const r=o.measureText(n.content);n.inlineBox.left=s,n.inlineBox.top=h,n.inlineBox.width=r.width,n.inlineBox.height=n.style.fontSize*n.style.lineHeight,n.contentBox.left=n.inlineBox.left,n.contentBox.width=n.inlineBox.width,n.contentBox.height=n.style.fontSize,n.contentBox.top=n.inlineBox.top+(n.inlineBox.height-n.contentBox.height)/2,n.textBox.width=r.actualBoundingBoxLeft+r.actualBoundingBoxRight,n.textBox.height=r.actualBoundingBoxAscent+r.actualBoundingBoxDescent,n.textBox.left=n.contentBox.left+(n.contentBox.width-n.textBox.width)/2,n.textBox.top=n.contentBox.top+(n.contentBox.height-n.textBox.height)/2,n.baseline=n.textBox.top+r.actualBoundingBoxAscent,s+=n.contentBox.width+n.style.letterSpacing,e.contentBox.height<n.contentBox.height&&(d=n),e.contentBox.left=Math.min(e.contentBox.left,n.contentBox.left),e.contentBox.top=Math.min(e.contentBox.top,n.contentBox.top),e.contentBox.height=Math.max(e.contentBox.height,n.contentBox.height),e.lineBox.height=Math.max(e.lineBox.height,n.inlineBox.height)}const B=e.fragments[e.fragments.length-1];e.contentBox.width=Math.max(e.contentBox.width,B?B.contentBox.left+Math.max(B.contentBox.width,B.textBox.width):0),e.lineBox.left=0,e.lineBox.top=h,e.lineBox.width=Math.max(i,e.contentBox.width),this._setContextStyle({...(d??e).style,textAlign:"left",verticalAlign:"baseline"});const f=o.measureText("X");e.baseline=e.lineBox.top+(e.lineBox.height-f.actualBoundingBoxAscent+f.actualBoundingBoxDescent)/2+f.actualBoundingBoxAscent,h+=e.lineBox.height}const a=l.reduce((c,x)=>(c.left=Math.min(c.left,x.lineBox.left),c.top=Math.min(c.top,x.lineBox.top),c.width=Math.max(c.width,x.lineBox.width),c.height+=x.lineBox.height,c),{left:0,top:0,width:0,height:0});for(let c=l.length,x=0;x<c;x++){const e=l[x];e.fragments.forEach(s=>{const d=s.inlineBox.left,B=s.inlineBox.top,f=e.lineBox.height-s.inlineBox.height;switch(s.style.textAlign){case"end":case"right":s.inlineBox.left+=e.lineBox.width-e.contentBox.width;break;case"center":s.inlineBox.left+=(e.lineBox.width-e.contentBox.width)/2;break;case"start":case"left":default:s.inlineBox.left+=e.lineBox.left;break}switch(s.style.verticalAlign){case"top":s.inlineBox.top=e.lineBox.top;break;case"middle":s.inlineBox.top=e.lineBox.top+f/2;break;case"bottom":s.inlineBox.top=e.lineBox.top+f;break;case"sub":case"text-top":case"text-bottom":break;case"baseline":default:s.inlineBox.height<e.lineBox.height&&(s.inlineBox.top+=e.baseline-s.baseline);break}const n=s.inlineBox.left-d,r=s.inlineBox.top-B;s.contentBox.left+=n,s.contentBox.top+=r,s.textBox.left+=n,s.textBox.top+=r})}return{...a,paragraphs:l}}_createParagraphs(i){const t=(h={})=>{const{width:a,height:c,...x}=this.style;return{contentBox:{left:0,top:0,width:0,height:0},lineBox:{left:0,top:0,width:0,height:0},baseline:0,fragments:[],...h,style:{...x,...h.style}}},l=(h={})=>{const a=[],{width:c,height:x,...e}=this.style;return a.push({contentBox:{left:0,top:0,width:0,height:0},inlineBox:{left:0,top:0,width:0,height:0},textBox:{left:0,top:0,width:0,height:0},baseline:0,...h,style:{...e,...h.style},content:h.content??""}),a},o=[];if(typeof i=="string")o.push(t({fragments:l({content:i})}));else{i=Array.isArray(i)?i:[i];for(const h of i)if("fragments"in h){const{fragments:a,...c}=h,x=t({style:c});for(const e of a){const{content:s,...d}=e;x.fragments.push(...l({content:s,style:{...c,...d}}))}o.push(x)}else if("content"in h){const{content:a,...c}=h,x=t({style:c});x.fragments.push(...l({content:a,style:c})),o.push(x)}}return o}_createWrapedParagraphs(i,t){const l=[],o=i.slice();let h,a;for(;h=o.shift();){const c=h.fragments.slice();let x=0;const e=[];let s=!0;for(;a=c.shift();){const d=a.style;this._setContextStyle(d);let B="",f=!1;for(const n of a.content){const r=this.context.measureText(n).width+(s?0:d.letterSpacing),w=/^[\r\n]$/.test(n);if(w||d.textWrap==="wrap"&&t&&x+r>t){let g=w?B.length+1:B.length;!x&&!g&&(B+=n,g++),B.length&&e.push({...a,text:B}),e.length&&(l.push({baseline:h.baseline,style:{...h.style},contentBox:{...h.contentBox},lineBox:{...h.lineBox},fragments:e.slice()}),e.length=0);const p=a.content.substring(g);(p.length||c.length)&&o.unshift({baseline:h.baseline,style:{...h.style},contentBox:{...h.contentBox},lineBox:{...h.lineBox},fragments:(p.length?[{...a,content:p}]:[]).concat(c.slice())}),c.length=0,f=!0;break}else x+=r;B+=n}f||e.push({...a}),s=!1}e.length&&l.push({...h,fragments:e})}return l}_draw(i){const t=this.context;this.style.backgroundColor&&(t.fillStyle=this.style.backgroundColor,t.fillRect(0,0,t.canvas.width,t.canvas.height)),i.forEach(l=>{l.style.backgroundColor&&(t.fillStyle=l.style.backgroundColor,t.fillRect(l.lineBox.left,l.lineBox.top,l.lineBox.width,l.lineBox.height))}),i.forEach(l=>{l.fragments.forEach(o=>{switch(o.style.backgroundColor&&(t.fillStyle=o.style.backgroundColor,t.fillRect(o.inlineBox.left,o.inlineBox.top,o.inlineBox.width,o.inlineBox.height)),this._setContextStyle({...o.style,textAlign:"left",verticalAlign:"top"}),o.style.textStrokeWidth&&t.strokeText(o.content,o.contentBox.left,o.contentBox.top),t.fillText(o.content,o.contentBox.left,o.contentBox.top),o.style.textDecoration){case"underline":t.beginPath(),t.moveTo(o.contentBox.left,o.contentBox.top+o.contentBox.height-2),t.lineTo(o.contentBox.left+o.contentBox.width,o.contentBox.top+o.contentBox.height-2),t.stroke();break;case"line-through":t.beginPath(),t.moveTo(o.contentBox.left,o.contentBox.top+o.contentBox.height/2),t.lineTo(o.contentBox.left+o.contentBox.width,o.contentBox.top+o.contentBox.height/2),t.stroke();break}})})}_resizeView(i,t){const l=this.view;l.style.width=`${i}px`,l.style.height=`${t}px`,l.dataset.width=String(i),l.dataset.height=String(t),l.width=Math.max(1,Math.floor(i*this.pixelRatio)),l.height=Math.max(1,Math.floor(t*this.pixelRatio))}_setContextStyle(i){const t=this.context;switch(t.shadowColor=i.shadowColor,t.shadowOffsetX=i.shadowOffsetX,t.shadowOffsetY=i.shadowOffsetY,t.shadowBlur=i.shadowBlur,t.strokeStyle=i.textStrokeColor,t.lineWidth=i.textStrokeWidth,t.fillStyle=i.color,t.direction=i.direction,t.textAlign=i.textAlign,i.verticalAlign){case"baseline":t.textBaseline="alphabetic";break;case"top":case"middle":case"bottom":t.textBaseline=i.verticalAlign;break}t.font=[i.fontStyle,i.fontWeight,`${i.fontSize}px`,i.fontFamily].join(" "),t.fontKerning=i.fontKerning,t.letterSpacing=`${i.letterSpacing}px`}update(){const i=this.context;let{width:t,height:l}=this.style;t==="auto"&&(t=0),l==="auto"&&(l=0);const o=this.measure(t,l);t||(t=o.width),l=Math.max(l,o.height),this._resizeView(t,l);const h=this.pixelRatio;i.scale(h,h),i.clearRect(0,0,i.canvas.width,i.canvas.height),this._draw(o.paragraphs)}}exports.Text=u;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class w{static get defaultStyle(){return{width:"auto",height:"auto",color:"#000000",fontSize:14,fontWeight:"normal",fontFamily:"sans-serif",fontStyle:"normal",fontKerning:"normal",textWrap:"wrap",textAlign:"start",verticalAlign:"baseline",textDecoration:null,textStrokeWidth:0,textStrokeColor:"#000000",direction:"inherit",lineHeight:1,letterSpacing:0,shadowColor:"#000000",shadowOffsetX:0,shadowOffsetY:0,shadowBlur:0}}constructor(o={}){const{view:t=document.createElement("canvas"),pixelRatio:l=window.devicePixelRatio||1,content:e="",style:x}=o;this.view=t,this.context=t.getContext("2d"),this.pixelRatio=l,this.content=e,this.style={...w.defaultStyle,...x},this.update()}measure(){let{width:o}=this.style;o==="auto"&&(o=0);let t=this._createParagraphs(this.content);t=this._createWrapedParagraphs(t,o);const l=this.context;let e=0;for(let h=t.length,s=0;s<h;s++){const i=t[s];i.contentBox.top=e;let c=0,d=null;for(const n of i.fragments){this._setContextStyle({...n.style,textAlign:"left",verticalAlign:"baseline"});const r=l.measureText(n.content);n.inlineBox.left=c,n.inlineBox.top=e,n.inlineBox.width=r.width,n.inlineBox.height=n.style.fontSize*n.style.lineHeight,n.contentBox.left=n.inlineBox.left,n.contentBox.width=n.inlineBox.width,n.contentBox.height=n.style.fontSize,n.contentBox.top=n.inlineBox.top+(n.inlineBox.height-n.contentBox.height)/2,n.textBox.width=r.actualBoundingBoxLeft+r.actualBoundingBoxRight,n.textBox.height=r.actualBoundingBoxAscent+r.actualBoundingBoxDescent,n.textBox.left=n.contentBox.left+(n.contentBox.width-n.textBox.width)/2,n.textBox.top=n.contentBox.top+(n.contentBox.height-n.textBox.height)/2,n.baseline=n.textBox.top+r.actualBoundingBoxAscent,c+=n.contentBox.width+n.style.letterSpacing,i.contentBox.height<n.contentBox.height&&(d=n),i.contentBox.left=Math.min(i.contentBox.left,n.contentBox.left),i.contentBox.top=Math.min(i.contentBox.top,n.contentBox.top),i.contentBox.height=Math.max(i.contentBox.height,n.contentBox.height),i.lineBox.height=Math.max(i.lineBox.height,n.inlineBox.height)}const B=i.fragments[i.fragments.length-1];i.contentBox.width=Math.max(i.contentBox.width,B?B.contentBox.left+Math.max(B.contentBox.width,B.textBox.width):0),i.lineBox.left=0,i.lineBox.top=e,i.lineBox.width=Math.max(o,i.contentBox.width),this._setContextStyle({...(d??i).style,textAlign:"left",verticalAlign:"baseline"});const f=l.measureText("X");i.baseline=i.lineBox.top+(i.lineBox.height-f.actualBoundingBoxAscent+f.actualBoundingBoxDescent)/2+f.actualBoundingBoxAscent,e+=i.lineBox.height}for(let h=t.length,s=0;s<h;s++){const i=t[s];i.fragments.forEach(c=>{const d=c.inlineBox.left,B=c.inlineBox.top,f=i.lineBox.height-c.inlineBox.height;switch(c.style.textAlign){case"end":case"right":c.inlineBox.left+=i.lineBox.width-i.contentBox.width;break;case"center":c.inlineBox.left+=(i.lineBox.width-i.contentBox.width)/2;break;case"start":case"left":default:c.inlineBox.left+=i.lineBox.left;break}switch(c.style.verticalAlign){case"top":c.inlineBox.top=i.lineBox.top;break;case"middle":c.inlineBox.top=i.lineBox.top+f/2;break;case"bottom":c.inlineBox.top=i.lineBox.top+f;break;case"sub":case"text-top":case"text-bottom":break;case"baseline":default:c.inlineBox.height<i.lineBox.height&&(c.inlineBox.top+=i.baseline-c.baseline);break}const n=c.inlineBox.left-d,r=c.inlineBox.top-B;c.contentBox.left+=n,c.contentBox.top+=r,c.textBox.left+=n,c.textBox.top+=r})}const x=t.reduce((h,s)=>(h.left=Math.min(h.left,s.contentBox.left),h.top=Math.min(h.top,s.contentBox.top),h.width=Math.max(h.width,s.contentBox.width),h.height+=s.contentBox.height,h),{left:0,top:0,width:0,height:0});return{lineBox:t.reduce((h,s)=>(h.left=Math.min(h.left,s.lineBox.left),h.top=Math.min(h.top,s.lineBox.top),h.width=Math.max(h.width,s.lineBox.width),h.height+=s.lineBox.height,h),{left:0,top:0,width:0,height:0}),contentBox:x,paragraphs:t}}_createParagraphs(o){const t=(x={})=>{const{width:a,height:h,...s}=this.style;return{contentBox:{left:0,top:0,width:0,height:0},lineBox:{left:0,top:0,width:0,height:0},baseline:0,fragments:[],...x,style:{...s,...x.style}}},l=(x={})=>{const a=[],{width:h,height:s,...i}=this.style;return a.push({contentBox:{left:0,top:0,width:0,height:0},inlineBox:{left:0,top:0,width:0,height:0},textBox:{left:0,top:0,width:0,height:0},baseline:0,...x,style:{...i,...x.style},content:x.content??""}),a},e=[];if(typeof o=="string")e.push(t({fragments:l({content:o})}));else{o=Array.isArray(o)?o:[o];for(const x of o)if("fragments"in x){const{fragments:a,...h}=x,s=t({style:h});for(const i of a){const{content:c,...d}=i;s.fragments.push(...l({content:c,style:{...h,...d}}))}e.push(s)}else if("content"in x){const{content:a,...h}=x,s=t({style:h});s.fragments.push(...l({content:a,style:h})),e.push(s)}}return e}_createWrapedParagraphs(o,t){const l=s=>JSON.parse(JSON.stringify(s)),e=[],x=o.slice();let a,h;for(;a=x.shift();){const s=a.fragments.slice();let i=0;const c=[];for(;h=s.shift();){const d=h.style;this._setContextStyle(d);let B="",f=!1;for(const n of h.content){const r=this.context.measureText(n).width,u=/^[\r\n]$/.test(n);if(u||d.textWrap==="wrap"&&t&&i+r>t){let g=u?B.length+1:B.length;!i&&!g&&(B+=n,g++),B.length&&c.push({...l(h),content:B}),c.length&&(e.push({...l(a),fragments:c.slice()}),c.length=0);const p=h.content.substring(g);(p.length||s.length)&&x.unshift({...l(a),fragments:(p.length?[{...l(h),content:p}]:[]).concat(s.slice())}),s.length=0,f=!0;break}else i+=r;B+=n}f||c.push(l(h))}c.length&&e.push({...l(a),fragments:c})}return e}_draw(o){const t=this.context;this.style.backgroundColor&&(t.fillStyle=this.style.backgroundColor,t.fillRect(0,0,t.canvas.width,t.canvas.height)),o.forEach(l=>{l.style.backgroundColor&&(t.fillStyle=l.style.backgroundColor,t.fillRect(l.lineBox.left,l.lineBox.top,l.lineBox.width,l.lineBox.height))}),o.forEach(l=>{l.fragments.forEach(e=>{switch(e.style.backgroundColor&&(t.fillStyle=e.style.backgroundColor,t.fillRect(e.inlineBox.left,e.inlineBox.top,e.inlineBox.width,e.inlineBox.height)),this._setContextStyle({...e.style,textAlign:"left",verticalAlign:"top"}),e.style.textStrokeWidth&&t.strokeText(e.content,e.contentBox.left,e.contentBox.top),t.fillText(e.content,e.contentBox.left,e.contentBox.top),e.style.textDecoration){case"underline":t.beginPath(),t.moveTo(e.contentBox.left,e.contentBox.top+e.contentBox.height-2),t.lineTo(e.contentBox.left+e.contentBox.width,e.contentBox.top+e.contentBox.height-2),t.stroke();break;case"line-through":t.beginPath(),t.moveTo(e.contentBox.left,e.contentBox.top+e.contentBox.height/2),t.lineTo(e.contentBox.left+e.contentBox.width,e.contentBox.top+e.contentBox.height/2),t.stroke();break}})})}_resizeView(o,t){const l=this.view;l.style.width=`${o}px`,l.style.height=`${t}px`,l.dataset.width=String(o),l.dataset.height=String(t),l.width=Math.max(1,Math.floor(o*this.pixelRatio)),l.height=Math.max(1,Math.floor(t*this.pixelRatio))}_setContextStyle(o){const t=this.context;switch(t.shadowColor=o.shadowColor,t.shadowOffsetX=o.shadowOffsetX,t.shadowOffsetY=o.shadowOffsetY,t.shadowBlur=o.shadowBlur,t.strokeStyle=o.textStrokeColor,t.lineWidth=o.textStrokeWidth,t.fillStyle=o.color,t.direction=o.direction,t.textAlign=o.textAlign,o.verticalAlign){case"baseline":t.textBaseline="alphabetic";break;case"top":case"middle":case"bottom":t.textBaseline=o.verticalAlign;break}t.font=[o.fontStyle,o.fontWeight,`${o.fontSize}px`,o.fontFamily].join(" "),t.fontKerning=o.fontKerning,t.letterSpacing=`${o.letterSpacing}px`}update(){const o=this.context;let{width:t,height:l}=this.style;t==="auto"&&(t=0),l==="auto"&&(l=0);const{lineBox:e,paragraphs:x}=this.measure();t||(t=e.width),l=Math.max(l,e.height),this._resizeView(t,l);const a=this.pixelRatio;o.scale(a,a),o.clearRect(0,0,o.canvas.width,o.canvas.height),this._draw(x)}}exports.Text=w;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- (function(p,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(p=typeof globalThis<"u"?globalThis:p||self,g(p.modernText={}))})(this,function(p){"use strict";class g{static get defaultStyle(){return{width:"auto",height:"auto",color:"#000000",fontSize:14,fontWeight:"normal",fontFamily:"sans-serif",fontStyle:"normal",fontKerning:"normal",textWrap:"wrap",textAlign:"start",verticalAlign:"baseline",textDecoration:null,textStrokeWidth:0,textStrokeColor:"#000000",direction:"inherit",lineHeight:1,letterSpacing:0,shadowColor:"#000000",shadowOffsetX:0,shadowOffsetY:0,shadowBlur:0}}constructor(i={}){const{view:t=document.createElement("canvas"),pixelRatio:l=window.devicePixelRatio||1,content:o="",style:s}=i;this.view=t,this.context=t.getContext("2d"),this.pixelRatio=l,this.content=o,this.style={...g.defaultStyle,...s},this.update()}measure(i=0,t=0){let l=this._createParagraphs(this.content);l=this._createWrapedParagraphs(l,i);const o=this.context;let s=0;for(let c=l.length,x=0;x<c;x++){const e=l[x];e.contentBox.top=s;let h=0,d=null;for(const n of e.fragments){this._setContextStyle({...n.style,textAlign:"left",verticalAlign:"baseline"});const r=o.measureText(n.content);n.inlineBox.left=h,n.inlineBox.top=s,n.inlineBox.width=r.width,n.inlineBox.height=n.style.fontSize*n.style.lineHeight,n.contentBox.left=n.inlineBox.left,n.contentBox.width=n.inlineBox.width,n.contentBox.height=n.style.fontSize,n.contentBox.top=n.inlineBox.top+(n.inlineBox.height-n.contentBox.height)/2,n.textBox.width=r.actualBoundingBoxLeft+r.actualBoundingBoxRight,n.textBox.height=r.actualBoundingBoxAscent+r.actualBoundingBoxDescent,n.textBox.left=n.contentBox.left+(n.contentBox.width-n.textBox.width)/2,n.textBox.top=n.contentBox.top+(n.contentBox.height-n.textBox.height)/2,n.baseline=n.textBox.top+r.actualBoundingBoxAscent,h+=n.contentBox.width+n.style.letterSpacing,e.contentBox.height<n.contentBox.height&&(d=n),e.contentBox.left=Math.min(e.contentBox.left,n.contentBox.left),e.contentBox.top=Math.min(e.contentBox.top,n.contentBox.top),e.contentBox.height=Math.max(e.contentBox.height,n.contentBox.height),e.lineBox.height=Math.max(e.lineBox.height,n.inlineBox.height)}const B=e.fragments[e.fragments.length-1];e.contentBox.width=Math.max(e.contentBox.width,B?B.contentBox.left+Math.max(B.contentBox.width,B.textBox.width):0),e.lineBox.left=0,e.lineBox.top=s,e.lineBox.width=Math.max(i,e.contentBox.width),this._setContextStyle({...(d??e).style,textAlign:"left",verticalAlign:"baseline"});const f=o.measureText("X");e.baseline=e.lineBox.top+(e.lineBox.height-f.actualBoundingBoxAscent+f.actualBoundingBoxDescent)/2+f.actualBoundingBoxAscent,s+=e.lineBox.height}const a=l.reduce((c,x)=>(c.left=Math.min(c.left,x.lineBox.left),c.top=Math.min(c.top,x.lineBox.top),c.width=Math.max(c.width,x.lineBox.width),c.height+=x.lineBox.height,c),{left:0,top:0,width:0,height:0});for(let c=l.length,x=0;x<c;x++){const e=l[x];e.fragments.forEach(h=>{const d=h.inlineBox.left,B=h.inlineBox.top,f=e.lineBox.height-h.inlineBox.height;switch(h.style.textAlign){case"end":case"right":h.inlineBox.left+=e.lineBox.width-e.contentBox.width;break;case"center":h.inlineBox.left+=(e.lineBox.width-e.contentBox.width)/2;break;case"start":case"left":default:h.inlineBox.left+=e.lineBox.left;break}switch(h.style.verticalAlign){case"top":h.inlineBox.top=e.lineBox.top;break;case"middle":h.inlineBox.top=e.lineBox.top+f/2;break;case"bottom":h.inlineBox.top=e.lineBox.top+f;break;case"sub":case"text-top":case"text-bottom":break;case"baseline":default:h.inlineBox.height<e.lineBox.height&&(h.inlineBox.top+=e.baseline-h.baseline);break}const n=h.inlineBox.left-d,r=h.inlineBox.top-B;h.contentBox.left+=n,h.contentBox.top+=r,h.textBox.left+=n,h.textBox.top+=r})}return{...a,paragraphs:l}}_createParagraphs(i){const t=(s={})=>{const{width:a,height:c,...x}=this.style;return{contentBox:{left:0,top:0,width:0,height:0},lineBox:{left:0,top:0,width:0,height:0},baseline:0,fragments:[],...s,style:{...x,...s.style}}},l=(s={})=>{const a=[],{width:c,height:x,...e}=this.style;return a.push({contentBox:{left:0,top:0,width:0,height:0},inlineBox:{left:0,top:0,width:0,height:0},textBox:{left:0,top:0,width:0,height:0},baseline:0,...s,style:{...e,...s.style},content:s.content??""}),a},o=[];if(typeof i=="string")o.push(t({fragments:l({content:i})}));else{i=Array.isArray(i)?i:[i];for(const s of i)if("fragments"in s){const{fragments:a,...c}=s,x=t({style:c});for(const e of a){const{content:h,...d}=e;x.fragments.push(...l({content:h,style:{...c,...d}}))}o.push(x)}else if("content"in s){const{content:a,...c}=s,x=t({style:c});x.fragments.push(...l({content:a,style:c})),o.push(x)}}return o}_createWrapedParagraphs(i,t){const l=[],o=i.slice();let s,a;for(;s=o.shift();){const c=s.fragments.slice();let x=0;const e=[];let h=!0;for(;a=c.shift();){const d=a.style;this._setContextStyle(d);let B="",f=!1;for(const n of a.content){const r=this.context.measureText(n).width+(h?0:d.letterSpacing),y=/^[\r\n]$/.test(n);if(y||d.textWrap==="wrap"&&t&&x+r>t){let u=y?B.length+1:B.length;!x&&!u&&(B+=n,u++),B.length&&e.push({...a,text:B}),e.length&&(l.push({baseline:s.baseline,style:{...s.style},contentBox:{...s.contentBox},lineBox:{...s.lineBox},fragments:e.slice()}),e.length=0);const w=a.content.substring(u);(w.length||c.length)&&o.unshift({baseline:s.baseline,style:{...s.style},contentBox:{...s.contentBox},lineBox:{...s.lineBox},fragments:(w.length?[{...a,content:w}]:[]).concat(c.slice())}),c.length=0,f=!0;break}else x+=r;B+=n}f||e.push({...a}),h=!1}e.length&&l.push({...s,fragments:e})}return l}_draw(i){const t=this.context;this.style.backgroundColor&&(t.fillStyle=this.style.backgroundColor,t.fillRect(0,0,t.canvas.width,t.canvas.height)),i.forEach(l=>{l.style.backgroundColor&&(t.fillStyle=l.style.backgroundColor,t.fillRect(l.lineBox.left,l.lineBox.top,l.lineBox.width,l.lineBox.height))}),i.forEach(l=>{l.fragments.forEach(o=>{switch(o.style.backgroundColor&&(t.fillStyle=o.style.backgroundColor,t.fillRect(o.inlineBox.left,o.inlineBox.top,o.inlineBox.width,o.inlineBox.height)),this._setContextStyle({...o.style,textAlign:"left",verticalAlign:"top"}),o.style.textStrokeWidth&&t.strokeText(o.content,o.contentBox.left,o.contentBox.top),t.fillText(o.content,o.contentBox.left,o.contentBox.top),o.style.textDecoration){case"underline":t.beginPath(),t.moveTo(o.contentBox.left,o.contentBox.top+o.contentBox.height-2),t.lineTo(o.contentBox.left+o.contentBox.width,o.contentBox.top+o.contentBox.height-2),t.stroke();break;case"line-through":t.beginPath(),t.moveTo(o.contentBox.left,o.contentBox.top+o.contentBox.height/2),t.lineTo(o.contentBox.left+o.contentBox.width,o.contentBox.top+o.contentBox.height/2),t.stroke();break}})})}_resizeView(i,t){const l=this.view;l.style.width=`${i}px`,l.style.height=`${t}px`,l.dataset.width=String(i),l.dataset.height=String(t),l.width=Math.max(1,Math.floor(i*this.pixelRatio)),l.height=Math.max(1,Math.floor(t*this.pixelRatio))}_setContextStyle(i){const t=this.context;switch(t.shadowColor=i.shadowColor,t.shadowOffsetX=i.shadowOffsetX,t.shadowOffsetY=i.shadowOffsetY,t.shadowBlur=i.shadowBlur,t.strokeStyle=i.textStrokeColor,t.lineWidth=i.textStrokeWidth,t.fillStyle=i.color,t.direction=i.direction,t.textAlign=i.textAlign,i.verticalAlign){case"baseline":t.textBaseline="alphabetic";break;case"top":case"middle":case"bottom":t.textBaseline=i.verticalAlign;break}t.font=[i.fontStyle,i.fontWeight,`${i.fontSize}px`,i.fontFamily].join(" "),t.fontKerning=i.fontKerning,t.letterSpacing=`${i.letterSpacing}px`}update(){const i=this.context;let{width:t,height:l}=this.style;t==="auto"&&(t=0),l==="auto"&&(l=0);const o=this.measure(t,l);t||(t=o.width),l=Math.max(l,o.height),this._resizeView(t,l);const s=this.pixelRatio;i.scale(s,s),i.clearRect(0,0,i.canvas.width,i.canvas.height),this._draw(o.paragraphs)}}p.Text=g,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
1
+ (function(p,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(p=typeof globalThis<"u"?globalThis:p||self,g(p.modernText={}))})(this,function(p){"use strict";class g{static get defaultStyle(){return{width:"auto",height:"auto",color:"#000000",fontSize:14,fontWeight:"normal",fontFamily:"sans-serif",fontStyle:"normal",fontKerning:"normal",textWrap:"wrap",textAlign:"start",verticalAlign:"baseline",textDecoration:null,textStrokeWidth:0,textStrokeColor:"#000000",direction:"inherit",lineHeight:1,letterSpacing:0,shadowColor:"#000000",shadowOffsetX:0,shadowOffsetY:0,shadowBlur:0}}constructor(o={}){const{view:t=document.createElement("canvas"),pixelRatio:l=window.devicePixelRatio||1,content:e="",style:x}=o;this.view=t,this.context=t.getContext("2d"),this.pixelRatio=l,this.content=e,this.style={...g.defaultStyle,...x},this.update()}measure(){let{width:o}=this.style;o==="auto"&&(o=0);let t=this._createParagraphs(this.content);t=this._createWrapedParagraphs(t,o);const l=this.context;let e=0;for(let h=t.length,s=0;s<h;s++){const i=t[s];i.contentBox.top=e;let c=0,r=null;for(const n of i.fragments){this._setContextStyle({...n.style,textAlign:"left",verticalAlign:"baseline"});const d=l.measureText(n.content);n.inlineBox.left=c,n.inlineBox.top=e,n.inlineBox.width=d.width,n.inlineBox.height=n.style.fontSize*n.style.lineHeight,n.contentBox.left=n.inlineBox.left,n.contentBox.width=n.inlineBox.width,n.contentBox.height=n.style.fontSize,n.contentBox.top=n.inlineBox.top+(n.inlineBox.height-n.contentBox.height)/2,n.textBox.width=d.actualBoundingBoxLeft+d.actualBoundingBoxRight,n.textBox.height=d.actualBoundingBoxAscent+d.actualBoundingBoxDescent,n.textBox.left=n.contentBox.left+(n.contentBox.width-n.textBox.width)/2,n.textBox.top=n.contentBox.top+(n.contentBox.height-n.textBox.height)/2,n.baseline=n.textBox.top+d.actualBoundingBoxAscent,c+=n.contentBox.width+n.style.letterSpacing,i.contentBox.height<n.contentBox.height&&(r=n),i.contentBox.left=Math.min(i.contentBox.left,n.contentBox.left),i.contentBox.top=Math.min(i.contentBox.top,n.contentBox.top),i.contentBox.height=Math.max(i.contentBox.height,n.contentBox.height),i.lineBox.height=Math.max(i.lineBox.height,n.inlineBox.height)}const B=i.fragments[i.fragments.length-1];i.contentBox.width=Math.max(i.contentBox.width,B?B.contentBox.left+Math.max(B.contentBox.width,B.textBox.width):0),i.lineBox.left=0,i.lineBox.top=e,i.lineBox.width=Math.max(o,i.contentBox.width),this._setContextStyle({...(r??i).style,textAlign:"left",verticalAlign:"baseline"});const f=l.measureText("X");i.baseline=i.lineBox.top+(i.lineBox.height-f.actualBoundingBoxAscent+f.actualBoundingBoxDescent)/2+f.actualBoundingBoxAscent,e+=i.lineBox.height}for(let h=t.length,s=0;s<h;s++){const i=t[s];i.fragments.forEach(c=>{const r=c.inlineBox.left,B=c.inlineBox.top,f=i.lineBox.height-c.inlineBox.height;switch(c.style.textAlign){case"end":case"right":c.inlineBox.left+=i.lineBox.width-i.contentBox.width;break;case"center":c.inlineBox.left+=(i.lineBox.width-i.contentBox.width)/2;break;case"start":case"left":default:c.inlineBox.left+=i.lineBox.left;break}switch(c.style.verticalAlign){case"top":c.inlineBox.top=i.lineBox.top;break;case"middle":c.inlineBox.top=i.lineBox.top+f/2;break;case"bottom":c.inlineBox.top=i.lineBox.top+f;break;case"sub":case"text-top":case"text-bottom":break;case"baseline":default:c.inlineBox.height<i.lineBox.height&&(c.inlineBox.top+=i.baseline-c.baseline);break}const n=c.inlineBox.left-r,d=c.inlineBox.top-B;c.contentBox.left+=n,c.contentBox.top+=d,c.textBox.left+=n,c.textBox.top+=d})}const x=t.reduce((h,s)=>(h.left=Math.min(h.left,s.contentBox.left),h.top=Math.min(h.top,s.contentBox.top),h.width=Math.max(h.width,s.contentBox.width),h.height+=s.contentBox.height,h),{left:0,top:0,width:0,height:0});return{lineBox:t.reduce((h,s)=>(h.left=Math.min(h.left,s.lineBox.left),h.top=Math.min(h.top,s.lineBox.top),h.width=Math.max(h.width,s.lineBox.width),h.height+=s.lineBox.height,h),{left:0,top:0,width:0,height:0}),contentBox:x,paragraphs:t}}_createParagraphs(o){const t=(x={})=>{const{width:a,height:h,...s}=this.style;return{contentBox:{left:0,top:0,width:0,height:0},lineBox:{left:0,top:0,width:0,height:0},baseline:0,fragments:[],...x,style:{...s,...x.style}}},l=(x={})=>{const a=[],{width:h,height:s,...i}=this.style;return a.push({contentBox:{left:0,top:0,width:0,height:0},inlineBox:{left:0,top:0,width:0,height:0},textBox:{left:0,top:0,width:0,height:0},baseline:0,...x,style:{...i,...x.style},content:x.content??""}),a},e=[];if(typeof o=="string")e.push(t({fragments:l({content:o})}));else{o=Array.isArray(o)?o:[o];for(const x of o)if("fragments"in x){const{fragments:a,...h}=x,s=t({style:h});for(const i of a){const{content:c,...r}=i;s.fragments.push(...l({content:c,style:{...h,...r}}))}e.push(s)}else if("content"in x){const{content:a,...h}=x,s=t({style:h});s.fragments.push(...l({content:a,style:h})),e.push(s)}}return e}_createWrapedParagraphs(o,t){const l=s=>JSON.parse(JSON.stringify(s)),e=[],x=o.slice();let a,h;for(;a=x.shift();){const s=a.fragments.slice();let i=0;const c=[];for(;h=s.shift();){const r=h.style;this._setContextStyle(r);let B="",f=!1;for(const n of h.content){const d=this.context.measureText(n).width,y=/^[\r\n]$/.test(n);if(y||r.textWrap==="wrap"&&t&&i+d>t){let u=y?B.length+1:B.length;!i&&!u&&(B+=n,u++),B.length&&c.push({...l(h),content:B}),c.length&&(e.push({...l(a),fragments:c.slice()}),c.length=0);const w=h.content.substring(u);(w.length||s.length)&&x.unshift({...l(a),fragments:(w.length?[{...l(h),content:w}]:[]).concat(s.slice())}),s.length=0,f=!0;break}else i+=d;B+=n}f||c.push(l(h))}c.length&&e.push({...l(a),fragments:c})}return e}_draw(o){const t=this.context;this.style.backgroundColor&&(t.fillStyle=this.style.backgroundColor,t.fillRect(0,0,t.canvas.width,t.canvas.height)),o.forEach(l=>{l.style.backgroundColor&&(t.fillStyle=l.style.backgroundColor,t.fillRect(l.lineBox.left,l.lineBox.top,l.lineBox.width,l.lineBox.height))}),o.forEach(l=>{l.fragments.forEach(e=>{switch(e.style.backgroundColor&&(t.fillStyle=e.style.backgroundColor,t.fillRect(e.inlineBox.left,e.inlineBox.top,e.inlineBox.width,e.inlineBox.height)),this._setContextStyle({...e.style,textAlign:"left",verticalAlign:"top"}),e.style.textStrokeWidth&&t.strokeText(e.content,e.contentBox.left,e.contentBox.top),t.fillText(e.content,e.contentBox.left,e.contentBox.top),e.style.textDecoration){case"underline":t.beginPath(),t.moveTo(e.contentBox.left,e.contentBox.top+e.contentBox.height-2),t.lineTo(e.contentBox.left+e.contentBox.width,e.contentBox.top+e.contentBox.height-2),t.stroke();break;case"line-through":t.beginPath(),t.moveTo(e.contentBox.left,e.contentBox.top+e.contentBox.height/2),t.lineTo(e.contentBox.left+e.contentBox.width,e.contentBox.top+e.contentBox.height/2),t.stroke();break}})})}_resizeView(o,t){const l=this.view;l.style.width=`${o}px`,l.style.height=`${t}px`,l.dataset.width=String(o),l.dataset.height=String(t),l.width=Math.max(1,Math.floor(o*this.pixelRatio)),l.height=Math.max(1,Math.floor(t*this.pixelRatio))}_setContextStyle(o){const t=this.context;switch(t.shadowColor=o.shadowColor,t.shadowOffsetX=o.shadowOffsetX,t.shadowOffsetY=o.shadowOffsetY,t.shadowBlur=o.shadowBlur,t.strokeStyle=o.textStrokeColor,t.lineWidth=o.textStrokeWidth,t.fillStyle=o.color,t.direction=o.direction,t.textAlign=o.textAlign,o.verticalAlign){case"baseline":t.textBaseline="alphabetic";break;case"top":case"middle":case"bottom":t.textBaseline=o.verticalAlign;break}t.font=[o.fontStyle,o.fontWeight,`${o.fontSize}px`,o.fontFamily].join(" "),t.fontKerning=o.fontKerning,t.letterSpacing=`${o.letterSpacing}px`}update(){const o=this.context;let{width:t,height:l}=this.style;t==="auto"&&(t=0),l==="auto"&&(l=0);const{lineBox:e,paragraphs:x}=this.measure();t||(t=e.width),l=Math.max(l,e.height),this._resizeView(t,l);const a=this.pixelRatio;o.scale(a,a),o.clearRect(0,0,o.canvas.width,o.canvas.height),this._draw(x)}}p.Text=g,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- class w {
1
+ class u {
2
2
  static get defaultStyle() {
3
3
  return {
4
4
  width: "auto",
@@ -24,76 +24,77 @@ class w {
24
24
  shadowBlur: 0
25
25
  };
26
26
  }
27
- constructor(i = {}) {
27
+ constructor(o = {}) {
28
28
  const {
29
29
  view: t = document.createElement("canvas"),
30
30
  pixelRatio: l = window.devicePixelRatio || 1,
31
- content: o = "",
32
- style: h
33
- } = i;
34
- this.view = t, this.context = t.getContext("2d"), this.pixelRatio = l, this.content = o, this.style = {
35
- ...w.defaultStyle,
36
- ...h
31
+ content: e = "",
32
+ style: x
33
+ } = o;
34
+ this.view = t, this.context = t.getContext("2d"), this.pixelRatio = l, this.content = e, this.style = {
35
+ ...u.defaultStyle,
36
+ ...x
37
37
  }, this.update();
38
38
  }
39
- measure(i = 0, t = 0) {
40
- let l = this._createParagraphs(this.content);
41
- l = this._createWrapedParagraphs(l, i);
42
- const o = this.context;
43
- let h = 0;
44
- for (let c = l.length, x = 0; x < c; x++) {
45
- const e = l[x];
46
- e.contentBox.top = h;
47
- let s = 0, d = null;
48
- for (const n of e.fragments) {
39
+ measure() {
40
+ let { width: o } = this.style;
41
+ o === "auto" && (o = 0);
42
+ let t = this._createParagraphs(this.content);
43
+ t = this._createWrapedParagraphs(t, o);
44
+ const l = this.context;
45
+ let e = 0;
46
+ for (let h = t.length, s = 0; s < h; s++) {
47
+ const i = t[s];
48
+ i.contentBox.top = e;
49
+ let c = 0, d = null;
50
+ for (const n of i.fragments) {
49
51
  this._setContextStyle({
50
52
  ...n.style,
51
53
  textAlign: "left",
52
54
  verticalAlign: "baseline"
53
55
  });
54
- const r = o.measureText(n.content);
55
- n.inlineBox.left = s, n.inlineBox.top = h, n.inlineBox.width = r.width, n.inlineBox.height = n.style.fontSize * n.style.lineHeight, n.contentBox.left = n.inlineBox.left, n.contentBox.width = n.inlineBox.width, n.contentBox.height = n.style.fontSize, n.contentBox.top = n.inlineBox.top + (n.inlineBox.height - n.contentBox.height) / 2, n.textBox.width = r.actualBoundingBoxLeft + r.actualBoundingBoxRight, n.textBox.height = r.actualBoundingBoxAscent + r.actualBoundingBoxDescent, n.textBox.left = n.contentBox.left + (n.contentBox.width - n.textBox.width) / 2, n.textBox.top = n.contentBox.top + (n.contentBox.height - n.textBox.height) / 2, n.baseline = n.textBox.top + r.actualBoundingBoxAscent, s += n.contentBox.width + n.style.letterSpacing, e.contentBox.height < n.contentBox.height && (d = n), e.contentBox.left = Math.min(e.contentBox.left, n.contentBox.left), e.contentBox.top = Math.min(e.contentBox.top, n.contentBox.top), e.contentBox.height = Math.max(e.contentBox.height, n.contentBox.height), e.lineBox.height = Math.max(e.lineBox.height, n.inlineBox.height);
56
+ const r = l.measureText(n.content);
57
+ n.inlineBox.left = c, n.inlineBox.top = e, n.inlineBox.width = r.width, n.inlineBox.height = n.style.fontSize * n.style.lineHeight, n.contentBox.left = n.inlineBox.left, n.contentBox.width = n.inlineBox.width, n.contentBox.height = n.style.fontSize, n.contentBox.top = n.inlineBox.top + (n.inlineBox.height - n.contentBox.height) / 2, n.textBox.width = r.actualBoundingBoxLeft + r.actualBoundingBoxRight, n.textBox.height = r.actualBoundingBoxAscent + r.actualBoundingBoxDescent, n.textBox.left = n.contentBox.left + (n.contentBox.width - n.textBox.width) / 2, n.textBox.top = n.contentBox.top + (n.contentBox.height - n.textBox.height) / 2, n.baseline = n.textBox.top + r.actualBoundingBoxAscent, c += n.contentBox.width + n.style.letterSpacing, i.contentBox.height < n.contentBox.height && (d = n), i.contentBox.left = Math.min(i.contentBox.left, n.contentBox.left), i.contentBox.top = Math.min(i.contentBox.top, n.contentBox.top), i.contentBox.height = Math.max(i.contentBox.height, n.contentBox.height), i.lineBox.height = Math.max(i.lineBox.height, n.inlineBox.height);
56
58
  }
57
- const B = e.fragments[e.fragments.length - 1];
58
- e.contentBox.width = Math.max(
59
- e.contentBox.width,
59
+ const B = i.fragments[i.fragments.length - 1];
60
+ i.contentBox.width = Math.max(
61
+ i.contentBox.width,
60
62
  B ? B.contentBox.left + Math.max(B.contentBox.width, B.textBox.width) : 0
61
- ), e.lineBox.left = 0, e.lineBox.top = h, e.lineBox.width = Math.max(i, e.contentBox.width), this._setContextStyle({
62
- ...(d ?? e).style,
63
+ ), i.lineBox.left = 0, i.lineBox.top = e, i.lineBox.width = Math.max(o, i.contentBox.width), this._setContextStyle({
64
+ ...(d ?? i).style,
63
65
  textAlign: "left",
64
66
  verticalAlign: "baseline"
65
67
  });
66
- const f = o.measureText("X");
67
- e.baseline = e.lineBox.top + (e.lineBox.height - f.actualBoundingBoxAscent + f.actualBoundingBoxDescent) / 2 + f.actualBoundingBoxAscent, h += e.lineBox.height;
68
+ const f = l.measureText("X");
69
+ i.baseline = i.lineBox.top + (i.lineBox.height - f.actualBoundingBoxAscent + f.actualBoundingBoxDescent) / 2 + f.actualBoundingBoxAscent, e += i.lineBox.height;
68
70
  }
69
- const a = l.reduce((c, x) => (c.left = Math.min(c.left, x.lineBox.left), c.top = Math.min(c.top, x.lineBox.top), c.width = Math.max(c.width, x.lineBox.width), c.height += x.lineBox.height, c), { left: 0, top: 0, width: 0, height: 0 });
70
- for (let c = l.length, x = 0; x < c; x++) {
71
- const e = l[x];
72
- e.fragments.forEach((s) => {
73
- const d = s.inlineBox.left, B = s.inlineBox.top, f = e.lineBox.height - s.inlineBox.height;
74
- switch (s.style.textAlign) {
71
+ for (let h = t.length, s = 0; s < h; s++) {
72
+ const i = t[s];
73
+ i.fragments.forEach((c) => {
74
+ const d = c.inlineBox.left, B = c.inlineBox.top, f = i.lineBox.height - c.inlineBox.height;
75
+ switch (c.style.textAlign) {
75
76
  case "end":
76
77
  case "right":
77
- s.inlineBox.left += e.lineBox.width - e.contentBox.width;
78
+ c.inlineBox.left += i.lineBox.width - i.contentBox.width;
78
79
  break;
79
80
  case "center":
80
- s.inlineBox.left += (e.lineBox.width - e.contentBox.width) / 2;
81
+ c.inlineBox.left += (i.lineBox.width - i.contentBox.width) / 2;
81
82
  break;
82
83
  case "start":
83
84
  case "left":
84
85
  default:
85
- s.inlineBox.left += e.lineBox.left;
86
+ c.inlineBox.left += i.lineBox.left;
86
87
  break;
87
88
  }
88
- switch (s.style.verticalAlign) {
89
+ switch (c.style.verticalAlign) {
89
90
  case "top":
90
- s.inlineBox.top = e.lineBox.top;
91
+ c.inlineBox.top = i.lineBox.top;
91
92
  break;
92
93
  case "middle":
93
- s.inlineBox.top = e.lineBox.top + f / 2;
94
+ c.inlineBox.top = i.lineBox.top + f / 2;
94
95
  break;
95
96
  case "bottom":
96
- s.inlineBox.top = e.lineBox.top + f;
97
+ c.inlineBox.top = i.lineBox.top + f;
97
98
  break;
98
99
  case "sub":
99
100
  case "text-top":
@@ -101,159 +102,153 @@ class w {
101
102
  break;
102
103
  case "baseline":
103
104
  default:
104
- s.inlineBox.height < e.lineBox.height && (s.inlineBox.top += e.baseline - s.baseline);
105
+ c.inlineBox.height < i.lineBox.height && (c.inlineBox.top += i.baseline - c.baseline);
105
106
  break;
106
107
  }
107
- const n = s.inlineBox.left - d, r = s.inlineBox.top - B;
108
- s.contentBox.left += n, s.contentBox.top += r, s.textBox.left += n, s.textBox.top += r;
108
+ const n = c.inlineBox.left - d, r = c.inlineBox.top - B;
109
+ c.contentBox.left += n, c.contentBox.top += r, c.textBox.left += n, c.textBox.top += r;
109
110
  });
110
111
  }
111
- return { ...a, paragraphs: l };
112
+ const x = t.reduce((h, s) => (h.left = Math.min(h.left, s.contentBox.left), h.top = Math.min(h.top, s.contentBox.top), h.width = Math.max(h.width, s.contentBox.width), h.height += s.contentBox.height, h), { left: 0, top: 0, width: 0, height: 0 });
113
+ return { lineBox: t.reduce((h, s) => (h.left = Math.min(h.left, s.lineBox.left), h.top = Math.min(h.top, s.lineBox.top), h.width = Math.max(h.width, s.lineBox.width), h.height += s.lineBox.height, h), { left: 0, top: 0, width: 0, height: 0 }), contentBox: x, paragraphs: t };
112
114
  }
113
- _createParagraphs(i) {
114
- const t = (h = {}) => {
115
- const { width: a, height: c, ...x } = this.style;
115
+ _createParagraphs(o) {
116
+ const t = (x = {}) => {
117
+ const { width: a, height: h, ...s } = this.style;
116
118
  return {
117
119
  contentBox: { left: 0, top: 0, width: 0, height: 0 },
118
120
  lineBox: { left: 0, top: 0, width: 0, height: 0 },
119
121
  baseline: 0,
120
122
  fragments: [],
121
- ...h,
123
+ ...x,
122
124
  style: {
123
- ...x,
124
- ...h.style
125
+ ...s,
126
+ ...x.style
125
127
  }
126
128
  };
127
- }, l = (h = {}) => {
128
- const a = [], { width: c, height: x, ...e } = this.style;
129
+ }, l = (x = {}) => {
130
+ const a = [], { width: h, height: s, ...i } = this.style;
129
131
  return a.push({
130
132
  contentBox: { left: 0, top: 0, width: 0, height: 0 },
131
133
  inlineBox: { left: 0, top: 0, width: 0, height: 0 },
132
134
  textBox: { left: 0, top: 0, width: 0, height: 0 },
133
135
  baseline: 0,
134
- ...h,
136
+ ...x,
135
137
  style: {
136
- ...e,
137
- ...h.style
138
+ ...i,
139
+ ...x.style
138
140
  },
139
- content: h.content ?? ""
141
+ content: x.content ?? ""
140
142
  }), a;
141
- }, o = [];
142
- if (typeof i == "string")
143
- o.push(t({ fragments: l({ content: i }) }));
143
+ }, e = [];
144
+ if (typeof o == "string")
145
+ e.push(t({ fragments: l({ content: o }) }));
144
146
  else {
145
- i = Array.isArray(i) ? i : [i];
146
- for (const h of i)
147
- if ("fragments" in h) {
148
- const { fragments: a, ...c } = h, x = t({ style: c });
149
- for (const e of a) {
150
- const { content: s, ...d } = e;
151
- x.fragments.push(...l({ content: s, style: { ...c, ...d } }));
147
+ o = Array.isArray(o) ? o : [o];
148
+ for (const x of o)
149
+ if ("fragments" in x) {
150
+ const { fragments: a, ...h } = x, s = t({ style: h });
151
+ for (const i of a) {
152
+ const { content: c, ...d } = i;
153
+ s.fragments.push(...l({ content: c, style: { ...h, ...d } }));
152
154
  }
153
- o.push(x);
154
- } else if ("content" in h) {
155
- const { content: a, ...c } = h, x = t({ style: c });
156
- x.fragments.push(...l({ content: a, style: c })), o.push(x);
155
+ e.push(s);
156
+ } else if ("content" in x) {
157
+ const { content: a, ...h } = x, s = t({ style: h });
158
+ s.fragments.push(...l({ content: a, style: h })), e.push(s);
157
159
  }
158
160
  }
159
- return o;
161
+ return e;
160
162
  }
161
- _createWrapedParagraphs(i, t) {
162
- const l = [], o = i.slice();
163
- let h, a;
164
- for (; h = o.shift(); ) {
165
- const c = h.fragments.slice();
166
- let x = 0;
167
- const e = [];
168
- let s = !0;
169
- for (; a = c.shift(); ) {
170
- const d = a.style;
163
+ _createWrapedParagraphs(o, t) {
164
+ const l = (s) => JSON.parse(JSON.stringify(s)), e = [], x = o.slice();
165
+ let a, h;
166
+ for (; a = x.shift(); ) {
167
+ const s = a.fragments.slice();
168
+ let i = 0;
169
+ const c = [];
170
+ for (; h = s.shift(); ) {
171
+ const d = h.style;
171
172
  this._setContextStyle(d);
172
173
  let B = "", f = !1;
173
- for (const n of a.content) {
174
- const r = this.context.measureText(n).width + (s ? 0 : d.letterSpacing), u = /^[\r\n]$/.test(n);
175
- if (u || d.textWrap === "wrap" && t && x + r > t) {
176
- let g = u ? B.length + 1 : B.length;
177
- !x && !g && (B += n, g++), B.length && e.push({ ...a, text: B }), e.length && (l.push({
178
- baseline: h.baseline,
179
- style: { ...h.style },
180
- contentBox: { ...h.contentBox },
181
- lineBox: { ...h.lineBox },
182
- fragments: e.slice()
183
- }), e.length = 0);
184
- const p = a.content.substring(g);
185
- (p.length || c.length) && o.unshift({
186
- baseline: h.baseline,
187
- style: { ...h.style },
188
- contentBox: { ...h.contentBox },
189
- lineBox: { ...h.lineBox },
190
- fragments: (p.length ? [{ ...a, content: p }] : []).concat(c.slice())
191
- }), c.length = 0, f = !0;
174
+ for (const n of h.content) {
175
+ const r = this.context.measureText(n).width, w = /^[\r\n]$/.test(n);
176
+ if (w || d.textWrap === "wrap" && t && i + r > t) {
177
+ let g = w ? B.length + 1 : B.length;
178
+ !i && !g && (B += n, g++), B.length && c.push({ ...l(h), content: B }), c.length && (e.push({
179
+ ...l(a),
180
+ fragments: c.slice()
181
+ }), c.length = 0);
182
+ const p = h.content.substring(g);
183
+ (p.length || s.length) && x.unshift({
184
+ ...l(a),
185
+ fragments: (p.length ? [{ ...l(h), content: p }] : []).concat(s.slice())
186
+ }), s.length = 0, f = !0;
192
187
  break;
193
188
  } else
194
- x += r;
189
+ i += r;
195
190
  B += n;
196
191
  }
197
- f || e.push({ ...a }), s = !1;
192
+ f || c.push(l(h));
198
193
  }
199
- e.length && l.push({ ...h, fragments: e });
194
+ c.length && e.push({ ...l(a), fragments: c });
200
195
  }
201
- return l;
196
+ return e;
202
197
  }
203
- _draw(i) {
198
+ _draw(o) {
204
199
  const t = this.context;
205
- this.style.backgroundColor && (t.fillStyle = this.style.backgroundColor, t.fillRect(0, 0, t.canvas.width, t.canvas.height)), i.forEach((l) => {
200
+ this.style.backgroundColor && (t.fillStyle = this.style.backgroundColor, t.fillRect(0, 0, t.canvas.width, t.canvas.height)), o.forEach((l) => {
206
201
  l.style.backgroundColor && (t.fillStyle = l.style.backgroundColor, t.fillRect(l.lineBox.left, l.lineBox.top, l.lineBox.width, l.lineBox.height));
207
- }), i.forEach((l) => {
208
- l.fragments.forEach((o) => {
209
- switch (o.style.backgroundColor && (t.fillStyle = o.style.backgroundColor, t.fillRect(o.inlineBox.left, o.inlineBox.top, o.inlineBox.width, o.inlineBox.height)), this._setContextStyle({
210
- ...o.style,
202
+ }), o.forEach((l) => {
203
+ l.fragments.forEach((e) => {
204
+ switch (e.style.backgroundColor && (t.fillStyle = e.style.backgroundColor, t.fillRect(e.inlineBox.left, e.inlineBox.top, e.inlineBox.width, e.inlineBox.height)), this._setContextStyle({
205
+ ...e.style,
211
206
  textAlign: "left",
212
207
  verticalAlign: "top"
213
- }), o.style.textStrokeWidth && t.strokeText(o.content, o.contentBox.left, o.contentBox.top), t.fillText(o.content, o.contentBox.left, o.contentBox.top), o.style.textDecoration) {
208
+ }), e.style.textStrokeWidth && t.strokeText(e.content, e.contentBox.left, e.contentBox.top), t.fillText(e.content, e.contentBox.left, e.contentBox.top), e.style.textDecoration) {
214
209
  case "underline":
215
- t.beginPath(), t.moveTo(o.contentBox.left, o.contentBox.top + o.contentBox.height - 2), t.lineTo(o.contentBox.left + o.contentBox.width, o.contentBox.top + o.contentBox.height - 2), t.stroke();
210
+ t.beginPath(), t.moveTo(e.contentBox.left, e.contentBox.top + e.contentBox.height - 2), t.lineTo(e.contentBox.left + e.contentBox.width, e.contentBox.top + e.contentBox.height - 2), t.stroke();
216
211
  break;
217
212
  case "line-through":
218
- t.beginPath(), t.moveTo(o.contentBox.left, o.contentBox.top + o.contentBox.height / 2), t.lineTo(o.contentBox.left + o.contentBox.width, o.contentBox.top + o.contentBox.height / 2), t.stroke();
213
+ t.beginPath(), t.moveTo(e.contentBox.left, e.contentBox.top + e.contentBox.height / 2), t.lineTo(e.contentBox.left + e.contentBox.width, e.contentBox.top + e.contentBox.height / 2), t.stroke();
219
214
  break;
220
215
  }
221
216
  });
222
217
  });
223
218
  }
224
- _resizeView(i, t) {
219
+ _resizeView(o, t) {
225
220
  const l = this.view;
226
- l.style.width = `${i}px`, l.style.height = `${t}px`, l.dataset.width = String(i), l.dataset.height = String(t), l.width = Math.max(1, Math.floor(i * this.pixelRatio)), l.height = Math.max(1, Math.floor(t * this.pixelRatio));
221
+ l.style.width = `${o}px`, l.style.height = `${t}px`, l.dataset.width = String(o), l.dataset.height = String(t), l.width = Math.max(1, Math.floor(o * this.pixelRatio)), l.height = Math.max(1, Math.floor(t * this.pixelRatio));
227
222
  }
228
- _setContextStyle(i) {
223
+ _setContextStyle(o) {
229
224
  const t = this.context;
230
- switch (t.shadowColor = i.shadowColor, t.shadowOffsetX = i.shadowOffsetX, t.shadowOffsetY = i.shadowOffsetY, t.shadowBlur = i.shadowBlur, t.strokeStyle = i.textStrokeColor, t.lineWidth = i.textStrokeWidth, t.fillStyle = i.color, t.direction = i.direction, t.textAlign = i.textAlign, i.verticalAlign) {
225
+ switch (t.shadowColor = o.shadowColor, t.shadowOffsetX = o.shadowOffsetX, t.shadowOffsetY = o.shadowOffsetY, t.shadowBlur = o.shadowBlur, t.strokeStyle = o.textStrokeColor, t.lineWidth = o.textStrokeWidth, t.fillStyle = o.color, t.direction = o.direction, t.textAlign = o.textAlign, o.verticalAlign) {
231
226
  case "baseline":
232
227
  t.textBaseline = "alphabetic";
233
228
  break;
234
229
  case "top":
235
230
  case "middle":
236
231
  case "bottom":
237
- t.textBaseline = i.verticalAlign;
232
+ t.textBaseline = o.verticalAlign;
238
233
  break;
239
234
  }
240
235
  t.font = [
241
- i.fontStyle,
242
- i.fontWeight,
243
- `${i.fontSize}px`,
244
- i.fontFamily
245
- ].join(" "), t.fontKerning = i.fontKerning, t.letterSpacing = `${i.letterSpacing}px`;
236
+ o.fontStyle,
237
+ o.fontWeight,
238
+ `${o.fontSize}px`,
239
+ o.fontFamily
240
+ ].join(" "), t.fontKerning = o.fontKerning, t.letterSpacing = `${o.letterSpacing}px`;
246
241
  }
247
242
  update() {
248
- const i = this.context;
243
+ const o = this.context;
249
244
  let { width: t, height: l } = this.style;
250
245
  t === "auto" && (t = 0), l === "auto" && (l = 0);
251
- const o = this.measure(t, l);
252
- t || (t = o.width), l = Math.max(l, o.height), this._resizeView(t, l);
253
- const h = this.pixelRatio;
254
- i.scale(h, h), i.clearRect(0, 0, i.canvas.width, i.canvas.height), this._draw(o.paragraphs);
246
+ const { lineBox: e, paragraphs: x } = this.measure();
247
+ t || (t = e.width), l = Math.max(l, e.height), this._resizeView(t, l);
248
+ const a = this.pixelRatio;
249
+ o.scale(a, a), o.clearRect(0, 0, o.canvas.width, o.canvas.height), this._draw(x);
255
250
  }
256
251
  }
257
252
  export {
258
- w as Text
253
+ u as Text
259
254
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modern-text",
3
3
  "type": "module",
4
- "version": "0.0.6",
4
+ "version": "0.0.7",
5
5
  "packageManager": "pnpm@8.14.1",
6
6
  "description": "Text measurement and rendering of canvas 2d",
7
7
  "author": "wxm",
package/types/Text.d.ts CHANGED
@@ -61,14 +61,16 @@ export interface TextParagraphWithFragmentsAndStyle extends Partial<TextFragment
61
61
  export interface TextFragmentWithStyle extends Partial<TextFragmentStyle> {
62
62
  content: string;
63
63
  }
64
- export type TextData = string | TextParagraphWithContentAndStyle | TextParagraphWithFragmentsAndStyle | Array<TextParagraphWithContentAndStyle | TextParagraphWithFragmentsAndStyle>;
64
+ export type TextContent = string | TextParagraphWithContentAndStyle | TextParagraphWithFragmentsAndStyle | Array<TextParagraphWithContentAndStyle | TextParagraphWithFragmentsAndStyle>;
65
65
  export interface TextOptions {
66
66
  view?: HTMLCanvasElement;
67
67
  pixelRatio?: number;
68
- content?: TextData;
68
+ content?: TextContent;
69
69
  style?: Partial<TextStyle>;
70
70
  }
71
- export interface MeasureResult extends BoundingBox {
71
+ export interface MeasureResult {
72
+ contentBox: BoundingBox;
73
+ lineBox: BoundingBox;
72
74
  paragraphs: Array<TextParagraph>;
73
75
  }
74
76
  export declare class Text {
@@ -77,10 +79,10 @@ export declare class Text {
77
79
  readonly context: CanvasRenderingContext2D;
78
80
  pixelRatio: number;
79
81
  style: TextStyle;
80
- content: TextData;
82
+ content: TextContent;
81
83
  constructor(options?: TextOptions);
82
- measure(width?: number, _height?: number): MeasureResult;
83
- protected _createParagraphs(content: TextData): Array<TextParagraph>;
84
+ measure(): MeasureResult;
85
+ protected _createParagraphs(content: TextContent): Array<TextParagraph>;
84
86
  protected _createWrapedParagraphs(paragraphs: Array<TextParagraph>, width: number): Array<TextParagraph>;
85
87
  protected _draw(paragraphs: Array<TextParagraph>): void;
86
88
  protected _resizeView(width: number, height: number): void;