Text

Align and draw immediate text, or prepare it once to draw repeatedly without per-frame allocation.

title = Text.from("Hello", font).size(38).prepare!()?
Text.from("Score", font).size(24).draw!(frame, { pos, color: Color.white, align: (Top, Right) })
model.title.draw!(frame, { pos: { x: 400, y: 60 }, color: Color.white, align: (Top, Center) })

Prepared.bounds returns the measured size. Placement.align selects which point of those bounds its pos identifies.

Preparation is legal in init!, update!, and tasks, and refused in render!. Drawing requires Draw.Frame and is legal only in render!. Retain repeatedly drawn Prepared values in the model.

font_stub : Font

Resource-free synthetic monospace font for pure layout tests.

default_spacing : F32

The letter spacing a Builder starts with, and what raylib's own text drawing uses.

from : Str, Font -> Builder

Start describing a string drawn in a font. Adjust the result with size, spacing and font, then draw or prepare it.

align_offset : Size, Align -> Vec2

How far the anchor named by an Align sits from the text's top-left corner, for a text of this size. origin_for is what a draw uses; this is the piece it is built from.

origin_for : Vec2, Size, Align -> Vec2

The top-left corner a text of this size must be drawn at for its align anchor to land on pos. Pure, so an app can compute the same box a draw will occupy without drawing anything.

draw_prepared! : Frame, PreparedPlacement => {}

Draw prepared text, as Prepared.draw! does.

Legal in render! only.

Prefer the method. This form takes the frame first, like every other free drawing function, and takes the text as a field of its config record rather than as its own argument.

Font : Font

A host-owned font and immutable metric snapshot. This is the shared type owned by the platform's Font module.

HAlign : [Left, Center, Right]

Which horizontal edge or centre of the text pos names.

VAlign : [Top, Middle, Bottom]

Which vertical edge or centre of the text pos names.

Align : (VAlign, HAlign)

Where pos sits within the text, as (vertical, horizontal).

Size : { width : F32, height : F32 }

A measured width and height, in the same logical units as every drawing call. This is Draw.TextSize and Font.Size under a third name; they are one type.

Placement

:= {
    pos : Vec2,
    color : Rgba,
    align : Align ?? (Top, Left),
}

Everything a draw needs beyond the text itself: where to put it, what colour to paint it, and which point of it pos names.

Builder

Text.Builder :: # (opaque)

A string and its drawing style. Start one with Text.from, adjust it with the methods below, then draw it immediately or finish it with prepare! for repeated drawing.

A builder is a plain description, so building and measuring one costs nothing and it can be assembled anywhere. draw! and prepare! are the operations that call the host.

size : Builder, F32 -> Builder

Draw this text at a different pixel size. The default is 20.

Sizes far above the font's own base_size scale its glyph atlas up rather than re-rasterizing, so load the font at the size wanted when the difference shows.

spacing : Builder, F32 -> Builder

Change the space added between glyphs. The default is Text.default_spacing.

font : Builder, Font -> Builder

Draw this text in a different font.

draw! : Builder, Frame, Placement => {}

Measure this description from the font's immutable metric snapshot, resolve placement.align, and draw it immediately.

Legal in render! only. This is an alignment convenience for text that does not need a retained Prepared resource; Draw.text! is the lower-level operation for callers that already resolved the origin.

prepare! : Builder => Try(Prepared, [ResourceLimit])

Cache immutable UTF-8 text, font and style, and measurement in the host.

Legal in init!, update!, and tasks; refused in render!.

Prepared

Text.Prepared :: # (opaque)

Host-owned immutable text. Its ARC handle retains any loaded font and its cached native NUL-terminated bytes are reused by every draw.

bounds : Prepared -> Size

The size the host measured while preparing this text.

Pure, and free: the measurement was taken once, at preparation. Use it to size a panel around the text or to hit-test it, in update! as readily as in render!.

draw! : Prepared, Frame, Placement => {}

Draw this prepared text at a placement.

Legal in render! only.

The frame is the second argument here because the prepared text is the value the method is called on; Text.draw_prepared! is the same call with the frame first.

stub : Prepared

Resource-free prepared text for pure tests.

Prepared text holds more than a handle: the host measured it once while preparing it, and the value keeps that size. A stub has no measurement to keep, so its measured bounds are zeroed -- bounds() returns { width: 0, height: 0 } and every alignment therefore resolves to the placement point itself. Copy this value with the bounds a test needs, the way the platform's Texture.stub is copied with dimensions.

The handle never resolves to a host resource, so drawing it is skipped the way a released one is. Do not use it to test drawing, measurement, or resource lifetime.

PreparedPlacement

:= { text : Prepared, pos : Vec2, color : Rgba, align : Align ?? (Top, Left) }

Prepared text and its placement, with top-left alignment by default.