render/shapes library

Key shapes as material_new_shapes polygons, and FlatMorph for per-frame morphing (motion brief §6.3; motion-flutter §3.2).

  • Every key shape is a RoundedPolygon generated at the cell aspect (non-uniform scaling would distort rounded corners) and then normalized() into the unit square.
  • A FlatMorph flattens a Morph's matched cubics once; each frame it lerps them into a reused Path (≈ 0.3–1.1 µs, no allocation).
  • KeyShapeCache builds morphs ahead of time (KeyShapeCache.prepare) so a commit frame never constructs a Morph; painters only look up.

Classes

FlatMorph
A Morph flattened to two coordinate arrays (8 doubles per cubic: anchor0, control0, control1, anchor1) so a frame only lerps numbers into a reused Path (motion-flutter §3.2). asCubics(t) is a pure per-coordinate lerp of the same matched pairs, so this is exact.
KeyGeometry
One resolved key outline: a KeyShapeKind (plus the Material shape id for KeyShapeKind.m3eMorph) and its corner radius as a fraction of the short side (0–0.5).
KeyMorph
A rest → pressed key morph at one cell aspect, ready to paint.
KeyShapeCache
Builds and caches KeyMorphs by (rest, pressed, aspect).

Functions

keyPolygon(KeyGeometry geometry, double aspect) → RoundedPolygon
The polygon for geometry at cell aspect (width / height), normalized into the unit square (the long side spans 0–1, the short side is centred).
materialShape(M3eShape shape) → RoundedPolygon
The MaterialShapes polygon for shape (unit square).