feat(gfx): proportional antialiased text via SDL2_ttf (#593)#595
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Starts the "EigenScript programs should not look outdated" train from today's DeslanStudio-vs-Qt side-by-side.
gfx_textgains 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.TTF_RenderUTF8_Blended→SDL_CreateTextureFromSurface→SDL_RenderCopy;TTF_Font*cached per size;gfx_textsignature unchanged (scalemaps to pixel size6*scale+2, sized so existing fixed-width layouts don't overflow).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.gfx_text_width of [text, scale?]andgfx_text_height of scale?— TTF metrics when active, exact bitmap math (len*6*scale/7*scale) in fallback; usable beforegfx_open. Registered via the single-lineext_names.hX-macro rows (lint E003 registry included for free).text_width/text_height/_draw_text_clippedroute through the builtins when present, probed once with the catch-undefined pattern — binaries without the gfx extension and headless tests that stubgfx_*keep the historical bitmap math. Clipping now truncates by measured width (reduces to the oldfloor(w/(6*scale))in bitmap mode). Two hardcoded7*scaleheight sites (badge, tooltip) now usetext_height.Tests
New suite section [120] (probe-gated on a gfx build, SDL dummy video driver): a forced-fallback run (
EIGS_GFX_FONT=/nonexistent/...) must reportfallback-mode: 1and pins the bitmap math exactly; a default-env run passes under either renderer (monotonic widths/heights, proportionaliiii<MMMMwhen TTF is active, degenerate inputs, windowed render smoke).test_ui.eigsgains faithful metric stubs so all 115 layout checks keep their historical values.Gates (all local, this branch)
detect_leaks=1: 2867/2867, leak tally 0Visual proof
Rendered
lib/uiwidgets on the real X display in both modes (screenshots kept at/tmp/claude-1000/ttf-proof.pngandttf-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