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 +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +124 -129
- package/package.json +1 -1
- package/types/Text.d.ts +8 -6
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class
|
|
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(
|
|
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
|
|
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(
|
|
27
|
+
constructor(o = {}) {
|
|
28
28
|
const {
|
|
29
29
|
view: t = document.createElement("canvas"),
|
|
30
30
|
pixelRatio: l = window.devicePixelRatio || 1,
|
|
31
|
-
content:
|
|
32
|
-
style:
|
|
33
|
-
} =
|
|
34
|
-
this.view = t, this.context = t.getContext("2d"), this.pixelRatio = l, this.content =
|
|
35
|
-
...
|
|
36
|
-
...
|
|
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(
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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 =
|
|
55
|
-
n.inlineBox.left =
|
|
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 =
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
),
|
|
62
|
-
...(d ??
|
|
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 =
|
|
67
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
78
|
+
c.inlineBox.left += i.lineBox.width - i.contentBox.width;
|
|
78
79
|
break;
|
|
79
80
|
case "center":
|
|
80
|
-
|
|
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
|
-
|
|
86
|
+
c.inlineBox.left += i.lineBox.left;
|
|
86
87
|
break;
|
|
87
88
|
}
|
|
88
|
-
switch (
|
|
89
|
+
switch (c.style.verticalAlign) {
|
|
89
90
|
case "top":
|
|
90
|
-
|
|
91
|
+
c.inlineBox.top = i.lineBox.top;
|
|
91
92
|
break;
|
|
92
93
|
case "middle":
|
|
93
|
-
|
|
94
|
+
c.inlineBox.top = i.lineBox.top + f / 2;
|
|
94
95
|
break;
|
|
95
96
|
case "bottom":
|
|
96
|
-
|
|
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
|
-
|
|
105
|
+
c.inlineBox.height < i.lineBox.height && (c.inlineBox.top += i.baseline - c.baseline);
|
|
105
106
|
break;
|
|
106
107
|
}
|
|
107
|
-
const n =
|
|
108
|
-
|
|
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
|
-
|
|
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(
|
|
114
|
-
const t = (
|
|
115
|
-
const { width: a, height:
|
|
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
|
-
...
|
|
123
|
+
...x,
|
|
122
124
|
style: {
|
|
123
|
-
...
|
|
124
|
-
...
|
|
125
|
+
...s,
|
|
126
|
+
...x.style
|
|
125
127
|
}
|
|
126
128
|
};
|
|
127
|
-
}, l = (
|
|
128
|
-
const a = [], { width:
|
|
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
|
-
...
|
|
136
|
+
...x,
|
|
135
137
|
style: {
|
|
136
|
-
...
|
|
137
|
-
...
|
|
138
|
+
...i,
|
|
139
|
+
...x.style
|
|
138
140
|
},
|
|
139
|
-
content:
|
|
141
|
+
content: x.content ?? ""
|
|
140
142
|
}), a;
|
|
141
|
-
},
|
|
142
|
-
if (typeof
|
|
143
|
-
|
|
143
|
+
}, e = [];
|
|
144
|
+
if (typeof o == "string")
|
|
145
|
+
e.push(t({ fragments: l({ content: o }) }));
|
|
144
146
|
else {
|
|
145
|
-
|
|
146
|
-
for (const
|
|
147
|
-
if ("fragments" in
|
|
148
|
-
const { fragments: a, ...
|
|
149
|
-
for (const
|
|
150
|
-
const { content:
|
|
151
|
-
|
|
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
|
-
|
|
154
|
-
} else if ("content" in
|
|
155
|
-
const { content: a, ...
|
|
156
|
-
|
|
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
|
|
161
|
+
return e;
|
|
160
162
|
}
|
|
161
|
-
_createWrapedParagraphs(
|
|
162
|
-
const l = [],
|
|
163
|
-
let
|
|
164
|
-
for (;
|
|
165
|
-
const
|
|
166
|
-
let
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
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
|
|
174
|
-
const r = this.context.measureText(n).width
|
|
175
|
-
if (
|
|
176
|
-
let g =
|
|
177
|
-
!
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
189
|
+
i += r;
|
|
195
190
|
B += n;
|
|
196
191
|
}
|
|
197
|
-
f ||
|
|
192
|
+
f || c.push(l(h));
|
|
198
193
|
}
|
|
199
|
-
|
|
194
|
+
c.length && e.push({ ...l(a), fragments: c });
|
|
200
195
|
}
|
|
201
|
-
return
|
|
196
|
+
return e;
|
|
202
197
|
}
|
|
203
|
-
_draw(
|
|
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)),
|
|
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
|
-
}),
|
|
208
|
-
l.fragments.forEach((
|
|
209
|
-
switch (
|
|
210
|
-
...
|
|
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
|
-
}),
|
|
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(
|
|
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(
|
|
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(
|
|
219
|
+
_resizeView(o, t) {
|
|
225
220
|
const l = this.view;
|
|
226
|
-
l.style.width = `${
|
|
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(
|
|
223
|
+
_setContextStyle(o) {
|
|
229
224
|
const t = this.context;
|
|
230
|
-
switch (t.shadowColor =
|
|
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 =
|
|
232
|
+
t.textBaseline = o.verticalAlign;
|
|
238
233
|
break;
|
|
239
234
|
}
|
|
240
235
|
t.font = [
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
`${
|
|
244
|
-
|
|
245
|
-
].join(" "), t.fontKerning =
|
|
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
|
|
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
|
|
252
|
-
t || (t =
|
|
253
|
-
const
|
|
254
|
-
|
|
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
|
-
|
|
253
|
+
u as Text
|
|
259
254
|
};
|
package/package.json
CHANGED
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
|
|
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?:
|
|
68
|
+
content?: TextContent;
|
|
69
69
|
style?: Partial<TextStyle>;
|
|
70
70
|
}
|
|
71
|
-
export interface MeasureResult
|
|
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:
|
|
82
|
+
content: TextContent;
|
|
81
83
|
constructor(options?: TextOptions);
|
|
82
|
-
measure(
|
|
83
|
-
protected _createParagraphs(content:
|
|
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;
|