simvx.graphics.draw2d_text

MSDF text rendering for Draw2D – the ONE 2D text builder.

This is the single glyph layout + measure + emit path for the whole engine. It feeds both the legacy flag-OFF Draw2D op stream (draw_text appends a TEXT :class:Op) and the flag-ON item pipeline (which re-runs the same layout natively via :func:layout_glyph_run). The desktop overlay TextRenderer.draw_text path it replaced is deleted; only the MSDF atlas generation in :mod:text_renderer survives (both paths share it).

Three text-layout reconciliations:

  • Font-size unit = font_scale * 16 is canonical (_LOGICAL_BASE = 16); the old divergent 14 is replaced so a label renders the same pixel height whichever node draws it and whichever backend. The * sy content-scale factor multiplies on top (applied by the caller / the _xf_sc factor).

  • Kerning is ported from the deleted overlay path – the cursor advances by font.get_kerning(prev, ch) * scale between glyph pairs, so the kerned advance is pixel-identical to the old overlay (0.00 px diff).

  • Quad rounding = ceil (fully contains the glyph + padding) replaces the old max(1.0, ...); align spelling = 'centre' (UK, repo rule) – the banned US 'center' is accepted transitionally and mapped to 'centre'.

Module Contents

Classes

Draw2DTextMixin

Mixin providing MSDF text rendering and measurement for Draw2D.

Functions

layout_glyph_run

Lay out text into MSDF glyph quads in LOCAL space (the item path).

Data

log

API

simvx.graphics.draw2d_text.log

‘getLogger(…)’

class simvx.graphics.draw2d_text.Draw2DTextMixin[source]

Mixin providing MSDF text rendering and measurement for Draw2D.

classmethod set_font(path: str | None = None, size: int = 48) None[source]

Load an MSDF font atlas via the shared TextRenderer.

classmethod draw_text(text, pos=None, *, colour=None, scale=1.0, rect=None, alignment='left', vertical_alignment='top', fit_to_width=False, min_scale=None, outline=0.0, outline_colour=None, screen_space=False)[source]

Draw text at pos or inside rect with optional alignment.

screen_space=True bypasses the active Camera2D transform (the screen-pinned HUD-label case – the behaviour Text2D’s deleted overlay pass had: text stays fixed while the world camera pans).

Two positioning modes:

  • pos=(x, y): text anchored at the given coordinate. alignment ('left'/'centre'/'right') anchors each line’s left edge / centre / right edge on x (the overlay-parity point anchor).

  • rect=(x, y, w, h): text positioned by alignment and vertical_alignment (top/centre/bottom) inside the rect. fit_to_width=True shrinks scale so the text fits rect.w, clamped to min_scale.

outline (in glyph-em units, e.g. 0.08) draws a 4-direction offset copy of the run in outline_colour (default opaque black) UNDER the main run – the common port “readable text on any background” pattern. min_scale=None applies the ~10px readable safety net; an explicit value honours the caller’s floor exactly.

Both the US 'center' and the UK 'centre' are accepted; 'centre' is canonical (repo spelling).

classmethod text_height(text, scale=1.0)[source]

Height of text in pixels at scale.

Multi-line strings (containing \n) accumulate line heights using the font’s line-height metric. Returns 0 for empty input.

classmethod text_size(text, scale=1.0)[source]

Return (width, height) in pixels at scale.

classmethod fit_scale(text, max_width, *, base_scale=1.0, min_scale=None)[source]

Largest scale ≤ base_scale that fits text within max_width.

Returns base_scale when the text already fits or when inputs are degenerate. The returned value matches what :meth:draw_text would actually use, so callers can compute width metrics that align with what’s drawn.

min_scale semantics mirror :meth:draw_text:

  • None (default): clamps from below by the readable-pixel floor (~10px) so the returned scale never produces illegible MSDF output.

  • explicit value: the caller’s floor is honoured exactly, bypassing the readable safety net.

classmethod text_width(text, scale=1)[source]

Width of text in pixels at scale.

Multi-line strings (containing \n) return the widest line; newlines themselves contribute no horizontal advance.

simvx.graphics.draw2d_text.layout_glyph_run(text, pos=None, *, colour=None, scale=1.0, rect=None, alignment='left', vertical_alignment='top', fit_to_width=False, min_scale=None, outline=0.0, outline_colour=None)[source]

Lay out text into MSDF glyph quads in LOCAL space (the item path).

The native-emission counterpart of :meth:Draw2DTextMixin.draw_text: it runs the SAME single layout (kerning, *16 unit, ceil, centre) but without baking any Draw2D transform and without appending an Op – it returns (verts, indices) so the item builder can stow them as a GLYPH item’s geometry (geometry stays camera-/parent-free, the node’s transform rides the item’s transform row). Returns ([], []) when there is no font or no visible glyphs.

Because both paths funnel through :meth:Draw2DTextMixin._layout_run, the item-path glyph geometry is byte-identical to the op-path geometry at the same position/scale – which is what makes flag-ON text match flag-OFF.