The live PenCanvas committed-ink layer now uses the relocated render/ painters
(render.StaticInkPainter + InkPictureCache + StrokeStore) instead of the old
canvas/ink_painters versions — the P0.5 perf prerequisite. The committed layer's
ui.Picture is recorded once per StrokeStore.revision and replayed on the raster
thread, so pinch / pan / live-stroke frames no longer re-rasterize committed ink.
- pen_canvas mirrors widget.strokes (PenStroke) into a StrokeStore (EditorStroke)
on every new-list identity (the parent already replaces the list on each
commit/erase), bumping the revision → cache invalidates → static layer repaints.
- thinning (PenConfig.pressureSensitivity) is threaded into the render painters
AND folded into the cache key + shouldRepaint, so a sensitivity change can't
replay a stale Picture built at the old thinning.
- live layer converts _liveStroke→EditorStroke per frame (correct: it must
repaint every move); eraser preview keeps the existing canvas painter.
- pen_canvas disposes the InkPictureCache.
Equivalent by construction (both paths call buildStrokeOutline with the same
thinning); device confirms final fidelity. The old canvas Static/LiveInkPainter
are now orphaned (buildStrokePath still used by tests) — P1 deletes them.
flutter analyze lib/editor clean; 90/90 tests (+6: thinning repaint/cache + live).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>