gum-runtime-fonts

Reference guide for Gum's runtime font loading system in MonoGame/KNI — the three font loading paths (custom font, font-property cache lookup, in-memory generation), the lookup cascade, FontCache naming, and common gotchas. Load when working on TextRuntime font properties, BitmapFont loading, CustomSetPropertyOnRenderable.UpdateToFontValues, IInMemoryFontCreator, or font-related documentation.

447 stars

Best use case

gum-runtime-fonts is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Reference guide for Gum's runtime font loading system in MonoGame/KNI — the three font loading paths (custom font, font-property cache lookup, in-memory generation), the lookup cascade, FontCache naming, and common gotchas. Load when working on TextRuntime font properties, BitmapFont loading, CustomSetPropertyOnRenderable.UpdateToFontValues, IInMemoryFontCreator, or font-related documentation.

Teams using gum-runtime-fonts should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/gum-runtime-fonts/SKILL.md --create-dirs "https://raw.githubusercontent.com/vchelaru/Gum/main/.claude/skills/gum-runtime-fonts/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/gum-runtime-fonts/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How gum-runtime-fonts Compares

Feature / Agentgum-runtime-fontsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Reference guide for Gum's runtime font loading system in MonoGame/KNI — the three font loading paths (custom font, font-property cache lookup, in-memory generation), the lookup cascade, FontCache naming, and common gotchas. Load when working on TextRuntime font properties, BitmapFont loading, CustomSetPropertyOnRenderable.UpdateToFontValues, IInMemoryFontCreator, or font-related documentation.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Runtime Font Loading

Gum renders text using **BitmapFont** — a `.fnt` descriptor file plus one or more `.png` texture atlases. There are three ways to get a BitmapFont onto a TextRuntime, each with different tradeoffs.

## Three Font Loading Paths

### Path 1: Custom Font File (UseCustomFont = true)

User provides a pre-built `.fnt` file directly:
```
textRuntime.UseCustomFont = true;
textRuntime.CustomFontFile = "fonts/MyFont.fnt";
```

- File path resolves relative to `FileManager.RelativeDirectory` (typically `Content/`)
- Loaded via `new BitmapFont(path)`, cached in `LoaderManager`
- If the file doesn't exist, load silently skips — element gets `DefaultBitmapFont`
- No property-to-filename mapping; user controls the exact file

### Path 2: Font Property Cache Lookup (UseCustomFont = false, the default)

Six properties combine into a deterministic filename in `FontCache/`:

| Property | Default | Effect on filename |
|----------|---------|-------------------|
| Font / FontFamily | "Arial" | Base name (spaces → underscores) |
| FontSize | 18 | Base size number |
| OutlineThickness | 0 | `_o{N}` suffix if non-zero |
| UseFontSmoothing | true | `_noSmooth` suffix if false |
| IsItalic | false | `_Italic` suffix if true |
| IsBold | false | `_Bold` suffix if true |

**Naming formula:** `FontCache/Font{size}{name}[_o{N}][_noSmooth][_Italic][_Bold].fnt`

Examples: `FontCache/Font18Arial.fnt`, `FontCache/Font24Times_New_Roman_o1_Bold.fnt`

`BmfcSave.GetFontCacheFileNameFor()` produces this name. Every property setter on TextRuntime (Font, FontSize, etc.) calls `UpdateToFontValues()`, which regenerates the filename and attempts to load.

**Key gotcha:** Unless an `IInMemoryFontCreator` or `IRuntimeFontService` is registered, the `.fnt` file must already exist in `FontCache/`. Users often set `FontSize = 24` expecting it to work, but silently get `DefaultBitmapFont` because `Font24Arial.fnt` was never generated. There is no error or warning — the text just renders in the default font.

### Path 3: In-Memory Font Creation (IInMemoryFontCreator) — New

Generates a `BitmapFont` entirely in memory at runtime — no pre-built `.fnt` files needed. The loading code already checks for this; it slots into the cascade between embedded resources and disk-based generation.

When registered on `CustomSetPropertyOnRenderable.InMemoryFontCreator`, font-property changes (Path 2) automatically create fonts on demand. This eliminates the FontCache pre-population requirement.

## Lookup Cascade

When `UseCustomFont = false` and a font property changes, `UpdateToFontValues` tries these sources in order:

1. **LoaderManager cache** — already-loaded BitmapFont by full path
2. **Embedded resource** — MonoGameGum ships `Font18Arial` (plus Bold/Italic/Bold_Italic variants) as embedded resources; these are the default fonts
3. **IInMemoryFontCreator** — generates BitmapFont in memory, no disk I/O
4. **IRuntimeFontService** — generates `.fnt`/`.png` files on disk, then falls through to step 5 (typically tool-only, not used in game code)
5. **Disk load** — `new BitmapFont(fullPath)` if the file exists
6. **DefaultBitmapFont fallback** — `Text.DefaultBitmapFont` (Font18Arial, set during `SystemManagers` initialization)

