@motion-script/web 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +47 -0
  2. package/dist/audio/player.d.ts +43 -0
  3. package/dist/audio/player.d.ts.map +1 -0
  4. package/dist/audio/player.js +165 -0
  5. package/dist/audio/player.js.map +1 -0
  6. package/dist/effects/bloom.d.ts +19 -0
  7. package/dist/effects/bloom.d.ts.map +1 -0
  8. package/dist/effects/bloom.js +64 -0
  9. package/dist/effects/bloom.js.map +1 -0
  10. package/dist/effects/blur.d.ts +8 -0
  11. package/dist/effects/blur.d.ts.map +1 -0
  12. package/dist/effects/blur.js +12 -0
  13. package/dist/effects/blur.js.map +1 -0
  14. package/dist/effects/bulge-pinch.d.ts +20 -0
  15. package/dist/effects/bulge-pinch.d.ts.map +1 -0
  16. package/dist/effects/bulge-pinch.js +86 -0
  17. package/dist/effects/bulge-pinch.js.map +1 -0
  18. package/dist/effects/chromatic-aberration.d.ts +19 -0
  19. package/dist/effects/chromatic-aberration.d.ts.map +1 -0
  20. package/dist/effects/chromatic-aberration.js +59 -0
  21. package/dist/effects/chromatic-aberration.js.map +1 -0
  22. package/dist/effects/effect.d.ts +32 -0
  23. package/dist/effects/effect.d.ts.map +1 -0
  24. package/dist/effects/effect.js +22 -0
  25. package/dist/effects/effect.js.map +1 -0
  26. package/dist/effects/grayscale.d.ts +12 -0
  27. package/dist/effects/grayscale.d.ts.map +1 -0
  28. package/dist/effects/grayscale.js +31 -0
  29. package/dist/effects/grayscale.js.map +1 -0
  30. package/dist/effects/index.d.ts +13 -0
  31. package/dist/effects/index.d.ts.map +1 -0
  32. package/dist/effects/index.js +13 -0
  33. package/dist/effects/index.js.map +1 -0
  34. package/dist/effects/pixelate.d.ts +23 -0
  35. package/dist/effects/pixelate.d.ts.map +1 -0
  36. package/dist/effects/pixelate.js +37 -0
  37. package/dist/effects/pixelate.js.map +1 -0
  38. package/dist/effects/registry.d.ts +17 -0
  39. package/dist/effects/registry.d.ts.map +1 -0
  40. package/dist/effects/registry.js +56 -0
  41. package/dist/effects/registry.js.map +1 -0
  42. package/dist/effects/sksl-cache.d.ts +6 -0
  43. package/dist/effects/sksl-cache.d.ts.map +1 -0
  44. package/dist/effects/sksl-cache.js +21 -0
  45. package/dist/effects/sksl-cache.js.map +1 -0
  46. package/dist/effects/sksl-layer.d.ts +30 -0
  47. package/dist/effects/sksl-layer.d.ts.map +1 -0
  48. package/dist/effects/sksl-layer.js +82 -0
  49. package/dist/effects/sksl-layer.js.map +1 -0
  50. package/dist/effects/texture.d.ts +31 -0
  51. package/dist/effects/texture.d.ts.map +1 -0
  52. package/dist/effects/texture.js +66 -0
  53. package/dist/effects/texture.js.map +1 -0
  54. package/dist/effects/vintage.d.ts +20 -0
  55. package/dist/effects/vintage.d.ts.map +1 -0
  56. package/dist/effects/vintage.js +47 -0
  57. package/dist/effects/vintage.js.map +1 -0
  58. package/dist/effects/zoom.d.ts +20 -0
  59. package/dist/effects/zoom.d.ts.map +1 -0
  60. package/dist/effects/zoom.js +65 -0
  61. package/dist/effects/zoom.js.map +1 -0
  62. package/dist/exporter.d.ts +24 -0
  63. package/dist/exporter.d.ts.map +1 -0
  64. package/dist/exporter.js +177 -0
  65. package/dist/exporter.js.map +1 -0
  66. package/dist/fills/conic-gradient.d.ts +12 -0
  67. package/dist/fills/conic-gradient.d.ts.map +1 -0
  68. package/dist/fills/conic-gradient.js +44 -0
  69. package/dist/fills/conic-gradient.js.map +1 -0
  70. package/dist/fills/filters/alpha.d.ts +9 -0
  71. package/dist/fills/filters/alpha.d.ts.map +1 -0
  72. package/dist/fills/filters/alpha.js +21 -0
  73. package/dist/fills/filters/alpha.js.map +1 -0
  74. package/dist/fills/filters/blur.d.ts +9 -0
  75. package/dist/fills/filters/blur.d.ts.map +1 -0
  76. package/dist/fills/filters/blur.js +12 -0
  77. package/dist/fills/filters/blur.js.map +1 -0
  78. package/dist/fills/filters/color-adjustment.d.ts +14 -0
  79. package/dist/fills/filters/color-adjustment.d.ts.map +1 -0
  80. package/dist/fills/filters/color-adjustment.js +147 -0
  81. package/dist/fills/filters/color-adjustment.js.map +1 -0
  82. package/dist/fills/filters/color-matrix.d.ts +9 -0
  83. package/dist/fills/filters/color-matrix.d.ts.map +1 -0
  84. package/dist/fills/filters/color-matrix.js +14 -0
  85. package/dist/fills/filters/color-matrix.js.map +1 -0
  86. package/dist/fills/filters/curves.d.ts +9 -0
  87. package/dist/fills/filters/curves.d.ts.map +1 -0
  88. package/dist/fills/filters/curves.js +89 -0
  89. package/dist/fills/filters/curves.js.map +1 -0
  90. package/dist/fills/filters/exposure.d.ts +9 -0
  91. package/dist/fills/filters/exposure.d.ts.map +1 -0
  92. package/dist/fills/filters/exposure.js +22 -0
  93. package/dist/fills/filters/exposure.js.map +1 -0
  94. package/dist/fills/filters/filter.d.ts +17 -0
  95. package/dist/fills/filters/filter.d.ts.map +1 -0
  96. package/dist/fills/filters/filter.js +16 -0
  97. package/dist/fills/filters/filter.js.map +1 -0
  98. package/dist/fills/filters/grayscale.d.ts +9 -0
  99. package/dist/fills/filters/grayscale.d.ts.map +1 -0
  100. package/dist/fills/filters/grayscale.js +25 -0
  101. package/dist/fills/filters/grayscale.js.map +1 -0
  102. package/dist/fills/filters/registry.d.ts +16 -0
  103. package/dist/fills/filters/registry.d.ts.map +1 -0
  104. package/dist/fills/filters/registry.js +50 -0
  105. package/dist/fills/filters/registry.js.map +1 -0
  106. package/dist/fills/gradient-cache.d.ts +29 -0
  107. package/dist/fills/gradient-cache.d.ts.map +1 -0
  108. package/dist/fills/gradient-cache.js +57 -0
  109. package/dist/fills/gradient-cache.js.map +1 -0
  110. package/dist/fills/handler.d.ts +49 -0
  111. package/dist/fills/handler.d.ts.map +1 -0
  112. package/dist/fills/handler.js +172 -0
  113. package/dist/fills/handler.js.map +1 -0
  114. package/dist/fills/image.d.ts +34 -0
  115. package/dist/fills/image.d.ts.map +1 -0
  116. package/dist/fills/image.js +91 -0
  117. package/dist/fills/image.js.map +1 -0
  118. package/dist/fills/linear-gradient.d.ts +12 -0
  119. package/dist/fills/linear-gradient.d.ts.map +1 -0
  120. package/dist/fills/linear-gradient.js +48 -0
  121. package/dist/fills/linear-gradient.js.map +1 -0
  122. package/dist/fills/noise.d.ts +11 -0
  123. package/dist/fills/noise.d.ts.map +1 -0
  124. package/dist/fills/noise.js +82 -0
  125. package/dist/fills/noise.js.map +1 -0
  126. package/dist/fills/radial-gradient.d.ts +9 -0
  127. package/dist/fills/radial-gradient.d.ts.map +1 -0
  128. package/dist/fills/radial-gradient.js +43 -0
  129. package/dist/fills/radial-gradient.js.map +1 -0
  130. package/dist/fills/registry.d.ts +10 -0
  131. package/dist/fills/registry.d.ts.map +1 -0
  132. package/dist/fills/registry.js +34 -0
  133. package/dist/fills/registry.js.map +1 -0
  134. package/dist/fills/renderer.d.ts +24 -0
  135. package/dist/fills/renderer.d.ts.map +1 -0
  136. package/dist/fills/renderer.js +5 -0
  137. package/dist/fills/renderer.js.map +1 -0
  138. package/dist/fills/solid.d.ts +7 -0
  139. package/dist/fills/solid.d.ts.map +1 -0
  140. package/dist/fills/solid.js +13 -0
  141. package/dist/fills/solid.js.map +1 -0
  142. package/dist/fills/stripe.d.ts +7 -0
  143. package/dist/fills/stripe.d.ts.map +1 -0
  144. package/dist/fills/stripe.js +85 -0
  145. package/dist/fills/stripe.js.map +1 -0
  146. package/dist/fills/video.d.ts +6 -0
  147. package/dist/fills/video.d.ts.map +1 -0
  148. package/dist/fills/video.js +14 -0
  149. package/dist/fills/video.js.map +1 -0
  150. package/dist/font-style.d.ts +23 -0
  151. package/dist/font-style.d.ts.map +1 -0
  152. package/dist/font-style.js +34 -0
  153. package/dist/font-style.js.map +1 -0
  154. package/dist/getter.d.ts +9 -0
  155. package/dist/getter.d.ts.map +1 -0
  156. package/dist/getter.js +26 -0
  157. package/dist/getter.js.map +1 -0
  158. package/dist/index.d.ts +9 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +11 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/master-clock.d.ts +42 -0
  163. package/dist/master-clock.d.ts.map +1 -0
  164. package/dist/master-clock.js +134 -0
  165. package/dist/master-clock.js.map +1 -0
  166. package/dist/measure-scope.d.ts +14 -0
  167. package/dist/measure-scope.d.ts.map +1 -0
  168. package/dist/measure-scope.js +29 -0
  169. package/dist/measure-scope.js.map +1 -0
  170. package/dist/render-context.d.ts +107 -0
  171. package/dist/render-context.d.ts.map +1 -0
  172. package/dist/render-context.js +940 -0
  173. package/dist/render-context.js.map +1 -0
  174. package/dist/shapes/alpha-contour.d.ts +27 -0
  175. package/dist/shapes/alpha-contour.d.ts.map +1 -0
  176. package/dist/shapes/alpha-contour.js +330 -0
  177. package/dist/shapes/alpha-contour.js.map +1 -0
  178. package/dist/shapes/base.d.ts +46 -0
  179. package/dist/shapes/base.d.ts.map +1 -0
  180. package/dist/shapes/base.js +95 -0
  181. package/dist/shapes/base.js.map +1 -0
  182. package/dist/shapes/boolean.d.ts +28 -0
  183. package/dist/shapes/boolean.d.ts.map +1 -0
  184. package/dist/shapes/boolean.js +90 -0
  185. package/dist/shapes/boolean.js.map +1 -0
  186. package/dist/shapes/ellipse.d.ts +32 -0
  187. package/dist/shapes/ellipse.d.ts.map +1 -0
  188. package/dist/shapes/ellipse.js +50 -0
  189. package/dist/shapes/ellipse.js.map +1 -0
  190. package/dist/shapes/image.d.ts +66 -0
  191. package/dist/shapes/image.d.ts.map +1 -0
  192. package/dist/shapes/image.js +214 -0
  193. package/dist/shapes/image.js.map +1 -0
  194. package/dist/shapes/index.d.ts +67 -0
  195. package/dist/shapes/index.d.ts.map +1 -0
  196. package/dist/shapes/index.js +297 -0
  197. package/dist/shapes/index.js.map +1 -0
  198. package/dist/shapes/line.d.ts +25 -0
  199. package/dist/shapes/line.d.ts.map +1 -0
  200. package/dist/shapes/line.js +87 -0
  201. package/dist/shapes/line.js.map +1 -0
  202. package/dist/shapes/mask.d.ts +28 -0
  203. package/dist/shapes/mask.d.ts.map +1 -0
  204. package/dist/shapes/mask.js +106 -0
  205. package/dist/shapes/mask.js.map +1 -0
  206. package/dist/shapes/paragraph-layout.d.ts +64 -0
  207. package/dist/shapes/paragraph-layout.d.ts.map +1 -0
  208. package/dist/shapes/paragraph-layout.js +156 -0
  209. package/dist/shapes/paragraph-layout.js.map +1 -0
  210. package/dist/shapes/path.d.ts +29 -0
  211. package/dist/shapes/path.d.ts.map +1 -0
  212. package/dist/shapes/path.js +71 -0
  213. package/dist/shapes/path.js.map +1 -0
  214. package/dist/shapes/polygon.d.ts +33 -0
  215. package/dist/shapes/polygon.d.ts.map +1 -0
  216. package/dist/shapes/polygon.js +86 -0
  217. package/dist/shapes/polygon.js.map +1 -0
  218. package/dist/shapes/polygram.d.ts +34 -0
  219. package/dist/shapes/polygram.d.ts.map +1 -0
  220. package/dist/shapes/polygram.js +90 -0
  221. package/dist/shapes/polygram.js.map +1 -0
  222. package/dist/shapes/rect.d.ts +41 -0
  223. package/dist/shapes/rect.d.ts.map +1 -0
  224. package/dist/shapes/rect.js +111 -0
  225. package/dist/shapes/rect.js.map +1 -0
  226. package/dist/shapes/richtext.d.ts +28 -0
  227. package/dist/shapes/richtext.d.ts.map +1 -0
  228. package/dist/shapes/richtext.js +32 -0
  229. package/dist/shapes/richtext.js.map +1 -0
  230. package/dist/shapes/shape-handler.d.ts +79 -0
  231. package/dist/shapes/shape-handler.d.ts.map +1 -0
  232. package/dist/shapes/shape-handler.js +304 -0
  233. package/dist/shapes/shape-handler.js.map +1 -0
  234. package/dist/shapes/text.d.ts +13 -0
  235. package/dist/shapes/text.d.ts.map +1 -0
  236. package/dist/shapes/text.js +67 -0
  237. package/dist/shapes/text.js.map +1 -0
  238. package/dist/shapes/trim.d.ts +10 -0
  239. package/dist/shapes/trim.d.ts.map +1 -0
  240. package/dist/shapes/trim.js +49 -0
  241. package/dist/shapes/trim.js.map +1 -0
  242. package/dist/storage-adapter.d.ts +56 -0
  243. package/dist/storage-adapter.d.ts.map +1 -0
  244. package/dist/storage-adapter.js +188 -0
  245. package/dist/storage-adapter.js.map +1 -0
  246. package/dist/stroke/index.d.ts +34 -0
  247. package/dist/stroke/index.d.ts.map +1 -0
  248. package/dist/stroke/index.js +360 -0
  249. package/dist/stroke/index.js.map +1 -0
  250. package/dist/stroke/stroke-handler.d.ts +45 -0
  251. package/dist/stroke/stroke-handler.d.ts.map +1 -0
  252. package/dist/stroke/stroke-handler.js +371 -0
  253. package/dist/stroke/stroke-handler.js.map +1 -0
  254. package/dist/video/extract.d.ts +54 -0
  255. package/dist/video/extract.d.ts.map +1 -0
  256. package/dist/video/extract.js +192 -0
  257. package/dist/video/extract.js.map +1 -0
  258. package/dist/video/extract.worker.d.ts +50 -0
  259. package/dist/video/extract.worker.d.ts.map +1 -0
  260. package/dist/video/extract.worker.js +224 -0
  261. package/dist/video/extract.worker.js.map +1 -0
  262. package/package.json +57 -0
