ttf_words.c: TTF-TEXT entry point, hmtx advance widths (item 4.3.7e)
Punch list §25 item 4.3.7e complete. New src/word_source/ttf_words.c registers TTF-TEXT ( c-addr u x y size color -- ): lazily loads the v1 default font capsule + raster cache once, decodes UTF-8 (C reimplementation mirroring capsules/fabric.4th's DECODE-UTF8 exactly), looks up each glyph's cached bitmap, blits via fb_put_pixel, advances the pen by the glyph's real hmtx advance width scaled to pixels. Necessary plumbing: ttf_parse() now also locates hhea/hmtx, and ttf_glyph_advance_width() reads a glyph's advance width -- required for this item's own "proportional spacing correct" acceptance clause, no advance-width data existed anywhere else in the parser. Verified in tools/ttftest.c: A/a/0/space all read advance_width=600, correctly uniform since JetBrainsMono-Regular.ttf is monospace. (x,y) is raster pixel space (top-left origin, Y-down), deliberately not the stroke font TEXT's Cartesian Y-up convention -- recorded explicitly in ttf_words.h, not conflated. Verified live, amd64, screendump: injected S" Hi 4.3.7e!" 200 200 28 16777215 TTF-TEXT over a serial socket after boot, no error, captured a screendump showing the string rendered legibly with correct mixed-case/digit/punctuation glyphs and even spacing. TTF-TEXT is this item's permanent deliverable, not a throwaway probe. Compile-checked clean on all three architectures. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2db4603d04
commit
715ebcc57e
@@ -93,6 +93,12 @@ typedef struct {
|
||||
/* Selected cmap subtable (format 4 only, see file header comment). */
|
||||
uint32_t cmap_subtable_off;
|
||||
int has_cmap;
|
||||
|
||||
/* hhea/hmtx, for ttf_glyph_advance_width() -- proportional spacing
|
||||
* (FABRIC.md item 4.3.7e). Mandatory tables per the TrueType spec,
|
||||
* so their absence fails ttf_parse() same as head/maxp/loca/glyf. */
|
||||
uint32_t hmtx_off;
|
||||
uint16_t num_h_metrics;
|
||||
} ttf_font_t;
|
||||
|
||||
/** Raw glyf record header, per §27.6/4.3.7's "done when" clause. */
|
||||
@@ -137,6 +143,19 @@ uint32_t ttf_codepoint_to_glyph(const ttf_font_t *font, uint32_t codepoint);
|
||||
int ttf_glyph_header(const ttf_font_t *font, uint32_t glyph_index,
|
||||
ttf_glyph_header_t *out);
|
||||
|
||||
/**
|
||||
* ttf_glyph_advance_width - Horizontal advance width via hmtx, in raw
|
||||
* font design units (NOT scaled by unitsPerEm -- caller's job, e.g.
|
||||
* `q48_mul(q48_from_u64(width), scale)`; always non-negative, so the
|
||||
* shared q48_mul is fine here unlike the signed cases documented in
|
||||
* ttf.c's rasterizer). Glyphs past hmtx's numberOfHMetrics entries share
|
||||
* the last entry's width, per spec.
|
||||
*
|
||||
* @param glyph_index As returned by ttf_codepoint_to_glyph()
|
||||
* @return advance width, or 0 if glyph_index is out of range
|
||||
*/
|
||||
uint16_t ttf_glyph_advance_width(const ttf_font_t *font, uint32_t glyph_index);
|
||||
|
||||
/** One outline point, in raw font design units (NOT scaled by unitsPerEm —
|
||||
* that's the caller's job, same convention as ttf_glyph_header_t's bbox),
|
||||
* expressed in Q48.16. Two's-complement negative values are expected and
|
||||
|
||||
Reference in New Issue
Block a user