Skip to content

UXTextRun

UXTextRun is a span of characters that has been placed: a UXRange into the original text, the x at which it starts, and the style to draw it in.

#use <UXKit> // or #import "UXTextLayout.xc"
class UXTextRun : UXRange {
i32 x; // pixels from the left of the line
UXCharAttr* attr; // null = the view's default style
}

UXTextLayout produces runs and a draw call consumes them: move to x, set the style, and stroke len characters starting at loc.

loc and len index the source text. Nothing is cut up or duplicated, so wrapping a paragraph allocates run objects, not strings.

The text must therefore outlive the layout:

Both are ranges with a style, but they answer different questions:

UXAttrRunwhat style these characters have — derived from the model
UXTextRunwhere these characters go — derived from measuring

A styled span may be split across two lines, becoming two UXTextRuns with different x values and the same attr. A single line may hold several runs because the style changes mid-line. The mapping is not one-to-one in either direction, so there are two types.

UXTextRun.at(loc, len, x); // attr == 0
UXTextRun.styled(loc, len, x, someAttr); // attr set

Null means the view’s default style. Plain unstyled text lays out without allocating an attribute per run, and a drawing pass reads null as “leave the font unchanged”.

Check before dereferencing:

if (r.attr != (UXCharAttr*)0 && r.attr.bold) { … }

at · styled

static UXTextRun* at(i32 l, i32 n, i32 px)

An unstyled run; attr is null.

static UXTextRun* styled(i32 l, i32 n, i32 px, UXCharAttr* a)

A run carrying a style. The attribute is kept, not copied, so it must outlive the run. Normally it does, because it comes from the attributed string being laid out.

i32 x

Pixels from the left edge of the line, including the width of the runs before it. The value is absolute within the line, not a delta.

UXCharAttr* attr // null = the view's default

Inherited from UXRange. Half-open, indexing the source text.