Skip to content

fix(sdl2): pixel-perfect rendering across DPI levels#2222

Merged
theangelperalta merged 2 commits into
lem-project:mainfrom
theangelperalta:sdl2-rendering-fixes
Jun 6, 2026
Merged

fix(sdl2): pixel-perfect rendering across DPI levels#2222
theangelperalta merged 2 commits into
lem-project:mainfrom
theangelperalta:sdl2-rendering-fixes

Conversation

@theangelperalta
Copy link
Copy Markdown
Collaborator

Summary

Fixes a set of SDL2 frontend rendering artefacts and adds a headless test suite to lock the invariants in.

Concern Fix
Baseline drift between glyphs on a row Anchor glyphs from cached font metrics: `glyph_y = bottom_y - ascent -
AA tail erosion at attribute boundaries (p/g/T/y/Y) Lift the two-pass :bg/:glyph rendering to span the whole physical line in redraw-physical-line — pass 1 paints all backgrounds, pass 2 blits all glyphs, so a 1px right-edge AA overhang isn't erased by the next run's background.
Oversized icon / folder / emoji glyphs plain-text-object-p routes only base text-object instances through the per-character path; icon-object/folder-object/emoji-object keep their scale-to-fit draw-object methods.
Stepped / padded highlight rectangles around descenders Pin object-height for base text-object to the stable display-char-height instead of per-string SDL_ttf surface height, so adjacent attribute runs paint identical vertical extents.
Buffer shrinks to upper-left quarter after monitor change Handle :size-changed / :display-changed window events: re-derive display scale, re-open the font at the new effective size, and refresh per-view textures via the new *post-display-change-hooks* mechanism.

Tests

Adds lem-sdl2/tests (tests/font.lisp, tests/drawing.lisp), wired into make test:

  • Font metric caching matches live TTF_FontAscent/TTF_FontDescent, sign sanity, baseline band fits within font height, and metrics refresh on reopen at a new size.
  • text-object height equals display-char-height regardless of string content, and tracks display-char-height changes (DPI swap).

12 expectations across 6 deftests, all passing (verified locally via asdf:test-system "lem-sdl2/tests"). The drawing tests use a minimal stub-display so they run headlessly without an SDL window/renderer.

Fixes several SDL2 rendering artefacts and adds a headless test suite:

- Baseline drift: anchor glyphs via cached font ascent/descent
  (glyph_y = bottom_y - ascent - |descent|) instead of surface height.
- AA tail erosion at attribute boundaries: lift the two-pass bg/glyph
  rendering to span the whole physical line in redraw-physical-line.
- Oversized icon/folder/emoji glyphs: plain-text-object-p routes only
  base text-objects through the per-character path, leaving subclasses
  their scale-to-fit draw-object methods.
- Stepped highlight rectangles: pin text-object height to the stable
  display-char-height rather than per-string SDL_ttf surface height.
- DPI transitions (Retina <-> standard): handle :size-changed /
  :display-changed by re-deriving scale, re-opening the font, and
  refreshing per-view textures via *post-display-change-hooks*.

Adds lem-sdl2/tests (font + drawing) wired into make test.
@code-contractor-app
Copy link
Copy Markdown
Contributor

code-contractor-app Bot commented Jun 5, 2026

⚠️ Violations Found (1):

[WARNING] max_total_changed_lines
  Too many lines changed: 544 > 400
  Limit: 400
  Actual: 544


ℹ️ 1 violation(s) dismissed


💬 Feedback

Reply to a violation comment with:

  • /dismiss <reason> - Report false positive or not applicable
📚 About Code Contractor

Declarative Code Standards That Learn and Improve

Define domain-specific validation rules in YAML.
Your contracts document team knowledge and evolve into more accurate AI enforcement.

Want this for your repo?
Install Code Contractor

Copy link
Copy Markdown
Contributor

@code-contractor-app code-contractor-app Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Contractor validation failed ❌ — see the sticky comment for full results.

Comment thread frontends/sdl2/display.lisp
Comment thread frontends/sdl2/drawing.lisp
Comment thread frontends/sdl2/display.lisp
Comment thread frontends/sdl2/drawing.lisp
Comment thread frontends/sdl2/display.lisp
Comment thread frontends/sdl2/lem-sdl2.asd
- Move *post-display-change-hooks* defvar into the declarations section
  at the top of display.lisp (file_structure_rule), and reword its
  docstring to note it is a hook registry analogous to Lem's other
  *...-hooks* variables.
- Export make-letter-object from lem-core/display and reference it
  unqualified in drawing.lisp instead of reaching through
  lem-core:: internal access (internal_symbol_rule).
@code-contractor-app code-contractor-app Bot dismissed their stale review June 5, 2026 22:24

All violations have been dismissed via resolved conversations.

Copy link
Copy Markdown
Contributor

@code-contractor-app code-contractor-app Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ All violations have been dismissed. This PR is ready to merge.

@theangelperalta theangelperalta merged commit 27f5567 into lem-project:main Jun 6, 2026
10 checks passed
@theangelperalta theangelperalta deleted the sdl2-rendering-fixes branch June 6, 2026 14:54
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.

1 participant