ttf.c/ttf.h/ttftest.c: TrueType parser core -- sfnt/head/maxp/loca/glyf/cmap (item 4.3.7)

Freestanding C module resolving a Unicode codepoint (cmap format 4) to a
glyph index and its outline header (contour count, bounding box), verified
against an independent from-scratch Python reference reader via
tools/ttftest.c. Not yet wired into the boot path or capsule system.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-10 21:41:42 -04:00
co-authored by Claude Sonnet 5
parent b9b7cb2c6a
commit 5f6cc054d4
4 changed files with 552 additions and 1 deletions
+47 -1
View File
@@ -4661,7 +4661,7 @@ document and committing that amendment as its own item.*
> before scoping REPL wiring (M8) — 4.3.7 (TrueType, adjunct) is the scoped-but-not-started
> next work, not M8.
- [ ] **4.3.7 — TTF parser core.** A C module (not FORTH — parsing and rasterization are
- [x] **4.3.7 — TTF parser core.** A C module (not FORTH — parsing and rasterization are
impractical to interpret) reading a `.ttf`'s `sfnt` directory plus `head`/`maxp`/`loca`/
`glyf`/`cmap` tables, resolving a codepoint to a glyph index and its outline data. All
scaled/derived values in Q48.16, not float — see §27.7. *Done when:* given an embedded test
@@ -4669,6 +4669,48 @@ document and committing that amendment as its own item.*
`glyf` table offset and reads its outline header (contour count, bounding box), verified
against values independently read from the same font with a reference tool (e.g.
`fonttools`/`ttx`), not just "doesn't crash." *Refs:* §27.7.
> **Done 2026-08-10.** `include/starkernel/ttf.h` + `src/starkernel/hal/ttf.c`: sfnt
> directory walk, `head` (unitsPerEm, indexToLocFormat)/`maxp` (numGlyphs)/`loca`/`glyf`
> table location, and a format-4 `cmap` subtable selector + lookup (format 12 explicitly
> deferred — not needed for the BMP-only v1 glyph repertoire). Every multi-byte read is
> manually big-endian-decoded with a bounds check against the buffer length first — no
> libc byteswap dependency, matches the freestanding/no-libc build (`-ffreestanding
> -nostdlib -fno-builtin`, confirmed by direct single-file compile against the real
> `Makefile.starkernel` amd64 `COMMON_CFLAGS`/`ARCH_CFLAGS`, zero warnings under
> `-Wall -Werror -Wextra`). No Q48.16 conversion needed here — every field this item reads
> is a raw on-disk integer, not a scaled/derived value; Q48.16 becomes relevant starting
> 4.3.7a (outline point extraction).
>
> Verification tool substitution, recorded plainly: `fonttools`/`ttx` is not installed in
> this environment (no network install attempted). Verified instead against a from-scratch
> second implementation — a plain `struct`-module Python script
> (`/tmp/.../scratchpad/ttf_ref.py`, not committed, reproducible from this note) that
> shares no code with `ttf.c` — arguably a stronger independence guarantee than a
> shared-library-backed tool would have given, though not what the item text named. A host
> test harness, `tools/ttftest.c` (new, follows `tools/README.md`'s already-established
> "host test, no QEMU needed" pattern — note `fbtest.c`, that entry's other example, turns
> out not to actually exist in `tools/`; stale-doc discrepancy, reported not fixed),
> compiles `ttf.c` directly and checks 7 codepoints from `fonts/JetBrainsMono-Regular.ttf`
> (`A a 0 . ! @` plus space, the empty-glyph case) against the Python reference's output —
> glyph index, contour count, bounding box (including two negative-`yMin` cases, `a` and
> `@`, which exercise signed-field decoding), `glyf` offset, and `glyf` length all match.
> `gcc -std=c99 -Wall -Wextra -Werror`, zero warnings.
>
> `.ttf` bytes reach the parser via a plain host `fopen`/`fread` into a `malloc` buffer in
> `ttftest.c`, not yet via a capsule (that's 4.3.7b, still open — see §27.7's 2026-08-10
> note on the raw-blob-vs-hex/base64 design question). `ttf_parse()` itself is agnostic to
> how its buffer arrived, so this doesn't gate 4.3.7's own "done when" clause.
>
> `fonts/JetBrainsMono-Regular.ttf` added (SIL OFL 1.1, confirmed by reading the font's own
> embedded `name`-table license string directly, not assumed from the filename) as the v1
> test/default font, resolving §27.7's licensing-check blocker — see `fonts/README.md`.
>
> Not a kernel-boot change (no FORTH words, no capsule/init.4th wiring, `ttf.c` isn't
> called from anywhere in the boot path yet — it's picked up by the existing
> `hal/*.c` wildcard in `Makefile.starkernel` but dead code until something calls it) — no
> three-arch QEMU acceptance boot applies to this item; the amd64 single-file freestanding
> compile check above is what stands in for it, per this item's own "done when" clause
> (which never asked for a kernel boot).
- [ ] **4.3.7a — Glyph outline extraction.** Simple and composite glyph outlines from `glyf`
— on-curve/off-curve point lists, quadratic Bézier control points, composite glyph
@@ -5480,4 +5522,8 @@ reverted or deprecated by this work.
(4.3.7c), hex vs. base64 encoding (4.3.7b), which `.ttf` file serves as the v1 test/default
font (not chosen yet — needs a licensing check before any specific font is embedded).
**Update 2026-08-10 — v1 test/default font chosen:** `JetBrainsMono-Regular.ttf`, licensed
SIL OFL 1.1 (permissive, embedding/redistribution allowed) — resolves the licensing-check
blocker above.
*Refs:* §25.5 (punch list), GAP-B2.