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