@flighthq/bitmapfont-formats 0.3.0 → 0.3.1-next.1041.35b950c
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/bitmapFontFnt.d.ts +2 -2
- package/dist/bitmapFontFnt.d.ts.map +1 -1
- package/dist/bitmapFontFnt.js +19 -7
- package/dist/bitmapFontFnt.js.map +1 -1
- package/dist/bitmapFontJson.d.ts +2 -2
- package/dist/bitmapFontJson.d.ts.map +1 -1
- package/dist/bitmapFontJson.js +16 -6
- package/dist/bitmapFontJson.js.map +1 -1
- package/dist/bitmapFontRecord.d.ts +10 -1
- package/dist/bitmapFontRecord.d.ts.map +1 -1
- package/dist/bitmapFontRecord.js +27 -0
- package/dist/bitmapFontRecord.js.map +1 -1
- package/dist/bitmapFontXml.d.ts +2 -2
- package/dist/bitmapFontXml.d.ts.map +1 -1
- package/dist/bitmapFontXml.js +19 -7
- package/dist/bitmapFontXml.js.map +1 -1
- package/package.json +5 -4
- package/src/bitmapFontFnt.test.ts +68 -1
- package/src/bitmapFontJson.test.ts +15 -0
- package/src/bitmapFontRecord.test.ts +31 -2
- package/src/bitmapFontXml.test.ts +15 -0
package/dist/bitmapFontFnt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BitmapFont, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
1
|
+
import type { BitmapFont, ImportDiagnostic, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
2
2
|
export declare function formatBitmapFontFnt(font: Readonly<BitmapFont>): string;
|
|
3
|
-
export declare function parseBitmapFontFnt(text: string, options?: Readonly<BitmapFontParseOptions
|
|
3
|
+
export declare function parseBitmapFontFnt(text: string, options?: Readonly<BitmapFontParseOptions>, diagnostics?: ImportDiagnostic[]): BitmapFont | null;
|
|
4
4
|
//# sourceMappingURL=bitmapFontFnt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontFnt.d.ts","sourceRoot":"","sources":["../src/bitmapFontFnt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,
|
|
1
|
+
{"version":3,"file":"bitmapFontFnt.d.ts","sourceRoot":"","sources":["../src/bitmapFontFnt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAKhB,sBAAsB,EAGvB,MAAM,0BAA0B,CAAC;AAYlC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,CAwCtE;AAOD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAC1C,WAAW,CAAC,EAAE,gBAAgB,EAAE,GAC/B,UAAU,GAAG,IAAI,CAInB"}
|
package/dist/bitmapFontFnt.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getBitmapFontMetrics, unpackBitmapFontKerningKey } from '@flighthq/bitmapfont/contract';
|
|
2
|
-
import { buildBitmapFontFromRecord } from './bitmapFontRecord';
|
|
2
|
+
import { buildBitmapFontFromRecord, reportDroppedBitmapFontRecords } from './bitmapFontRecord';
|
|
3
3
|
// Re-emits a `BitmapFont` as the classic AngelCode/BMFont text `.fnt` (`info`/`common`/`page`/`char`/
|
|
4
4
|
// `kerning` lines of `key=value` pairs). Lossless for the fields the model carries — the glyph table
|
|
5
5
|
// (including each glyph's `page`), kerning pairs, encoding, and line metrics all round-trip
|
|
@@ -44,8 +44,8 @@ export function formatBitmapFontFnt(font) {
|
|
|
44
44
|
// values are bare tokens, quoted strings, or comma lists. The atlas page named on the `page` line is
|
|
45
45
|
// rehydrated through `options.resolvePage`. Returns the `null` sentinel — never throwing — when the
|
|
46
46
|
// text carries no `common` line metrics, no `char` records, or its atlas page cannot be resolved.
|
|
47
|
-
export function parseBitmapFontFnt(text, options) {
|
|
48
|
-
const record = parseBitmapFontFntRecord(text);
|
|
47
|
+
export function parseBitmapFontFnt(text, options, diagnostics) {
|
|
48
|
+
const record = parseBitmapFontFntRecord(text, diagnostics);
|
|
49
49
|
if (record === null)
|
|
50
50
|
return null;
|
|
51
51
|
return buildBitmapFontFromRecord(record, options);
|
|
@@ -53,12 +53,17 @@ export function parseBitmapFontFnt(text, options) {
|
|
|
53
53
|
// Parses the text `.fnt` into the neutral record, or `null` when required blocks are absent or
|
|
54
54
|
// malformed. Kept separate from `buildBitmapFontFromRecord` so the atlas-resolution step is shared
|
|
55
55
|
// across the text/XML/JSON front-ends.
|
|
56
|
-
function parseBitmapFontFntRecord(text) {
|
|
56
|
+
function parseBitmapFontFntRecord(text, diagnostics) {
|
|
57
57
|
let lineHeight = null;
|
|
58
58
|
let base = null;
|
|
59
59
|
const pages = [];
|
|
60
60
|
const chars = [];
|
|
61
61
|
const kernings = [];
|
|
62
|
+
// Counted and reported ONCE after the scan: a font carries thousands of char lines, and the seam's
|
|
63
|
+
// perf contract forbids a per-element crumb in a loop that size.
|
|
64
|
+
let droppedPages = 0;
|
|
65
|
+
let droppedChars = 0;
|
|
66
|
+
let droppedKernings = 0;
|
|
62
67
|
for (const rawLine of text.split(/\r\n?|\n/)) {
|
|
63
68
|
const line = rawLine.trim();
|
|
64
69
|
if (line === '')
|
|
@@ -72,20 +77,27 @@ function parseBitmapFontFntRecord(text) {
|
|
|
72
77
|
}
|
|
73
78
|
else if (tag === 'page') {
|
|
74
79
|
const id = readFntNumber(fields.id);
|
|
75
|
-
if (id
|
|
80
|
+
if (id === null)
|
|
81
|
+
droppedPages++;
|
|
82
|
+
else
|
|
76
83
|
pages.push({ file: fields.file ?? '', id });
|
|
77
84
|
}
|
|
78
85
|
else if (tag === 'char') {
|
|
79
86
|
const char = readFntChar(fields);
|
|
80
|
-
if (char
|
|
87
|
+
if (char === null)
|
|
88
|
+
droppedChars++;
|
|
89
|
+
else
|
|
81
90
|
chars.push(char);
|
|
82
91
|
}
|
|
83
92
|
else if (tag === 'kerning') {
|
|
84
93
|
const kerning = readFntKerning(fields);
|
|
85
|
-
if (kerning
|
|
94
|
+
if (kerning === null)
|
|
95
|
+
droppedKernings++;
|
|
96
|
+
else
|
|
86
97
|
kernings.push(kerning);
|
|
87
98
|
}
|
|
88
99
|
}
|
|
100
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseBitmapFontFntRecord', droppedPages, droppedChars, droppedKernings);
|
|
89
101
|
if (lineHeight === null || base === null || chars.length === 0)
|
|
90
102
|
return null;
|
|
91
103
|
return { base, chars, encoding: 'raster', kernings, lineHeight, pages };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontFnt.js","sourceRoot":"","sources":["../src/bitmapFontFnt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"bitmapFontFnt.js","sourceRoot":"","sources":["../src/bitmapFontFnt.ts"],"names":[],"mappings":"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"}
|
package/dist/bitmapFontJson.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { BitmapFont, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
2
|
-
export declare function parseBitmapFontJson(text: string, options?: Readonly<BitmapFontParseOptions
|
|
1
|
+
import type { BitmapFont, ImportDiagnostic, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
2
|
+
export declare function parseBitmapFontJson(text: string, options?: Readonly<BitmapFontParseOptions>, diagnostics?: ImportDiagnostic[]): BitmapFont | null;
|
|
3
3
|
//# sourceMappingURL=bitmapFontJson.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontJson.d.ts","sourceRoot":"","sources":["../src/bitmapFontJson.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,
|
|
1
|
+
{"version":3,"file":"bitmapFontJson.d.ts","sourceRoot":"","sources":["../src/bitmapFontJson.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAKhB,sBAAsB,EAEvB,MAAM,0BAA0B,CAAC;AAWlC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAC1C,WAAW,CAAC,EAAE,gBAAgB,EAAE,GAC/B,UAAU,GAAG,IAAI,CAInB"}
|
package/dist/bitmapFontJson.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildBitmapFontFromRecord } from './bitmapFontRecord';
|
|
1
|
+
import { buildBitmapFontFromRecord, reportDroppedBitmapFontRecords } from './bitmapFontRecord';
|
|
2
2
|
// Parses the JSON AngelCode/BMFont export into a `BitmapFont`. The shape mirrors the text/XML blocks as
|
|
3
3
|
// an object: `{ common: { lineHeight, base }, pages: [file, …], chars: [{ id, x, … }], kernings: [{
|
|
4
4
|
// first, second, amount }] }`, where `pages` is a filename array whose index is the page id. A
|
|
@@ -6,15 +6,15 @@ import { buildBitmapFontFromRecord } from './bitmapFontRecord';
|
|
|
6
6
|
// exports stay `raster`. Semantics otherwise match `parseBitmapFontFnt`, including `resolvePage` atlas
|
|
7
7
|
// rehydration. Returns the `null` sentinel — never throwing — for malformed JSON, a missing
|
|
8
8
|
// `common`/`chars`, or an atlas page that cannot be resolved.
|
|
9
|
-
export function parseBitmapFontJson(text, options) {
|
|
10
|
-
const record = parseBitmapFontJsonRecord(text);
|
|
9
|
+
export function parseBitmapFontJson(text, options, diagnostics) {
|
|
10
|
+
const record = parseBitmapFontJsonRecord(text, diagnostics);
|
|
11
11
|
if (record === null)
|
|
12
12
|
return null;
|
|
13
13
|
return buildBitmapFontFromRecord(record, options);
|
|
14
14
|
}
|
|
15
15
|
// Parses the JSON export into the neutral record, or `null` when the JSON is malformed or the
|
|
16
16
|
// `common`/`chars` blocks are absent or malformed.
|
|
17
|
-
function parseBitmapFontJsonRecord(text) {
|
|
17
|
+
function parseBitmapFontJsonRecord(text, diagnostics) {
|
|
18
18
|
let root;
|
|
19
19
|
try {
|
|
20
20
|
root = JSON.parse(text);
|
|
@@ -31,13 +31,20 @@ function parseBitmapFontJsonRecord(text) {
|
|
|
31
31
|
const base = readJsonNumber(common.base);
|
|
32
32
|
if (lineHeight === null || base === null)
|
|
33
33
|
return null;
|
|
34
|
+
// Counted and reported ONCE after the scan: a font carries thousands of char records, and the seam's
|
|
35
|
+
// perf contract forbids a per-element crumb in a loop that size.
|
|
36
|
+
let droppedPages = 0;
|
|
37
|
+
let droppedChars = 0;
|
|
38
|
+
let droppedKernings = 0;
|
|
34
39
|
const rawChars = root.chars;
|
|
35
40
|
if (!Array.isArray(rawChars))
|
|
36
41
|
return null;
|
|
37
42
|
const chars = [];
|
|
38
43
|
for (const raw of rawChars) {
|
|
39
44
|
const char = readJsonChar(raw);
|
|
40
|
-
if (char
|
|
45
|
+
if (char === null)
|
|
46
|
+
droppedChars++;
|
|
47
|
+
else
|
|
41
48
|
chars.push(char);
|
|
42
49
|
}
|
|
43
50
|
if (chars.length === 0)
|
|
@@ -53,10 +60,13 @@ function parseBitmapFontJsonRecord(text) {
|
|
|
53
60
|
if (Array.isArray(root.kernings)) {
|
|
54
61
|
for (const raw of root.kernings) {
|
|
55
62
|
const kerning = readJsonKerning(raw);
|
|
56
|
-
if (kerning
|
|
63
|
+
if (kerning === null)
|
|
64
|
+
droppedKernings++;
|
|
65
|
+
else
|
|
57
66
|
kernings.push(kerning);
|
|
58
67
|
}
|
|
59
68
|
}
|
|
69
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseBitmapFontJsonRecord', droppedPages, droppedChars, droppedKernings);
|
|
60
70
|
return { base, chars, encoding: readJsonEncoding(root.distanceField), kernings, lineHeight, pages };
|
|
61
71
|
}
|
|
62
72
|
function isObject(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontJson.js","sourceRoot":"","sources":["../src/bitmapFontJson.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bitmapFontJson.js","sourceRoot":"","sources":["../src/bitmapFontJson.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
import type { BitmapFont, BitmapFontParseOptions, BitmapFontRecord } from '@flighthq/types/contract';
|
|
1
|
+
import type { BitmapFont, ImportDiagnostic, BitmapFontParseOptions, BitmapFontRecord } from '@flighthq/types/contract';
|
|
2
2
|
export declare function buildBitmapFontFromRecord(record: Readonly<BitmapFontRecord>, options?: Readonly<BitmapFontParseOptions>): BitmapFont | null;
|
|
3
|
+
/**
|
|
4
|
+
* Reports the records a parse dropped, once per kind rather than once per record.
|
|
5
|
+
*
|
|
6
|
+
* A malformed page, char or kerning line is skipped so the rest of the font still loads, which is the
|
|
7
|
+
* right call — but the font then reports a glyph count lower than the file authored, and nothing else
|
|
8
|
+
* says so. `origin` is the caller's own name because a shared reporter must not put itself in that
|
|
9
|
+
* field; every parse encoding shares these kinds and is told apart by the origin instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function reportDroppedBitmapFontRecords(diagnostics: ImportDiagnostic[] | undefined, origin: string, pages: number, chars: number, kernings: number): void;
|
|
3
12
|
//# sourceMappingURL=bitmapFontRecord.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontRecord.d.ts","sourceRoot":"","sources":["../src/bitmapFontRecord.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bitmapFontRecord.d.ts","sourceRoot":"","sources":["../src/bitmapFontRecord.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAIhB,sBAAsB,EACtB,gBAAgB,EAEjB,MAAM,0BAA0B,CAAC;AAclC,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAClC,OAAO,CAAC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GACzC,UAAU,GAAG,IAAI,CAyDnB;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,gBAAgB,EAAE,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,IAAI,CAgBN"}
|
package/dist/bitmapFontRecord.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createBitmapFont } from '@flighthq/bitmapfont/contract';
|
|
2
|
+
import { reportImportDiagnostic } from '@flighthq/importdiagnostics/contract';
|
|
3
|
+
import { ImportDiagnosticSeverity } from '@flighthq/types/contract';
|
|
2
4
|
// Maps a parsed `BitmapFontRecord` onto a `BitmapFont` via `createBitmapFont`, resolving every atlas
|
|
3
5
|
// page the record declares through `options.resolvePage` (called once per page id). The resolved
|
|
4
6
|
// atlases become the font's page-indexed `pages` (page id = index), and each `char`'s `page` carries
|
|
@@ -68,4 +70,29 @@ export function buildBitmapFontFromRecord(record, options) {
|
|
|
68
70
|
};
|
|
69
71
|
return createBitmapFont(data);
|
|
70
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Reports the records a parse dropped, once per kind rather than once per record.
|
|
75
|
+
*
|
|
76
|
+
* A malformed page, char or kerning line is skipped so the rest of the font still loads, which is the
|
|
77
|
+
* right call — but the font then reports a glyph count lower than the file authored, and nothing else
|
|
78
|
+
* says so. `origin` is the caller's own name because a shared reporter must not put itself in that
|
|
79
|
+
* field; every parse encoding shares these kinds and is told apart by the origin instead.
|
|
80
|
+
*/
|
|
81
|
+
export function reportDroppedBitmapFontRecords(diagnostics, origin, pages, chars, kernings) {
|
|
82
|
+
if (pages > 0) {
|
|
83
|
+
reportImportDiagnostic(diagnostics, ImportDiagnosticSeverity.Drop, 'bmfont.page-unreadable', origin, {
|
|
84
|
+
records: pages,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (chars > 0) {
|
|
88
|
+
reportImportDiagnostic(diagnostics, ImportDiagnosticSeverity.Drop, 'bmfont.char-unreadable', origin, {
|
|
89
|
+
records: chars,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (kernings > 0) {
|
|
93
|
+
reportImportDiagnostic(diagnostics, ImportDiagnosticSeverity.Drop, 'bmfont.kerning-unreadable', origin, {
|
|
94
|
+
records: kernings,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
71
98
|
//# sourceMappingURL=bitmapFontRecord.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontRecord.js","sourceRoot":"","sources":["../src/bitmapFontRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"bitmapFontRecord.js","sourceRoot":"","sources":["../src/bitmapFontRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAW9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,qGAAqG;AACrG,iGAAiG;AACjG,qGAAqG;AACrG,+FAA+F;AAC/F,oGAAoG;AACpG,oGAAoG;AACpG,yFAAyF;AACzF,+FAA+F;AAC/F,gGAAgG;AAChG,+FAA+F;AAC/F,cAAc;AACd,MAAM,UAAU,yBAAyB,CACvC,MAAkC,EAClC,OAA0C;IAE1C,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjD,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;gBAC7B,IAAI,IAAI,CAAC,EAAE,GAAG,SAAS;oBAAE,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,oGAAoG;IACpG,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,GAAG,SAAS;YAAE,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;IACnD,CAAC;IAED,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B,2FAA2F;QAC3F,sFAAsF;QACtF,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAA0B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAChE,OAAO,EAAE,IAAI,CAAC,QAAQ;QACtB,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,oGAAoG;QACpG,yFAAyF;QACzF,iGAAiG;QACjG,0GAA0G;QAC1G,QAAQ,EAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO;QACpC,SAAS,EAAE,IAAI,CAAC,EAAE;QAClB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,CAAC,EAAE,IAAI,CAAC,CAAC;KACV,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,GAA4B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,KAAK;QAChB,KAAK,EAAE,IAAI,CAAC,MAAM;KACnB,CAAC,CAAC,CAAC;IAEJ,MAAM,IAAI,GAAmB;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM;QACN,OAAO;QACP,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;QACtF,KAAK;KACN,CAAC;IACF,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,8BAA8B,CAC5C,WAA2C,EAC3C,MAAc,EACd,KAAa,EACb,KAAa,EACb,QAAgB;IAEhB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,sBAAsB,CAAC,WAAW,EAAE,wBAAwB,CAAC,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE;YACnG,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,sBAAsB,CAAC,WAAW,EAAE,wBAAwB,CAAC,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE;YACnG,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,sBAAsB,CAAC,WAAW,EAAE,wBAAwB,CAAC,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE;YACtG,OAAO,EAAE,QAAQ;SAClB,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/dist/bitmapFontXml.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { BitmapFont, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
2
|
-
export declare function parseBitmapFontXml(text: string, options?: Readonly<BitmapFontParseOptions
|
|
1
|
+
import type { BitmapFont, ImportDiagnostic, BitmapFontParseOptions } from '@flighthq/types/contract';
|
|
2
|
+
export declare function parseBitmapFontXml(text: string, options?: Readonly<BitmapFontParseOptions>, diagnostics?: ImportDiagnostic[]): BitmapFont | null;
|
|
3
3
|
//# sourceMappingURL=bitmapFontXml.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontXml.d.ts","sourceRoot":"","sources":["../src/bitmapFontXml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,
|
|
1
|
+
{"version":3,"file":"bitmapFontXml.d.ts","sourceRoot":"","sources":["../src/bitmapFontXml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAIhB,sBAAsB,EAEvB,MAAM,0BAA0B,CAAC;AAiBlC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAC1C,WAAW,CAAC,EAAE,gBAAgB,EAAE,GAC/B,UAAU,GAAG,IAAI,CAInB"}
|
package/dist/bitmapFontXml.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { getXmlElementAttribute, getXmlElementAttributeNumber, getXmlElementChildByName, getXmlElementChildrenByName, parseXmlDocument, } from '@flighthq/xml/contract';
|
|
2
|
-
import { buildBitmapFontFromRecord } from './bitmapFontRecord';
|
|
2
|
+
import { buildBitmapFontFromRecord, reportDroppedBitmapFontRecords } from './bitmapFontRecord';
|
|
3
3
|
// Parses the XML AngelCode/BMFont `.fnt` variant into a `BitmapFont`. The document is
|
|
4
4
|
// `<font><info/><common/><pages><page/></pages><chars><char/></chars><kernings><kerning/></kernings></font>`
|
|
5
5
|
// with every field an element attribute. Semantics match `parseBitmapFontFnt` — the same line metrics,
|
|
6
6
|
// glyph mapping, and `resolvePage` atlas rehydration. Returns the `null` sentinel — never throwing —
|
|
7
7
|
// for malformed XML, a missing `common`/`chars`, or an atlas page that cannot be resolved.
|
|
8
|
-
export function parseBitmapFontXml(text, options) {
|
|
9
|
-
const record = parseBitmapFontXmlRecord(text);
|
|
8
|
+
export function parseBitmapFontXml(text, options, diagnostics) {
|
|
9
|
+
const record = parseBitmapFontXmlRecord(text, diagnostics);
|
|
10
10
|
if (record === null)
|
|
11
11
|
return null;
|
|
12
12
|
return buildBitmapFontFromRecord(record, options);
|
|
13
13
|
}
|
|
14
14
|
// Parses the XML `.fnt` into the neutral record, or `null` when the root/`common`/`chars` blocks are
|
|
15
15
|
// absent or a required attribute is malformed.
|
|
16
|
-
function parseBitmapFontXmlRecord(text) {
|
|
16
|
+
function parseBitmapFontXmlRecord(text, diagnostics) {
|
|
17
17
|
const root = parseXmlDocument(text);
|
|
18
18
|
if (root === null || root.name !== 'font')
|
|
19
19
|
return null;
|
|
@@ -25,11 +25,18 @@ function parseBitmapFontXmlRecord(text) {
|
|
|
25
25
|
if (lineHeight === null || base === null)
|
|
26
26
|
return null;
|
|
27
27
|
const pages = [];
|
|
28
|
+
// Counted and reported ONCE after the scan: a font carries thousands of char records, and the seam's
|
|
29
|
+
// perf contract forbids a per-element crumb in a loop that size.
|
|
30
|
+
let droppedPages = 0;
|
|
31
|
+
let droppedChars = 0;
|
|
32
|
+
let droppedKernings = 0;
|
|
28
33
|
const pagesElement = getXmlElementChildByName(root, 'pages');
|
|
29
34
|
if (pagesElement !== null) {
|
|
30
35
|
for (const pageElement of getXmlElementChildrenByName(pagesElement, 'page')) {
|
|
31
36
|
const id = getXmlElementAttributeNumber(pageElement, 'id');
|
|
32
|
-
if (id
|
|
37
|
+
if (id === null)
|
|
38
|
+
droppedPages++;
|
|
39
|
+
else
|
|
33
40
|
pages.push({ file: getXmlElementAttribute(pageElement, 'file') ?? '', id });
|
|
34
41
|
}
|
|
35
42
|
}
|
|
@@ -38,7 +45,9 @@ function parseBitmapFontXmlRecord(text) {
|
|
|
38
45
|
if (charsElement !== null) {
|
|
39
46
|
for (const charElement of getXmlElementChildrenByName(charsElement, 'char')) {
|
|
40
47
|
const char = readXmlChar(charElement);
|
|
41
|
-
if (char
|
|
48
|
+
if (char === null)
|
|
49
|
+
droppedChars++;
|
|
50
|
+
else
|
|
42
51
|
chars.push(char);
|
|
43
52
|
}
|
|
44
53
|
}
|
|
@@ -49,10 +58,13 @@ function parseBitmapFontXmlRecord(text) {
|
|
|
49
58
|
if (kerningsElement !== null) {
|
|
50
59
|
for (const kerningElement of getXmlElementChildrenByName(kerningsElement, 'kerning')) {
|
|
51
60
|
const kerning = readXmlKerning(kerningElement);
|
|
52
|
-
if (kerning
|
|
61
|
+
if (kerning === null)
|
|
62
|
+
droppedKernings++;
|
|
63
|
+
else
|
|
53
64
|
kernings.push(kerning);
|
|
54
65
|
}
|
|
55
66
|
}
|
|
67
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseBitmapFontXmlRecord', droppedPages, droppedChars, droppedKernings);
|
|
56
68
|
return { base, chars, encoding: 'raster', kernings, lineHeight, pages };
|
|
57
69
|
}
|
|
58
70
|
function readXmlChar(element) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFontXml.js","sourceRoot":"","sources":["../src/bitmapFontXml.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bitmapFontXml.js","sourceRoot":"","sources":["../src/bitmapFontXml.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/bitmapfont-formats",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.1041.35b950c",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,9 +38,10 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/bitmapfont": "0.3.
|
|
42
|
-
"@flighthq/
|
|
43
|
-
"@flighthq/
|
|
41
|
+
"@flighthq/bitmapfont": "0.3.1-next.1041.35b950c",
|
|
42
|
+
"@flighthq/importdiagnostics": "0.3.1-next.1041.35b950c",
|
|
43
|
+
"@flighthq/types": "0.3.1-next.1041.35b950c",
|
|
44
|
+
"@flighthq/xml": "0.3.1-next.1041.35b950c"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@flighthq/textureatlas": "*",
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getBitmapFontPage,
|
|
7
7
|
} from '@flighthq/bitmapfont/contract';
|
|
8
8
|
import { createTextureAtlas, createTextureAtlasFromImageResource } from '@flighthq/textureatlas/contract';
|
|
9
|
-
import type { BitmapFontParseOptions, Image, TextureAtlas } from '@flighthq/types/contract';
|
|
9
|
+
import type { BitmapFontParseOptions, Image, ImportDiagnostic, TextureAtlas } from '@flighthq/types/contract';
|
|
10
10
|
import { describe, expect, it } from 'vitest';
|
|
11
11
|
|
|
12
12
|
import { formatBitmapFontFnt, parseBitmapFontFnt } from './bitmapFontFnt';
|
|
@@ -79,6 +79,20 @@ describe('formatBitmapFontFnt', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
describe('parseBitmapFontFnt', () => {
|
|
82
|
+
// A clean parse is two claims: the values are right AND THE PARSER IS NOT COMPLAINING. Every other test
|
|
83
|
+
// here checks the first. This checks the second — the one that catches a walk that desynchronised and
|
|
84
|
+
// still left the asserted fields looking plausible. Asserted as an EMPTY list rather than a filter over
|
|
85
|
+
// truncation-shaped kind names: a pattern built from expected vocabulary silently exempts every kind
|
|
86
|
+
// whose name nobody guessed, and this importer has kinds like that.
|
|
87
|
+
it('raises no diagnostic at all for a well-formed file', () => {
|
|
88
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
89
|
+
|
|
90
|
+
parseBitmapFontFnt(FNT_TEXT, { resolvePage: () => createTextureAtlas() }, diagnostics);
|
|
91
|
+
|
|
92
|
+
const complaints = diagnostics.map((diagnostic) => diagnostic.kind);
|
|
93
|
+
expect(complaints, `a good fnt file made the parser complain: ${complaints.join(', ')}`).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
|
|
82
96
|
it('parses glyphs, kerning, and line metrics with the resolved atlas', () => {
|
|
83
97
|
const atlas = createTextureAtlas();
|
|
84
98
|
const font = parseBitmapFontFnt(FNT_TEXT, { resolvePage: () => atlas });
|
|
@@ -165,6 +179,59 @@ describe('parseBitmapFontFnt', () => {
|
|
|
165
179
|
});
|
|
166
180
|
});
|
|
167
181
|
|
|
182
|
+
describe('parseBitmapFontFntDroppedRecords', () => {
|
|
183
|
+
// A malformed char line is skipped so the rest of the font still loads, which is right. What is not
|
|
184
|
+
// right is that the font then reports FEWER GLYPHS THAN THE FILE AUTHORED with nothing saying so —
|
|
185
|
+
// a caller sees a complete-looking font that is quietly missing characters.
|
|
186
|
+
it('reports the records it could not read instead of dropping them silently', () => {
|
|
187
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
188
|
+
const font = parseBitmapFontFnt(
|
|
189
|
+
[
|
|
190
|
+
'common lineHeight=32 base=26',
|
|
191
|
+
'page id=0 file="a.png"',
|
|
192
|
+
'page file="nopage.png"',
|
|
193
|
+
'char id=65 x=0 y=0 width=8 height=8 xoffset=0 yoffset=0 xadvance=8 page=0',
|
|
194
|
+
'char x=0 y=0 width=8 height=8',
|
|
195
|
+
'kerning first=65 second=66 amount=-1',
|
|
196
|
+
'kerning first=65 amount=-1',
|
|
197
|
+
].join('\n'),
|
|
198
|
+
{ resolvePage: () => createTextureAtlas() },
|
|
199
|
+
diagnostics,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// The font still parses — that is exactly why the loss is invisible without the crumbs.
|
|
203
|
+
expect(font).not.toBeNull();
|
|
204
|
+
expect(diagnostics.map((entry) => entry.kind).sort()).toEqual([
|
|
205
|
+
'bmfont.char-unreadable',
|
|
206
|
+
'bmfont.kerning-unreadable',
|
|
207
|
+
'bmfont.page-unreadable',
|
|
208
|
+
]);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('reports once per kind however many records are unreadable', () => {
|
|
212
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
213
|
+
const lines = [
|
|
214
|
+
'common lineHeight=32 base=26',
|
|
215
|
+
'char id=65 x=0 y=0 width=8 height=8 xoffset=0 yoffset=0 xadvance=8 page=0',
|
|
216
|
+
];
|
|
217
|
+
for (let index = 0; index < 5; index++) lines.push('char x=0 y=0 width=8 height=8');
|
|
218
|
+
parseBitmapFontFnt(lines.join('\n'), { resolvePage: () => createTextureAtlas() }, diagnostics);
|
|
219
|
+
|
|
220
|
+
// A font carries thousands of char lines; one crumb each would drown the report it is making.
|
|
221
|
+
expect(diagnostics).toHaveLength(1);
|
|
222
|
+
expect(diagnostics[0]!.detail).toMatchObject({ records: 5 });
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('stays silent for a font whose records all read', () => {
|
|
226
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
227
|
+
const font = parseBitmapFontFnt(FNT_MULTIPAGE, { resolvePage: () => createTextureAtlas() }, diagnostics);
|
|
228
|
+
|
|
229
|
+
// Asserting a real glyph keeps the silence from being vacuous.
|
|
230
|
+
expect(getBitmapFontGlyph(font!, 65)).not.toBeNull();
|
|
231
|
+
expect(diagnostics).toEqual([]);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
168
235
|
function pageOptions(): BitmapFontParseOptions {
|
|
169
236
|
const atlas: TextureAtlas = createTextureAtlas();
|
|
170
237
|
return { resolvePage: () => atlas };
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getBitmapFontPage,
|
|
6
6
|
} from '@flighthq/bitmapfont/contract';
|
|
7
7
|
import { createTextureAtlas } from '@flighthq/textureatlas/contract';
|
|
8
|
+
import type { ImportDiagnostic } from '@flighthq/types/contract';
|
|
8
9
|
import type { BitmapFont } from '@flighthq/types/contract';
|
|
9
10
|
import { describe, expect, it } from 'vitest';
|
|
10
11
|
|
|
@@ -46,6 +47,20 @@ const FNT_XML = [
|
|
|
46
47
|
].join('\n');
|
|
47
48
|
|
|
48
49
|
describe('parseBitmapFontJson', () => {
|
|
50
|
+
// A clean parse is two claims: the values are right AND THE PARSER IS NOT COMPLAINING. Every other test
|
|
51
|
+
// here checks the first. This checks the second — the one that catches a walk that desynchronised and
|
|
52
|
+
// still left the asserted fields looking plausible. Asserted as an EMPTY list rather than a filter over
|
|
53
|
+
// truncation-shaped kind names: a pattern built from expected vocabulary silently exempts every kind
|
|
54
|
+
// whose name nobody guessed, and this importer has kinds like that.
|
|
55
|
+
it('raises no diagnostic at all for a well-formed file', () => {
|
|
56
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
57
|
+
|
|
58
|
+
parseBitmapFontJson(FNT_JSON, { resolvePage: () => createTextureAtlas() }, diagnostics);
|
|
59
|
+
|
|
60
|
+
const complaints = diagnostics.map((diagnostic) => diagnostic.kind);
|
|
61
|
+
expect(complaints, `a good fnt-json file made the parser complain: ${complaints.join(', ')}`).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
|
|
49
64
|
it('parses glyphs, kerning, and line metrics with the resolved atlas', () => {
|
|
50
65
|
const atlas = createTextureAtlas();
|
|
51
66
|
const font = parseBitmapFontJson(FNT_JSON, { resolvePage: () => atlas });
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
getBitmapFontPage,
|
|
6
6
|
} from '@flighthq/bitmapfont/contract';
|
|
7
7
|
import { createTextureAtlas } from '@flighthq/textureatlas/contract';
|
|
8
|
-
import type { BitmapFontRecord } from '@flighthq/types/contract';
|
|
8
|
+
import type { BitmapFontRecord, ImportDiagnostic } from '@flighthq/types/contract';
|
|
9
9
|
import { describe, expect, it } from 'vitest';
|
|
10
10
|
|
|
11
|
-
import { buildBitmapFontFromRecord } from './bitmapFontRecord';
|
|
11
|
+
import { buildBitmapFontFromRecord, reportDroppedBitmapFontRecords } from './bitmapFontRecord';
|
|
12
12
|
|
|
13
13
|
describe('buildBitmapFontFromRecord', () => {
|
|
14
14
|
it('maps chars, kernings, and common metrics onto a BitmapFont', () => {
|
|
@@ -119,3 +119,32 @@ function sampleRecord(): BitmapFontRecord {
|
|
|
119
119
|
pages: [{ file: 'test_0.png', id: 0 }],
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
+
|
|
123
|
+
describe('reportDroppedBitmapFontRecords', () => {
|
|
124
|
+
it('reports one crumb per kind that lost records, carrying the count', () => {
|
|
125
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
126
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseSomething', 1, 7, 2);
|
|
127
|
+
|
|
128
|
+
expect(diagnostics).toMatchObject([
|
|
129
|
+
{ detail: { records: 1 }, kind: 'bmfont.page-unreadable', origin: 'parseSomething' },
|
|
130
|
+
{ detail: { records: 7 }, kind: 'bmfont.char-unreadable', origin: 'parseSomething' },
|
|
131
|
+
{ detail: { records: 2 }, kind: 'bmfont.kerning-unreadable', origin: 'parseSomething' },
|
|
132
|
+
]);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('says nothing about a kind that lost nothing', () => {
|
|
136
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
137
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseSomething', 0, 3, 0);
|
|
138
|
+
|
|
139
|
+
expect(diagnostics.map((entry) => entry.kind)).toEqual(['bmfont.char-unreadable']);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('takes the origin from its caller rather than naming itself', () => {
|
|
143
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
144
|
+
reportDroppedBitmapFontRecords(diagnostics, 'parseBitmapFontXmlRecord', 0, 1, 0);
|
|
145
|
+
|
|
146
|
+
// A shared reporter that named itself would put a wrapper in the field whose whole job is to say
|
|
147
|
+
// which function lost the data, and all three parse encodings would become indistinguishable.
|
|
148
|
+
expect(diagnostics[0]!.origin).toBe('parseBitmapFontXmlRecord');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getBitmapFontPage,
|
|
6
6
|
} from '@flighthq/bitmapfont/contract';
|
|
7
7
|
import { createTextureAtlas } from '@flighthq/textureatlas/contract';
|
|
8
|
+
import type { ImportDiagnostic } from '@flighthq/types/contract';
|
|
8
9
|
import { describe, expect, it } from 'vitest';
|
|
9
10
|
|
|
10
11
|
import { parseBitmapFontXml } from './bitmapFontXml';
|
|
@@ -26,6 +27,20 @@ const FNT_XML = [
|
|
|
26
27
|
].join('\n');
|
|
27
28
|
|
|
28
29
|
describe('parseBitmapFontXml', () => {
|
|
30
|
+
// A clean parse is two claims: the values are right AND THE PARSER IS NOT COMPLAINING. Every other test
|
|
31
|
+
// here checks the first. This checks the second — the one that catches a walk that desynchronised and
|
|
32
|
+
// still left the asserted fields looking plausible. Asserted as an EMPTY list rather than a filter over
|
|
33
|
+
// truncation-shaped kind names: a pattern built from expected vocabulary silently exempts every kind
|
|
34
|
+
// whose name nobody guessed, and this importer has kinds like that.
|
|
35
|
+
it('raises no diagnostic at all for a well-formed file', () => {
|
|
36
|
+
const diagnostics: ImportDiagnostic[] = [];
|
|
37
|
+
|
|
38
|
+
parseBitmapFontXml(FNT_XML, { resolvePage: () => createTextureAtlas() }, diagnostics);
|
|
39
|
+
|
|
40
|
+
const complaints = diagnostics.map((diagnostic) => diagnostic.kind);
|
|
41
|
+
expect(complaints, `a good fnt-xml file made the parser complain: ${complaints.join(', ')}`).toEqual([]);
|
|
42
|
+
});
|
|
43
|
+
|
|
29
44
|
it('parses glyphs, kerning, and line metrics with the resolved atlas', () => {
|
|
30
45
|
const atlas = createTextureAtlas();
|
|
31
46
|
const font = parseBitmapFontXml(FNT_XML, { resolvePage: () => atlas });
|