ttf.c: glyph raster cache, fixed slots, no allocation (item 4.3.7d)
Punch list §25 item 4.3.7d complete. ttf_raster_cache_get() looks up (font, codepoint, size_px) in a caller-owned fixed slot array, evicting round-robin once full, rasterizing into a slot on a miss. Verified live in tools/ttftest.c: an identical (font, 'A', 24px) call made twice returns was_hit=0 then was_hit=1, and the slot's own hits counter reads exactly 1 afterward -- checked programmatically. A different-codepoint call misses again, proving the key actually discriminates. Wall-clock timing (miss 0.040ms vs hit 0.001ms) is printed as informational corroboration only, not the load-bearing check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
095860251a
commit
2db4603d04
@@ -813,6 +813,96 @@ int ttf_rasterize_glyph(const ttf_font_t *font, uint32_t glyph_index,
|
||||
return TTF_OK;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* 4.3.7d — glyph raster cache: fixed caller-owned slots, no allocation.
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
void ttf_raster_cache_init(ttf_raster_cache_t *cache, ttf_raster_cache_slot_t *slots,
|
||||
uint32_t slot_count) {
|
||||
uint32_t i;
|
||||
cache->slots = slots;
|
||||
cache->slot_count = slot_count;
|
||||
cache->evict_next = 0;
|
||||
for (i = 0; i < slot_count; i++) {
|
||||
slots[i].valid = 0;
|
||||
slots[i].hits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ttf_raster_cache_get(ttf_raster_cache_t *cache, const ttf_font_t *font,
|
||||
uint32_t codepoint, uint32_t size_px,
|
||||
ttf_bitmap_t *out, int *was_hit) {
|
||||
uint32_t i, slot_idx;
|
||||
ttf_raster_cache_slot_t *slot;
|
||||
int rc;
|
||||
|
||||
if (!cache || !font || !out) return TTF_ERR_BAD_TABLE;
|
||||
if (size_px > TTF_CACHE_MAX_SIZE_PX) return TTF_ERR_UNSUPPORTED;
|
||||
|
||||
for (i = 0; i < cache->slot_count; i++) {
|
||||
slot = &cache->slots[i];
|
||||
if (slot->valid && slot->font == font && slot->codepoint == codepoint
|
||||
&& slot->size_px == size_px) {
|
||||
slot->hits++;
|
||||
out->pixels = slot->pixels;
|
||||
out->width = slot->width;
|
||||
out->height = slot->height;
|
||||
if (was_hit) *was_hit = 1;
|
||||
return TTF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Miss: use a free slot if one exists, else evict round-robin. */
|
||||
slot_idx = cache->slot_count;
|
||||
for (i = 0; i < cache->slot_count; i++) {
|
||||
if (!cache->slots[i].valid) { slot_idx = i; break; }
|
||||
}
|
||||
if (slot_idx == cache->slot_count) {
|
||||
slot_idx = cache->evict_next;
|
||||
cache->evict_next = (cache->evict_next + 1) % cache->slot_count;
|
||||
}
|
||||
slot = &cache->slots[slot_idx];
|
||||
|
||||
{
|
||||
uint32_t j;
|
||||
ttf_bitmap_t bmp;
|
||||
q48_16_t scale;
|
||||
uint32_t gid;
|
||||
|
||||
for (j = 0; j < TTF_CACHE_BITMAP_BYTES; j++) slot->pixels[j] = 0;
|
||||
|
||||
gid = ttf_codepoint_to_glyph(font, codepoint);
|
||||
scale = q48_div(q48_from_u64(size_px), q48_from_u64(font->units_per_em));
|
||||
|
||||
bmp.pixels = slot->pixels;
|
||||
bmp.width = TTF_CACHE_BITMAP_DIM;
|
||||
bmp.height = TTF_CACHE_BITMAP_DIM;
|
||||
rc = ttf_rasterize_glyph(font, gid, scale,
|
||||
q48_from_u64(TTF_CACHE_MARGIN),
|
||||
q48_from_u64(size_px + TTF_CACHE_MARGIN),
|
||||
255, &bmp);
|
||||
if (rc != TTF_OK) {
|
||||
slot->valid = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
slot->valid = 1;
|
||||
slot->font = font;
|
||||
slot->codepoint = codepoint;
|
||||
slot->size_px = size_px;
|
||||
slot->width = TTF_CACHE_BITMAP_DIM;
|
||||
slot->height = TTF_CACHE_BITMAP_DIM;
|
||||
slot->hits = 0;
|
||||
}
|
||||
|
||||
out->pixels = slot->pixels;
|
||||
out->width = slot->width;
|
||||
out->height = slot->height;
|
||||
if (was_hit) *was_hit = 0;
|
||||
return TTF_OK;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* 4.3.7b — font data ingestion (capsule-backed, zero-copy)
|
||||
* ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user