reckfellENGINE

Fonts: loading, sizing, wrapping and fallbacks

A complete C# example with the built-in font, FontFile, SystemFont and FontVariation; quality and export settings.

On this page

Run without an external file

Add UiSampleStyle.cs and FontsDemo.cs to a C# project. Attach FontsDemo to a separate level's Control root, build and run with F6.

Two labels contain Latin, Cyrillic and a combining accent. Their sizes differ; the larger uses a synthetically emboldened FontVariation. The lower long label wraps as the window narrows. The multilingual sample string is intentionally identical in both versions.

FontsDemo.cs
C#
using Reckfell;

public partial class FontsDemo : Control
{
    public Label Small { get; private set; } = null!;
    public Label Large { get; private set; } = null!;
    public FontVariation Bold { get; private set; } = null!;
    public Label Wrapped { get; private set; } = null!;
    public override void _Ready()
    {
        UiSampleStyle.Prepare(this);
        var margin = new MarginContainer(); AddChild(margin); margin.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect, margin: 24);
        var column = new VBoxContainer(); margin.AddChild(column);
        Small = new Label { Text = "Reckfell — Привет!  Cafe\u0301", AutowrapMode = TextServer.AutowrapMode.WordSmart };
        Large = new Label { Text = Small.Text, AutowrapMode = TextServer.AutowrapMode.WordSmart };
        column.AddChild(Small); column.AddChild(Large);
        Small.AddThemeFontSizeOverride("font_size", 16); Large.AddThemeFontSizeOverride("font_size", 28);
        Wrapped = new Label
        {
            Text = UiSampleStyle.Text("Длинная надпись переносится в пределах доступной ширины. Размер шрифта задаётся отдельно от файла.", "A longer label wraps within the available width. Font size is configured separately from the font file."),
            AutowrapMode = TextServer.AutowrapMode.WordSmart
        };
        column.AddChild(Wrapped); SetFont(Small.GetThemeFont("font"));
    }
    private void SetFont(Font font)
    {
        Theme.DefaultFont = font;
        Bold = new FontVariation { BaseFont = font, VariationEmbolden = 1.2f };
        Large.AddThemeFontOverride("font", Bold);
    }
    public Error LoadProjectFont(string path)
    {
        if (!path.StartsWith("asset://") || !FileAccess.FileExists(path)) return Error.FileNotFound;
        var font = ResourceLoader.Load<FontFile>(path);
        if (font is null) return Error.FileUnrecognized;
        SetFont(font); return Error.Ok;
    }
    public Error LoadExternalFont(string path)
    {
        const ulong maxBytes = 16UL * 1024 * 1024;
        if (!FileAccess.FileExists(path)) return Error.FileNotFound;
        byte[] data;
        using (var file = FileAccess.Open(path, FileAccess.ModeFlags.Read))
        {
            if (file is null) return FileAccess.GetOpenError();
            ulong length = file.GetLength();
            if (length == 0 || length > maxBytes) return Error.InvalidData;
            data = file.GetBuffer((long)length);
            if ((ulong)data.LongLength != length) return Error.InvalidData;
        }
        var font = new FontFile(); font.SetData(data);
        SetFont(font); return Error.Ok;
    }
    public void UseSystemFont(string[] names) => SetFont(new SystemFont { FontNames = names });
}

Load your font

SourceAction
Project fontAdd a TTF/OTF, wait for import, then call LoadProjectFont with a asset:// path
External dynamic file at runtimeLoadExternalFont limits reading to 16 MiB, checks byte count and assigns bytes through FontFile.SetData
OS-installed familyUseSystemFont with family names; availability/results differ between devices
Bitmap fontImport a BMFont .fnt or a font image; configure its grid/character set for the source

Set size on the Control through Theme Overrides → Font Sizes or Theme.SetFontSize, not by copying the TTF for each size. Fonts/Default Font select a resource. This build's built-in fallback is Open Sans SemiBold; a project theme/font can replace it. Include required font and fallback resources for reproducible exports: SystemFont does not package OS-installed fonts into a game.

The external loader above rejects missing, empty, oversized or short-read files before replacing the font. 16 MiB is this example’s limit rather than an engine format limit. Error.Ok means bytes were accepted: this is not a validator for arbitrary fonts. Check the format, required characters and rendered result; untrusted user uploads require separate input validation.

LoadDynamicFont is a different path: it reads the file and resets options itself, but in 1.0.0 returns Error.Ok without validating decoding. That result alone is insufficient. This example bounds reading beforehand; SetData on a new resource does not perform that reset.

Glyph coverage and shaping

A missing glyph needs an appropriate fallback. Assign Font.Fallbacks in the intended order and test real language strings, punctuation, accents and emoji. HasChar helps with one character but does not prove whole-script, ligature or emoji-sequence support. System fallback depends on the device. For icon fonts, retain a stable code-point/icon mapping and check file versions.

.NET string length counts UTF-16 units, not visible graphemes. RTL, combining marks, ligatures and IME require TextServer/shaping rather than manual letter positioning. Enable wrapping and allocate width before checking alignment/TextDirection. Scaling the entire Control is not a substitute for font size.

Quality and font features

SettingUse / limitation
AntialiasingSmoothing choice; test disabled smoothing/integer positions for pixel fonts
HintingFits a dynamic font to a pixel grid, particularly at small sizes
SubpixelPositioningPositioning precision; affects caching and moving small text
MipmapsHelp downscaling and consume memory; cannot repair a low-resolution bitmap source
MSDF, MsdfSize, MsdfPixelRangeScaling/outlines within configured ranges; check small sizes and artifacts
Control outline/shadowTheme entries set color, outline size and shadow offsets; allow space before clipping edges
Variable fontFontVariation.VariationOpentype sets supported axes. Use the numeric key TextServerManager.GetPrimaryInterface().NameToTag("wght") and ranges from GetSupportedVariationList. The raw string "wght" can fail to change the selected cache in 1.0.0
Faux bold/italicVariationEmbolden/VariationTransform synthesize a style rather than supplying a genuine bold/italic face
Spacing / baselineFontVariation adjusts spacing/offset; recheck line and control heights
OpenType featuresSet supported tags through OpentypeFeatures; ligature/number behavior depends on the font. Separate from FontVariation.VariationOpentype axes
Color emojiRequire coverage and a supported color format; check target platforms
PrerenderingImport settings can prebuild required glyphs/sizes, trading first-display work for size/memory

Dynamic import formats include TTF/OTF/WOFF/WOFF2; FontFile and advanced import settings expose options. Bitmap quality is bounded by source images and scale. Do not prebuild every size/axis combination without checking memory.

A new FontFile has MsdfPixelRange = 16, MsdfSize = 48 and SubpixelPositioning = Auto. After LoadDynamicFont, these reset to 14, 128 and Disabled respectively. Configure quality options after loading. MSDF does not support hinting; Oversampling is bypassed for MSDF and positive FixedSize. Exact FontFile settings.

Project settings and diagnosis

gui/theme/custom_font selects the shared resource; gui/theme/default_font_* controls built-in font quality and gui/theme/default_theme_scale scales the theme. Respect restart/reimport requirements. The example retains the previous font on checked read failures; successfully read file content needs separate validation.

For missing-glyph boxes, check coverage/fallbacks. For clipped text, check width, wrapping, minima, clipping and outlines. For changed export appearance, check bundled resources and SystemFont use. For first-display stalls, inspect cached glyphs/sizes/import rather than only game FPS. The article's checks use a private Windows TTF to exercise loading; the font file is not distributed with the example.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.