Skip to main content
Use decodeUnihexGlyphs from @groundsgg/motd/fonts to decode explicitly supplied .hex bytes. The function returns paired glyph metrics and RGBA cells without a DOM, React, Portal, filesystem, or network connection.
This is an unreleased addition after 0.3.0. It produces standalone glyph data, not a renderable FontProfile. Viewer/layout integration, archive selection, resource stacks and full native rendered calibration remain under font import issue #8.

Decode selected records

The host extracts the selected archive and passes its .hex entries as Uint8Array values in the desired entry order. The library does not unzip files, inspect entry names, download assets, or retain the supplied buffers. A normalized Unihex leaf from provider inspection can be passed as the definition.
decode-unihex.mjs
The frozen result has schemaVersion: 1, a glyphs array sorted by numeric code point, and pixelsFor(codePoint). Each lookup returns a fresh trimmed RGBA cell, or undefined for an absent code point. Mutating an input or returned buffer does not change later reads or metrics. The private representation stores bit rows; RGBA cells are allocated only when requested.

Accepted syntax

Each record has a 4–6-digit Unicode code point, a colon, and exactly 16 bitmap rows. The rows are written consecutively as hexadecimal digits on the same line. The bitmap width is inferred from the digit count. Native hexadecimal syntax accepts only 0–9 and uppercase A–F. Records end with LF or the end of the byte stream. Lowercase hex, CRLF, comments, blank lines, BOMs and malformed records return an error. Empty files and an empty selected file list are valid; success does not prove resource completeness. The importer additionally requires Unicode scalar values. Surrogates and values above U+10FFFF are rejected rather than represented as imported glyphs. U+0000 is retained by this provider; this differs from the reserved U+0000 grid cell in bitmap providers. Importing a glyph does not change how the viewer interprets text control characters. A later record replaces an earlier record for the same code point, including across files. One aggregate font-unihex-duplicates warning reports the number of replacements. No partial glyph set is returned if a later record is invalid.

Native glyph metrics

Rows are aligned to the left of a 32-bit mask. The default bounds span the first and last columns containing ink across all 16 rows. Pixels are white with alpha 255 when set; transparent pixels contain four zero bytes. An entirely blank native record has the special bounds left = 0 and right = bitWidth, including the extra right column. Its decoded widths are therefore 9, 17, 25 or 33 pixels, with advances 5, 9, 13 or 17 GUI pixels. Do not collapse blank glyphs to zero width or reuse a bitmap provider’s empty-cell advance. Each UnihexGlyph contains: Odd pixel widths keep their half-pixel drawing extent while the advance uses integer division. Keep these per-glyph metrics paired with their raster cells; the bitmap provider’s global one-pixel offsets do not describe Unihex glyphs.

Size overrides

definition.sizeOverrides accepts the normalized numeric ranges returned by provider inspection. Both endpoints are inclusive, and from < to is required. The first matching override wins. For example, a first range fixing A–Z to columns 0–7 takes precedence over a later range fixing them to columns 0–15. Decoded ranges require scalar code-point endpoints and usable bounds 0 <= left <= right <= 31. Bounds can include transparent columns beyond an 8-, 16- or 24-bit source width. Raw metadata inspection can preserve a wider set of native integer definitions; this decoder intentionally rejects negative, reversed or wrapping column bounds. The automatic 33-column blank-glyph rule is separate from explicit override validation. Override processing sorts the code points actually present and assigns each at most once. It does not expand every code point in a large range or scan every range for every glyph. Missing code points remain absent.

Limits and host responsibilities

The optional third argument configures positive integer budgets up to fixed ceilings. The decoder fixes selected byte-view extents before applying budgets or parsing; later backing-buffer growth cannot enlarge those selected inputs. It captures each file view once and uses actual typed-array storage metadata. Shared contents still need to remain stable if you require a consistent source version. Parsing uses a bounded 128-digit scratch buffer instead of splitting or decoding an entire file into strings. Each stored glyph has 16 bit rows. A returned RGBA cell has at most 33 * 16 * 4 = 2,112 bytes; repeated pixelsFor calls allocate separate copies. Cache them in your renderer as needed. Your archive adapter must separately bound compressed and uncompressed bytes, entry counts, extraction allocation and local paths. Native provider archives select entries ending in .hex; apply that selection and preserve the chosen entry order before calling this API. The library cannot undo allocations already made by the host and does not infer a complete Vanilla resource set from selected files. See indexed Vanilla sources. Decoding is synchronous. Run large imports in a host worker when you need to keep the interface responsive or cancel work. No decoder-owned external resource needs disposal.

Diagnostics and verification

Errors return value: null. Paths identify zero-based files and one-based record lines, for example files[0].line[1]. Messages use the normal localization API. Parsing, trimming, override precedence and metrics were checked against the official Java 26.3 Unihex provider classes. Tests use original synthetic records, all four native widths, supplementary characters, blank cells, overlapping ranges, duplicates, mutation isolation and malformed/oversized input. This coverage does not certify a fully rendered resource-pack font or other encoded font formats. Viewer integration and native rendered calibration remain separate; see profile verification limits. An isolated headless JVM also executed the official 26.3 provider’s Definition.loadData, glyph info / bake, and CPU unpackBitsToBytes methods. The input was an in-memory ZIP containing original synthetic records. The observational stitcher performed no GPU upload. Default and overlapping-override cases establish the native odd/blank widths, half-pixel offsets, first-match precedence and RGBA cell hashes; a negative probe confirms lowercase hex is rejected. The numeric reference manifest contains client/class hashes, the original input recipe, measured metrics and raster hashes. Tests rebuild the input and compare decoder metrics and pixels with these observations. No game font data or class bytes are included, and this is not a rendered Minecraft screenshot comparison.