From 0b964ff84d15b1aabcf29b9ce03e03b526dfa640 Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Thu, 14 May 2026 15:42:28 +0800 Subject: [PATCH] feat(shell-core/canvas): thread VariableTable through paint_node + node_fill helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plumbing for paint-time `$ref` substitution. `paint_node` now takes `&VariableTable` alongside the existing args; recursive calls pass it through unchanged. The new `node_fill(node, var_table)` helper resolves `var_table.fill_for(node.id).or(node.fill)` — ready for paint sites to swap in. Full substitution still requires `paint_fill_then_stroke` / icon_font branches to call `node_fill(node, var_table)` instead of reading `node.fill` directly — that's a focused refactor (changes the helper's signature in `canvas_viewport_overlay.rs` + every NodeKind branch in paint_node) and lands separately. With the plumbing in place today, the helper switch is a single per-site edit; no more API reshape needed. #5 Variables now ~90% — types, storage, loader, fill_refs map, paint plumbing all shipped. Only the per-site `node.fill → node_fill(node, var_table)` substitution remains. Tests total: 236 shell-core. Wasm32 build clean. --- .../src/widgets/canvas_viewport.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/openpencil-shell-core/src/widgets/canvas_viewport.rs b/crates/openpencil-shell-core/src/widgets/canvas_viewport.rs index fe2fc59e5..8bdae843f 100644 --- a/crates/openpencil-shell-core/src/widgets/canvas_viewport.rs +++ b/crates/openpencil-shell-core/src/widgets/canvas_viewport.rs @@ -258,6 +258,7 @@ impl<'a> Widget for CanvasViewport<'a> { self.document.selected, edit_caret, cull, + &self.document.var_table, ); } } @@ -354,6 +355,13 @@ struct EditCaret { now_ms: u64, } +/// Resolve a node's paint-time fill — `var_table.fill_for` (a +/// registered `$ref`) wins over `node.fill`. Mirrors TS +/// `resolveNodeForCanvas` (`pen-core/variables/resolve.ts`). +fn node_fill(node: &Node, var_table: &crate::document::VariableTable) -> Option { + var_table.fill_for(node.id).or(node.fill) +} + fn paint_node( cx: &mut PaintCx<'_>, node: &Node, @@ -362,6 +370,7 @@ fn paint_node( selected: NodeId, edit_caret: Option, cull: Rect, + var_table: &crate::document::VariableTable, ) { // Hidden nodes (and their subtree) skip canvas paint entirely. // Layer panel still shows them, dimmed, so the user can unhide. @@ -405,7 +414,7 @@ fn paint_node( NodeKind::Frame => { paint_fill_then_stroke(cx, node, world_rect, zoom); for child in &node.children { - paint_node(cx, child, viewport_origin, zoom, selected, edit_caret, cull); + paint_node(cx, child, viewport_origin, zoom, selected, edit_caret, cull, var_table); } } NodeKind::Other(tag) if tag == "icon_font" => crate::widgets::icons::paint_icon_font_node( @@ -413,7 +422,7 @@ fn paint_node( ), NodeKind::Group | NodeKind::Other(_) => { for child in &node.children { - paint_node(cx, child, viewport_origin, zoom, selected, edit_caret, cull); + paint_node(cx, child, viewport_origin, zoom, selected, edit_caret, cull, var_table); } } NodeKind::Rect => {