Skip to main content

build_layout_engine

Function build_layout_engine 

Source
pub fn build_layout_engine(
    arena: &Arena,
    root_id: u32,
    width: u16,
) -> Option<(TaffyEngine, Rect)>
Expand description

Build a fresh layout engine for the arena tree rooted at root_id, compute layout at the given width, and return the built engine plus the root rect.

This is the M3-A engine-lifetime seam (ADR-3, docs/adr3-engine-lifetime.md) — the public entry InkRoot (inkferro-napi, M3-D) calls each render_frame. render_to_string calls it as step 1 of its own body, so the two paths cannot drift. It is the single place the taffy tree is constructed, so callers cannot accidentally re-run node creation against a populated engine (which would duplicate child lists — insert_child appends).

It is pub (not pub(crate)) because the consumer lives in a different crate (inkferro-napi). Returning the concrete TaffyEngine — rather than impl LayoutEngine — lets InkRoot store it as a named field and read computed(id) later (still via the LayoutEngine trait). This deliberately names the concrete backend across the napi boundary; the ADR-1 LayoutEngine-trait seam still governs behavior, and a backend swap would change only this return type in one place.

Returns the built-and-computed engine so a single per-frame build serves both the render walk (M3-E reads engine.computed(id) as the rect accessor) and measure(id) (M3-F reads engine.computed(id) from the same stored build) — no second rebuild.

§Per-frame rebuild (ADR-3 Option A)

Always allocates a fresh TaffyEngine. Persistence is the Arena’s job; the engine is a pure function of the arena at render time. A fresh engine re-set_measures every text node, satisfying the measure-invalidation discipline (layout/engine.rs:78-82) for free.

Returns None if calculate fails (e.g. an inconsistent tree); the caller renders an empty frame, matching the prior render_to_string error path.