docs: deep-derive glyph rendering design (4.3.6-4.3.6g), FABRIC.md \xc2\xa727.6.1-6
Expands the previously sparse \xc2\xa727.6 to match the derivation depth of
\xc2\xa727.3/\xc2\xa727.5.1/\xc2\xa727.5.2 -- worked line items, not just prose scoping.
Every primitive used (*/, WITHIN, CASE/OF/ENDOF, CREATE, EXECUTE, ',
LSHIFT/RSHIFT/AND/OR) was confirmed against src/word_source/*.c before
being used in a formula; no $/0x hex literal syntax exists in this tree,
so all formulas use decimal only.
Concrete design landed, in order derived:
- EM-UNITS 1000, standard Type1/OpenType em-square proportions; EM-X/
EM-Y/G-LINE scale-and-translate into CART-PLOT space via */ (noting
*/'s "avoid overflow" rationale is vestigial at this VM's 64-bit
cell_t width -- not a bug, just an observation)
- UTF-8 decoder: full bit-level 1/2/3/4-byte assembly formulas. Found
mid-derivation that the 3-byte path is v1-required, not future-i18n-
only -- smart quotes/dashes/ellipsis are Unicode General Punctuation
(U+2000-206F), NOT Latin-1 Supplement despite the original framing
lumping them together
- Dispatch: bucketed CASE/OF/ENDOF chains (DISPATCH-DIGIT/-UPPER/-LOWER/
-ASCII-PUNCT/-LATIN1/-GENPUNCT) routed by WITHIN range checks, chosen
over a flat 256-entry xt-table despite the table composing more
cleanly with override -- explicit tradeoff, not an oversight
- Glyph-word contract ( -- em-advance ), TOFU placeholder for misses,
~8-10 block budget estimate for dispatch alone
- Character list corrected and finalized: 113 glyphs (95 ASCII + 11
Latin-1 Supplement + 7 General Punctuation), itemized
- User font override: found CASE's early binding means redefining a
single glyph word does NOT retroactively change an already-compiled
DISPATCH-* caller (same binding behavior 4.3.3b found for CART-PLOT).
Resolved: override replaces a whole DISPATCH-* bucket word, not
individual glyphs -- explicit granularity tradeoff for keeping CASE
- TEXT entry point sketched at algorithm level
DECODE-UTF8's exact byte-consumption stack mechanics and TEXT's loop
are deliberately left as algorithm-level spec, not final FORTH -- this
project's history (VARIABLE alignment, Q.TO-INT sign bug) shows exactly
this class of stack/precision bug surfaces only under live testing, not
design review; presenting untested stack-juggling code as settled would
be the "confidently wrong" mistake \xc2\xa725.0 rule 4 warns against.
Punch-list items 4.3.6-4.3.6g (\xc2\xa725.5) updated to match: concrete Done-
when criteria replacing several that were previously vague or TBD
(4.3.6b now names the six buckets; 4.3.6c names the 113-glyph list;
4.3.6e goes from "TBD" to a real, testable override-mechanism
criterion; 4.3.6f requires proportional-width verification). Still no
implementation -- scoping and derivation only, per \xc2\xa725.0 rule 2.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b69dcfd050
commit
0a03ba7871
@@ -4388,52 +4388,68 @@ document and committing that amendment as its own item.*
|
|||||||
> `#ifdef __STARKERNEL__`, or elsewhere is an open question for that later item, not
|
> `#ifdef __STARKERNEL__`, or elsewhere is an open question for that later item, not
|
||||||
> decided here.
|
> decided here.
|
||||||
|
|
||||||
- [ ] **4.3.6 — Em-square glyph coordinate convention.** Define the normalized coordinate
|
- [ ] **4.3.6 — Em-square glyph coordinate convention.** `EM-UNITS 1000` (baseline Y=0,
|
||||||
space glyph strokes are authored in and the scale/translate step into `CART-PLOT` screen
|
x-height ≈500, cap-height ≈700, ascender ≈750, descender ≈-250), plus `EM-X`/`EM-Y`/
|
||||||
coordinates, parallel to 4.3.3's `PROJECT`. Prerequisite for every glyph-drawing word that
|
`G-LINE` scaling/translating em-square strokes into `CART-PLOT` screen coordinates via
|
||||||
follows. *Done when:* a normalized test shape scales/translates correctly onto raster
|
`*/`, parallel to 4.3.3's `PROJECT`. Prerequisite for every glyph-drawing word that follows.
|
||||||
coordinates at two different requested sizes, verified live via screendump against
|
*Done when:* a normalized test shape scales/translates correctly onto raster coordinates at
|
||||||
hand-calculated pixel positions. *Refs:* §27.6.
|
two different requested sizes, verified live via screendump against hand-calculated pixel
|
||||||
|
positions. *Refs:* §27.6.1.
|
||||||
|
|
||||||
- [ ] **4.3.6a — UTF-8 decoder.** A FORTH word (or small wordset) walking a byte string and
|
- [ ] **4.3.6a — UTF-8 decoder.** `DECODE-UTF8`, composed in FORTH per the
|
||||||
yielding one Unicode codepoint at a time, composed in FORTH per the compose-in-FORTH-first
|
compose-in-FORTH-first rule — no existing UTF-8 decoding anywhere in this tree (checked).
|
||||||
rule — no existing UTF-8 decoding anywhere in this tree (checked). *Done when:* correctly
|
Must handle 1-byte and 2-byte sequences (ASCII, Latin-1) *and* 3-byte sequences (General
|
||||||
decodes a test string mixing 1-byte ASCII and 2-byte Latin-1 sequences (e.g. `é` U+00E9),
|
Punctuation — confirmed load-bearing for v1, not future-i18n-only, since smart
|
||||||
verified live against hand-computed expected codepoints. *Refs:* §27.6.
|
quotes/dashes/ellipsis live outside Latin-1). *Done when:* correctly decodes a test string
|
||||||
|
mixing 1-byte ASCII, 2-byte Latin-1 (e.g. `°` U+00B0), and 3-byte General Punctuation (e.g.
|
||||||
|
`—` U+2014) sequences, verified live against hand-computed expected codepoints. *Refs:*
|
||||||
|
§27.6.2.
|
||||||
|
|
||||||
- [ ] **4.3.6b — Codepoint → glyph dispatch.** Lookup mapping a decoded codepoint to its
|
- [ ] **4.3.6b — Codepoint → glyph dispatch.** Bucketed `CASE`/`OF`/`ENDOF` chain
|
||||||
stroke-drawing word within the active font-set capsule. *Done when:* dispatch correctly
|
(`DISPATCH-DIGIT`/`-UPPER`/`-LOWER`/`-ASCII-PUNCT`/`-LATIN1`/`-GENPUNCT`) routed by
|
||||||
invokes the right stroke word for at least 3 codepoints spanning ASCII and Latin-1, and
|
`DISPATCH-GLYPH` via `WITHIN` range checks, per §27.6.3 — chosen over a flat xt-table
|
||||||
fails safely (defined, non-crashing behavior) for a codepoint outside the v1 repertoire.
|
despite the table composing more cleanly with override (§27.6.5's finding). Every glyph
|
||||||
*Refs:* §27.6.
|
word follows the `( -- em-advance )` contract; unmatched codepoints fall to `TOFU`. *Done
|
||||||
|
when:* dispatch correctly invokes the right stroke word and returns its advance for at
|
||||||
|
least one codepoint from each of the six buckets, and falls through to `TOFU` (not a crash)
|
||||||
|
for a codepoint outside all six ranges. *Refs:* §27.6.3.
|
||||||
|
|
||||||
- [ ] **4.3.6c — Default system font-set capsule.** ASCII printable + the agreed Latin-1
|
- [ ] **4.3.6c — Default system font-set capsule.** The confirmed 113-glyph v1 repertoire
|
||||||
typographic set, each glyph a stroke-drawing word in the 4.3.6 em-square convention, one
|
(95 ASCII printable + 11 Latin-1 Supplement + 7 General Punctuation, itemized in §27.6.4),
|
||||||
capsule. *Done when:* every glyph in the v1 repertoire is defined, lint-clean
|
each glyph a stroke-drawing word in the 4.3.6 em-square convention returning its own
|
||||||
(`mkcapsule --lint`), individually verified to render a recognizable shape via screendump.
|
`em-advance`, one capsule. *Done when:* every glyph in the 113-glyph v1 repertoire is
|
||||||
*Refs:* §27.6.
|
defined, lint-clean (`mkcapsule --lint`), individually verified to render a recognizable
|
||||||
|
shape via screendump. *Refs:* §27.6.4.
|
||||||
|
|
||||||
- [ ] **4.3.6d — Boot-time loading.** Wire `fabric.4th` and the 4.3.6c font capsule into
|
- [ ] **4.3.6d — Boot-time loading.** Wire `fabric.4th` and the 4.3.6c font capsule into
|
||||||
`init.4th`'s boot chain. *Done when:* standard three-arch QEMU boot shows both capsules
|
`init.4th`'s boot chain. *Done when:* standard three-arch QEMU boot shows both capsules
|
||||||
`EXEC`'d cleanly as part of the normal boot sequence (not manual injection), no errors,
|
`EXEC`'d cleanly as part of the normal boot sequence (not manual injection), no errors,
|
||||||
logs committed. *Refs:* §27.6.
|
logs committed. *Refs:* §27.6.
|
||||||
|
|
||||||
- [ ] **4.3.6e — User font override.** Mechanism to load and activate a replacement font-set
|
- [ ] **4.3.6e — User font override.** Mechanism resolved 2026-08-09 (§27.6.5): override
|
||||||
capsule over the default without redefining every caller. *Done when:* TBD — scoped in
|
replaces a whole `DISPATCH-*` bucket word, not individual glyphs — `CASE`'s early binding
|
||||||
detail once 4.3.6c exists (a second font-set is needed to test "override" against).
|
means redefining a single glyph word (e.g. `G-A`) alone does not change what an
|
||||||
*Refs:* §27.6.
|
already-compiled `DISPATCH-UPPER` calls, so the override capsule must redefine the entire
|
||||||
|
bucket it wants to change. *Done when:* a second, user-supplied capsule redefines one
|
||||||
|
`DISPATCH-*` bucket word (e.g. `DISPATCH-UPPER`), and after loading it, drawing a codepoint
|
||||||
|
from that bucket renders the overridden glyph, not the default — verified live via
|
||||||
|
screendump, both before and after the override loads. *Refs:* §27.6.5.
|
||||||
|
|
||||||
- [ ] **4.3.6f — TEXT-drawing entry point.** Decode a UTF-8 string, dispatch each codepoint
|
- [ ] **4.3.6f — `TEXT` entry point.** `TEXT ( c-addr u x y size color -- )`: decode UTF-8 via
|
||||||
through 4.3.6b, draw via its stroke word, advance the cursor by glyph width. *Done when:*
|
4.3.6a, dispatch each codepoint through 4.3.6b/`DRAW-GLYPH`, draw via its stroke word, scale
|
||||||
a string containing both ASCII and at least one Latin-1 character renders correctly on the
|
its returned `em-advance` to pixels (`GSIZE @ EM-UNITS */`) and accumulate into the cursor
|
||||||
CANVAS in one call, verified via screendump, no overlapping/misspaced glyphs. *Refs:* §27.6.
|
X, per §27.6.6. *Done when:* a string containing ASCII, at least one Latin-1 character, and
|
||||||
|
at least one General Punctuation character (e.g. an em dash) renders correctly on the
|
||||||
|
CANVAS in one call, verified via screendump, with correct proportional spacing (no
|
||||||
|
overlapping/misspaced glyphs, visibly different advance widths for e.g. `i` vs `M`).
|
||||||
|
*Refs:* §27.6.6.
|
||||||
|
|
||||||
- [ ] **4.3.6g — Checkpoint: render every v1 glyph on the CANVAS.** Same posture as
|
- [ ] **4.3.6g — Checkpoint: render every v1 glyph on the CANVAS.** Same posture as
|
||||||
4.3.4/4.3.5f — stop and review here before scoping REPL wiring (M8). *Done when:* a single
|
4.3.4/4.3.5f — stop and review here before scoping REPL wiring (M8). *Done when:* a single
|
||||||
screendump shows every glyph in the v1 repertoire rendered legibly and correctly
|
screendump shows all 113 glyphs in the v1 repertoire (§27.6.4) rendered legibly and
|
||||||
positioned, on all three architectures, matching the 4.3.3b/4.3.4 completion pattern
|
correctly positioned, on all three architectures, matching the 4.3.3b/4.3.4 completion
|
||||||
(screendump-verified, not just non-crashing). Three-arch acceptance boot clean, logs
|
pattern (screendump-verified, not just non-crashing). Three-arch acceptance boot clean,
|
||||||
committed. *Refs:* §27.6.
|
logs committed. *Refs:* §27.6.
|
||||||
|
|
||||||
⋯ *(4.3.x is open-ended — more items get appended here as Console work is scoped item by*
|
⋯ *(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*
|
*item, developed on the fly per §25.0. 4.4 below is unaffected by anything added above*
|
||||||
@@ -4977,4 +4993,188 @@ still open, not blocking anything below.
|
|||||||
`capsules/BLOCK_MAP.md`); 4916+ in that family is free. Whether glyph work extends
|
`capsules/BLOCK_MAP.md`); 4916+ in that family is free. Whether glyph work extends
|
||||||
`fabric.4th` or lands in a new capsule file is an open call for whichever item creates it.
|
`fabric.4th` or lands in a new capsule file is an open call for whichever item creates it.
|
||||||
|
|
||||||
|
Detailed derivation follows, §27.6.1–§27.6.6, worked out 2026-08-09 against confirmed
|
||||||
|
primitives only (`cell_t = int64_t` — `include/vm.h:71`; `*/`, `WITHIN`, `CASE`/`OF`/
|
||||||
|
`ENDOF`/`ENDCASE`, `CREATE`, `EXECUTE`, `'`, `LSHIFT`/`RSHIFT`/`AND`/`OR` all confirmed
|
||||||
|
registered in `src/word_source/*.c` — no word or syntax below was assumed without checking).
|
||||||
|
No `$`/`0x` hex-literal syntax was found anywhere in this tree, so every formula below uses
|
||||||
|
decimal literals only.
|
||||||
|
|
||||||
|
### 27.6.1 Em-square coordinate convention (4.3.6)
|
||||||
|
|
||||||
|
`PROJECT`/`TO-RASTER` take plain Cartesian pixel-space integers, not Q48.16 — confirmed by
|
||||||
|
reading `fabric.4th`: `Z->DELTA` is the only place Q48.16 conversion happens, and it is
|
||||||
|
already integer-in/integer-out at the `PROJECT` boundary. So a glyph stroke needs one
|
||||||
|
scale-and-translate step from a normalized em square into that same pixel space, then hands
|
||||||
|
straight off to the existing `LINE`.
|
||||||
|
|
||||||
|
**`EM-UNITS 1000`**, standard Type1/OpenType proportions: baseline `Y=0`, x-height `≈500`,
|
||||||
|
cap-height `≈700`, ascender `≈750`, descender `≈-250`.
|
||||||
|
|
||||||
|
Using `*/ ( n1 n2 n3 -- n4 )` = `n1*n2/n3` (confirmed C source, `arithmetic_words.c:212-234`:
|
||||||
|
`int64_t intermediate = n1 * n2; result = intermediate / n3`). Worth noting: the "64-bit
|
||||||
|
intermediate to avoid overflow" comment there is vestigial at this cell width — `cell_t` is
|
||||||
|
*already* `int64_t` (`include/vm.h:71`), so the intermediate buys nothing over plain `* /`
|
||||||
|
that classic 16-bit-cell FORTH-79 needed `*/` for. Not a bug, just an observation; `*/` is
|
||||||
|
still used below for its self-documenting "scale by a ratio" idiom.
|
||||||
|
|
||||||
|
```forth
|
||||||
|
VARIABLE GOX VARIABLE GOY VARIABLE GSIZE VARIABLE GCOLOR
|
||||||
|
: EM-X ( em-x -- cart-x ) GSIZE @ EM-UNITS */ GOX @ + ;
|
||||||
|
: EM-Y ( em-y -- cart-y ) GSIZE @ EM-UNITS */ GOY @ + ;
|
||||||
|
|
||||||
|
VARIABLE GX1 VARIABLE GY1 VARIABLE GX2 VARIABLE GY2
|
||||||
|
: G-LINE ( gx1 gy1 gx2 gy2 -- )
|
||||||
|
GY2 ! GX2 ! GY1 ! GX1 !
|
||||||
|
GX1 @ EM-X GY1 @ EM-Y 0
|
||||||
|
GX2 @ EM-X GY2 @ EM-Y 0
|
||||||
|
GCOLOR @
|
||||||
|
LINE ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Store-then-fetch via `VARIABLE`s rather than deep stack-juggling four values — matches the
|
||||||
|
house style already used throughout `CIRCLE`/`ARC`/`ELLIPSE`/`EDGE`, not a new pattern.
|
||||||
|
`GOX`/`GOY` are the glyph's screen-space baseline-left anchor; `GSIZE` the requested pixel
|
||||||
|
size; both set by `DRAW-GLYPH` (§27.6.3) before a glyph word runs.
|
||||||
|
|
||||||
|
**Precision note, stated not silently assumed:** `*/`'s C division truncates toward zero,
|
||||||
|
not floor. For negative em-y values (descenders, below baseline) this loses sub-pixel
|
||||||
|
precision (e.g. `-1 16 1000 */` = `0`, not `-1`) — not a bug, but on record given this
|
||||||
|
project's history with exactly this class of truncation issue (`Q.TO-INT`, 4.3.3b).
|
||||||
|
|
||||||
|
### 27.6.2 UTF-8 decoder (4.3.6a)
|
||||||
|
|
||||||
|
Standard, unambiguous algorithm — not a design choice, just correct implementation. Lead-byte
|
||||||
|
classification by bit pattern:
|
||||||
|
|
||||||
|
```forth
|
||||||
|
: UTF8-SEQ-LEN ( lead -- n ) \ 0 = invalid lead byte
|
||||||
|
DUP 128 < IF DROP 1 EXIT THEN
|
||||||
|
DUP 224 AND 192 = IF DROP 2 EXIT THEN
|
||||||
|
DUP 240 AND 224 = IF DROP 3 EXIT THEN
|
||||||
|
DUP 248 AND 240 = IF DROP 4 EXIT THEN
|
||||||
|
DROP 0 ;
|
||||||
|
|
||||||
|
: UTF8-CONT? ( byte -- flag ) \ true if 10xxxxxx continuation byte
|
||||||
|
192 AND 128 = ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Codepoint assembly formulas (the specification `DECODE-UTF8` must compute — the exact FORTH
|
||||||
|
stack mechanics for consuming 1-4 bytes from a buffer and returning both the codepoint and
|
||||||
|
the advanced pointer are left to 4.3.6a's own implementation and live testing, per this
|
||||||
|
project's demonstrated history of subtle stack/precision bugs surfacing only under real
|
||||||
|
testing, not design review — presenting untested stack-juggling code here as settled would
|
||||||
|
be exactly the kind of confidently-wrong mistake §25.0 rule 4 warns against):
|
||||||
|
|
||||||
|
- 1-byte: `codepoint = lead`
|
||||||
|
- 2-byte: `codepoint = ((lead AND 31) LSHIFT 6) OR (cont1 AND 63)`
|
||||||
|
- 3-byte: `((lead AND 15) LSHIFT 12) OR ((cont1 AND 63) LSHIFT 6) OR (cont2 AND 63)`
|
||||||
|
- 4-byte: `((lead AND 7) LSHIFT 18) OR ((cont1 AND 63) LSHIFT 12) OR ((cont2 AND 63) LSHIFT 6)
|
||||||
|
OR (cont3 AND 63)`
|
||||||
|
|
||||||
|
**Correction found while scoping the character list (§27.6.4): the 3-byte path is v1-required,
|
||||||
|
not future-i18n-only.** Smart quotes/en-dash/em-dash/ellipsis are Unicode General Punctuation
|
||||||
|
(U+2000–U+206F), which is *not* Latin-1 Supplement despite being commonly lumped in with
|
||||||
|
"Latin typography" — it encodes as 3-byte UTF-8. Originally assumed 3/4-byte decoding was
|
||||||
|
pure future-proofing; it is not, once those specific characters are in scope.
|
||||||
|
|
||||||
|
### 27.6.3 Codepoint → glyph dispatch (4.3.6b)
|
||||||
|
|
||||||
|
`WITHIN`'s exact semantics confirmed against `logical_words.c:370-384`, not assumed from the
|
||||||
|
ANS spec: `( n low high -- flag )` = `low <= n < high` (inclusive-low, exclusive-high).
|
||||||
|
|
||||||
|
Dispatch is a bucketed `CASE`/`OF`/`ENDOF` chain (not the flat 256-entry execution-token
|
||||||
|
table originally proposed — deliberately chosen over the table despite the table composing
|
||||||
|
more cleanly with override, see §27.6.5). `CASE` bodies cannot span block boundaries (4.3.3b
|
||||||
|
finding), so ~113 glyphs are split into range buckets, each its own word:
|
||||||
|
|
||||||
|
```forth
|
||||||
|
: DISPATCH-DIGIT ( codepoint -- em-advance ) \ 48-57
|
||||||
|
: DISPATCH-UPPER ( codepoint -- em-advance ) \ 65-90
|
||||||
|
: DISPATCH-LOWER ( codepoint -- em-advance ) \ 97-122
|
||||||
|
: DISPATCH-ASCII-PUNCT ( codepoint -- em-advance ) \ scattered 32-47,58-64,91-96,123-126
|
||||||
|
: DISPATCH-LATIN1 ( codepoint -- em-advance ) \ Latin-1 Supplement subset, §27.6.4
|
||||||
|
: DISPATCH-GENPUNCT ( codepoint -- em-advance ) \ General Punctuation subset, §27.6.4
|
||||||
|
|
||||||
|
: DISPATCH-GLYPH ( codepoint -- em-advance )
|
||||||
|
DUP 48 58 WITHIN IF DISPATCH-DIGIT EXIT THEN
|
||||||
|
DUP 65 91 WITHIN IF DISPATCH-UPPER EXIT THEN
|
||||||
|
DUP 97 123 WITHIN IF DISPATCH-LOWER EXIT THEN
|
||||||
|
DUP 32 127 WITHIN IF DISPATCH-ASCII-PUNCT EXIT THEN
|
||||||
|
DUP 160 256 WITHIN IF DISPATCH-LATIN1 EXIT THEN
|
||||||
|
DUP 8192 8304 WITHIN IF DISPATCH-GENPUNCT EXIT THEN
|
||||||
|
DROP TOFU ;
|
||||||
|
|
||||||
|
: DRAW-GLYPH ( codepoint x y size color -- em-advance )
|
||||||
|
GCOLOR ! GSIZE ! GOY ! GOX !
|
||||||
|
DISPATCH-GLYPH ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Each bucket word ends with the same default-clause pattern already used by `doe.4th`'s
|
||||||
|
`WL-HI` (`DROP` the unmatched selector, then the default expression) — not a new idiom:
|
||||||
|
|
||||||
|
```forth
|
||||||
|
: DISPATCH-DIGIT ( codepoint -- em-advance )
|
||||||
|
CASE
|
||||||
|
48 OF G-0 ENDOF 49 OF G-1 ENDOF ( ... ) 57 OF G-9 ENDOF
|
||||||
|
DROP TOFU
|
||||||
|
ENDCASE ;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Glyph-word contract: `( -- em-advance )`.** Every glyph word (`G-A`, `G-0`, …) draws itself
|
||||||
|
via `G-LINE` using the `GOX`/`GOY`/`GSIZE`/`GCOLOR` context `DRAW-GLYPH` already set, then
|
||||||
|
leaves its own advance width in em-units on the stack (per the proportional-width decision,
|
||||||
|
§27.6.4). `TOFU ( -- em-advance )` draws an empty box roughly cap-height tall and returns a
|
||||||
|
fixed default advance — proposing `500` (half an em); flag if a different default is wanted.
|
||||||
|
|
||||||
|
**Block budget, concretely estimated.** `WL-HI` (8 entries, one line each) fits in one block
|
||||||
|
with room to spare. At a conservative ~15 entries/block: `DISPATCH-UPPER`/`DISPATCH-LOWER`
|
||||||
|
(26 each) need ~2 blocks apiece, `DISPATCH-DIGIT` (10) needs 1, `DISPATCH-ASCII-PUNCT` (~32)
|
||||||
|
needs ~2-3, `DISPATCH-LATIN1`+`DISPATCH-GENPUNCT` (18 combined, §27.6.4) need ~1-2. **~8-10
|
||||||
|
blocks for dispatch alone**, before any glyph's actual stroke data — on record so 4.3.6c
|
||||||
|
isn't scoped against a fantasy budget.
|
||||||
|
|
||||||
|
### 27.6.4 Character list, confirmed 2026-08-09 (4.3.6c)
|
||||||
|
|
||||||
|
**Correction to the original "ASCII + Latin-1 typographic set" framing:** curly quotes,
|
||||||
|
en/em dash, and ellipsis are *not* Latin-1 Supplement (U+0080–U+00FF) — they're Unicode
|
||||||
|
General Punctuation (U+2000–U+206F), a separate, non-contiguous block. The confirmed v1
|
||||||
|
repertoire spans both, correctly bucketed:
|
||||||
|
|
||||||
|
- **ASCII printable** (32–126): all 95, `DISPATCH-DIGIT`/`DISPATCH-UPPER`/`DISPATCH-LOWER`/
|
||||||
|
`DISPATCH-ASCII-PUNCT`.
|
||||||
|
- **Latin-1 Supplement** (11): `°` `©` `®` `±` `×` `÷` `¢` `£` `§` `¶`, plus non-breaking
|
||||||
|
space (U+00A0 — non-printing, advance-only glyph, no visible stroke).
|
||||||
|
- **General Punctuation** (7): `'` `'` (U+2018/2019), `"` `"` (U+201C/201D), `–` `—`
|
||||||
|
(U+2013/2014), `…` (U+2026).
|
||||||
|
|
||||||
|
**113 glyphs total for v1** (95 + 11 + 7), each needing its own stroke-drawing word plus a
|
||||||
|
`CASE OF...ENDOF` entry in its bucket.
|
||||||
|
|
||||||
|
### 27.6.5 User font override (4.3.6e)
|
||||||
|
|
||||||
|
**Real constraint, found while deriving, not designed around silently.** `CASE`/`OF`/`ENDOF`
|
||||||
|
compiles an early-bound call — `DISPATCH-UPPER`'s `CASE` body bakes in a call to `G-A`'s
|
||||||
|
address at the point `DISPATCH-UPPER` is *compiled* (during the default font capsule's
|
||||||
|
load), the same way 4.3.3b found `CART-PLOT`-style redefinition only affects code compiled
|
||||||
|
*after* the redefinition. A user-font capsule that later redefines `G-A` alone does **not**
|
||||||
|
change what `DISPATCH-UPPER` calls — the override silently does nothing. This is the direct
|
||||||
|
cost of choosing `CASE` dispatch over the flat xt-table (which would have made override a
|
||||||
|
trivial table-slot overwrite, checked live via `@` on every dispatch).
|
||||||
|
|
||||||
|
**Resolved 2026-08-09: override replaces the whole bucket word, not individual glyphs.** A
|
||||||
|
user-font capsule that wants to change even one letter must redefine the entire relevant
|
||||||
|
`DISPATCH-*` word (e.g. all of `DISPATCH-UPPER` to change one uppercase letter) — no new data
|
||||||
|
structure, pure `CASE`, at the cost of override granularity. Worth stating in the open item
|
||||||
|
itself, not discovered fresh when 4.3.6e is implemented.
|
||||||
|
|
||||||
|
### 27.6.6 `TEXT` entry point, algorithm-level (4.3.6f)
|
||||||
|
|
||||||
|
`TEXT ( c-addr u x y size color -- )` walks the UTF-8 byte string left-to-right: decode one
|
||||||
|
codepoint via `DECODE-UTF8` (§27.6.2), call `DRAW-GLYPH` with the running cursor position to
|
||||||
|
draw it and get back its `em-advance`, scale that advance to pixels via `GSIZE @ EM-UNITS
|
||||||
|
*/ ` (same idiom as `EM-X`/`EM-Y`), accumulate into the cursor X, repeat until the buffer is
|
||||||
|
exhausted. Presented at the algorithm level, same caveat as `DECODE-UTF8` — the exact loop
|
||||||
|
construction is 4.3.6f's own implementation work, not settled here.
|
||||||
|
|
||||||
*Refs:* §25.5 (punch list).
|
*Refs:* §25.5 (punch list).
|
||||||
|
|||||||
Reference in New Issue
Block a user