D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
home
/
etb1lp46s9ed
/
washeet.softurecs.com
/
node_modules
/
@jimp
/
plugin-print
/
src
/
Filename :
load-bitmap-font.ts
back
Copy
import parseASCII from "parse-bmfont-ascii"; import parseXML from "parse-bmfont-xml"; import readBinary from "parse-bmfont-binary"; import { BmCharacter, BmKerning, BmFont, BmCommonProps } from "./types.js"; import png from "@jimp/js-png"; import { createJimp } from "@jimp/core"; import path from "path"; import xmlPackage from "simple-xml-to-json"; const { convertXML } = xmlPackage; export const isWebWorker = typeof self !== "undefined" && self.document === undefined; const CharacterJimp = createJimp({ formats: [png] }); const HEADER = Buffer.from([66, 77, 70, 3]); function isBinary(buf: Buffer | string) { if (typeof buf === "string") { return buf.substring(0, 3) === "BMF"; } const startOfHeader = buf.slice(0, 4); return ( buf.length > 4 && startOfHeader[0] === HEADER[0] && startOfHeader[1] === HEADER[1] && startOfHeader[2] === HEADER[2] ); } export interface LoadedFont { chars: BmCharacter[]; kernings: BmKerning[]; common: BmCommonProps; // eslint-disable-next-line @typescript-eslint/no-explicit-any info: Record<string, any>; pages: string[]; } function parseFont(file: string, data: Buffer | string): LoadedFont { if (isBinary(data)) { if (typeof data === "string") { data = Buffer.from(data, "binary"); } return readBinary(data); } data = data.toString().trim(); if (/.json$/.test(file) || data.charAt(0) === "{") { return JSON.parse(data); } if (/.xml$/.test(file) || data.charAt(0) === "<") { return parseXML(data); } return parseASCII(data); } // eslint-disable-next-line @typescript-eslint/no-explicit-any function parseNumbersInObject<T extends Record<string, any>>(obj: T) { for (const key in obj) { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any (obj as any)[key] = parseInt(obj[key], 10); } catch { // do nothing } if (typeof obj[key] === "object") { parseNumbersInObject(obj[key]); } } return obj; } /** * * @param bufferOrUrl A URL to a file or a buffer * @returns */ export async function loadBitmapFontData( bufferOrUrl: string | Buffer ): Promise<LoadedFont> { if (isWebWorker && typeof bufferOrUrl === "string") { const res = await fetch(bufferOrUrl); const text = await res.text(); const json = convertXML(text); const font = json.font.children.reduce( // eslint-disable-next-line @typescript-eslint/no-explicit-any (acc: Record<string, any>, i: any) => ({ ...acc, ...i }), {} ); const pages: LoadedFont["pages"] = []; const chars: LoadedFont["chars"] = []; const kernings: LoadedFont["kernings"] = []; for (let i = 0; i < font.pages.children.length; i++) { const p = font.pages.children[i].page; const id = parseInt(p.id, 10); pages[id] = parseNumbersInObject(p.file); } for (let i = 0; i < font.chars.children.length; i++) { chars.push(parseNumbersInObject(font.chars.children[i].char)); } for (let i = 0; i < font.kernings.children.length; i++) { kernings.push(parseNumbersInObject(font.kernings.children[i].kerning)); } return { info: font.info, common: font.common, pages, chars, kernings, } satisfies LoadedFont; } else if (typeof bufferOrUrl === "string") { const res = await fetch(bufferOrUrl); const text = await res.text(); return parseFont(bufferOrUrl, text); } else { return parseFont("", bufferOrUrl); } } type RawFont = Awaited<ReturnType<typeof loadBitmapFontData>>; export type ResolveBmFont = Omit<BmFont, "pages"> & Pick<RawFont, "pages">; export async function processBitmapFont(file: string, font: LoadedFont) { const chars: Record<string, BmCharacter> = {}; const kernings: Record<string, BmKerning> = {}; for (let i = 0; i < font.chars.length; i++) { const char = font.chars[i]!; chars[String.fromCharCode(char.id)] = char; } for (let i = 0; i < font.kernings.length; i++) { const firstString = String.fromCharCode(font.kernings[i]!.first); kernings[firstString] = kernings[firstString]! || {}; kernings[firstString]![String.fromCharCode(font.kernings[i]!.second)] = font.kernings[i]!.amount; } return { ...font, chars, kernings, pages: await Promise.all( font.pages.map(async (page) => CharacterJimp.read(path.join(path.dirname(file), page)) ) ), }; }