Skip to content

FigletText

Display large ASCII-art text rendered from a FIGfont. Useful for splash screens, banners, and any place a normal Text widget feels too understated.

Basic Usage

Use FigletText(...) and pick a font from the bundled FigletFonts catalog:

csharp
using Hex1b;
using Hex1b.Widgets;

await using var terminal = Hex1bTerminal.CreateBuilder()
    .WithHex1bApp((app, options) => ctx => ctx.VStack(v => [
        v.FigletText("Hello").Font(FigletFonts.Standard),
        v.Text(""),
        v.Text("Press Ctrl+C to exit.")
    ]))
    .Build();

await terminal.RunAsync();

FigletText measures to the natural width and height of the rendered glyphs, so you can compose it inside any layout container just like an ordinary widget.

Choosing a Font

Hex1b ships eight royalty-free FIGfonts as embedded resources, exposed as lazily-loaded singletons on FigletFonts:

PropertyDescription
FigletFonts.StandardThe default monospace banner font from the FIGlet distribution
FigletFonts.SlantItalicized variant of standard
FigletFonts.SmallCompact 5-row variant for narrower terminals
FigletFonts.BigEnlarged 8-row banner font
FigletFonts.MiniTiny 4-row font for extremely narrow output
FigletFonts.ShadowText with a drop-shadow effect
FigletFonts.BlockSolid block letters
FigletFonts.BannerWide hash-shaped letters reminiscent of banner(1)

Pass any of them to .Font(...):

csharp
using Hex1b;
using Hex1b.Widgets;

await using var terminal = Hex1bTerminal.CreateBuilder()
    .WithHex1bApp((app, options) => ctx => ctx.VStack(v => [
        v.Text("standard:"),
        v.FigletText("Hex1b").Font(FigletFonts.Standard),
        v.Text(""),
        v.Text("slant:"),
        v.FigletText("Hex1b").Font(FigletFonts.Slant),
        v.Text(""),
        v.Text("small:"),
        v.FigletText("Hex1b").Font(FigletFonts.Small),
    ]))
    .Build();

await terminal.RunAsync();
csharp

TIP

Loading bundled fonts via the FigletFonts.* properties is essentially free after the first access — each font is parsed once and cached for the lifetime of the process. Avoid FigletFont.LoadBundled(string) in render paths because it re-parses the resource on every call.

Layout Modes

FIGfonts can be composed in three different ways. The same FigletLayoutMode enum is used for both axes — apply it via .Layout(mode) for both, or .Horizontal(mode) / .Vertical(mode) to set them independently.

ModeBehavior
DefaultDefer to whatever layout mode the font's header declares (usually smushing).
FullWidthConcatenate glyphs at their natural width with no overlap. Widest output.
FittedSlide glyphs together until any non-space cells touch (kerning).
SmushedOverlap glyphs by the maximum amount allowed by the font's smushing rules. Tightest output.

FullWidth

csharp

Fitted

csharp

Smushed

csharp

Vertical layout

Vertical layout only affects output that has multiple FIGlet rows (input containing \n characters or wrapped paragraphs). For single-line text, the vertical mode has no observable effect.

Overflow Behavior

FIGcharacters are typically much wider than ordinary text, so even short strings can overflow narrow containers. FigletText exposes independent horizontal and vertical overflow policies.

Horizontal: Clip vs Wrap

ModeBehavior
Clip (default)Render at the natural unwrapped width; the parent clips overflow at the right edge.
WrapWord-wrap the input on whitespace boundaries so each rendered FIGlet block fits the available width. Single tokens that exceed the width are broken at character boundaries.

Clip

csharp

Wrap

csharp

WARNING

The wrap algorithm is intentionally not byte-compatible with reference FIGlet's -w CLI option. The FIGfont 2.0 specification does not define line wrapping, so implementations differ. Hex1b's wrapper greedily fits whitespace-separated tokens and breaks overlong words at character boundaries.

Vertical: Clip vs Truncate

ModeBehavior
Clip (default)Render at full height; the parent clips at the bottom, possibly leaving a partial FIGlet row visible.
TruncateDrop entire FIGlet rows that don't fully fit. Never emits a partial row.
csharp
v.FigletText(longMultiLineText)
    .VerticalOverflow(FigletVerticalOverflow.Truncate)

Use Truncate when partial rows of glyphs would look broken (for example inside a fixed-height status panel).

Adding Color and Animation

FIGlet text is rendered monochrome by design — the widget produces a grid of sub-characters and applies no styling of its own. To colorize the output, wrap the widget in an EffectPanel and supply a per-frame surface filter:

csharp
using Hex1b;
using Hex1b.Surfaces;
using Hex1b.Widgets;

await using var terminal = Hex1bTerminal.CreateBuilder()
    .WithHex1bApp((app, options) => ctx => ctx.VStack(v => [
        v.EffectPanel(
            v.FigletText("Hex1b").Font(FigletFonts.Slant),
            surface =>
            {
                // Apply a horizontal gradient to non-blank cells.
                var start = (R: (byte)64,  G: (byte)156, B: (byte)255);
                var end   = (R: (byte)255, G: (byte)128, B: (byte)64);
                for (var y = 0; y < surface.Height; y++)
                for (var x = 0; x < surface.Width; x++)
                {
                    var cell = surface[x, y];
                    if (string.IsNullOrEmpty(cell.Character) || cell.Character == " ") continue;
                    var t = (double)x / Math.Max(1, surface.Width - 1);
                    var r = (byte)(start.R + (end.R - start.R) * t);
                    var g = (byte)(start.G + (end.G - start.G) * t);
                    var b = (byte)(start.B + (end.B - start.B) * t);
                    surface[x, y] = cell with { Foreground = Hex1bColor.FromRgb(r, g, b) };
                }
            }),
        v.Text(""),
        v.Text("FigletText is monochrome — apply colors with EffectPanel.")
    ]))
    .Build();

await terminal.RunAsync();

The effect callback runs on every render and gets full read/write access to the rendered cells, so you can also implement rainbows, waves, shimmer, or any other post-processing pass without modifying the underlying FIGlet output.

Using Custom Fonts

To use a font that isn't bundled, load any .flf file at startup with FigletFont.LoadFileAsync (or LoadAsync from any Stream) and pass the resulting font to .Font(...):

csharp

FigletFont instances are immutable and safe to share across threads. Cache them at application startup — parsing is moderately expensive and there's no benefit to re-parsing on each frame.

Subclassing FigletFont

FigletFont is intentionally extensible. Override TryGetGlyph(int, out FigletGlyph) to substitute, decorate, or lazily generate glyphs — this is the hook for fallback chains, character substitution, or fully synthetic fonts:

csharp

Two constructors are available for subclasses:

  • protected FigletFont(FigletFont inner) — decorator constructor; delegates everything to inner until you override.
  • protected FigletFont(int height, int baseline, char hardblank, ...) — primitive constructor for fully synthetic fonts that don't wrap an existing one.

You can also override GetMissingGlyph() to provide a custom appearance for characters that aren't present in the font (the default returns the font's space glyph, matching reference figlet behavior).

  • Text — Ordinary text rendering for body content
  • EffectPanel — Apply post-processing effects (color, gradients, animations) to any rendered subtree

Released under the MIT License.