* Replace saveLayer with MaskFilter for drop shadows
Drop shadows now draw directly with MaskFilter.MakeBlur instead of
saveLayer + ImageFilter. Eliminates per-shadow offscreen buffer
allocation, significantly improving render throughput for scenes
with many shadowed nodes.
Text shadows still use saveLayer (MaskFilter can't be applied to
text glyphs individually).
Benchmark: 50 shadow nodes render at 1.55ms/frame (scene change).
* Cache per-node SkPictures for effect rendering
Nodes with visible effects (shadows, blurs) are recorded into
individual SkPictures and replayed on subsequent scene redraws.
Only the modified node re-records; unchanged shadow nodes replay
from cache.
- MaskFilter.MakeBlur for drop shadows instead of saveLayer
- Reusable effectLayerPaint and cached ImageFilters/MaskFilters
- invalidateNodePicture() called on node update
- invalidateAllPictures() on font load; invalidateScenePicture()
preserves node cache for scene-only invalidation
- Shadow benchmark: 50 nodes at 1.47ms/frame (scene change)
* Update changelog with shadow rendering performance improvements
Use ffurrer2/extract-release-notes@v2 to extract the version section
and pass it as releaseBody to the Tauri action.
Switch changelog headings to Keep a Changelog format (## [X.Y.Z])
to match the action's expected pattern.
29 tools: open_file, save_file, new_document + all 26 from @open-pencil/core.
Stdio for MCP clients (Claude Code, Cursor), HTTP (Hono + Streamable HTTP
with sessions) for scripts, browser extensions, CI.
Runs on both Bun and Node.js (via tsx).
- AppToast component: top-center blue pill (info), red pill (errors)
- Global error handler catches window.error + unhandledrejection
- Link copied toast on share and copy link button
- use-toast composable: toast.show(message, variant)