Make a digits-only font and save flash

A full ASCII bitmap font is convenient, but most embedded UIs only render a handful of characters — a clock, a temperature reading, a status code. Trimming the character set in /font shrinks the generated table proportionally. This guide walks through the numbers for one real font and size.


1. Pick a font

Open /font and select JetBrains MonoBold in Font Family.


2. Set the size to 24×22

In Dimensions, switch to Advanced mode and set Font Height to 24 px (Glyph Width derives to 22 px). With the default Full ASCII character set (95 glyphs), the CHARACTERS panel header shows:

Table: 6840 bytes (All ASCII Glyphs)

95 glyphs × 72 bytes/glyph (24 rows × 3 bytes/row) = 6840 bytes.


3. Switch to "Digits 0-9"

Open CHARACTERS and click the Digits 0-9 preset pill. The set is now 0123456789 — 10 glyphs, and (because the digits are contiguous codepoints) no separate index table is needed:

Table: 720 bytes (10 glyphs)

4. Add a space and a colon

For a clock display you'll likely also need a space (for leading-zero blanking) and a colon (for HH:MM). Type a space followed by 0123456789: into Custom characters — the chip row shows the space as โฃ, for 12 glyphs total. Because space (0x20) and colon (0x3A) sit outside the contiguous digit range, the set is now non-contiguous and the panel adds an index clause:

Table: 864 bytes (12 glyphs) + 12 bytes (index)

5. Download and inspect the header

Click the nav glyph preview to generate the header, then download it. The glyph table now has 12 entries (864 bytes) and a 12-byte {name}_codes[] index table listing the included codepoints in ascending order:

#define FONT_JETBRAINS_MONO_BOLD_24X22_GLYPH_COUNT 12
#define FONT_JETBRAINS_MONO_BOLD_24X22_TABLE_SIZE 864
#define FONT_JETBRAINS_MONO_BOLD_24X22_HAS_CODE_TABLE 1

const uint8_t font_jetbrains_mono_bold_24x22[] = {
    // @0 ' '
    ...

    // @72 '0'
    0x00, 0x00, 0x00,  // Row 00:        |                        |
    0x00, 0x00, 0x00,  // Row 01:        |                        |
    0x00, 0x00, 0x00,  // Row 02:        |                        |
    0x00, 0xFC, 0x00,  // Row 03:        |        ######          |
    0x01, 0xFE, 0x00,  // Row 04:        |       ########         |
    0x03, 0xFF, 0x00,  // Row 05:        |      ##########        |
    0x03, 0x87, 0x00,  // Row 06:        |      ###    ###        |
    0x07, 0x03, 0x80,  // Row 07:        |     ###      ###       |
    0x07, 0x03, 0x80,  // Row 08:        |     ###      ###       |
    0x07, 0x03, 0x80,  // Row 09:        |     ###      ###       |
    0x07, 0x13, 0x80,  // Row 10:        |     ###   #  ###       |
    0x07, 0x33, 0x80,  // Row 11:        |     ###  ##  ###       |
    0x07, 0x33, 0x80,  // Row 12:        |     ###  ##  ###       |
    0x07, 0x03, 0x80,  // Row 13:        |     ###      ###       |
    0x07, 0x03, 0x80,  // Row 14:        |     ###      ###       |
    0x07, 0x03, 0x80,  // Row 15:        |     ###      ###       |
    0x07, 0x03, 0x80,  // Row 16:        |     ###      ###       |
    0x03, 0x87, 0x00,  // Row 17:        |      ###    ###        |
    0x03, 0xFF, 0x00,  // Row 18:        |      ##########        |
    0x01, 0xFE, 0x00,  // Row 19:        |       ########         |
    0x00, 0x78, 0x00,  // Row 20:        |         ####           |
    0x00, 0x00, 0x00,  // Row 21:        |                        |
    0x00, 0x00, 0x00,  // Row 22:        |                        |
    0x00, 0x00, 0x00,  // Row 23:        |                        |

    ...

    // @792 ':'
    0x00, 0x00, 0x00,  // Row 00:        |                        |
    0x00, 0x00, 0x00,  // Row 01:        |                        |
    0x00, 0x00, 0x00,  // Row 02:        |                        |
    0x00, 0x00, 0x00,  // Row 03:        |                        |
    0x00, 0x00, 0x00,  // Row 04:        |                        |
    0x00, 0x00, 0x00,  // Row 05:        |                        |
    0x00, 0x00, 0x00,  // Row 06:        |                        |
    0x00, 0x30, 0x00,  // Row 07:        |          ##            |
    0x00, 0x78, 0x00,  // Row 08:        |         ####           |
    0x00, 0x78, 0x00,  // Row 09:        |         ####           |
    0x00, 0x78, 0x00,  // Row 10:        |         ####           |
    0x00, 0x00, 0x00,  // Row 11:        |                        |
    0x00, 0x00, 0x00,  // Row 12:        |                        |
    0x00, 0x00, 0x00,  // Row 13:        |                        |
    0x00, 0x00, 0x00,  // Row 14:        |                        |
    0x00, 0x00, 0x00,  // Row 15:        |                        |
    0x00, 0x00, 0x00,  // Row 16:        |                        |
    0x00, 0x78, 0x00,  // Row 17:        |         ####           |
    0x00, 0x78, 0x00,  // Row 18:        |         ####           |
    0x00, 0x78, 0x00,  // Row 19:        |         ####           |
    0x00, 0x30, 0x00,  // Row 20:        |          ##            |
    0x00, 0x00, 0x00,  // Row 21:        |                        |
    0x00, 0x00, 0x00,  // Row 22:        |                        |
    0x00, 0x00, 0x00,  // Row 23:        |                        |
};

// Sparse character set: this font does not cover a contiguous codepoint range.
// font_jetbrains_mono_bold_24x22_codes[] lists the included codepoints in ascending order; a
// character's glyph index is its position in that array (see the reference
// renderer below).
static const uint8_t font_jetbrains_mono_bold_24x22_codes[] = {
    0x20, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
};

Looking up '0' means a linear search over font_jetbrains_mono_bold_24x22_codes[] — it's at index 1, so its glyph is font_jetbrains_mono_bold_24x22[1 * 72]. See the header format reference for how the sparse reference renderer does this lookup.


6. The byte savings

Character set Glyphs Table size
Full ASCII (95) 95 6840 bytes
Digits only (10) 10 720 bytes
Digits + space + : 12 864 bytes (+ 12 bytes index)

Trimming Full ASCII down to digits + space + colon cuts the glyph table from 6840 bytes to 864 bytes — about 87% smaller, plus a 12-byte index table.


7. C++ wrapper and out-of-set characters

If your firmware ever receives a character outside this 12-glyph set (a stray letter in a debug string, for example), the plain C reference renderer silently skips it. If you enable "Generate C++ class wrapper" in Header Options, the generated {name}_font::glyph(char) instead returns a configurable fallback glyph — blank, a hollow box, or a copy of another glyph in the set — for any character contains(char) reports as missing. See the header format reference for the full wrapper output.

Open Font Tool →