@@ -41,60 +41,59 @@ const COLOR_MAP: Record<string, string> = {
4141 black : '#000000' ,
4242}
4343
44- type JsonTextComponent =
45- | string
46- | JsonTextArray
47- | {
48- text ?: string
49- font ?: string
50- color ?: JsonTextColor
51- extra ?: JsonTextArray
52- bold ?: true | false
53- italic ?: true | false
54- underlined ?: true | false
55- strikethrough ?: true | false
56- obfuscated ?: true | false
57- insertion ?: string
58- clickEvent ?: {
59- action :
60- | 'open_url'
61- | 'open_file'
62- | 'run_command'
63- | 'suggest_command'
64- | 'change_page'
65- | 'copy_to_clipboard'
66- value : string
67- }
68- hoverEvent ?: {
69- action : 'show_text' | 'show_item' | 'show_entity'
70- contents :
71- | JsonTextComponent
72- | {
73- type : string
74- id : string
75- name ?: string
76- }
77- | {
78- id : string
79- count ?: number
80- tag ?: string
81- }
82- }
83- tl ?: string
84- with ?: JsonTextArray
85- score ?: {
86- name : string
87- objective : string
88- value ?: number
89- }
90- selector ?: string
91- separator ?: string
92- keybind ?: string
93- nbt ?: string
94- block ?: string
95- entity ?: string
96- storage ?: string
97- }
44+ type JsonTextObject = {
45+ text ?: string
46+ font ?: string
47+ color ?: JsonTextColor
48+ extra ?: JsonTextArray
49+ bold ?: true | false
50+ italic ?: true | false
51+ underlined ?: true | false
52+ strikethrough ?: true | false
53+ obfuscated ?: true | false
54+ insertion ?: string
55+ clickEvent ?: {
56+ action :
57+ | 'open_url'
58+ | 'open_file'
59+ | 'run_command'
60+ | 'suggest_command'
61+ | 'change_page'
62+ | 'copy_to_clipboard'
63+ value : string
64+ }
65+ hoverEvent ?: {
66+ action : 'show_text' | 'show_item' | 'show_entity'
67+ contents :
68+ | JsonTextComponent
69+ | {
70+ type : string
71+ id : string
72+ name ?: string
73+ }
74+ | {
75+ id : string
76+ count ?: number
77+ tag ?: string
78+ }
79+ }
80+ tl ?: string
81+ with ?: JsonTextArray
82+ score ?: {
83+ name : string
84+ objective : string
85+ value ?: number
86+ }
87+ selector ?: string
88+ separator ?: string
89+ keybind ?: string
90+ nbt ?: string
91+ block ?: string
92+ entity ?: string
93+ storage ?: string
94+ }
95+
96+ type JsonTextComponent = string | JsonTextArray | JsonTextObject
9897
9998type JsonTextArray = JsonTextComponent [ ] | string [ ]
10099
@@ -112,30 +111,136 @@ export class JsonText {
112111 return this . text
113112 }
114113
115- renderToCanvas ( ) : CanvasFrame {
116- const canvas = new CanvasFrame ( 1 , 1 )
114+ renderToCanvas ( ) : TextCanvas {
115+ const textCanvas = new TextCanvas ( )
116+
117+ this . _renderToCanvas ( this . text , textCanvas )
118+ // textCanvas.canvas.width = textCanvas.width
119+ // textCanvas.canvas.height = textCanvas.height
120+ textCanvas . render ( )
121+
122+ return textCanvas
123+ }
124+
125+ private _renderToCanvas ( comp : JsonTextComponent , textCanvas : TextCanvas ) {
126+ if ( comp instanceof Array ) {
127+ console . log ( 'array' , comp )
128+ comp . forEach ( c => this . _renderToCanvas ( c , textCanvas ) )
129+ } else if ( typeof comp === 'string' ) {
130+ console . log ( 'string' , comp )
131+ } else {
132+ console . log ( 'obj' , comp )
133+ this . _renderObj ( comp , textCanvas )
134+ }
135+ }
136+
137+ private _renderObj ( obj : JsonTextObject , textCanvas : TextCanvas ) {
138+ const writeOptions : Record < string , any > = { }
139+ // canvas.ctx.font = FONT
140+ if ( obj . color )
141+ writeOptions . fillStyle = obj . color [ 0 ] === '#' ? obj . color : COLOR_MAP [ obj . color ]
142+
143+ if ( obj . bold ) writeOptions . font = 'bold ' + FONT
144+ if ( obj . italic ) writeOptions . font = 'italic ' + FONT
145+ // if (obj.underlined) canvas.canvas.style.textDecoration = 'underline'
146+ // if (obj.strikethrough) canvas.canvas.style.textDecoration = 'line-through'
147+ // if (obj.obfuscated) canvas.canvas.style.textDecoration = 'blink'
148+
149+ if ( obj . text ) {
150+ textCanvas . write ( obj . text , writeOptions )
151+ } else if ( obj . score ) {
152+ textCanvas . write (
153+ obj . score . value === undefined
154+ ? `(${ obj . score . name } ${ obj . score . objective } )`
155+ : obj . score . value . toString ( ) ,
156+ writeOptions
157+ )
158+ } else if ( obj . nbt ) {
159+ let text = `${ obj . nbt } `
160+ if ( obj . block ) text += ` ${ obj . block } `
161+ else if ( obj . entity ) text += ` ${ obj . entity } `
162+ else if ( obj . storage ) text += ` ${ obj . storage } `
163+ textCanvas . write ( text , writeOptions )
164+ } else if ( obj . selector ) {
165+ textCanvas . write ( `(${ obj . selector } )` , writeOptions )
166+ }
167+ }
168+ }
169+
170+ interface TextBit {
171+ canvas : CanvasFrame
172+ posX : number
173+ posY : number
174+ }
175+
176+ class TextCanvas {
177+ canvasFrame : CanvasFrame
178+ canvas : HTMLCanvasElement
179+ ctx : CanvasRenderingContext2D
180+
181+ private textBits : TextBit [ ] = [ ]
182+
183+ currentX = 0
184+ currentY = 0
185+
186+ constructor ( ) {
187+ this . canvasFrame = new CanvasFrame ( 1 , 1 )
188+ this . canvas = this . canvasFrame . canvas
189+ this . ctx = this . canvasFrame . ctx
190+ }
191+
192+ get width ( ) {
193+ return this . canvas . width
194+ }
195+
196+ set width ( width : number ) {
197+ this . canvas . width = width
198+ }
199+
200+ get height ( ) {
201+ return this . canvas . height
202+ }
203+
204+ set height ( height : number ) {
205+ this . canvas . height = height
206+ }
207+
208+ write ( text : string , writeOptions : Record < string , any > = { } ) {
209+ const measure = new CanvasFrame ( 1 , 1 )
210+ measure . ctx . font = FONT
211+ measure . ctx . filter = PIXEL_FILTER
212+ const metrics = measure . ctx . measureText ( text )
213+ const width = Math . ceil ( metrics . width )
214+ const height = Math . ceil ( metrics . fontBoundingBoxAscent + metrics . fontBoundingBoxDescent )
215+
216+ const canvas = new CanvasFrame ( width , height )
117217 canvas . ctx . font = FONT
118218 canvas . ctx . filter = PIXEL_FILTER
219+ canvas . ctx . fillStyle = '#ffffff'
220+ canvas . ctx . textBaseline = 'top'
119221
120- function recurse ( text : JsonTextComponent ) {
121- if ( text instanceof Array ) {
122- text . forEach ( recurse )
123- } else if ( typeof text === 'string' ) {
124- //
125- } else {
126- canvas . ctx . fillStyle = text . color
127- ? text . color [ 0 ] === '#'
128- ? text . color
129- : COLOR_MAP [ text . color ]
130- : '#FFFFFF'
131- }
132- }
222+ Object . assign ( canvas . ctx , writeOptions )
223+
224+ canvas . ctx . fillText ( text , 0 , 0 )
133225
134- recurse ( this . text )
226+ this . textBits . push ( { canvas , posX : this . currentX , posY : this . currentY } )
135227
136- // canvas.canvas.width = 0
137- // canvas.canvas.height = 0
228+ this . currentX += width
229+ // this.currentY += height
230+ }
231+
232+ render ( ) {
233+ console . log ( 'rendering' , this . textBits )
234+
235+ const totalWidth = this . textBits . reduce ( ( acc , bit ) => acc + bit . canvas . width , 0 )
236+ const totalHeight = this . textBits . reduce ( ( acc , bit ) => Math . max ( acc , bit . canvas . height ) , 0 )
138237
139- return canvas
238+ this . width = totalWidth
239+ this . height = totalHeight
240+
241+ for ( const bit of this . textBits ) {
242+ console . log ( 'drawing' , bit )
243+ this . ctx . drawImage ( bit . canvas . canvas , bit . posX , bit . posY )
244+ }
140245 }
141246}
0 commit comments