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
@@ -131,6 +131,24 @@ int ttf_parse(const uint8_t *data, uint32_t size, ttf_font_t *out) {
|
||||
if (rc != TTF_OK) return rc;
|
||||
if (!in_bounds(out, out->glyf_off, out->glyf_len)) return TTF_ERR_OUT_OF_BOUNDS;
|
||||
|
||||
/* hhea (for numberOfHMetrics) + hmtx (advance widths) -- mandatory,
|
||||
* needed for ttf_glyph_advance_width() (4.3.7e's proportional
|
||||
* spacing). numberOfHMetrics is hhea's 18th field, a fixed 36-byte
|
||||
* table per spec. */
|
||||
{
|
||||
uint32_t hhea_off, hhea_len_unused, hmtx_len;
|
||||
rc = find_table(data, size, num_tables, TAG('h', 'h', 'e', 'a'), &hhea_off, &hhea_len_unused);
|
||||
if (rc != TTF_OK) return rc;
|
||||
if (!in_bounds(out, hhea_off, 36)) return TTF_ERR_BAD_TABLE;
|
||||
out->num_h_metrics = rd_u16(data, hhea_off + 34);
|
||||
|
||||
rc = find_table(data, size, num_tables, TAG('h', 'm', 't', 'x'), &out->hmtx_off, &hmtx_len);
|
||||
if (rc != TTF_OK) return rc;
|
||||
if (out->num_h_metrics == 0
|
||||
|| !in_bounds(out, out->hmtx_off, (uint32_t) out->num_h_metrics * 4))
|
||||
return TTF_ERR_BAD_TABLE;
|
||||
}
|
||||
|
||||
/* cmap is optional to overall parse success; codepoint lookup just
|
||||
* fails cleanly (TTF_GLYPH_MISSING) if it's absent or unrecognized. */
|
||||
{
|
||||
@@ -262,6 +280,16 @@ int ttf_glyph_header(const ttf_font_t *font, uint32_t glyph_index, ttf_glyph_hea
|
||||
return TTF_OK;
|
||||
}
|
||||
|
||||
uint16_t ttf_glyph_advance_width(const ttf_font_t *font, uint32_t glyph_index) {
|
||||
uint32_t idx, off;
|
||||
|
||||
if (!font || font->num_h_metrics == 0) return 0;
|
||||
idx = glyph_index < font->num_h_metrics ? glyph_index : (uint32_t) font->num_h_metrics - 1;
|
||||
off = font->hmtx_off + idx * 4;
|
||||
if (!in_bounds(font, off, 2)) return 0;
|
||||
return rd_u16(font->data, off);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* 4.3.7a — glyph outline extraction
|
||||
* ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user