The result is cached in `LoaderManager` so subsequent lookups for the same font properties hit step 1.

## Wiring

`SystemManagers` initialization (called by `GumService.Initialize`) sets up the font system:
- Loads embedded Font18Arial as `Text.DefaultBitmapFont`
- Wires `GraphicalUiElement.UpdateFontFromProperties` → `CustomSetPropertyOnRenderable.UpdateToFontValues`

Game code can optionally set `CustomSetPropertyOnRenderable.InMemoryFontCreator` to enable Path 3.

## Key Files

| File | Purpose |
|------|---------|
| `MonoGameGum/GueDeriving/TextRuntime.cs` | User-facing font properties; each setter calls `UpdateToFontValues()` |
| `RenderingLibrary/Graphics/Text.cs` | Renderable; holds `BitmapFont` instance and static `DefaultBitmapFont` |
| `RenderingLibrary/Graphics/Fonts/BitmapFont.cs` | Loads `.fnt` + `.png` textures; stores character metrics |
| `RenderingLibrary/Graphics/Fonts/BmfcSave.cs` | `GetFontCacheFileNameFor()` — deterministic cache filename from properties |
| `Gum/Wireframe/CustomSetPropertyOnRenderable.cs` | `UpdateToFontValues()` — orchestrates the lookup cascade |
| `RenderingLibrary/Graphics/Fonts/IInMemoryFontCreator.cs` | Interface for runtime font generation without disk I/O |
| `RenderingLibrary/Graphics/Fonts/IRuntimeFontService.cs` | Interface for disk-based font generation (typically tool-only) |
| `RenderingLibrary/SystemManagers.cs` | Wires font delegates and loads default embedded font |

Related Skills

gum-runtime-variable-references

447
from vchelaru/Gum

Reference guide for runtime variable reference propagation and the optional Gum.Expressions NuGet. Load this when working on ApplyAllVariableReferences, GumExpressionService, runtime styling/theming, or the GumExpressions project.

gum-runtime-binding

447
from vchelaru/Gum

Reference guide for Gum's runtime data binding system — BindingContext, SetBinding on both GraphicalUiElement visuals and FrameworkElement Forms controls, binding types (string, Binding object, lambda), and how the two systems differ.

validate-code-changes

447
from vchelaru/Gum

Validate all code changes on the current branch. Spawns QA and refactoring agents in parallel to review for correctness, edge cases, code quality, and pattern adherence. Use when ready to review branch changes before merging.

skills-writer

447
from vchelaru/Gum

Creates and updates skill files (.claude/skills/*/SKILL.md) by reading source code and condensing knowledge into concise reference guides. Use when asked to create a new skill, update an existing skill, or document a subsystem for Claude Code agent context.

gum-variable-deep-dive

447
from vchelaru/Gum

Deep dive into the full variable lifecycle — from VariableSave on ElementSave through runtime application on GraphicalUiElement and Forms controls. Load this when working on styling, theming, RefreshStyles, or when you need to understand how variable values flow from save data to live visuals.

gum-unit-tests

447
from vchelaru/Gum

Reference guide for writing unit tests in the Gum repository. Load this when writing or modifying tests in Gum.ProjectServices.Tests, Gum.Cli.Tests, or any other Gum test project.

gum-tool-viewmodels

447
from vchelaru/Gum

Reference guide for Gum tool ViewModel conventions. Load this when working on ViewModels, XAML views, data binding, DependsOn, or visibility properties in the Gum tool.

gum-tool-variable-references

447
from vchelaru/Gum

Reference guide for Gum's variable reference system — Excel-like cross-instance/cross-element variable binding using Roslyn-parsed assignment syntax. Load this when working on VariableReferenceLogic, EvaluatedSyntax, ApplyVariableReferences, VariableChangedThroughReference, or the VariableReferences VariableListSave.

gum-tool-variable-grid

447
from vchelaru/Gum

Reference guide for Gum's Variables tab and DataUiGrid system. Load this when working on the Variables tab, DataUiGrid control, MemberCategory, InstanceMember, category population, property grid refresh, or category expansion state persistence.

gum-tool-undo

447
from vchelaru/Gum

Reference guide for Gum's undo/redo system. Load this when working on undo/redo behavior, the History tab, UndoManager, UndoPlugin, UndoSnapshot, or stale reference issues after undo.

gum-tool-selection

447
from vchelaru/Gum

Reference guide for Gum's editor selection system. Load this when working on click/drag selection, the rectangle/marquee selector, input handlers (move, resize, rotate, polygon points), the IsActive flag, locked instance behavior, SelectionManager coordination, or the selection event cascade (plugin events, forced default state, tree view sync).

gum-tool-save-classes

447
from vchelaru/Gum

Reference guide for Gum's save/load data model. Load this when working with GumProjectSave, ScreenSave, ComponentSave, StandardElementSave, ElementSave, StateSave, VariableSave, InstanceSave, BehaviorSave, or any serialization/deserialization of Gum project files.