Skip to main content

render_static

Function render_static 

Source
pub fn render_static<'a>(
    arena: &'a Arena,
    root_id: u32,
    width: u16,
    transform_of: &'a TransformAccessor<'a>,
    color_level: ColorLevel,
) -> String
Expand description

Render the static subtree (ink’s <Static>) to its standalone output string — the text ink prints once, above the live region.

This is the SECOND render pass, a faithful port of renderer.ts’s static branch (renderer.ts:46-66):

let staticOutput;
if (node.staticNode?.yogaNode) {
  staticOutput = new Output({
    width:  node.staticNode.yogaNode.getComputedWidth(),
    height: node.staticNode.yogaNode.getComputedHeight(),
  });
  renderNodeToOutput(node.staticNode, staticOutput, {skipStaticElements: false});
}
// …
staticOutput: staticOutput ? `${staticOutput.get().output}\n` : '',

Semantics, point by point:

  1. Find the static node. ink tracks a single node.staticNode set by the reconciler when internal_static is applied (reconciler.ts:236-244). The arena instead marks the node with is_static (set by Op::SetStatic), so we DFS from root_id for the first is_static node. No static node → return "" (the common case; matches staticNode being undefined).
  2. Layout. Reuse build_layout_engine at the SAME width ink lays the root out at — the static node is part of that one tree, so its computed rect (engine.computed(static_id)) falls out of the single root layout, exactly as node.staticNode.yogaNode is laid out by the root’s calculateLayout. If the static id has no computed rect, return "" (matches node.staticNode?.yogaNode being absent).
  3. Own-sized grid. Size the static grid to the static node’s OWN computed width/height (renderer.ts:50-52: new Output({width: …getComputedWidth(), height: …getComputedHeight()})), NOT the root’s.
  4. Walk at offset 0 via walk_static (skipStaticElements: false): the static entry’s own computed left/top become the first write position (render-node-to-output.ts:129-130 with offsetX/Y defaulting to 0).
  5. Trailing newline (renderer.ts:64-66): a PRESENT static node always appends \n (“static output doesn’t have one, so interactive output will override last line of static output”), even for an empty body (→ "\n"). An ABSENT static node yields "". A zero-dimensioned static node skips Grid::new and still yields "\n", matching staticOutput.get().output being "" for an empty Output plus the appended newline.

transform_of is the same per-node own-transform seam render_styled uses; the napi caller passes the SAME accessor so a <Transform>/<Text color> inside <Static> is honored in the static pass too.