@@ -2,7 +2,12 @@ import parseASCII from "parse-bmfont-ascii";
2
2
import parseXML from "parse-bmfont-xml" ;
3
3
import readBinary from "parse-bmfont-binary" ;
4
4
import { BmCharacter , BmKerning , BmFont , BmCommonProps } from "./types.js" ;
5
+ import png from "@jimp/js-png" ;
6
+ import { createJimp } from "@jimp/core" ;
7
+ import path from "path" ;
8
+ import { convertXML } from "simple-xml-to-json" ;
5
9
10
+ const CharacterJimp = createJimp ( { formats : [ png ] } ) ;
6
11
const HEADER = Buffer . from ( [ 66 , 77 , 70 , 3 ] ) ;
7
12
8
13
function isBinary ( buf : Buffer | string ) {
@@ -20,17 +25,16 @@ function isBinary(buf: Buffer | string) {
20
25
) ;
21
26
}
22
27
23
- function parseFont (
24
- file : string ,
25
- data : Buffer | string ,
26
- ) : {
28
+ export interface LoadedFont {
27
29
chars : BmCharacter [ ] ;
28
30
kernings : BmKerning [ ] ;
29
31
common : BmCommonProps ;
30
32
// eslint-disable-next-line @typescript-eslint/no-explicit-any
31
33
info : Record < string , any > ;
32
34
pages : string [ ] ;
33
- } {
35
+ }
36
+
37
+ function parseFont ( file : string , data : Buffer | string ) : LoadedFont {
34
38
if ( isBinary ( data ) ) {
35
39
if ( typeof data === "string" ) {
36
40
data = Buffer . from ( data , "binary" ) ;
@@ -52,13 +56,70 @@ function parseFont(
52
56
return parseASCII ( data ) ;
53
57
}
54
58
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ function parseNumbersInObject < T extends Record < string , any > > ( obj : T ) {
61
+ for ( const key in obj ) {
62
+ try {
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ ( obj as any ) [ key ] = parseInt ( obj [ key ] , 10 ) ;
65
+ } catch {
66
+ // do nothing
67
+ }
68
+
69
+ if ( typeof obj [ key ] === "object" ) {
70
+ parseNumbersInObject ( obj [ key ] ) ;
71
+ }
72
+ }
73
+
74
+ return obj ;
75
+ }
76
+
55
77
/**
56
78
*
57
79
* @param bufferOrUrl A URL to a file or a buffer
58
80
* @returns
59
81
*/
60
- async function loadBitmapFontData ( bufferOrUrl : string | Buffer ) {
61
- if ( typeof bufferOrUrl === "string" ) {
82
+ export async function loadBitmapFontData (
83
+ bufferOrUrl : string | Buffer
84
+ ) : Promise < LoadedFont > {
85
+ const isWebWorker = self . document === undefined ;
86
+
87
+ if ( isWebWorker && typeof bufferOrUrl === "string" ) {
88
+ const res = await fetch ( bufferOrUrl ) ;
89
+ const text = await res . text ( ) ;
90
+ const json = convertXML ( text ) ;
91
+
92
+ const font = json . font . children . reduce (
93
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
+ ( acc : Record < string , any > , i : any ) => ( { ...acc , ...i } ) ,
95
+ { }
96
+ ) ;
97
+ const pages : LoadedFont [ "pages" ] = [ ] ;
98
+ const chars : LoadedFont [ "chars" ] = [ ] ;
99
+ const kernings : LoadedFont [ "kernings" ] = [ ] ;
100
+
101
+ for ( let i = 0 ; i < font . pages . children . length ; i ++ ) {
102
+ const p = font . pages . children [ i ] . page ;
103
+ const id = parseInt ( p . id , 10 ) ;
104
+ pages [ id ] = parseNumbersInObject ( p . file ) ;
105
+ }
106
+
107
+ for ( let i = 0 ; i < font . chars . children . length ; i ++ ) {
108
+ chars . push ( parseNumbersInObject ( font . chars . children [ i ] . char ) ) ;
109
+ }
110
+
111
+ for ( let i = 0 ; i < font . kernings . children . length ; i ++ ) {
112
+ kernings . push ( parseNumbersInObject ( font . kernings . children [ i ] . kerning ) ) ;
113
+ }
114
+
115
+ return {
116
+ info : font . info ,
117
+ common : font . common ,
118
+ pages,
119
+ chars,
120
+ kernings,
121
+ } satisfies LoadedFont ;
122
+ } else if ( typeof bufferOrUrl === "string" ) {
62
123
const res = await fetch ( bufferOrUrl ) ;
63
124
const text = await res . text ( ) ;
64
125
@@ -69,11 +130,9 @@ async function loadBitmapFontData(bufferOrUrl: string | Buffer) {
69
130
}
70
131
71
132
type RawFont = Awaited < ReturnType < typeof loadBitmapFontData > > ;
133
+ export type ResolveBmFont = Omit < BmFont , "pages" > & Pick < RawFont , "pages" > ;
72
134
73
- export async function loadBitmapFont (
74
- bufferOrUrl : string | Buffer ,
75
- ) : Promise < Omit < BmFont , "pages" > & Pick < RawFont , "pages" > > {
76
- const font = await loadBitmapFontData ( bufferOrUrl ) ;
135
+ export async function processBitmapFont ( file : string , font : LoadedFont ) {
77
136
const chars : Record < string , BmCharacter > = { } ;
78
137
const kernings : Record < string , BmKerning > = { } ;
79
138
@@ -94,5 +153,10 @@ export async function loadBitmapFont(
94
153
...font ,
95
154
chars,
96
155
kernings,
156
+ pages : await Promise . all (
157
+ font . pages . map ( async ( page ) =>
158
+ CharacterJimp . read ( path . join ( path . dirname ( file ) , page ) )
159
+ )
160
+ ) ,
97
161
} ;
98
162
}
0 commit comments