Skip to content

TextObject

Generated from engine/render/text_object.h at 862e08b. The text under each declaration is the header's own comment, word for word. About the reference says how these pages are made.

Browse the render module

#include "engine/render/text_object.h" · namespace labrador

class TextObject : public DrawObject

A string drawn in one font.

Text is held wide, which the seam requires and renderer.h explains. The short of it: a glyph table is keyed by code unit, so a narrow entry point is a conversion, and a conversion on the draw path is either an allocation per string per view per frame or a buffer shared between workers. widen() in text_encoding.h is where narrow content comes across, once.

The font name is resolved to a handle at construction. A handle rather than a cached font pointer, because the registry slot is what survives a device loss: a font is engine data, but its atlas is not, and the reload remakes the font into the same slot. A pointer taken before the loss would dangle after it.

TextObject() = default;
TextObject(const std::wstring& text,
const std::string& font_name,
const mattmath::Vector2F& position,
RenderResources* render_resources,
const Colour& color = Colour::white,
float scale = 1.0f,
float rotation = 0.0f,
const mattmath::Vector2F& origin = mattmath::Vector2F::ZERO,
float layer_depth = 0.0f);
virtual void draw(DrawList& draw_list) const;
void draw_with(DrawList& draw_list,
const Colour& colour,
const mattmath::Vector2F& position,
float scale) const;

Draws with the given colour, position and scale without storing any of them. Drawing a shadow by assigning those three members, drawing, and assigning them back is a save/restore, and a data race the moment two render workers run it on the same object.

mattmath::RectangleF text_bounds() const;

The box this string occupies, for whoever has to cull or index it.

The measurement is taken in the constructor and in the two setters that can change it, never here. Measuring walks the string, and this is on the culling path: taking it here would be a per-object, per-view, per-frame walk of every label on screen. Caching it lazily instead is not an option - this method is const and every view worker enters it on the same object at the same time, so a mutable cache filled on first read is a data race by construction.

Cached across device loss deliberately. The font object is rebuilt, but it is rebuilt from the same font, so the metrics are the same - it is the pointer that goes stale, not the measurement.

Turned by draw_rotation(), about the position, because that is what draw() does to every glyph - so for a rotated string this is the axis-aligned box around the turned one, which is the box a cull has to see: a Label is a GameObject, and a rotated one reporting its unrotated box would be culled at the edge of a view it is drawn inside. The arithmetic is sprite_geometry.h's text_quad_bounds, beside the glyph quad it has to agree with, and an unrotated string costs it no trigonometry.

mattmath::RectangleF text_bounds_at(const mattmath::Vector2F& position,
float scale) const;

The same box for a hypothetical draw at another position and scale, so TextDropShadow can size its shadow exactly rather than assuming the shadow matches the text.

text · font · position · scale (protected)

Section titled “text · font · position · scale (protected)”
const std::wstring& text() const;
FontHandle font() const;
const mattmath::Vector2F& position() const;
float scale() const;

set_text · set_font · set_position · set_scale (protected)

Section titled “set_text · set_font · set_position · set_scale (protected)”
virtual void set_text(const std::wstring& text);
void set_font(const std::string& font_name);
virtual void set_position(const mattmath::Vector2F& position);
virtual void set_scale(float scale);

Named in the public declarations above: Colour, DrawList, DrawObject, RectangleF, RenderResources, Vector2F.

No sample or test includes this header directly.

Development documentation (unreleased). Built from Labrador 862e08b of 2026-10-08.