@shopify/react-native-skia 2.13.1 → 2.14.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 (103) hide show
  1. package/android/CMakeLists.txt +2 -0
  2. package/android/cpp/jni/include/JniSkiaPictureView.h +16 -15
  3. package/apple/RNSkApplePlatformContext.h +3 -4
  4. package/apple/RNSkiaModule.h +11 -3
  5. package/apple/RNSkiaModule.mm +46 -19
  6. package/apple/SkiaPictureView.mm +2 -2
  7. package/apple/SkiaUIView.h +0 -1
  8. package/apple/SkiaUIView.mm +1 -1
  9. package/apple/ViewScreenshotService.h +2 -2
  10. package/apple/ViewScreenshotService.mm +5 -4
  11. package/cpp/api/JsiSkPath.h +0 -431
  12. package/cpp/api/JsiSkSkottie.h +2 -3
  13. package/cpp/api/JsiSkStrutStyle.h +1 -1
  14. package/cpp/api/JsiSkSurfaceFactory.h +41 -0
  15. package/cpp/api/recorder/Convertor.h +152 -131
  16. package/cpp/api/recorder/DataTypes.h +11 -11
  17. package/cpp/api/recorder/ImageFit.h +8 -5
  18. package/cpp/api/recorder/JsiRecorder.h +9 -29
  19. package/cpp/api/recorder/Paint.h +3 -3
  20. package/cpp/api/recorder/RNRecorder.h +56 -0
  21. package/cpp/jsi/ViewProperty.cpp +23 -0
  22. package/cpp/jsi/ViewProperty.h +31 -10
  23. package/cpp/rnskia/RNDawnContext.h +33 -0
  24. package/cpp/rnskia/RNSkJsiViewApi.h +69 -2
  25. package/cpp/rnskia/RNSkPictureView.cpp +58 -0
  26. package/cpp/rnskia/RNSkPictureView.h +110 -24
  27. package/lib/commonjs/Platform/IPlatform.js.map +1 -1
  28. package/lib/commonjs/animation/functions/interpolate.js.map +1 -1
  29. package/lib/commonjs/skia/core/Image.js.map +1 -1
  30. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.js.map +1 -1
  31. package/lib/commonjs/skia/types/Path/Path.d.ts +2 -336
  32. package/lib/commonjs/skia/types/Path/Path.js.map +1 -1
  33. package/lib/commonjs/skia/types/Recorder.d.ts +10 -0
  34. package/lib/commonjs/skia/types/Recorder.js.map +1 -1
  35. package/lib/commonjs/skia/types/Shader/Shader.js.map +1 -1
  36. package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +16 -0
  37. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  38. package/lib/commonjs/skia/web/JsiSkPath.d.ts +4 -38
  39. package/lib/commonjs/skia/web/JsiSkPath.js +3 -275
  40. package/lib/commonjs/skia/web/JsiSkPath.js.map +1 -1
  41. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.d.ts +2 -1
  42. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js +3 -0
  43. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  44. package/lib/commonjs/sksg/Container.native.d.ts +15 -1
  45. package/lib/commonjs/sksg/Container.native.js +34 -33
  46. package/lib/commonjs/sksg/Container.native.js.map +1 -1
  47. package/lib/commonjs/specs/NativeSkiaModule.web.js +4 -0
  48. package/lib/commonjs/specs/NativeSkiaModule.web.js.map +1 -1
  49. package/lib/commonjs/views/types.d.ts +9 -0
  50. package/lib/commonjs/views/types.js.map +1 -1
  51. package/lib/module/Platform/IPlatform.js.map +1 -1
  52. package/lib/module/animation/functions/interpolate.js.map +1 -1
  53. package/lib/module/skia/core/Image.js.map +1 -1
  54. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.js.map +1 -1
  55. package/lib/module/skia/types/Path/Path.d.ts +2 -336
  56. package/lib/module/skia/types/Path/Path.js.map +1 -1
  57. package/lib/module/skia/types/Recorder.d.ts +10 -0
  58. package/lib/module/skia/types/Recorder.js.map +1 -1
  59. package/lib/module/skia/types/Shader/Shader.js.map +1 -1
  60. package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +16 -0
  61. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  62. package/lib/module/skia/web/JsiSkPath.d.ts +4 -38
  63. package/lib/module/skia/web/JsiSkPath.js +4 -276
  64. package/lib/module/skia/web/JsiSkPath.js.map +1 -1
  65. package/lib/module/skia/web/JsiSkSurfaceFactory.d.ts +2 -1
  66. package/lib/module/skia/web/JsiSkSurfaceFactory.js +4 -1
  67. package/lib/module/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  68. package/lib/module/sksg/Container.native.d.ts +15 -1
  69. package/lib/module/sksg/Container.native.js +34 -33
  70. package/lib/module/sksg/Container.native.js.map +1 -1
  71. package/lib/module/specs/NativeSkiaModule.web.js +4 -0
  72. package/lib/module/specs/NativeSkiaModule.web.js.map +1 -1
  73. package/lib/module/views/types.d.ts +9 -0
  74. package/lib/module/views/types.js.map +1 -1
  75. package/lib/typescript/lib/commonjs/skia/web/JsiSkPath.d.ts +1 -35
  76. package/lib/typescript/lib/commonjs/skia/web/JsiSkSurfaceFactory.d.ts +1 -0
  77. package/lib/typescript/lib/commonjs/sksg/Container.native.d.ts +15 -1
  78. package/lib/typescript/lib/module/skia/web/JsiSkPath.d.ts +3 -37
  79. package/lib/typescript/lib/module/skia/web/JsiSkSurfaceFactory.d.ts +1 -0
  80. package/lib/typescript/lib/module/sksg/Container.native.d.ts +15 -1
  81. package/lib/typescript/src/skia/types/Path/Path.d.ts +2 -336
  82. package/lib/typescript/src/skia/types/Recorder.d.ts +10 -0
  83. package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +16 -0
  84. package/lib/typescript/src/skia/web/JsiSkPath.d.ts +4 -38
  85. package/lib/typescript/src/skia/web/JsiSkSurfaceFactory.d.ts +2 -1
  86. package/lib/typescript/src/sksg/Container.native.d.ts +15 -1
  87. package/lib/typescript/src/views/types.d.ts +9 -0
  88. package/package.json +2 -2
  89. package/src/Platform/IPlatform.ts +1 -4
  90. package/src/animation/functions/interpolate.ts +1 -4
  91. package/src/skia/core/Image.ts +1 -2
  92. package/src/skia/types/NativeBuffer/NativeBufferFactory.ts +2 -5
  93. package/src/skia/types/Path/Path.ts +2 -420
  94. package/src/skia/types/Recorder.ts +10 -0
  95. package/src/skia/types/Shader/Shader.ts +1 -5
  96. package/src/skia/types/Surface/SurfaceFactory.ts +17 -0
  97. package/src/skia/web/JsiSkPath.ts +4 -495
  98. package/src/skia/web/JsiSkSurfaceFactory.ts +6 -2
  99. package/src/sksg/Container.native.ts +34 -37
  100. package/src/specs/NativeSkiaModule.web.ts +4 -0
  101. package/src/views/types.ts +13 -0
  102. package/apple/SkiaManager.h +0 -23
  103. package/apple/SkiaManager.mm +0 -63
