Resolves a scene's computed layout before it is drawn:
- Text wrap — each text/stamp element's resolved content is wrapped to
its box width, storing the lines and the rendered block height.
Measurement-accurate when
measure: true+ resvg is available (wrap points match the render); a character-count estimate otherwise. - Button auto-width — a button with
auto_width: truegets its box widened to the measured label plus horizontal padding. - Anchor reflow — an element anchored to another (edge + gap + align)
is repositioned relative to the target's rendered box; chains resolve
in dependency order and cycles are rejected (
validate/1) — duringresolve/3a cyclic anchor is dropped so rendering still proceeds.
Runs on every render (cheap in estimate mode; OpenFresco.render/3 opts
into measurement). Results are stashed on transient :_lines /
:_rendered_h element keys the SVG generator reads.
International text: the supported-scripts matrix
Line-break opportunities are honest about their limits:
- Space-separated LTR scripts (Latin, Cyrillic, Greek, …) — fully supported in both estimate and measured modes.
- CJK and other UAX #14 scripts — supported when the optional
:unicode_stringdependency is installed: break opportunities come from UAX #14 line-breaking segmentation instead of whitespace. Without it, unspaced CJK runs as one unbreakable unit (it will overflow rather than mis-break). - Thai / Khmer / Lao / Myanmar — NOT supported: correct breaking requires dictionary segmentation, which neither this library nor UAX #14 alone provides. Text renders, but break points inside unspaced runs will be wrong.
- RTL / bidi (Arabic, Hebrew) — visual ordering and shaping are
delegated to the rasterizer (resvg shapes with rustybuzz, including
bidi). Set the element's
:direction("rtl") so renderers order runs correctly. Wrap-point measurement treats the text as a sequence of space-separated words, which is usually correct for Arabic/Hebrew prose. - Grapheme clusters (emoji ZWJ sequences, combining marks) — never split: breaking only happens at whitespace or UAX #14 opportunities, both of which respect cluster boundaries.
Summary
Functions
Resolve wrap, auto-width, and anchor positions. Returns the scene with
updated element boxes and :_lines / :_rendered_h annotations. Never
raises; a cyclic anchor is left un-applied.
:ok, or {:error, {:anchor_cycle, ids}} if the anchor graph has a cycle.
Functions
@spec resolve(OpenFresco.Scene.t(), map(), keyword()) :: OpenFresco.Scene.t()
Resolve wrap, auto-width, and anchor positions. Returns the scene with
updated element boxes and :_lines / :_rendered_h annotations. Never
raises; a cyclic anchor is left un-applied.
@spec validate(OpenFresco.Scene.t()) :: :ok | {:error, {:anchor_cycle, [String.t()]}}
:ok, or {:error, {:anchor_cycle, ids}} if the anchor graph has a cycle.