Skip to content

Load font files passed as font_name, and accept lists of names - #2922

Merged
pvcraven merged 1 commit into
developmentfrom
fix/text-font-paths
Oct 6, 2026
Merged

pvcraven merged 1 commit into
developmentfrom
fix/text-font-paths

Conversation

@pvcraven

@pvcraven pvcraven commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Summary

PR 5 of the text improvements: font_name paths to font files, and lists of names.

Bugs

Problem Before After
A path to a font file drew the default font Text(..., font_name=":system:fonts/ttf/Kenney/Kenney_Future.ttf") (or the real path) passed "Kenney_Future.ttf" to pyglet as the font name, and never loaded the file. pyglet found no such font and used Segoe UI Loads the file and uses its family, "Kenney Future"
The font_name setter ignored paths text.font_name = path drew the default font Same as the constructor
Lists of names raised TypeError font_name=["NoSuchFont", "arial"] raised in Text and draw_text, even though the docs say lists are accepted Works like a tuple
A path beat earlier names ("Liberation Sans", path) used the file, because any path found anywhere in the tuple was returned right away The first available font is used, in order

create_text_sprite() and draw_text() go through Text, so they're fixed too.

How

  • Loading a path: _attempt_font_name_resolution checks each name. If it resolves to a file, the file is loaded with pyglet.font.add_file and the name is replaced by the font's family name. The resulting list goes to pyglet.font.load, as before, which picks the first font that exists.
  • Finding the family name: it comes from pyglet's on_font_loaded event during add_file. That event gives the name the platform registers the font under, which is the name pyglet can load it by. If the file was already added to pyglet some other way, there's no event, so the name is read from the file with pyglet.font.ttf.TruetypeInfo instead.
  • Each file is loaded once: loaded files and their family names are remembered. arcade.load_font() uses the same code, so a path to a font loaded earlier (for example by load_kenney_fonts()) doesn't add the file again.
  • Errors stay the same: a resource that doesn't exist falls back to the next name, and an unknown resource handle or an empty name still raises.

Creating a Text costs the same as before: about 690 µs with the default ("calibri", "arial"), measured alternating old and new.

Tests

New tests/unit/text/test_text_fonts.py (14 tests). Each test starts with no remembered font files.

  • Paths: a resource handle and a real path, in the constructor and in the setter, render pixel-identical to the family name.
  • Name order: a path inside a tuple works, and the first available font wins in order.
  • Lists: lists work in Text and draw_text.
  • Files: each file is loaded once across several Text objects and load_font(). A file already added to pyglet directly gets its name from the file.
  • Errors: a missing resource falls back to the next name, while an unknown handle and an empty name raise.

On development, 9 of them fail. The tests load every bundled font up front, so a path in the tests always points to a font that's already loaded. I checked the first-time load separately, in a fresh process: a path to the unloaded Kenney Future file draws Kenney Future.

Full suite on pyglet 3.0.dev11: 1557 passed, no warnings, plus the same 3 render tests that fail only on my machine. Ruff is clean, and mypy has no new errors.

The changelog has an entry under Unreleased → Fixes.

🤖 Generated with Claude Code

- A path or resource handle passed as font_name was turned into the
  file name (e.g. "Kenney_Future.ttf") and never loaded, so pyglet
  drew the default font. The file is now loaded the first time it's
  used, and its family name is used. Each file is loaded once.
- The family name comes from pyglet's on_font_loaded event, which
  uses the platform's name for the font. If the file was already
  added to pyglet some other way, it's read from the file instead.
- Lists of font names raised TypeError, although the docs allow them.
- A path no longer takes priority over names listed before it.
- The Text.font_name setter now resolves paths too.
- load_font() records the family name, so a later path is cheap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pvcraven
pvcraven force-pushed the fix/text-font-paths branch from 5ad0cce to 0877dca Compare October 6, 2026 15:30
@pvcraven
pvcraven merged commit 0175079 into development Oct 6, 2026
7 checks passed
@pvcraven
pvcraven deleted the fix/text-font-paths branch October 6, 2026 15:35
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