Replace the split snapshot/native renderer paths with a single
composition pipeline (compositionRenderer.ts) that:
- Loads actual source images and uses naturalWidth/Height for
correct full-resolution sampling (fixes top-left-corner-only bug
caused by data.w/h being capped to 600px display dimensions)
- Routes image-only selections through native Canvas 2D composition
- Falls back to viewport snapshot for mixed/unsupported selections
with explicit warnings instead of silent degradation
- Resolves group children via itemResolver for proper group export
- Rejects group children from native composition (local coords
incompatible with world-space drawing)
- Adds canvas size safety limits with auto-downscale
- Guards VideoSprite._drawFrame against null texture source race
condition during zoom-triggered culling
New files:
- compositionRenderer.ts — unified composition module
- compositionRenderer.test.ts — 16 tests for entry flattening,
bounds, dimensions, group handling
Modified:
- clipboard.ts — uses composeSelection() instead of direct renderers
- export.ts — uses composeSelection() + getCompositionDimensions()
- Editor.tsx, useShortcutHandler.ts — pass scene for group resolution
- VideoSprite.ts — null guard on texture source in frame loop