diff --git a/FABRIC.md b/FABRIC.md index 9957b5d..d4b80f3 100644 --- a/FABRIC.md +++ b/FABRIC.md @@ -4641,6 +4641,62 @@ document and committing that amendment as its own item.* correctly positioned, on all three architectures, matching the 4.3.3b/4.3.4 completion pattern (screendump-verified, not just non-crashing). Three-arch acceptance boot clean, logs committed. *Refs:* §27.6. + > **Paused 2026-08-09, mid-verification.** amd64's 113-glyph grid screendump (1280×800 GOP + > framebuffer) looked correct. Re-running the same grid on aarch64 surfaced a real, + > previously-unaccounted-for cross-arch difference: aarch64 boots with an 800×600 `ramfb` + > device, not amd64's 1280×800 linear GOP framebuffer — the grid's Y coordinates (laid out + > for 800px height) ran off the top of the smaller screen. Not yet re-run with corrected, + > screen-size-aware coordinates on any architecture. This checkbox stays open. + > + > The review this checkpoint exists for happened here, ahead of schedule: seeing the + > stroke-rendered repertoire together prompted the decision to add TrueType rendering as + > an adjunct rather than continue refining the stroke system alone — see 4.3.7 below. The + > stroke font itself is being kept, not reverted; this item still needs to finish (grid + > fixed, all three arches, screendump-verified) before REPL wiring (M8) is scoped, per its + > own "Done when." + +- [ ] **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 + font's bytes in memory, the parser resolves at least one ASCII codepoint to the correct + `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. + +- [ ] **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 + transforms — in Q48.16. *Done when:* outline point lists for a handful of test glyphs + (including at least one composite, e.g. an accented character if the test font has one) + match reference-tool output within Q48.16 rounding tolerance. *Refs:* §27.7. + +- [ ] **4.3.7b — Font data ingestion.** `.ttf` bytes encoded (hex or base64 — pick one, record + why) into capsule blocks per the resolved design decision (§27.7), decoded into a `kmalloc` + buffer at capsule load time. *Done when:* a font capsule loads cleanly (`mkcapsule --lint`), + and the decoded in-memory bytes checksum-match the original `.ttf` file. *Refs:* §27.7. + +- [ ] **4.3.7c — Rasterization.** Bézier curve flattening to line segments (reusing the + existing `LINE`/Bresenham primitive where practical), then fill. Antialiasing approach is + an open question — not decided here, resolve when this item is picked up. *Done when:* a + single glyph outline rasterizes to a recognizable filled (or outlined, if AA is deferred) + shape on the CANVAS, screendump-verified. *Refs:* §27.7. + +- [ ] **4.3.7d — Glyph raster cache.** Rasterizing on every draw call is too slow for + repeated text; cache rasterized bitmaps keyed by (font, codepoint, size). *Done when:* + drawing the same codepoint/size twice measurably hits the cache on the second call (e.g. a + counter or timing difference), verified live, not just "code that should cache." *Refs:* + §27.7. + +- [ ] **4.3.7e — `TTF-TEXT` entry point.** `TTF-TEXT ( c-addr u x y size color -- )`, + analogous to 4.3.6f's `TEXT` but TrueType-backed — becomes the primary text-rendering path + per the resolved relationship to the stroke font (§27.7); `TEXT`/the stroke system remain + available, not deprecated. *Done when:* a UTF-8 string renders correctly via `TTF-TEXT` in + one call, screendump-verified, proportional spacing correct. *Refs:* §27.7. + +- [ ] **4.3.7f — Checkpoint: TTF rendering, all three architectures.** Same posture as + 4.3.6g. *Done when:* a single screendump per architecture shows a representative sample + string rendered correctly via `TTF-TEXT`, three-arch acceptance boot clean, logs committed. + *Refs:* §27.7. ⋯ *(4.3.x is open-ended — more items get appended here as Console work is scoped item by* *item, developed on the fly per §25.0. 4.4 below is unaffected by anything added above* @@ -5369,3 +5425,53 @@ exhausted. Presented at the algorithm level, same caveat as `DECODE-UTF8` — th construction is 4.3.6f's own implementation work, not settled here. *Refs:* §25.5 (punch list). + +### 27.7 TrueType rendering, adjunct to the stroke font (4.3.7–4.3.7f) + +Scoped 2026-08-09, immediately after the 4.3.6g checkpoint review (which surfaced this +decision ahead of that item finishing — see 4.3.6g's paused note). **Adjunct, not a +replacement:** the stroke-drawn font system (4.3.6–4.3.6g) stays; nothing from it is being +reverted or deprecated by this work. + +**Four design decisions resolved 2026-08-09, before any implementation:** + +1. **Implementation layer: C, not FORTH.** TTF parsing (table lookups, glyph index + resolution) and rasterization (Bézier flattening, scanline fill) are impractical to write + as interpreted FORTH — same reasoning that put `LINE`/`CIRCLE`/`ARC`/`ELLIPSE` (4.3.3b) in + C rather than FORTH. A new C module, parallel to those, exposes a handful of new words to + FORTH. + +2. **Q48.16 fixed-point throughout, not float.** Checked before deciding, not assumed. + **GAP-B2** (this doc, §"unverified prerequisites") already flagged the *question* — + "if the kernel is not built with `-mgeneral-regs-only` (aarch64) / soft-float (riscv64), + a C interrupt handler may clobber FP registers" — as unverified, one grep away from + settled. That grep was run while scoping this item: `Makefile.starkernel`'s + `ARCH_CFLAGS` show amd64/aarch64 with no explicit FPU disable and riscv64 built `lp64d` + (a hard-float ABI, not soft-float) — so hardware FP is implicitly available on all three, + and GAP-B2's hypothesized risk is real, not hypothetical: none of the three + architectures' ISR paths save/restore FP register state. This resolves GAP-B2's open + question (confirmed real) but does not fix the underlying gap itself, which stays open + for whatever eventually does need hardware FP. There is no documented project-wide + "no float" policy — this is a targeted decision for this item. Building the rasterizer in + Q48.16 sidesteps the risk for this work specifically (it never touches FP hardware), and + incidentally keeps it consistent with the determinism convention the rest of the runtime + (Compudynamics, the geometry primitives) already uses Q48.16 for. + +3. **Font data storage: encoded into capsule blocks.** A `.ttf` is binary; capsule blocks are + text (64 chars/line, 16 lines/block, per `tools/mkcapsule.c`'s `validate_forth_blocks()`). + Chose hex/base64 encode-at-build/decode-at-load over a parallel build-time embedded-binary + asset (like `capsule_generated.c` bakes in capsule text) specifically to keep font data + inside the existing content-addressed capsule system rather than introduce a second, + parallel asset-embedding mechanism. Hex vs. base64 not yet chosen — 4.3.7b's own call. + +4. **Relationship to the stroke font: TrueType becomes the primary text path.** Once + `TTF-TEXT` (4.3.7e) exists, it's the intended path for real text rendering; `TEXT`/the + stroke system (4.3.6f) remain available and are not deprecated — useful for early boot + (before the capsule/VM bootstrap, same reason `font_8x16.c` stays per §27.6), low-memory + contexts, or diagnostic/geometric use. Both continue to exist; callers choose. + +**Explicitly not decided here, left to the item that owns them:** antialiasing approach +(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). + +*Refs:* §25.5 (punch list), GAP-B2.