--- name: schunix-text-rendering description: "The text layer that replaces the 8x16 character-cell grid — glyph metrics, surfaces, coverage blending, UTF-8." metadata: node_type: memory type: project originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95 modified: 2026-08-08T22:45:34.934Z --- Built 2026-08-09. `include/gfx/text.h` + `kernel/dev/text.c`. Nexoniarz: "using ANSI fonts in 2026 is a not funny joke." **The font was never the problem — the grid was.** The console indexes `font_data[256][16]` and steps the cursor eight pixels. A grid cannot do variable-width glyphs, cannot position text off a multiple of eight, cannot anti-alias, and cannot represent a codepoint above 255. A nicer bitmap fixes none of that. Three decisions that make the layer worth having: - **Glyphs carry metrics** (`w`, `h`, `bearing_x/y`, `advance`). Variable-width text *is* that; everything else follows. `text_measure()` exists because you cannot centre or lay out anything without it. - **Draws into a `struct surface`, not the screen.** `{pixels, stride, width, height}`. A compositor draws off-screen and presents; rendering that writes straight to the VGA aperture is useless to it. Works on the virtio-gpu back buffer, a window buffer, or the VGA aperture, none of which know about each other. - **`struct font_ops` behind an interface, and glyphs carry 8-bit *coverage*, not bits.** The bitmap font fills it with 0 and 255 only, which costs nothing — and a TrueType rasteriser then plugs in with no caller changing, because it already has somewhere to put anti-aliased edges. `blend_px()` reads the destination for the same reason. Pen position is on the **baseline**, as every non-terminal text API does, so glyphs of different heights sit on a common line. **Verified** with `echo t > /proc/sysrq` + `tools/textshot.ps1`: text at x=61 and x=63, a checkerboard background visible *around* the glyphs (no cell boxes), `┌─┐ █▓▒░ ° ± → •` above U+00FF, and a string measured at 160 px then centred on it. The old console renders in the same screenshot with solid cell backgrounds — a useful side-by-side. ## Traps hit - `include/gfx/font.h` **defines** `font_data` rather than declaring it, so including it from a second file duplicates the symbol under `-fno-common`. text.c declares `extern unsigned char font_data[256][16];` instead; the header is generated data and is better left alone. - The built-in font is **CP437, not Latin-1** (known trap in this codebase). `to_cp437()` maps the ~25 codepoints worth having — box drawing, blocks, arrows, degree. **That table exists to be deleted** when a real font lands; it is a bridge, not a design. - A missing glyph draws U+25A1 or `?`, never nothing. Silently shorter text hides the fault. - `utf8_next()` always advances, even on malformed input — a decoder that does not is a hang, not a rendering artefact. Rejects surrogates and overlong encodings. ## The typefaces, decided 2026-08-09 - **Roboto** for the DE / WM / compositor. **Apache-2.0** -- the same licence as Schunix, so it needs only a NOTICE entry. - **JetBrains Mono** for the terminal / TTY. **SIL OFL 1.1**, and it declares **no Reserved Font Name** (checked: the copyright line names none; the only "reserved font name" hit in OFL.txt is the licence defining the term). So a modified version may keep the name -- which matters, because pre-rasterising a font into bitmaps at build time *is* a modification and an RFN would have forbidden keeping the name on the result. OFL keeps the font under OFL inside an Apache-2.0 system, does not reach anything else, and only forbids selling the font on its own. Both fetched and verified at source, not assumed. Full note in `docs/licensing.md` ("Fonts"). Neither is in the tree yet -- there is no rasteriser to use them, and shipping a TTF nothing can read would be dead weight. ## Not done The console still uses the old path; nothing is ported to this yet. Porting `vga_putc` onto it is the obvious follow-up and would delete the cell grid for good. A TTF rasteriser is a separate provider behind `font_ops` — the layer is what was blocking it, and it no longer is.