Skip to content

feat(gfx): proportional antialiased text via SDL2_ttf (#593)#595

Merged
InauguralPhysicist merged 1 commit into
mainfrom
feat/gfx-ttf-text
Jul 14, 2026
Merged

feat(gfx): proportional antialiased text via SDL2_ttf (#593)#595
InauguralPhysicist merged 1 commit into
mainfrom
feat/gfx-ttf-text

Conversation

@InauguralPhysicist

Copy link
Copy Markdown
Collaborator

What

Starts the "EigenScript programs should not look outdated" train from today's DeslanStudio-vs-Qt side-by-side. gfx_text gains a proportional antialiased TTF renderer, loaded lazily via dlopen exactly like SDL2/SDL2_mixer (no dev headers, no hard dependency), with the 5x7 bitmap font as a byte-identical load-bearing fallback.

  • Rendering: TTF_RenderUTF8_BlendedSDL_CreateTextureFromSurfaceSDL_RenderCopy; TTF_Font* cached per size; gfx_text signature unchanged (scale maps to pixel size 6*scale+2, sized so existing fixed-width layouts don't overflow).
  • Font discovery: EIGS_GFX_FONT (absolute path) wins — set-but-unreadable warns once and stays on bitmap (the deterministic off-switch); else DejaVu Sans / Liberation Sans / Noto Sans probed under /usr/share/fonts/truetype/. No fontconfig.
  • New metrics builtins: gfx_text_width of [text, scale?] and gfx_text_height of scale? — TTF metrics when active, exact bitmap math (len*6*scale / 7*scale) in fallback; usable before gfx_open. Registered via the single-line ext_names.h X-macro rows (lint E003 registry included for free).
  • lib/ui: text_width/text_height/_draw_text_clipped route through the builtins when present, probed once with the catch-undefined pattern — binaries without the gfx extension and headless tests that stub gfx_* keep the historical bitmap math. Clipping now truncates by measured width (reduces to the old floor(w/(6*scale)) in bitmap mode). Two hardcoded 7*scale height sites (badge, tooltip) now use text_height.
  • Tape: output-only, no trace records (gfx_rect class); metrics builtins untraced (gfx_ticks class).

Tests

New suite section [120] (probe-gated on a gfx build, SDL dummy video driver): a forced-fallback run (EIGS_GFX_FONT=/nonexistent/...) must report fallback-mode: 1 and pins the bitmap math exactly; a default-env run passes under either renderer (monotonic widths/heights, proportional iiii<MMMM when TTF is active, degenerate inputs, windowed render smoke). test_ui.eigs gains faithful metric stubs so all 115 layout checks keep their historical values.

Gates (all local, this branch)

  • release suite: 2863/2863
  • ASan+UBSan detect_leaks=1: 2867/2867, leak tally 0
  • gfx-build suite: 2904/2904 including [62] audio and the new [120]
  • lint: changed lib files at their baseline (no new warnings)

Visual proof

Rendered lib/ui widgets on the real X display in both modes (screenshots kept at /tmp/claude-1000/ttf-proof.png and ttf-proof-bitmap.png): TTF mode shows proportional antialiased labels/buttons; forced-fallback mode reproduces today's bitmap rendering exactly.

Closes #593

🤖 Generated with Claude Code

The DeslanStudio side-by-side against its Qt prototype read a decade
old at feature parity; the dominant gap was the 5x7 bitmap monospace
font. gfx_text now lazily dlopens libSDL2_ttf-2.0.so.0 (the same
no-headers / no-hard-dependency pattern as SDL2/SDL2_mixer) and renders
TTF_RenderUTF8_Blended through the texture path when a font is
available. EIGS_GFX_FONT overrides discovery; else DejaVu / Liberation
/ Noto Sans are probed. TTF_Font* cached per size; the gfx_text
signature is unchanged (scale maps to pixel size 6*scale+2).

THE FALLBACK IS LOAD-BEARING: without the library or a font the bitmap
path is byte-identical to before (CI containers may have neither), and
a bogus EIGS_GFX_FONT is the deterministic off-switch, pinned by the
new suite section [120] (forced-fallback exact-math run + default-env
either-renderer run, SDL dummy video for the render smoke).

New metrics builtins gfx_text_width of [text, scale?] and
gfx_text_height of scale? return pixel metrics under the active text
renderer (bitmap math in fallback; usable before gfx_open). lib/ui
text_width / text_height / _draw_text_clipped route through them when
present — probed once with the catch-undefined pattern so binaries
without the gfx extension and headless tests that stub gfx_* keep the
historical bitmap math (test_ui gains faithful metric stubs).

Output-only: no trace-tape records in either mode (gfx_rect class);
the metrics builtins are untraced, gfx_ticks class.

Gates: release suite 2863/2863; ASan+UBSan detect_leaks=1 2867/2867
(leak tally 0); gfx-build suite 2904/2904 incl. [62]+[120]; visual
proof on the real X display in both modes.

Closes #593

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@InauguralPhysicist InauguralPhysicist merged commit 4b639a2 into main Jul 14, 2026
17 checks passed
@InauguralPhysicist InauguralPhysicist deleted the feat/gfx-ttf-text branch July 14, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gfx: proportional antialiased text rendering (SDL2_ttf) — EigenScript UIs look outdated

1 participant