@@ -4,20 +4,16 @@ import { PathVerb } from "../types";
4
4
  import type {
5
5
  FillType,
6
6
  PathCommand,
7
- PathOp,
8
7
  SkMatrix,
9
8
  SkPath,
10
9
  SkPoint,
11
10
  SkRect,
12
- InputRRect,
13
- StrokeOpts,
14
11
  InputMatrix,
15
12
  } from "../types";
16
13
 
17
- import { getEnum, HostObject, optEnum } from "./Host";
14
+ import { HostObject } from "./Host";
18
15
  import { JsiSkPoint } from "./JsiSkPoint";
19
16
  import { JsiSkRect } from "./JsiSkRect";
20
- import { JsiSkRRect } from "./JsiSkRRect";
21
17
  import { JsiSkMatrix } from "./JsiSkMatrix";
22
18
 
23
19
  const CommandCount = {
@@ -29,22 +25,6 @@ const CommandCount = {
29
25
  [PathVerb.Close]: 1,
30
26
  };
31
27
 
32
- // Track which deprecation warnings have been shown to avoid spam
33
- const shownDeprecationWarnings = new Set<string>();
34
-
35
- const warnDeprecatedPathMethod = (
36
- methodName: string,
37
- suggestion: string
38
- ): void => {
39
- if (shownDeprecationWarnings.has(methodName)) {
40
- return;
41
- }
42
- shownDeprecationWarnings.add(methodName);
43
- console.warn(
44
- `[react-native-skia] SkPath.${methodName}() is deprecated and will be removed in a future release. ${suggestion} See migration guide: https://shopify.github.io/react-native-skia/docs/shapes/path-migration`
45
- );
46
- };
47
-
48
28
  export const toMatrix3x3 = (m: InputMatrix): number[] => {
49
29
  let matrix =
50
30
  m instanceof JsiSkMatrix
@@ -69,8 +49,8 @@ export const toMatrix3x3 = (m: InputMatrix): number[] => {
69
49
  };
70
50
 
71
51
  /**
72
- * SkPath wraps a CK PathBuilder internally, providing both mutable building
73
- * methods and immutable query methods. Use snapshot() internally to get
52
+ * SkPath wraps a CK PathBuilder internally, providing immutable query
53
+ * methods. Use snapshot() internally to get
74
54
  * an immutable CK Path for read-only operations.
75
55
  */
76
56
  export class JsiSkPath
@@ -91,469 +71,6 @@ export class JsiSkPath
91
71
  return JsiSkPath.fromValue<CKPathBuilder>(value).snapshot();
92
72
  }
93
73
 
94
- // ---- Mutable building methods (deprecated) ----
95
-
96
- addPath(src: SkPath, matrix?: SkMatrix, extend = false) {
97
- warnDeprecatedPathMethod(
98
- "addPath",
99
- "Use Skia.PathBuilder.Make().addPath() instead."
100
- );
101
- const srcBuilder = JsiSkPath.fromValue<CKPathBuilder>(src);
102
- const srcPath = srcBuilder.snapshot();
103
- const args = [
104
- srcPath,
105
- ...(matrix ? JsiSkMatrix.fromValue<Float32Array>(matrix) : []),
106
- extend,
107
- ];
108
- this.ref.addPath(...args);
109
- srcPath.delete();
110
- return this;
111
- }
112
-
113
- addArc(
114
- oval: SkRect,
115
- startAngleInDegrees: number,
116
- sweepAngleInDegrees: number
117
- ) {
118
- warnDeprecatedPathMethod(
119
- "addArc",
120
- "Use Skia.PathBuilder.Make().addArc() instead."
121
- );
122
- this.ref.addArc(
123
- JsiSkRect.fromValue(this.CanvasKit, oval),
124
- startAngleInDegrees,
125
- sweepAngleInDegrees
126
- );
127
- return this;
128
- }
129
-
130
- addOval(oval: SkRect, isCCW?: boolean, startIndex?: number) {
131
- warnDeprecatedPathMethod(
132
- "addOval",
133
- "Use Skia.Path.Oval() or Skia.PathBuilder.Make().addOval() instead."
134
- );
135
- this.ref.addOval(
136
- JsiSkRect.fromValue(this.CanvasKit, oval),
137
- isCCW,
138
- startIndex
139
- );
140
- return this;
141
- }
142
-
143
- addPoly(points: SkPoint[], close: boolean) {
144
- warnDeprecatedPathMethod(
145
- "addPoly",
146
- "Use Skia.Path.Polygon() or Skia.PathBuilder.Make().addPoly() instead."
147
- );
148
- this.ref.addPolygon(
149
- points.map((p) => Array.from(JsiSkPoint.fromValue(p))).flat(),
150
- close
151
- );
152
- return this;
153
- }
154
-
155
- addRect(rect: SkRect, isCCW?: boolean) {
156
- warnDeprecatedPathMethod(
157
- "addRect",
158
- "Use Skia.Path.Rect() or Skia.PathBuilder.Make().addRect() instead."
159
- );
160
- this.ref.addRect(JsiSkRect.fromValue(this.CanvasKit, rect), isCCW);
161
- return this;
162
- }
163
-
164
- addRRect(rrect: InputRRect, isCCW?: boolean) {
165
- warnDeprecatedPathMethod(
166
- "addRRect",
167
- "Use Skia.Path.RRect() or Skia.PathBuilder.Make().addRRect() instead."
168
- );
169
- this.ref.addRRect(JsiSkRRect.fromValue(this.CanvasKit, rrect), isCCW);
170
- return this;
171
- }
172
-
173
- addCircle(x: number, y: number, r: number) {
174
- warnDeprecatedPathMethod(
175
- "addCircle",
176
- "Use Skia.Path.Circle() or Skia.PathBuilder.Make().addCircle() instead."
177
- );
178
- this.ref.addCircle(x, y, r);
179
- return this;
180
- }
181
-
182
- moveTo(x: number, y: number) {
183
- warnDeprecatedPathMethod(
184
- "moveTo",
185
- "Use Skia.PathBuilder.Make().moveTo() instead."
186
- );
187
- this.ref.moveTo(x, y);
188
- return this;
189
- }
190
-
191
- rMoveTo(x: number, y: number) {
192
- warnDeprecatedPathMethod(
193
- "rMoveTo",
194
- "Use Skia.PathBuilder.Make().rMoveTo() instead."
195
- );
196
- this.ref.rMoveTo(x, y);
197
- return this;
198
- }
199
-
200
- lineTo(x: number, y: number) {
201
- warnDeprecatedPathMethod(
202
- "lineTo",
203
- "Use Skia.PathBuilder.Make().lineTo() instead."
204
- );
205
- this.ref.lineTo(x, y);
206
- return this;
207
- }
208
-
209
- rLineTo(x: number, y: number) {
210
- warnDeprecatedPathMethod(
211
- "rLineTo",
212
- "Use Skia.PathBuilder.Make().rLineTo() instead."
213
- );
214
- this.ref.rLineTo(x, y);
215
- return this;
216
- }
217
-
218
- quadTo(x1: number, y1: number, x2: number, y2: number) {
219
- warnDeprecatedPathMethod(
220
- "quadTo",
221
- "Use Skia.PathBuilder.Make().quadTo() instead."
222
- );
223
- this.ref.quadTo(x1, y1, x2, y2);
224
- return this;
225
- }
226
-
227
- rQuadTo(x1: number, y1: number, x2: number, y2: number) {
228
- warnDeprecatedPathMethod(
229
- "rQuadTo",
230
- "Use Skia.PathBuilder.Make().rQuadTo() instead."
231
- );
232
- this.ref.rQuadTo(x1, y1, x2, y2);
233
- return this;
234
- }
235
-
236
- conicTo(x1: number, y1: number, x2: number, y2: number, w: number) {
237
- warnDeprecatedPathMethod(
238
- "conicTo",
239
- "Use Skia.PathBuilder.Make().conicTo() instead."
240
- );
241
- this.ref.conicTo(x1, y1, x2, y2, w);
242
- return this;
243
- }
244
-
245
- rConicTo(x1: number, y1: number, x2: number, y2: number, w: number) {
246
- warnDeprecatedPathMethod(
247
- "rConicTo",
248
- "Use Skia.PathBuilder.Make().rConicTo() instead."
249
- );
250
- this.ref.rConicTo(x1, y1, x2, y2, w);
251
- return this;
252
- }
253
-
254
- cubicTo(
255
- cpx1: number,
256
- cpy1: number,
257
- cpx2: number,
258
- cpy2: number,
259
- x: number,
260
- y: number
261
- ) {
262
- warnDeprecatedPathMethod(
263
- "cubicTo",
264
- "Use Skia.PathBuilder.Make().cubicTo() instead."
265
- );
266
- this.ref.cubicTo(cpx1, cpy1, cpx2, cpy2, x, y);
267
- return this;
268
- }
269
-
270
- rCubicTo(
271
- cpx1: number,
272
- cpy1: number,
273
- cpx2: number,
274
- cpy2: number,
275
- x: number,
276
- y: number
277
- ) {
278
- warnDeprecatedPathMethod(
279
- "rCubicTo",
280
- "Use Skia.PathBuilder.Make().rCubicTo() instead."
281
- );
282
- this.ref.rCubicTo(cpx1, cpy1, cpx2, cpy2, x, y);
283
- return this;
284
- }
285
-
286
- close() {
287
- warnDeprecatedPathMethod(
288
- "close",
289
- "Use Skia.PathBuilder.Make().close() instead."
290
- );
291
- this.ref.close();
292
- return this;
293
- }
294
-
295
- reset() {
296
- warnDeprecatedPathMethod(
297
- "reset",
298
- "Use Skia.PathBuilder.Make().reset() instead."
299
- );
300
- // CK PathBuilder has no reset — recreate
301
- const newBuilder = new this.CanvasKit.PathBuilder();
302
- if (
303
- this.ref !== null &&
304
- typeof this.ref === "object" &&
305
- "delete" in this.ref &&
306
- typeof this.ref.delete === "function"
307
- ) {
308
- this.ref.delete();
309
- }
310
- this.ref = newBuilder;
311
- return this;
312
- }
313
-
314
- rewind() {
315
- warnDeprecatedPathMethod(
316
- "rewind",
317
- "Use Skia.PathBuilder.Make().reset() instead."
318
- );
319
- return this.reset();
320
- }
321
-
322
- arcToOval(
323
- oval: SkRect,
324
- startAngleInDegrees: number,
325
- sweepAngleInDegrees: number,
326
- forceMoveTo: boolean
327
- ) {
328
- warnDeprecatedPathMethod(
329
- "arcToOval",
330
- "Use Skia.PathBuilder.Make().arcToOval() instead."
331
- );
332
- this.ref.arcToOval(
333
- JsiSkRect.fromValue(this.CanvasKit, oval),
334
- startAngleInDegrees,
335
- sweepAngleInDegrees,
336
- forceMoveTo
337
- );
338
- return this;
339
- }
340
-
341
- arcToRotated(
342
- rx: number,
343
- ry: number,
344
- xAxisRotateInDegrees: number,
345
- useSmallArc: boolean,
346
- isCCW: boolean,
347
- x: number,
348
- y: number
349
- ) {
350
- warnDeprecatedPathMethod(
351
- "arcToRotated",
352
- "Use Skia.PathBuilder.Make().arcToRotated() instead."
353
- );
354
- this.ref.arcToRotated(
355
- rx,
356
- ry,
357
- xAxisRotateInDegrees,
358
- useSmallArc,
359
- isCCW,
360
- x,
361
- y
362
- );
363
- return this;
364
- }
365
-
366
- rArcTo(
367
- rx: number,
368
- ry: number,
369
- xAxisRotateInDegrees: number,
370
- useSmallArc: boolean,
371
- isCCW: boolean,
372
- dx: number,
373
- dy: number
374
- ) {
375
- warnDeprecatedPathMethod(
376
- "rArcTo",
377
- "Use Skia.PathBuilder.Make().rArcTo() instead."
378
- );
379
- this.ref.rArcTo(rx, ry, xAxisRotateInDegrees, useSmallArc, isCCW, dx, dy);
380
- return this;
381
- }
382
-
383
- arcToTangent(x1: number, y1: number, x2: number, y2: number, radius: number) {
384
- warnDeprecatedPathMethod(
385
- "arcToTangent",
386
- "Use Skia.PathBuilder.Make().arcToTangent() instead."
387
- );
388
- this.ref.arcToTangent(x1, y1, x2, y2, radius);
389
- return this;
390
- }
391
-
392
- setFillType(fill: FillType) {
393
- warnDeprecatedPathMethod(
394
- "setFillType",
395
- "Use Skia.PathBuilder.Make().setFillType() instead."
396
- );
397
- this.ref.setFillType(getEnum(this.CanvasKit, "FillType", fill));
398
- return this;
399
- }
400
-
401
- setIsVolatile(_volatile: boolean) {
402
- warnDeprecatedPathMethod(
403
- "setIsVolatile",
404
- "Use Skia.PathBuilder.Make().setIsVolatile() instead."
405
- );
406
- // Not supported in CK PathBuilder — no-op
407
- return this;
408
- }
409
-
410
- // ---- Mutable path operations (deprecated) ----
411
-
412
- offset(dx: number, dy: number) {
413
- warnDeprecatedPathMethod(
414
- "offset",
415
- "Use Skia.PathBuilder.Make().offset() instead."
416
- );
417
- this.ref.offset(dx, dy);
418
- return this;
419
- }
420
-
421
- transform(m: InputMatrix) {
422
- warnDeprecatedPathMethod(
423
- "transform",
424
- "Use Skia.PathBuilder.Make().transform() instead."
425
- );
426
- const matrix = toMatrix3x3(m);
427
- this.ref.transform(matrix);
428
- return this;
429
- }
430
-
431
- makeAsWinding() {
432
- warnDeprecatedPathMethod(
433
- "makeAsWinding",
434
- "Use Skia.Path.AsWinding(path) instead."
435
- );
436
- const path = this.asPath();
437
- const result = path.makeAsWinding();
438
- path.delete();
439
- if (result === null) {
440
- return null;
441
- }
442
- const old = this.ref;
443
- this.ref = new this.CanvasKit.PathBuilder(result);
444
- result.delete();
445
- old.delete();
446
- return this;
447
- }
448
-
449
- simplify() {
450
- warnDeprecatedPathMethod(
451
- "simplify",
452
- "Use Skia.Path.Simplify(path) instead."
453
- );
454
- const path = this.asPath();
455
- const result = path.makeSimplified();
456
- path.delete();
457
- if (result === null) {
458
- return false;
459
- }
460
- const old = this.ref;
461
- this.ref = new this.CanvasKit.PathBuilder(result);
462
- result.delete();
463
- old.delete();
464
- return true;
465
- }
466
-
467
- op(path: SkPath, op: PathOp) {
468
- warnDeprecatedPathMethod("op", "Use Skia.Path.MakeFromOp() instead.");
469
- const self = this.asPath();
470
- const other = JsiSkPath.fromValue<CKPathBuilder>(path).snapshot();
471
- const result = self.makeCombined(
472
- other,
473
- getEnum(this.CanvasKit, "PathOp", op)
474
- );
475
- self.delete();
476
- other.delete();
477
- if (result === null) {
478
- return false;
479
- }
480
- const old = this.ref;
481
- this.ref = new this.CanvasKit.PathBuilder(result);
482
- result.delete();
483
- old.delete();
484
- return true;
485
- }
486
-
487
- dash(on: number, off: number, phase: number) {
488
- warnDeprecatedPathMethod(
489
- "dash",
490
- "Use Skia.Path.Dash(path, on, off, phase) instead."
491
- );
492
- const path = this.asPath();
493
- const result = path.makeDashed(on, off, phase);
494
- path.delete();
495
- if (result === null) {
496
- return false;
497
- }
498
- const old = this.ref;
499
- this.ref = new this.CanvasKit.PathBuilder(result);
500
- result.delete();
501
- old.delete();
502
- return true;
503
- }
504
-
505
- stroke(opts?: StrokeOpts) {
506
- warnDeprecatedPathMethod(
507
- "stroke",
508
- "Use Skia.Path.Stroke(path, opts) instead."
509
- );
510
- const path = this.asPath();
511
- const result = path.makeStroked(
512
- opts === undefined
513
- ? undefined
514
- : {
515
- width: opts.width,
516
- // eslint-disable-next-line camelcase
517
- miter_limit: opts.miter_limit,
518
- precision: opts.precision,
519
- join: optEnum(this.CanvasKit, "StrokeJoin", opts.join),
520
- cap: optEnum(this.CanvasKit, "StrokeCap", opts.cap),
521
- }
522
- );
523
- path.delete();
524
- if (result === null) {
525
- return null;
526
- }
527
- const old = this.ref;
528
- this.ref = new this.CanvasKit.PathBuilder(result);
529
- result.delete();
530
- old.delete();
531
- return this;
532
- }
533
-
534
- trim(start: number, stop: number, isComplement: boolean) {
535
- warnDeprecatedPathMethod(
536
- "trim",
537
- "Use Skia.Path.Trim(path, start, end, isComplement) instead."
538
- );
539
- const startT = Math.min(Math.max(start, 0), 1);
540
- const stopT = Math.min(Math.max(stop, 0), 1);
541
- if (startT === 0 && stopT === 1 && !isComplement) {
542
- return this;
543
- }
544
- const path = this.asPath();
545
- const result = path.makeTrimmed(startT, stopT, isComplement);
546
- path.delete();
547
- if (result === null) {
548
- return null;
549
- }
550
- const old = this.ref;
551
- this.ref = new this.CanvasKit.PathBuilder(result);
552
- result.delete();
553
- old.delete();
554
- return this;
555
- }
556
-
557
74
  // ---- Query methods (use snapshot for read-only) ----
558
75
 
559
76
  countPoints() {
@@ -646,7 +163,7 @@ export class JsiSkPath
646
163
  return result;
647
164
  }
648
165
 
649
- interpolate(end: SkPath, weight: number, output?: SkPath): SkPath | null {
166
+ interpolate(end: SkPath, weight: number): SkPath | null {
650
167
  const p1 = this.asPath();
651
168
  const p2 = JsiSkPath.fromValue<CKPathBuilder>(end).snapshot();
652
169
  const path = this.CanvasKit.Path.MakeFromPathInterpolation(p1, p2, weight);
@@ -655,14 +172,6 @@ export class JsiSkPath
655
172
  if (path === null) {
656
173
  return null;
657
174
  }
658
- if (output) {
659
- const outRef = output as JsiSkPath;
660
- const old = outRef.ref;
661
- outRef.ref = new this.CanvasKit.PathBuilder(path);
662
- path.delete();
663
- old.delete();
664
- return output;
665
- }
666
175
  const result = new JsiSkPath(
667
176
  this.CanvasKit,
668
177
  new this.CanvasKit.PathBuilder(path)
@@ -1,8 +1,8 @@
1
1
  import type { CanvasKit, Surface } from "canvaskit-wasm";
2
2
 
3
- import type { SurfaceFactory } from "../types";
3
+ import type { SkSurface, SurfaceFactory } from "../types";
4
4
 
5
- import { Host } from "./Host";
5
+ import { Host, throwNotImplementedOnRNWeb } from "./Host";
6
6
  import { JsiSkSurface } from "./JsiSkSurface";
7
7
 
8
8
  export class JsiSkSurfaceFactory extends Host implements SurfaceFactory {
@@ -38,4 +38,8 @@ export class JsiSkSurfaceFactory extends Host implements SurfaceFactory {
38
38
  }
39
39
  return new JsiSkSurface(this.CanvasKit, surface);
40
40
  }
41
+
42
+ MakeFromNativeTexture(_pointer: bigint): SkSurface {
43
+ return throwNotImplementedOnRNWeb<SkSurface>();
44
+ }
41
45
  }
@@ -1,11 +1,10 @@
1
1
  import Rea from "../external/reanimated/ReanimatedProxy";
2
- import type { Skia, SkPicture } from "../skia/types";
2
+ import type { Skia } from "../skia/types";
3
3
  import {
4
4
  HAS_REANIMATED_3,
5
5
  HAS_REANIMATED_4,
6
6
  REANIMATED_VERSION_MAJOR,
7
7
  } from "../external/reanimated/renderHelpers";
8
- import type { JsiRecorder } from "../skia/types/Recorder";
9
8
 
10
9
  import { ReanimatedRecorder } from "./Recorder/ReanimatedRecorder";
11
10
  import { Container, StaticContainer } from "./StaticContainer";
@@ -17,67 +16,65 @@ import "../views/api";
17
16
  // create local reference for `strictGlobal` option in Worklets
18
17
  const { SkiaViewApi } = globalThis;
19
18
 
20
- const nativeDrawOnscreen = (
21
- nativeId: number,
22
- recorder: JsiRecorder,
23
- picture: SkPicture
24
- ) => {
25
- "worklet";
26
-
27
- //const start = performance.now();
28
- recorder.play(picture);
29
- //const end = performance.now();
30
- //console.log("Recording time: ", end - start);
31
- SkiaViewApi.setJsiProperty(nativeId, "picture", picture);
32
- };
33
-
19
+ /**
20
+ * Records the scene graph on the JS thread and hands the native recorder to
21
+ * the view, which owns it and replays it on every draw. The Reanimated mapper
22
+ * only pushes the shared values into that recorder through the view id: no
23
+ * Skia object is captured by a worklet, so nothing on the UI runtime holds
24
+ * native memory. The JS wrapper is disposed right after the handoff, so the
25
+ * view is the sole owner and the resources referenced by the recording
26
+ * (images, pictures) are released when the view replaces it or is torn down,
27
+ * not when a garbage collector gets around to a wrapper.
28
+ *
29
+ * Unmounting does not clear the view: the native view can outlive the React
30
+ * tree (exit animations, screen transitions) and keeps showing its last frame
31
+ * until it is torn down, which is when the recording is released.
32
+ */
34
33
  class NativeReanimatedContainer extends Container {
35
34
  private mapperId: number | null = null;
36
- private picture: SkPicture;
37
35
 
38
36
  constructor(
39
37
  Skia: Skia,
40
38
  private nativeId: number
41
39
  ) {
42
40
  super(Skia);
43
- this.picture = Skia.Picture.MakePicture(null)!;
44
41
  }
45
42
 
46
- unmount() {
47
- super.unmount();
43
+ private stopMapper() {
48
44
  if (this.mapperId !== null) {
49
- // The mapper closure retains the recorder and its resources (e.g.
50
- // images) on the UI runtime and keeps updating the picture of an
51
- // unmounted view — stop it or it leaks for the lifetime of the app.
52
45
  Rea.stopMapper(this.mapperId);
53
46
  this.mapperId = null;
54
47
  }
55
48
  }
56
49
 
50
+ unmount() {
51
+ super.unmount();
52
+ this.stopMapper();
53
+ }
54
+
57
55
  redraw() {
58
- if (this.mapperId !== null) {
59
- Rea.stopMapper(this.mapperId);
60
- this.mapperId = null;
61
- }
56
+ this.stopMapper();
62
57
  if (this.unmounted) {
63
58
  return;
64
59
  }
65
60
  const recorder = new ReanimatedRecorder(this.Skia);
66
- const { nativeId, picture } = this;
67
61
  visit(recorder, this.root);
68
62
  const sharedValues = recorder.getSharedValues();
69
- const sharedRecorder = recorder.getRecorder();
70
- // Draw first frame
71
- Rea.runOnUI(() => {
72
- "worklet";
73
- nativeDrawOnscreen(nativeId, sharedRecorder, picture);
74
- })();
75
- // Animate
63
+ const { nativeId } = this;
64
+ const nativeRecorder = recorder.getRecorder();
65
+ // stopMapper() only takes effect on the UI thread later, so the previous
66
+ // mapper can still fire after the new recording is installed. Tagging the
67
+ // updates with the recording id lets the view ignore them.
68
+ const recorderId = nativeRecorder.getId();
69
+ // The view takes ownership of the recorder and draws the first frame. The
70
+ // wrapper is disposed right away: it would otherwise co-own the recording
71
+ // until the JS garbage collector finalizes it.
72
+ SkiaViewApi.setJsiProperty(nativeId, "recorder", nativeRecorder);
73
+ nativeRecorder.dispose();
76
74
  if (sharedValues.length > 0) {
77
75
  this.mapperId = Rea.startMapper(() => {
78
76
  "worklet";
79
- sharedRecorder.applyUpdates(sharedValues);
80
- nativeDrawOnscreen(nativeId, sharedRecorder, picture);
77
+ SkiaViewApi.applyUpdates(nativeId, recorderId, sharedValues);
81
78
  }, sharedValues);
82
79
  }
83
80
  }
@@ -58,6 +58,10 @@ global.SkiaViewApi = {
58
58
  // The view may already have unmounted (e.g. a trailing animation frame).
59
59
  this.views[`${nativeId}`]?.redraw();
60
60
  },
61
+ applyUpdates() {
62
+ // Web canvases are driven from JS (see Container.web.ts); there is no
63
+ // view-owned recorder to update.
64
+ },
61
65
  makeImageSnapshot(nativeId: number, rect?: SkRect) {
62
66
  const view = this.views[`${nativeId}`];
63
67
  if (!view) {