Text measurement — the primitive that turns estimate-based layout into measurement-accurate layout (the checklist's "same wrap points, same measured sizes" gate).
When the :resvg dependency is available, widths come from resvg's own
layout engine via query_all — the same engine that paints the final
PNG, so wrap points match the render exactly. Without resvg (SVG-only
hosts), it falls back to a character-count estimate (~0.55em), matching
phoenix_kit_og's heuristic.
Measurement writes a probe SVG to a tempfile and calls the NIF, so it is
used by the layout pass (OpenFresco.Layout) rather than the hot render
path directly. Batch related strings into one widths/2 call.
Summary
Functions
Whether resvg-backed measurement is available (else estimate).
Measure a single string's width.
Measure a batch of text specs. Returns %{id => width_px}. Uses resvg
when available (one NIF call for the whole batch); estimates otherwise or
on any error. Empty strings measure 0.
Types
Functions
@spec available?() :: boolean()
Whether resvg-backed measurement is available (else estimate).
@spec text_width( String.t(), %{size: number(), font: String.t(), weight: number()}, keyword() ) :: float()
Measure a single string's width.
Measure a batch of text specs. Returns %{id => width_px}. Uses resvg
when available (one NIF call for the whole batch); estimates otherwise or
on any error. Empty strings measure 0.