Add a Glyph Script
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).
How it works
Section titled “How it works”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.
-
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
fsTypeof0(installable). The other values restrict embedding to documents:2forbids it,4allows preview and print only, and8allows 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. -
Add the enum value. Append to
enum poly_glyph_scriptinstate.h— it is append-only and byte-identical to the host’sGlyphScriptenum. Add a matching row toglyph_script_blocks[]inpoly_keymap.cwith the next free 0x40-spaced block base, and the script’s short name (five characters at most) to the settings-key labels inkeycode_helper.c. A static assert fails the build if that label is missing. -
Generate the font into its block. Add a
fonts.yamlentry that emits the font at the new PUA block using fontconvert’s sequence remap, soa..z(and digits, if the script has them) are placed atbase+0... Put the entry at the end of thefonts: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 thefantasybundle and increase itscontent_versionso the host re-flashes it on connect. -
Update the host. In PolyKybdHost: add the same value to the
GlyphScriptenum (command_ids.py) and a label toGLYPH_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. Thepolyctl glyph-script <name>choices come from the enum — see the Command Line page. -
Ship the rebuilt bundle. Copy the regenerated
fantasy.plyfintopolyhost/res/fontpack/and updatebundles.jsonwith 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 needfontconvert, because the bundle is built from them and the result is always the same. -
Build and test. Compile the firmware and select the new script from the tray menu or
polyctl. With thefantasybundle flashed the legends switch; without it, they stay Latin. The test rig has amin_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.