gum-tool-font-generation
Reference guide for Gum's bitmap font generation pipeline — how the tool converts font properties into .fnt/.png files via bmfont.exe. Load this when working on BmfcSave, HeadlessFontGenerationService, FontManager, BmfcTemplate.bmfc, font cache naming, texture size estimation, or the GumProjectFontGenerator CLI.
Best use case
gum-tool-font-generation is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Reference guide for Gum's bitmap font generation pipeline — how the tool converts font properties into .fnt/.png files via bmfont.exe. Load this when working on BmfcSave, HeadlessFontGenerationService, FontManager, BmfcTemplate.bmfc, font cache naming, texture size estimation, or the GumProjectFontGenerator CLI.
Teams using gum-tool-font-generation 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
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/gum-tool-font-generation/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How gum-tool-font-generation Compares
| Feature / Agent | gum-tool-font-generation | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Reference guide for Gum's bitmap font generation pipeline — how the tool converts font properties into .fnt/.png files via bmfont.exe. Load this when working on BmfcSave, HeadlessFontGenerationService, FontManager, BmfcTemplate.bmfc, font cache naming, texture size estimation, or the GumProjectFontGenerator CLI.
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
# Font Generation Pipeline
Gum generates BMFont-format bitmap fonts (`.fnt` + `.png` atlas) by shelling out to `bmfont.exe`. The pipeline is: **collect font properties → build BmfcSave → write .bmfc file → invoke bmfont.exe → produce .fnt + .png**.
> **Future direction:** The bmfont.exe dependency is being evaluated for replacement due to platform limitations (Windows-only) and other concerns.
## Architecture
```
FontManager (tool facade)
└─ HeadlessFontGenerationService (core logic, headless)
├─ BmfcSave (data model + .bmfc serialization)
│ └─ BmfcTemplate.bmfc (template file with placeholders)
└─ bmfont.exe (external process, one per font, run in parallel)
```
**FontManager** is the tool-facing entry point. It wires `IFontGenerationCallbacks` (UI output, spinner, file-watch suppression) and delegates all real work to **HeadlessFontGenerationService** via `IHeadlessFontGenerationService`.
**HeadlessFontGenerationService** is platform-checked (Windows-only, throws `PlatformNotSupportedException` otherwise). It owns:
- Collecting all unique fonts a project needs (`CollectRequiredFonts`)
- Deciding whether a font file already exists or needs (re)generation
- Launching bmfont.exe processes — one per font, all awaited via `Task.WhenAll` for parallelism
- Texture size estimation (heuristic) and optimization (binary search over `AvailableSizes`)
**BmfcSave** holds the six font properties (FontName, FontSize, OutlineThickness, UseSmoothing, IsItalic, IsBold) plus ranges, spacing, and output dimensions. Its `Save()` method loads `BmfcTemplate.bmfc` and does string replacement to produce the `.bmfc` file that bmfont.exe consumes. It also owns `FontCacheFileName` which determines the output path.
## Generation Flow
1. **Property collection**: `TryGetBmfcSaveFor` reads font properties from a `StateSave` (with optional instance prefix and forced overrides) and returns a `BmfcSave` or null. For direct Text instances this is sufficient, but for component instances containing Text, `CollectFontsFromNestedTextInstances` recursively descends using `RecursiveVariableFinder` to resolve font properties through exposed variables and inheritance.
2. **Deduplication**: `CollectRequiredFonts` iterates all elements/states/instances and deduplicates by `FontCacheFileName` (a deterministic name encoding all font parameters).
3. **Size estimation**: Before generating, `AssignEstimatedNeededSizeOn` either runs a binary-search optimization (`GetOptimizedSizeFor`, controlled by `AutoSizeFontOutputs` project setting) or uses a heuristic lookup table (`EstimateBlocksNeeded`) based on effective font size.
4. **Template expansion**: `BmfcSave.Save()` loads `Content/BmfcTemplate.bmfc`, replaces placeholders, and writes the `.bmfc` file alongside the target `.fnt` path.
5. **bmfont.exe invocation**: `CreateBitmapFontFilesIfNecessaryAsync` launches `bmfont.exe -c "<bmfc>" -o "<fnt>"` via `Process.Start` with `UseShellExecute = true`. The process is awaited async (`WaitForExitAsync`) or synchronously depending on `createTask`.
6. **File-watch suppression**: Before writing, all expected output paths (.bmfc, .fnt, .png pages) are registered with `IFontGenerationCallbacks.OnIgnoreFileChange` so the file watcher doesn't trigger reloads.
## Font Cache Naming
`BmfcSave.FontCacheFileName` produces paths like `FontCache/Font18Arial.fnt`. The name encodes all parameters that affect output:
- Base: `Font{size}{name}` (spaces in font name → underscores)
- Suffixes: `_o{N}` (outline), `_noSmooth`, `_Italic`, `_Bold`
This means two elements with identical font settings share one cached file.
## Channel Behavior (Outline vs No-Outline)
When OutlineThickness is 0: alpha=0, RGB channels=4 (glyph in alpha channel).
When OutlineThickness > 0: alpha=1, RGB channels=0 (outline uses color channels).
## Texture Size Optimization
`GetOptimizedSizeFor` does a binary search over `AvailableSizes` (32x32 up to 8192x8192) to find the smallest texture that keeps the font on a single page. Each probe generates the font to a temp directory and parses the `pages=` line from the resulting `.fnt` file.
The heuristic fallback (`EstimateBlocksNeeded`) uses a lookup table mapping effective font size to a number of 256-pixel blocks, then factors the block count into width x height.
## Character Ranges
- Default: `32-126,160-255` (ASCII + Latin-1 Supplement)
- Project-level `FontRanges` setting overrides for all fonts
- Ranges are validated (no spaces, proper start < end), with automatic fallback to default
- Space character (32) is always included via `EnsureRangesContainSpace`
- Large range sets are split across multiple `chars=` lines (max 10 blocks per line) for bmfont.exe compatibility
- `GenerateRangesFromFile` can derive ranges from a text file's unique characters
## Embedded Resources
`bmfont.exe` and `BmfcTemplate.bmfc` are embedded in the `Gum.ProjectServices` assembly and extracted on first use by `EnsureToolsExtracted`. The template uses placeholder tokens like `FontNameVariable`, `FontSizeVariable`, `{UseSmoothing}`, etc.
## Standalone CLI
`GumProjectFontGenerator` is a standalone console app that loads a `.gumx` project and generates all missing fonts. It uses `HeadlessFontGenerationService` directly with no callbacks.
## Font Creation Paths
All font generation now routes through `HeadlessFontGenerationService`. There are two call sites:
**On-demand:** `CustomSetPropertyOnRenderable` resolves `IFontManager` via DI (`Builder.Get<IFontManager>()`) and calls `CreateFontIfNecessary(BmfcSave)` when a font property changes. The BBCode path (`GetAndCreateFontIfNecessary`) uses the same pattern for inline font tags.
**Bulk (tool-only):** `CreateAllMissingFontFiles` scans the entire project on load or "regenerate fonts" and generates all missing font files in parallel.
Both delegate to `HeadlessFontGenerationService`. Legacy `IRuntimeFontService`, `GenerateMissingFontsForReferencingElements`, and the embedded bmfont.exe in RenderingLibrary have been removed.
## Key Files
| File | Purpose |
|------|---------|
| `Gum/Services/Fonts/IFontManager.cs` | Interface for the tool-facing font manager |
| `Gum/Services/Fonts/FontManager.cs` | Tool facade — delegates to headless service via DI |
| `Tools/Gum.ProjectServices/FontGeneration/HeadlessFontGenerationService.cs` | Core generation logic — collection, size estimation, bmfont.exe invocation |
| `Tools/Gum.ProjectServices/FontGeneration/IHeadlessFontGenerationService.cs` | Interface for the headless service |
| `Tools/Gum.ProjectServices/FontGeneration/IFontGenerationCallbacks.cs` | Callback interface (output, spinner, file-watch ignore) |
| `Gum/Services/Fonts/ToolFontGenerationCallbacks.cs` | Tool-specific callback implementation |
| `RenderingLibrary/Graphics/Fonts/BmfcSave.cs` | Font data model, .bmfc serialization, cache file naming, range utilities |
| `Gum/Content/BmfcTemplate.bmfc` | Template with placeholders for bmfont.exe config |
| `GumProjectFontGenerator/Program.cs` | Standalone CLI for batch font generation |Related Skills
gum-tool-viewmodels
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
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
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
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
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
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.
gum-tool-plugins
Reference guide for the Gum tool's plugin system, including visualization plugins (EditorTabPlugin_XNA, TextureCoordinateSelectionPlugin). Load this when working on plugin registration, PluginBase, InternalPlugin, PluginManager, plugin events, visualization/rendering concerns, or finding which internal plugin owns a feature.
gum-tool-output
Reference guide for Gum's Output tab system. Load this when working on the Output tab, IOutputManager, MainOutputViewModel, GuiCommands.PrintOutput, or adding output/error messages to the tool.
gum-tool-file-watch
Reference guide for Gum's FileWatch system. Load this when working on file watching, external file change detection, IgnoreNextChangeUntil, FileWatchManager, FileWatchLogic, FileChangeReactionLogic, or reloading assets/elements when files change on disk.
gum-tool-errors
Reference guide for Gum's error detection and display system. Load this when working on the Errors tab, error icons ("!" mark) in the tree view, ErrorChecker, ErrorViewModel, IErrorChecker, AllErrorsViewModel, MainErrorsPlugin, RequestErrorRefreshMessage, or adding new error checks.
gum-tool-dialogs
Reference guide for Gum's dialog/popup systems. Load this when working on dialog windows, DialogService, DialogWindow, DeleteOptionsWindow, dialog scrolling, dialog layout, or adding new dialog types.
gum-tool-delete-logic
Reference guide for Gum's delete architecture. Load this when working on delete commands, IEditCommands delete methods, IDeleteLogic, DeleteLogic, DeleteOptionsWindow, HandleDeleteCommand, AskToDeleteState, AskToDeleteStateCategory, or DeleteSelection.