@@ -0,0 +1,297 @@
1
+ import { RectShape } from "./rect";
2
+ import { EllipseShape } from "./ellipse";
3
+ import { PathShape } from "./path";
4
+ import { LineShape } from "./line";
5
+ import { buildText } from "./text";
6
+ import { PolygonShape } from "./polygon";
7
+ import { PolygramShape } from "./polygram";
8
+ import { BooleanHandler } from "./boolean";
9
+ import { MaskHandler } from "./mask";
10
+ // Shallow equality check for plain state objects. Handles the common case where
11
+ // all values are primitives or the same object reference (e.g. arrays held stable).
12
+ function shallowEqual(a, b) {
13
+ const keysA = Object.keys(a);
14
+ if (keysA.length !== Object.keys(b).length)
15
+ return false;
16
+ for (const k of keysA) {
17
+ if (a[k] !== b[k])
18
+ return false;
19
+ }
20
+ return true;
21
+ }
22
+ function shallowEqualExcluding(a, b, ...exclude) {
23
+ const excSet = new Set(exclude);
24
+ const keysA = Object.keys(a).filter(k => !excSet.has(k));
25
+ const keysB = Object.keys(b).filter(k => !excSet.has(k));
26
+ if (keysA.length !== keysB.length)
27
+ return false;
28
+ for (const k of keysA) {
29
+ if (a[k] !== b[k])
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ export class ShapeHandler {
35
+ canvasKit;
36
+ getCanvas;
37
+ getPaint;
38
+ fontMgr;
39
+ shapes = [];
40
+ paintApplied = false;
41
+ pendingShadows = null;
42
+ boolean;
43
+ mask;
44
+ // Bounds override stack. Callers like the image-node renderer push their
45
+ // own rect so fills that depend on shape bounds (gradients, image-shaders)
46
+ // resolve correctly even though no path lives in `shapes`.
47
+ boundsOverride = [];
48
+ // Shape instance cache: survives reset() so ckPaths persist across frames.
49
+ // Key format: "<nodeId>:<shapeIndex>"
50
+ shapeCache = new Map();
51
+ currentNodeId = "";
52
+ shapeIndex = 0;
53
+ // Cached union bounds for the current shape set, cleared when shapes change.
54
+ _cachedBounds = null;
55
+ _boundsDirty = true;
56
+ constructor(canvasKit, getCanvas, getPaint, fontMgr) {
57
+ this.canvasKit = canvasKit;
58
+ this.getCanvas = getCanvas;
59
+ this.getPaint = getPaint;
60
+ this.fontMgr = fontMgr;
61
+ this.boolean = new BooleanHandler(canvasKit, getCanvas);
62
+ this.mask = new MaskHandler(canvasKit, getCanvas, this.boolean);
63
+ }
64
+ beginNode(nodeId) {
65
+ this.currentNodeId = nodeId;
66
+ this.shapeIndex = 0;
67
+ }
68
+ reset() {
69
+ this.shapes = [];
70
+ this.paintApplied = false;
71
+ this.pendingShadows = null;
72
+ this._boundsDirty = true;
73
+ this._cachedBounds = null;
74
+ }
75
+ storePendingShadows(shadows) {
76
+ this.pendingShadows = shadows.length > 0 ? shadows : null;
77
+ }
78
+ takePendingShadows() {
79
+ const s = this.pendingShadows;
80
+ this.pendingShadows = null;
81
+ return s;
82
+ }
83
+ dispose() {
84
+ this.shapes = [];
85
+ for (const entry of this.shapeCache.values()) {
86
+ entry.shape.deletePaths();
87
+ }
88
+ this.shapeCache.clear();
89
+ this.boolean.dispose();
90
+ this.mask.dispose();
91
+ }
92
+ isCollectingPaths() {
93
+ return this.boolean.isCollecting();
94
+ }
95
+ pushBounds(b) {
96
+ this.boundsOverride.push(b);
97
+ }
98
+ popBounds() {
99
+ this.boundsOverride.pop();
100
+ }
101
+ getShapeBounds() {
102
+ if (this.boundsOverride.length > 0) {
103
+ return this.boundsOverride[this.boundsOverride.length - 1];
104
+ }
105
+ if (!this._boundsDirty && this._cachedBounds !== null) {
106
+ return this._cachedBounds;
107
+ }
108
+ let left = Infinity, top = Infinity, right = -Infinity, bottom = -Infinity;
109
+ for (const shape of this.shapes) {
110
+ if (shape.ckPath) {
111
+ const b = shape.ckPath.getBounds();
112
+ if (b[0] < left)
113
+ left = b[0];
114
+ if (b[1] < top)
115
+ top = b[1];
116
+ if (b[2] > right)
117
+ right = b[2];
118
+ if (b[3] > bottom)
119
+ bottom = b[3];
120
+ }
121
+ else if (shape.bounds) {
122
+ if (shape.bounds.left < left)
123
+ left = shape.bounds.left;
124
+ if (shape.bounds.top < top)
125
+ top = shape.bounds.top;
126
+ if (shape.bounds.right > right)
127
+ right = shape.bounds.right;
128
+ if (shape.bounds.bottom > bottom)
129
+ bottom = shape.bounds.bottom;
130
+ }
131
+ }
132
+ this._boundsDirty = false;
133
+ this._cachedBounds = isFinite(left) ? { left, top, right, bottom } : null;
134
+ return this._cachedBounds;
135
+ }
136
+ addShape(newShape) {
137
+ this._boundsDirty = true;
138
+ const isolated = !this.boolean.isCollecting();
139
+ // Try to reuse a cached shape if we have a stable node ID.
140
+ let shape = newShape;
141
+ if (this.currentNodeId) {
142
+ const key = `${this.currentNodeId}:${this.shapeIndex++}`;
143
+ const entry = this.shapeCache.get(key);
144
+ if (entry) {
145
+ const cached = entry.shape;
146
+ const newState = newShape.inputState;
147
+ const oldState = cached.inputState;
148
+ if (shallowEqual(newState, oldState)) {
149
+ // Exact match — reuse the cached shape (with its ckPath intact).
150
+ shape = cached;
151
+ }
152
+ else if (cached.hasTrim() && newShape.hasTrim()
153
+ && shallowEqualExcluding(newState, oldState, 'start', 'end')) {
154
+ // Only trim range changed — re-trim from the cached base path.
155
+ const { start, end } = newShape.trimRange();
156
+ if (entry.trimStart !== start || entry.trimEnd !== end) {
157
+ cached.retrim(start, end);
158
+ entry.trimStart = start;
159
+ entry.trimEnd = end;
160
+ }
161
+ cached.inputState = newShape.inputState;
162
+ shape = cached;
163
+ }
164
+ else {
165
+ // State mismatch — evict old entry and use new shape.
166
+ cached.deletePaths();
167
+ const tr = newShape.hasTrim() ? newShape.trimRange() : { start: 0, end: 1 };
168
+ this.shapeCache.set(key, { shape: newShape, trimStart: tr.start, trimEnd: tr.end });
169
+ shape = newShape;
170
+ }
171
+ }
172
+ else {
173
+ const tr = newShape.hasTrim() ? newShape.trimRange() : { start: 0, end: 1 };
174
+ this.shapeCache.set(key, { shape: newShape, trimStart: tr.start, trimEnd: tr.end });
175
+ }
176
+ }
177
+ if (!isolated) {
178
+ shape.ensurePath();
179
+ if (shape.ckPath)
180
+ this.boolean.contributeToPathCollection(shape.ckPath);
181
+ }
182
+ this.shapes.push(shape.toCurrentShape(isolated));
183
+ }
184
+ rect(state) {
185
+ this.addShape(new RectShape(this.canvasKit, this.getCanvas(), state));
186
+ }
187
+ ellipse(state) {
188
+ this.addShape(new EllipseShape(this.canvasKit, this.getCanvas(), state));
189
+ }
190
+ path(state) {
191
+ this.addShape(new PathShape(this.canvasKit, this.getCanvas(), state));
192
+ }
193
+ line(state) {
194
+ this.addShape(new LineShape(this.canvasKit, this.getCanvas(), state));
195
+ }
196
+ polygon(state) {
197
+ this.addShape(new PolygonShape(this.canvasKit, this.getCanvas(), state));
198
+ }
199
+ polygram(state) {
200
+ this.addShape(new PolygramShape(this.canvasKit, this.getCanvas(), state));
201
+ }
202
+ text(state) {
203
+ this._boundsDirty = true;
204
+ const shape = buildText(this.canvasKit, this.getCanvas(), this.fontMgr, state);
205
+ this.shapes.push(shape);
206
+ }
207
+ // ─── Cut ───────────────────────────────────────────────────────────────────
208
+ // Use the most-recently drawn shape as a cutter: union all the shapes before
209
+ // it, then subtract that last shape, so only it punches a hole. The combined
210
+ // path replaces `shapes`, so anything drawn afterward stacks onto it and the
211
+ // whole thing paints as one surface — a single gradient resolves across all
212
+ // of it. Shapes without a ckPath (text) are skipped.
213
+ cut() {
214
+ const withPaths = this.shapes.filter(s => s.ckPath);
215
+ if (withPaths.length === 0)
216
+ return;
217
+ // The last shape is the cutter; everything before it is the base.
218
+ const cutter = withPaths[withPaths.length - 1].ckPath.copy();
219
+ const baseShapes = withPaths.slice(0, -1);
220
+ let combined;
221
+ if (baseShapes.length === 0) {
222
+ // Nothing to cut from — the lone shape stays as-is.
223
+ cutter.delete();
224
+ combined = withPaths[0].ckPath.copy();
225
+ }
226
+ else {
227
+ const base = this.boolean.combinePaths(baseShapes.map(s => s.ckPath.copy()), "union");
228
+ if (!base) {
229
+ cutter.delete();
230
+ combined = null;
231
+ }
232
+ else {
233
+ combined = this.boolean.combinePaths([base, cutter], "subtract");
234
+ }
235
+ }
236
+ // combinePaths consumed/deleted the copies; now drop the originals.
237
+ for (const shape of this.shapes)
238
+ shape.ckPath?.delete();
239
+ this.shapes = [];
240
+ this.paintApplied = false;
241
+ if (!combined)
242
+ return;
243
+ const canvas = this.getCanvas();
244
+ this.shapes.push({
245
+ draw: (paint) => { canvas.drawPath(combined, paint); },
246
+ ckPath: combined,
247
+ });
248
+ }
249
+ // Build a single shape from the union of all accumulated path shapes, so a
250
+ // stroke follows only the outer boundary with no seams where shapes overlap.
251
+ // Returns null when there are fewer than two path shapes (caller strokes the
252
+ // shapes directly) or text is involved (no path to union). The caller owns
253
+ // the returned shape's ckPath and must delete() it. Does not mutate `shapes`.
254
+ unionStrokeShape() {
255
+ if (this.shapes.some(s => s.isText))
256
+ return null;
257
+ const withPaths = this.shapes.filter(s => s.ckPath);
258
+ if (withPaths.length < 2)
259
+ return null;
260
+ const combined = this.boolean.combinePaths(withPaths.map(s => s.ckPath.copy()), "union");
261
+ if (!combined)
262
+ return null;
263
+ const canvas = this.getCanvas();
264
+ return {
265
+ draw: (paint) => { canvas.drawPath(combined, paint); },
266
+ ckPath: combined,
267
+ };
268
+ }
269
+ // ─── Boolean ─────────────────────────────────────────────────────────────
270
+ beginBoolean(op) {
271
+ this.boolean.beginBoolean(op);
272
+ }
273
+ endBoolean() {
274
+ const shape = this.boolean.endBoolean(this.getCanvas);
275
+ this.shapes = [];
276
+ this.paintApplied = false;
277
+ if (shape)
278
+ this.shapes.push(shape);
279
+ }
280
+ // ─── Mask ─────────────────────────────────────────────────────────────────
281
+ beginMask(options) {
282
+ this.mask.beginMask(options);
283
+ }
284
+ applyMask() {
285
+ this.mask.applyMask(() => {
286
+ this.shapes = [];
287
+ this.paintApplied = false;
288
+ });
289
+ }
290
+ endMask() {
291
+ this.mask.endMask();
292
+ }
293
+ getMaskApply() {
294
+ return this.mask.getApply();
295
+ }
296
+ }
297
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shapes/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { LineState, Vector2 } from "@motion-script/core";
2
+ import { BaseShape } from "./base";
3
+ type LineGeo = {
4
+ points: Vector2[];
5
+ radius: number;
6
+ closed: boolean;
7
+ };
8
+ /**
9
+ * Polyline (open or closed) through `points`, with corners optionally rounded
10
+ * by cutting back along each adjacent edge and joining with a quadratic curve
11
+ * (`radius` clamped to half the shorter adjacent edge to avoid overshoot).
12
+ */
13
+ export declare class LineShape extends BaseShape<LineState, LineGeo> {
14
+ protected resolveState(state: Partial<LineState>): LineState;
15
+ protected computeGeometry(): LineGeo;
16
+ protected buildSVGPath(geo: LineGeo): string;
17
+ protected needsTrim(): boolean;
18
+ protected getTrimRange(): {
19
+ start: number;
20
+ end: number;
21
+ };
22
+ ensurePath(): void;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/shapes/line.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAsB,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,KAAK,OAAO,GAAG;IACX,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AA6DF;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC;IACxD,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS;IAI5D,SAAS,CAAC,eAAe,IAAI,OAAO;IAKpC,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAI5C,SAAS,CAAC,SAAS,IAAI,OAAO;IAI9B,SAAS,CAAC,YAAY;;;;IAKb,UAAU,IAAI,IAAI;CAI9B"}
@@ -0,0 +1,87 @@
1
+ import { withLineDescriptor } from "@motion-script/core";
2
+ import { BaseShape } from "./base";
3
+ function buildLineSvg(points, radius, closed) {
4
+ if (points.length === 0)
5
+ return "M 0 0";
6
+ if (points.length === 1)
7
+ return `M ${points[0].x} ${points[0].y}`;
8
+ const r = Math.max(0, radius);
9
+ const parts = [];
10
+ const count = points.length;
11
+ const getDir = (a, b) => {
12
+ const dx = b.x - a.x;
13
+ const dy = b.y - a.y;
14
+ const len = Math.sqrt(dx * dx + dy * dy);
15
+ return len > 0 ? { dx: dx / len, dy: dy / len, len } : { dx: 0, dy: 0, len: 0 };
16
+ };
17
+ if (r === 0) {
18
+ parts.push(`M ${points[0].x} ${points[0].y}`);
19
+ for (let i = 1; i < count; i++) {
20
+ parts.push(`L ${points[i].x} ${points[i].y}`);
21
+ }
22
+ }
23
+ else {
24
+ const endIdx = closed ? count : count - 1;
25
+ for (let i = 0; i <= endIdx; i++) {
26
+ const prev = points[(i - 1 + count) % count];
27
+ const curr = points[i % count];
28
+ const next = points[(i + 1) % count];
29
+ if (!closed && i === 0) {
30
+ parts.push(`M ${curr.x} ${curr.y}`);
31
+ continue;
32
+ }
33
+ if (!closed && i === count - 1) {
34
+ parts.push(`L ${curr.x} ${curr.y}`);
35
+ continue;
36
+ }
37
+ const dIn = getDir(prev, curr);
38
+ const dOut = getDir(curr, next);
39
+ const cutIn = Math.min(r, dIn.len / 2);
40
+ const cutOut = Math.min(r, dOut.len / 2);
41
+ const inX = curr.x - dIn.dx * cutIn;
42
+ const inY = curr.y - dIn.dy * cutIn;
43
+ const outX = curr.x + dOut.dx * cutOut;
44
+ const outY = curr.y + dOut.dy * cutOut;
45
+ if (i === 0 && closed) {
46
+ parts.push(`M ${inX} ${inY}`);
47
+ }
48
+ else {
49
+ parts.push(`L ${inX} ${inY}`);
50
+ }
51
+ parts.push(`Q ${curr.x} ${curr.y} ${outX} ${outY}`);
52
+ }
53
+ }
54
+ if (closed)
55
+ parts.push("Z");
56
+ return parts.join(" ");
57
+ }
58
+ /**
59
+ * Polyline (open or closed) through `points`, with corners optionally rounded
60
+ * by cutting back along each adjacent edge and joining with a quadratic curve
61
+ * (`radius` clamped to half the shorter adjacent edge to avoid overshoot).
62
+ */
63
+ export class LineShape extends BaseShape {
64
+ resolveState(state) {
65
+ return withLineDescriptor(state);
66
+ }
67
+ computeGeometry() {
68
+ const { points, radius, closed } = this.fullState;
69
+ return { points, radius, closed };
70
+ }
71
+ buildSVGPath(geo) {
72
+ return buildLineSvg(geo.points, geo.radius, geo.closed);
73
+ }
74
+ needsTrim() {
75
+ return this.fullState.start !== 0 || this.fullState.end !== 1;
76
+ }
77
+ getTrimRange() {
78
+ return { start: this.fullState.start, end: this.fullState.end };
79
+ }
80
+ // ensurePath() guards against empty points before attempting path creation
81
+ ensurePath() {
82
+ if (this.fullState.points.length === 0)
83
+ return;
84
+ super.ensurePath();
85
+ }
86
+ }
87
+ //# sourceMappingURL=line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.js","sourceRoot":"","sources":["../../src/shapes/line.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { CanvasKit, Canvas } from "@motion-script/canvaskit";
2
+ import { MaskApplyLayer, MaskOptions } from "@motion-script/core";
3
+ import type { BooleanHandler } from "./boolean";
4
+ /**
5
+ * Implements the three mask modes by composing canvas save/clip/blend
6
+ * primitives:
7
+ * - "vector": collect contributed paths into a union and `clipPath` directly
8
+ * (no layer — cheapest, but limited to geometric shapes).
9
+ * - "luminance": render the mask content through a luminance-to-alpha color
10
+ * filter into a layer, so pixel brightness drives opacity.
11
+ * - "alpha": render the mask content into a plain layer and blend the masked
12
+ * content against it with `SrcIn`/`SrcOut`.
13
+ * `restores` records how many `canvas.restore()` calls `endMask` must issue
14
+ * to unwind the saves made in `beginMask`/`applyMask`.
15
+ */
16
+ export declare class MaskHandler {
17
+ private canvasKit;
18
+ private getCanvas;
19
+ private boolean;
20
+ private maskStack;
21
+ constructor(canvasKit: CanvasKit, getCanvas: () => Canvas, boolean: BooleanHandler);
22
+ dispose(): void;
23
+ beginMask(options?: MaskOptions): void;
24
+ getApply(): Set<MaskApplyLayer> | null;
25
+ applyMask(onReset: () => void): void;
26
+ endMask(): void;
27
+ }
28
+ //# sourceMappingURL=mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../../src/shapes/mask.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAY,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAUhD;;;;;;;;;;;GAWG;AACH,qBAAa,WAAW;IAIhB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IALnB,OAAO,CAAC,SAAS,CAAmB;gBAGxB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,MAAM,EACvB,OAAO,EAAE,cAAc;IAGnC,OAAO,IAAI,IAAI;IAIf,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI;IAuCtC,QAAQ,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI;IAKtC,SAAS,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAsCpC,OAAO,IAAI,IAAI;CAQlB"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Implements the three mask modes by composing canvas save/clip/blend
3
+ * primitives:
4
+ * - "vector": collect contributed paths into a union and `clipPath` directly
5
+ * (no layer — cheapest, but limited to geometric shapes).
6
+ * - "luminance": render the mask content through a luminance-to-alpha color
7
+ * filter into a layer, so pixel brightness drives opacity.
8
+ * - "alpha": render the mask content into a plain layer and blend the masked
9
+ * content against it with `SrcIn`/`SrcOut`.
10
+ * `restores` records how many `canvas.restore()` calls `endMask` must issue
11
+ * to unwind the saves made in `beginMask`/`applyMask`.
12
+ */
13
+ export class MaskHandler {
14
+ canvasKit;
15
+ getCanvas;
16
+ boolean;
17
+ maskStack = [];
18
+ constructor(canvasKit, getCanvas, boolean) {
19
+ this.canvasKit = canvasKit;
20
+ this.getCanvas = getCanvas;
21
+ this.boolean = boolean;
22
+ }
23
+ dispose() {
24
+ this.maskStack = [];
25
+ }
26
+ beginMask(options) {
27
+ const canvas = this.getCanvas();
28
+ const mode = options?.mode ?? "alpha";
29
+ const inverted = options?.inverted ?? false;
30
+ const raw = options?.apply;
31
+ const apply = raw != null
32
+ ? new Set(Array.isArray(raw) ? raw : [raw])
33
+ : null;
34
+ if (mode === "vector") {
35
+ canvas.save();
36
+ this.boolean.pushFrame();
37
+ this.maskStack.push({ mode, inverted, apply, restores: 1 });
38
+ return;
39
+ }
40
+ if (mode === "luminance") {
41
+ canvas.saveLayer();
42
+ const lumPaint = new this.canvasKit.Paint();
43
+ const lumFilter = this.canvasKit.ColorFilter.MakeMatrix([
44
+ 0, 0, 0, 0, 0,
45
+ 0, 0, 0, 0, 0,
46
+ 0, 0, 0, 0, 0,
47
+ 0.2126, 0.7152, 0.0722, 0, 0,
48
+ ]);
49
+ lumPaint.setColorFilter(lumFilter);
50
+ canvas.saveLayer(lumPaint);
51
+ lumPaint.delete();
52
+ this.maskStack.push({ mode, inverted, apply, restores: 2 });
53
+ return;
54
+ }
55
+ // alpha
56
+ canvas.saveLayer();
57
+ this.maskStack.push({ mode, inverted, apply, restores: 2 });
58
+ }
59
+ // Returns the apply set for the innermost active mask, or null if no mask
60
+ // is active / no apply restriction was set (= all layers pass through).
61
+ getApply() {
62
+ const top = this.maskStack[this.maskStack.length - 1];
63
+ return top?.apply ?? null;
64
+ }
65
+ applyMask(onReset) {
66
+ const canvas = this.getCanvas();
67
+ const top = this.maskStack[this.maskStack.length - 1];
68
+ if (!top) {
69
+ console.warn("applyMask() called outside of a mask scope.");
70
+ return;
71
+ }
72
+ if (top.mode === "vector") {
73
+ const paths = this.boolean.popFrame();
74
+ const combined = this.boolean.combinePaths(paths, "union");
75
+ onReset();
76
+ if (combined) {
77
+ const op = top.inverted
78
+ ? this.canvasKit.ClipOp.Difference
79
+ : this.canvasKit.ClipOp.Intersect;
80
+ canvas.clipPath(combined, op, true);
81
+ combined.delete();
82
+ }
83
+ return;
84
+ }
85
+ if (top.mode === "luminance") {
86
+ canvas.restore();
87
+ }
88
+ const blendPaint = new this.canvasKit.Paint();
89
+ blendPaint.setBlendMode(top.inverted
90
+ ? this.canvasKit.BlendMode.SrcOut
91
+ : this.canvasKit.BlendMode.SrcIn);
92
+ canvas.saveLayer(blendPaint);
93
+ blendPaint.delete();
94
+ onReset();
95
+ }
96
+ endMask() {
97
+ const frame = this.maskStack.pop();
98
+ if (!frame)
99
+ return;
100
+ const canvas = this.getCanvas();
101
+ for (let i = 0; i < frame.restores; i++) {
102
+ canvas.restore();
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../../src/shapes/mask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { CanvasKit, Font, Paint, Canvas, TypefaceFontProvider } from "@motion-script/canvaskit";
2
+ import type { FontStyle, TextAlign } from "@motion-script/core";
3
+ /**
4
+ * One styled run of text fed to the paragraph layout. Mirrors the fields the
5
+ * layout engine needs; callers attach their own draw-time data (fills/strokes)
6
+ * separately, keyed by run index.
7
+ */
8
+ export interface ParagraphSegment {
9
+ text: string;
10
+ fontFamily: string;
11
+ fontSize: number;
12
+ fontWeight: number;
13
+ fontStyle: FontStyle;
14
+ letterSpacing: number;
15
+ }
16
+ /**
17
+ * A shaped run ready to draw with our own paints. We let CanvasKit's
18
+ * ParagraphBuilder do shaping/line-breaking/positioning (the layout power),
19
+ * but draw via canvas.drawGlyphs with a Font we own (the path-glyph power) so
20
+ * gradient/image fills and glyph-union strokes keep working. We build that Font
21
+ * from the run's own `typeface` (this CanvasKit build hands back the
22
+ * variation-positioned instance, e.g. a variable font at the run's `wght`), so
23
+ * the drawn glyphs match the shaped weight exactly.
24
+ */
25
+ export interface ShapedRun {
26
+ /** Index of the originating ParagraphSegment, for mapping fills/strokes. */
27
+ segmentIndex: number;
28
+ glyphs: Uint16Array;
29
+ /** x,y pairs, already offset to the shape's centered coordinate space. */
30
+ positions: Float32Array;
31
+ font: Font;
32
+ }
33
+ export interface ParagraphLayoutResult {
34
+ runs: ShapedRun[];
35
+ bounds: {
36
+ left: number;
37
+ top: number;
38
+ right: number;
39
+ bottom: number;
40
+ };
41
+ /** Intrinsic block width/height of the laid-out text. */
42
+ width: number;
43
+ height: number;
44
+ /** Fonts created during layout; caller must delete() each after drawing. */
45
+ fonts: Font[];
46
+ }
47
+ /**
48
+ * Lay out styled segments through ParagraphBuilder and return shaped glyph runs
49
+ * positioned in a coordinate space centered on (originX, originY). `maxWidth`
50
+ * bounds line wrapping; pass Infinity (mapped to a large value) for no wrap.
51
+ *
52
+ * The fontMgr must already have the families registered (loadFont); a private
53
+ * FontCollection wrapping it is created per call.
54
+ */
55
+ export declare function layoutParagraph(canvasKit: CanvasKit, fontMgr: TypefaceFontProvider, segments: ParagraphSegment[], opts: {
56
+ align: TextAlign;
57
+ lineHeight: number;
58
+ maxWidth: number;
59
+ originX: number;
60
+ originY: number;
61
+ }): ParagraphLayoutResult;
62
+ /** Draw a shaped run with the given paint via our own glyph pipeline. */
63
+ export declare function drawShapedRun(canvas: Canvas, run: ShapedRun, paint: Paint): void;
64
+ //# sourceMappingURL=paragraph-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paragraph-layout.d.ts","sourceRoot":"","sources":["../../src/shapes/paragraph-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAY,MAAM,0BAA0B,CAAC;AAC/G,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACtB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,0EAA0E;IAC1E,SAAS,EAAE,YAAY,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,EAAE,IAAI,EAAE,CAAC;CACjB;AAqBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,IAAI,EAAE;IACF,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB,GACF,qBAAqB,CA4HvB;AAeD,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAEhF"}