Skip to content

Add a Glyph Script

Firmware protocol v10+open-ended glyph-script index

A glyph script restyles the keycap letter and digit legends in an alternative script — Tengwar, runes, Braille and others (see Glyph Scripts for the user-facing side). This HowTo adds a new one.

Since firmware protocol v10 the glyph-script index is open-ended. The firmware accepts any script byte and draws the normal legend for one it does not know. So adding a script does not change the protocol version: you add an enum value, a codepoint block, a font and a host label. A keyboard without the new font shows Latin.

All firmware paths are relative to keyboards/polykybd/ in the qmk_firmware fork; the glyphs ship in the fantasy font-pack bundle (see Font Packs & Resources).

Each script’s letters and digits are rendered into a dense private codepoint block (0x40 apart: Tengwar 0xE800, Runes 0xE840, …). A table in poly_keymap.c (glyph_script_blocks[], indexed by the poly_glyph_script enum) maps a script to its block base; letters a..z are placed at base+0..25, and scripts with their own numerals put digits at base+26..35. The render hook in render_key() swaps the legend for the block glyph when a script is active.

  1. Pick a font with a suitable license. The glyph shapes must be embeddable and redistributable (OFL, Apache, CC0, permissive). Keep user-facing script names generic where a script is a trademark, even though the fonts themselves are fine to embed. Check the font file as well as the repository. With no license, the font is all rights reserved. The project also asks for an OS/2 fsType of 0 (installable). The other values restrict embedding to documents: 2 forbids it, 4 allows preview and print only, and 8 allows editable documents. A font converted to bitmaps and flashed onto a keyboard is none of those. Add the source to the font downloader (fonts/dl-fonts.sh), pinned to a commit or release tag.

  2. Add the enum value. Append to enum poly_glyph_script in state.h — it is append-only and byte-identical to the host’s GlyphScript enum. Add a matching row to glyph_script_blocks[] in poly_keymap.c with the next free 0x40-spaced block base, and the script’s short name (five characters at most) to the settings-key labels in keycode_helper.c. A static assert fails the build if that label is missing.

  3. Generate the font into its block. Add a fonts.yaml entry that emits the font at the new PUA block using fontconvert’s sequence remap, so a..z (and digits, if the script has them) are placed at base+0... Put the entry at the end of the fonts: list, not next to the other glyph scripts: a font’s position in that list is its index in the font table, so an entry in the middle shifts every later font and means other bundles must also be rebuilt and shipped again. Regenerate the headers, then rebuild the fantasy bundle and increase its content_version so the host re-flashes it on connect.

  4. Update the host. In PolyKybdHost: add the same value to the GlyphScript enum (command_ids.py) and a label to GLYPH_SCRIPT_LABELS (host.py). The tray’s Keycap Script submenu lists scripts in the order of that label list, so add the label where it belongs: the C64 keycap script comes directly after the C64 screen font. A test fails if a script has no label. The polyctl glyph-script <name> choices come from the enum — see the Command Line page.

  5. Ship the rebuilt bundle. Copy the regenerated fantasy.plyf into polyhost/res/fontpack/ and update bundles.json with the new size, hash and version so the host ships the new glyphs and re-flashes them on the next connect. If the category headers are already committed you do not need fontconvert, because the bundle is built from them and the result is always the same.

  6. Build and test. Compile the firmware and select the new script from the tray menu or polyctl. With the fantasy bundle flashed the legends switch; without it, they stay Latin. The test rig has a min_protocol-gated round-trip test you can extend.

See Contributing for how to open the pull requests, and the HID Protocol Reference for the GLYPH_SCRIPT command.