Skip to content

fix(scoreboards): announce the last-ditch font fallback - #412

Open
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/announce-font-fallback
Open

fix(scoreboards): announce the last-ditch font fallback#412
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/announce-font-fallback

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

_load_custom_font's final fallback caught every exception, passed, and returned PIL's built-in face.

That face doesn't match the panel's pixel grid, so a missing or unreadable font file rendered as fuzzy text with nothing in the log to explain it — it reads as a rendering bug rather than a missing file.

Both paths now warn: the one where the fallback font itself fails to load (naming the path and the exception), and the one that reaches PIL's built-in face regardless.

Nothing renders differently. This only makes an existing failure visible.

Scope

An audit of the font and odds paths across all eight scoreboards:

broad handlers (except Exception / bare) 77
already logging 74
broad and silent 5 → 1

football/game_renderer.py keeps its silent BDF handler deliberately — its own comment states the warning is deferred to the downstream fallback, and one is emitted there. Changing it would add noise for an expected condition.

Companion to core ChuckBuilds/LEDMatrix#520, which does the same for the schema lookup — the failure that shipped a 3px-wide glyph and was found by a user counting pixels rather than by any log line.

Fleet: 246 passed, 0 failed.

_load_custom_font's final fallback caught every exception, passed, and returned
PIL's built-in face. That face does not match the panel's pixel grid, so a
missing or unreadable font file rendered as fuzzy text with nothing in the log
to explain it -- it reads as a rendering bug rather than a missing file.

Both paths now warn: the one where the fallback font itself fails to load
(naming the path and the exception), and the one that reaches PIL's built-in
face regardless.

Nothing renders differently. This only makes an existing failure visible.

Scope: an audit of the font and odds paths across all eight scoreboards found
77 broad handlers, of which 74 already log. These two were the only ones that
were both broad and silent. football/game_renderer.py keeps its silent BDF
handler deliberately -- its comment states the warning is deferred to the
downstream fallback, and one is emitted there.
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 57f1fd03-11f4-406f-b949-784ba98b1dc9


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

ChuckBuilds pushed a commit that referenced this pull request Sep 4, 2026
Addresses three CodeRabbit findings on #417, all of them real.

The first is the one that mattered: ledmatrix-flights had six anti-aliased
draws this PR had already claimed to fix. None of its ten Draw sites calls
.text() itself -- every renderer hands the Draw to _draw_centered()/_draw(),
which do. The first version of this gate matched `<var>.text(` file-wide and
caught them; tightening it to same-scope AST matching to cut false positives
threw the real findings away and reported the file clean. The runtime probe
missed them too, because the harness never renders those flight paths.

So the gate now resolves, to a fixpoint, which functions draw text on a
parameter, and treats a Draw handed to one of those as text-rendering. That
sits between the file-wide regex (130 findings, mostly noise) and same-scope
matching (missed real ones): an overlay Draw passed to a compositing helper is
still ignored, while _draw_centered(draw, ...) counts.

Two smaller gate defects, also reported and also real:

  * any `.fontmode` assignment satisfied the check, so `fontmode = "L"` -- the
    anti-aliasing default -- would have passed. Now only the constant "1".
  * ast.walk() descended into nested scopes and ignored statement order, so a
    fontmode set *before* its Draw() counted. Now scoped and ordered.

Each is mutation-tested: removing a hand-off fontmode, setting it to "L", or
moving it above its Draw() each make the gate fail.

That found 40 further sites in 13 plugins, including overlay and celebration
paths in all eight scoreboards that the harness never renders.

Versions are picked above every number claimed by #409 and #412; football takes
3.4.3 so #424 keeps 3.5.0. Merge order: #409, #412, this, then #424.

Verified: 246 passed / 2 skipped / 0 failed, 72-card scroll guard passes, all
repo gates pass, and the runtime probe still reports 0 anti-aliased text draws
across 31 plugins at every panel size.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RRtqXDCnvnY6EQwhT5CV9
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.

2 participants