@shopify/react-native-skia 0.1.141 → 0.1.142

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 (114) hide show
  1. package/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp +2 -2
  2. package/android/cpp/rnskia-android/RNSkDrawViewImpl.h +1 -1
  3. package/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp +15 -16
  4. package/android/cpp/rnskia-android/SkiaOpenGLRenderer.h +2 -2
  5. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +69 -27
  6. package/cpp/rnskia/RNSkDrawView.cpp +66 -66
  7. package/cpp/rnskia/RNSkDrawView.h +22 -6
  8. package/cpp/rnskia/RNSkJsiViewApi.h +2 -2
  9. package/cpp/rnskia/values/RNSkComputedValue.h +10 -7
  10. package/cpp/rnskia/values/RNSkReadonlyValue.h +21 -2
  11. package/cpp/rnskia/values/RNSkValue.h +1 -0
  12. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +1 -1
  13. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +2 -2
  14. package/ios/RNSkia-iOS/SkiaDrawView.mm +4 -0
  15. package/lib/commonjs/mock/index.js +3 -1
  16. package/lib/commonjs/mock/index.js.map +1 -1
  17. package/lib/commonjs/renderer/DependencyManager.js +1 -1
  18. package/lib/commonjs/renderer/DependencyManager.js.map +1 -1
  19. package/lib/commonjs/renderer/processors/Animations/Animations.js +18 -5
  20. package/lib/commonjs/renderer/processors/Animations/Animations.js.map +1 -1
  21. package/lib/commonjs/skia/core/Data.js +10 -22
  22. package/lib/commonjs/skia/core/Data.js.map +1 -1
  23. package/lib/commonjs/skia/core/Font.js +2 -3
  24. package/lib/commonjs/skia/core/Font.js.map +1 -1
  25. package/lib/commonjs/skia/core/Image.js.map +1 -1
  26. package/lib/commonjs/skia/core/SVG.js.map +1 -1
  27. package/lib/commonjs/skia/core/Typeface.js.map +1 -1
  28. package/lib/commonjs/skia/types/Data/Data.js +5 -0
  29. package/lib/commonjs/skia/types/Data/Data.js.map +1 -1
  30. package/lib/commonjs/skia/web/JsiSkCanvas.js +9 -7
  31. package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
  32. package/lib/commonjs/skia/web/JsiSkPath.js +7 -5
  33. package/lib/commonjs/skia/web/JsiSkPath.js.map +1 -1
  34. package/lib/commonjs/skia/web/JsiSkRRect.js +8 -0
  35. package/lib/commonjs/skia/web/JsiSkRRect.js.map +1 -1
  36. package/lib/commonjs/skia/web/JsiSkRect.js +2 -2
  37. package/lib/commonjs/skia/web/JsiSkRect.js.map +1 -1
  38. package/lib/commonjs/values/hooks/useComputedValue.js +6 -2
  39. package/lib/commonjs/values/hooks/useComputedValue.js.map +1 -1
  40. package/lib/commonjs/values/index.js +13 -0
  41. package/lib/commonjs/values/index.js.map +1 -1
  42. package/lib/commonjs/values/selector.js +24 -0
  43. package/lib/commonjs/values/selector.js.map +1 -0
  44. package/lib/commonjs/values/web/RNSkComputedValue.js +8 -0
  45. package/lib/commonjs/values/web/RNSkComputedValue.js.map +1 -1
  46. package/lib/commonjs/values/web/RNSkReadonlyValue.js +4 -0
  47. package/lib/commonjs/values/web/RNSkReadonlyValue.js.map +1 -1
  48. package/lib/module/mock/index.js +2 -1
  49. package/lib/module/mock/index.js.map +1 -1
  50. package/lib/module/renderer/DependencyManager.js +2 -2
  51. package/lib/module/renderer/DependencyManager.js.map +1 -1
  52. package/lib/module/renderer/processors/Animations/Animations.js +13 -4
  53. package/lib/module/renderer/processors/Animations/Animations.js.map +1 -1
  54. package/lib/module/skia/core/Data.js +10 -20
  55. package/lib/module/skia/core/Data.js.map +1 -1
  56. package/lib/module/skia/core/Font.js +2 -3
  57. package/lib/module/skia/core/Font.js.map +1 -1
  58. package/lib/module/skia/core/Image.js.map +1 -1
  59. package/lib/module/skia/core/SVG.js.map +1 -1
  60. package/lib/module/skia/core/Typeface.js.map +1 -1
  61. package/lib/module/skia/types/Data/Data.js +1 -1
  62. package/lib/module/skia/types/Data/Data.js.map +1 -1
  63. package/lib/module/skia/web/JsiSkCanvas.js +8 -7
  64. package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
  65. package/lib/module/skia/web/JsiSkPath.js +6 -5
  66. package/lib/module/skia/web/JsiSkPath.js.map +1 -1
  67. package/lib/module/skia/web/JsiSkRRect.js +8 -0
  68. package/lib/module/skia/web/JsiSkRRect.js.map +1 -1
  69. package/lib/module/skia/web/JsiSkRect.js +2 -2
  70. package/lib/module/skia/web/JsiSkRect.js.map +1 -1
  71. package/lib/module/values/hooks/useComputedValue.js +7 -3
  72. package/lib/module/values/hooks/useComputedValue.js.map +1 -1
  73. package/lib/module/values/index.js +1 -0
  74. package/lib/module/values/index.js.map +1 -1
  75. package/lib/module/values/selector.js +15 -0
  76. package/lib/module/values/selector.js.map +1 -0
  77. package/lib/module/values/web/RNSkComputedValue.js +8 -0
  78. package/lib/module/values/web/RNSkComputedValue.js.map +1 -1
  79. package/lib/module/values/web/RNSkReadonlyValue.js +4 -0
  80. package/lib/module/values/web/RNSkReadonlyValue.js.map +1 -1
  81. package/lib/typescript/src/renderer/processors/Animations/Animations.d.ts +7 -2
  82. package/lib/typescript/src/skia/core/Data.d.ts +3 -5
  83. package/lib/typescript/src/skia/core/Font.d.ts +2 -2
  84. package/lib/typescript/src/skia/core/Image.d.ts +2 -2
  85. package/lib/typescript/src/skia/core/SVG.d.ts +2 -2
  86. package/lib/typescript/src/skia/core/Typeface.d.ts +2 -2
  87. package/lib/typescript/src/skia/types/Data/Data.d.ts +10 -3
  88. package/lib/typescript/src/skia/web/JsiSkRRect.d.ts +1 -0
  89. package/lib/typescript/src/skia/web/JsiSkRect.d.ts +1 -1
  90. package/lib/typescript/src/values/index.d.ts +1 -0
  91. package/lib/typescript/src/values/selector.d.ts +14 -0
  92. package/lib/typescript/src/values/types.d.ts +4 -0
  93. package/lib/typescript/src/values/web/RNSkComputedValue.d.ts +1 -0
  94. package/lib/typescript/src/values/web/RNSkReadonlyValue.d.ts +1 -0
  95. package/package.json +2 -2
  96. package/src/mock/index.ts +2 -1
  97. package/src/renderer/DependencyManager.tsx +5 -2
  98. package/src/renderer/processors/Animations/Animations.ts +27 -5
  99. package/src/skia/core/Data.ts +20 -51
  100. package/src/skia/core/Font.ts +4 -5
  101. package/src/skia/core/Image.ts +2 -2
  102. package/src/skia/core/SVG.ts +2 -2
  103. package/src/skia/core/Typeface.ts +2 -2
  104. package/src/skia/types/Data/Data.ts +11 -1
  105. package/src/skia/web/JsiSkCanvas.ts +22 -10
  106. package/src/skia/web/JsiSkPath.ts +14 -5
  107. package/src/skia/web/JsiSkRRect.ts +11 -0
  108. package/src/skia/web/JsiSkRect.ts +2 -5
  109. package/src/values/hooks/useComputedValue.ts +6 -3
  110. package/src/values/index.ts +1 -0
  111. package/src/values/selector.ts +24 -0
  112. package/src/values/types.ts +4 -0
  113. package/src/values/web/RNSkComputedValue.ts +6 -0
  114. package/src/values/web/RNSkReadonlyValue.ts +4 -0
@@ -65,9 +65,9 @@ namespace RNSkia {
65
65
  requestRedraw();
66
66
  }
67
67
 
68
- void RNSkDrawViewImpl::drawPicture(const sk_sp <SkPicture> picture) {
68
+ void RNSkDrawViewImpl::renderToSkiaCanvas(const std::function<void(SkCanvas*)>& cb) {
69
69
  if(_renderer != nullptr) {
70
- _renderer->run(picture, _scaledWidth, _scaledHeight);
70
+ _renderer->run(cb, _scaledWidth, _scaledHeight);
71
71
  }
72
72
  }
73
73
  }
@@ -32,7 +32,7 @@ namespace RNSkia {
32
32
 
33
33
  float getScaledHeight() override { return _scaledHeight; };
34
34
 
35
- void drawPicture(const sk_sp <SkPicture> picture) override;
35
+ void renderToSkiaCanvas(const std::function<void(SkCanvas*)>&) override;
36
36
 
37
37
  private:
38
38
  bool createSkiaSurface();
@@ -20,12 +20,12 @@ namespace RNSkia
20
20
  return threadContexts.at(threadId);
21
21
  }
22
22
 
23
- SkiaOpenGLRenderer::SkiaOpenGLRenderer(ANativeWindow *surface, size_t renderId):
24
- _surfaceTexture(surface),
25
- _renderId(renderId) {
23
+ SkiaOpenGLRenderer::SkiaOpenGLRenderer(ANativeWindow *surface, size_t renderId) : _surfaceTexture(surface),
24
+ _renderId(renderId)
25
+ {
26
26
  }
27
27
 
28
- void SkiaOpenGLRenderer::run(const sk_sp<SkPicture> picture, int width, int height)
28
+ void SkiaOpenGLRenderer::run(const std::function<void(SkCanvas *)> &cb, int width, int height)
29
29
  {
30
30
  switch (_renderState)
31
31
  {
@@ -51,7 +51,7 @@ namespace RNSkia
51
51
  return;
52
52
  }
53
53
 
54
- if (picture != nullptr)
54
+ if (cb != nullptr)
55
55
  {
56
56
  // Reset Skia Context since it might be modified by another Skia View during
57
57
  // rendering.
@@ -62,11 +62,10 @@ namespace RNSkia
62
62
  glClear(GL_COLOR_BUFFER_BIT);
63
63
 
64
64
  // Draw picture into surface
65
- _skSurface->getCanvas()->drawPicture(picture);
65
+ cb(_skSurface->getCanvas());
66
66
 
67
67
  // Flush
68
- _skSurface->getCanvas()->flush();
69
- getThreadDrawingContext()->skContext->flush();
68
+ _skSurface->flush();
70
69
 
71
70
  if (!eglSwapBuffers(getThreadDrawingContext()->glDisplay, _glSurface))
72
71
  {
@@ -180,10 +179,10 @@ namespace RNSkia
180
179
  EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
181
180
 
182
181
  getThreadDrawingContext()->glContext = eglCreateContext(
183
- getThreadDrawingContext()->glDisplay,
184
- getThreadDrawingContext()->glConfig,
185
- NULL,
186
- contextAttribs);
182
+ getThreadDrawingContext()->glDisplay,
183
+ getThreadDrawingContext()->glConfig,
184
+ NULL,
185
+ contextAttribs);
187
186
 
188
187
  if (getThreadDrawingContext()->glContext == EGL_NO_CONTEXT)
189
188
  {
@@ -239,10 +238,10 @@ namespace RNSkia
239
238
  // Create the opengl surface
240
239
  _glSurface =
241
240
  eglCreateWindowSurface(
242
- getThreadDrawingContext()->glDisplay,
243
- getThreadDrawingContext()->glConfig,
244
- _surfaceTexture,
245
- nullptr);
241
+ getThreadDrawingContext()->glDisplay,
242
+ getThreadDrawingContext()->glConfig,
243
+ _surfaceTexture,
244
+ nullptr);
246
245
 
247
246
  if (_glSurface == EGL_NO_SURFACE)
248
247
  {
@@ -52,11 +52,11 @@ namespace RNSkia
52
52
  * renderer. All OpenGL/Skia context operations are done on a separate thread which must
53
53
  * be the same for all calls to the render method.
54
54
  *
55
- * @param picture Picture to render, can be nullptr, then no rendering will be performed
55
+ * @param callback Render callback
56
56
  * @param width Width of surface to render if there is a picture
57
57
  * @param height Height of surface to render if there is a picture
58
58
  */
59
- void run(const sk_sp<SkPicture> picture, int width, int height);
59
+ void run(const std::function<void(SkCanvas*)> &cb, int width, int height);
60
60
 
61
61
  /**
62
62
  * Sets the state to finishing. Next time the renderer will be called it
@@ -2,7 +2,6 @@ package com.shopify.reactnative.skia;
2
2
 
3
3
  import android.content.Context;
4
4
  import android.graphics.SurfaceTexture;
5
- import android.util.Log;
6
5
  import android.view.Surface;
7
6
  import android.view.TextureView;
8
7
  import android.view.MotionEvent;
@@ -52,41 +51,84 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
52
51
 
53
52
  void onViewRemoved() {
54
53
  mViewRemoved = true;
54
+ // We can only reset the native side when the view was removed from screen.
55
+ // releasing the surface can also be done when the view is hidden and then
56
+ // we should only release the surface - and keep the native part around.
57
+ if(mSurface == null) {
58
+ mHybridData.resetNative();
59
+ }
55
60
  }
56
61
 
57
62
  @Override
58
63
  public boolean onTouchEvent(MotionEvent ev) {
59
- int action = ev.getAction();
60
- int count = ev.getPointerCount();
64
+ // https://developer.android.com/training/gestures/multi
65
+ int action = ev.getActionMasked();
66
+
61
67
  MotionEvent.PointerCoords r = new MotionEvent.PointerCoords();
62
- double[] points = new double[count*5];
63
- for (int i = 0; i < count; i++) {
64
- ev.getPointerCoords(i, r);
65
- points[i] = r.x;
66
- points[i+1] = r.y;
67
- points[i+2] = ev.getPressure(i);
68
- switch (action) {
69
- case MotionEvent.ACTION_DOWN:
70
- case MotionEvent.ACTION_POINTER_DOWN:
71
- points[i+3] = 0;
72
- break;
73
- case MotionEvent.ACTION_MOVE:
74
- points[i+3] = 1;
75
- break;
76
- case MotionEvent.ACTION_UP:
77
- case MotionEvent.ACTION_POINTER_UP:
78
- points[i+3] = 2;
79
- break;
80
- case MotionEvent.ACTION_CANCEL:
81
- points[i+3] = 3;
82
- break;
68
+
69
+ double[] points;
70
+
71
+ // If this is a pointer_up/down event we need to handle it a bit specialized
72
+ switch (action) {
73
+ case MotionEvent.ACTION_POINTER_DOWN:
74
+ case MotionEvent.ACTION_POINTER_UP: {
75
+ points = new double[5];
76
+ int pointerIndex = ev.getActionIndex();
77
+ ev.getPointerCoords(pointerIndex, r);
78
+ points[0] = r.x;
79
+ points[1] = r.y;
80
+ points[2] = ev.getPressure(pointerIndex);
81
+ points[3] = motionActionToType(action);
82
+ points[4] = ev.getPointerId(pointerIndex);
83
+
84
+ updateTouchPoints(points);
85
+
86
+ break;
87
+ }
88
+ default: {
89
+ // For the rest we can just handle it like expected
90
+ int count = ev.getPointerCount();
91
+ int pointerIndex = 0;
92
+ points = new double[5 * count];
93
+ for (int i = 0; i < count; i++) {
94
+ ev.getPointerCoords(i, r);
95
+ points[pointerIndex++] = r.x;
96
+ points[pointerIndex++] = r.y;
97
+ points[pointerIndex++] = ev.getPressure(i);
98
+ points[pointerIndex++] = motionActionToType(action);
99
+ points[pointerIndex++] = ev.getPointerId(i);
100
+ }
101
+
102
+ updateTouchPoints(points);
103
+
104
+ break;
83
105
  }
84
- points[i+4] = ev.getPointerId(i);
85
106
  }
86
- updateTouchPoints(points);
107
+
87
108
  return true;
88
109
  }
89
110
 
111
+ private static int motionActionToType(int action) {
112
+ int actionType = 3;
113
+ switch (action) {
114
+ case MotionEvent.ACTION_DOWN:
115
+ case MotionEvent.ACTION_POINTER_DOWN:
116
+ actionType = 0;
117
+ break;
118
+ case MotionEvent.ACTION_MOVE:
119
+ actionType = 1;
120
+ break;
121
+ case MotionEvent.ACTION_UP:
122
+ case MotionEvent.ACTION_POINTER_UP:
123
+ actionType = 2;
124
+ break;
125
+ case MotionEvent.ACTION_CANCEL:
126
+ actionType = 3;
127
+ break;
128
+ }
129
+ return actionType;
130
+ }
131
+
90
132
  @Override
91
133
  public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
92
134
  mSurface = new Surface(surface);
@@ -104,7 +146,7 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
104
146
  // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture)
105
147
  // Invoked when the specified SurfaceTexture is about to be destroyed. If returns true,
106
148
  // no rendering should happen inside the surface texture after this method is invoked.
107
- // If returns false, the client needs to call SurfaceTexture#release().
149
+ // When returning false, the client needs to call SurfaceTexture#release().
108
150
  return false;
109
151
  }
110
152
 
@@ -54,7 +54,63 @@ void RNSkDrawView::setNativeId(size_t nativeId) {
54
54
  beginDrawingLoop();
55
55
  }
56
56
 
57
- void RNSkDrawView::setDrawCallback(std::shared_ptr<jsi::Function> callback) {
57
+ void RNSkDrawView::callJsDrawCallback(int width, int height, double timestamp) {
58
+ if(_drawCallback == nullptr) {
59
+ return;
60
+ }
61
+
62
+ // Reset timing info
63
+ _jsTimingInfo.reset();
64
+ _gpuTimingInfo.reset();
65
+
66
+ auto runtime = getPlatformContext()->getJsRuntime();
67
+
68
+ // Update info parameter
69
+ _infoObject->beginDrawOperation(width, height, timestamp);
70
+
71
+ // Set up arguments array
72
+ std::vector<jsi::Value> args(2);
73
+ args[0] = jsi::Object::createFromHostObject(*runtime, _jsiCanvas);
74
+ args[1] = jsi::Object::createFromHostObject(*runtime, _infoObject);
75
+
76
+ // To be able to call the drawing function we'll wrap it once again
77
+ _drawCallback->call(*runtime,
78
+ static_cast<const jsi::Value *>(args.data()),
79
+ (size_t)2);
80
+
81
+ // Reset touches
82
+ _infoObject->endDrawOperation();
83
+
84
+ // Draw debug overlays
85
+ if (_showDebugOverlay) {
86
+
87
+ // Display average rendering timer
88
+ auto jsAvg = _jsTimingInfo.getAverage();
89
+ //auto jsFps = _jsTimingInfo.getFps();
90
+
91
+ auto gpuAvg = _gpuTimingInfo.getAverage();
92
+ //auto gpuFps = _gpuTimingInfo.getFps();
93
+
94
+ auto total = jsAvg + gpuAvg;
95
+
96
+ // Build string
97
+ std::ostringstream stream;
98
+ stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms";
99
+
100
+ std::string debugString = stream.str();
101
+
102
+ // Set up debug font/paints
103
+ auto font = SkFont();
104
+ font.setSize(14);
105
+ auto paint = SkPaint();
106
+ paint.setColor(SkColors::kRed);
107
+ _jsiCanvas->getCanvas()->drawSimpleText(
108
+ debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8,
109
+ 18, font, paint);
110
+ }
111
+ }
112
+
113
+ void RNSkDrawView::setDrawCallback(std::shared_ptr<FunctionWrapper> callback) {
58
114
 
59
115
  if (callback == nullptr) {
60
116
  _drawCallback = nullptr;
@@ -62,69 +118,9 @@ void RNSkDrawView::setDrawCallback(std::shared_ptr<jsi::Function> callback) {
62
118
  endDrawingLoop();
63
119
  return;
64
120
  }
65
-
66
- // Reset timing info
67
- _jsTimingInfo.reset();
68
- _gpuTimingInfo.reset();
69
-
70
- // Create draw drawCallback wrapper
71
- _drawCallback = std::make_shared<RNSkDrawCallback>(
72
- [weakSelf = weak_from_this(),
73
- callback = std::move(callback)](std::shared_ptr<JsiSkCanvas> canvas,
74
- int width,
75
- int height,
76
- double timestamp,
77
- std::shared_ptr<RNSkPlatformContext> context) {
78
-
79
- auto self = weakSelf.lock();
80
- if(self) {
81
- auto runtime = context->getJsRuntime();
82
-
83
- // Update info parameter
84
- self->_infoObject->beginDrawOperation(width, height, timestamp);
85
-
86
- // Set up arguments array
87
- std::vector<jsi::Value> args(2);
88
- args[0] = jsi::Object::createFromHostObject(*runtime, canvas);
89
- args[1] = jsi::Object::createFromHostObject(*runtime, self->_infoObject);
90
-
91
- // To be able to call the drawing function we'll wrap it once again
92
- callback->call(*runtime,
93
- static_cast<const jsi::Value *>(args.data()),
94
- (size_t)2);
95
-
96
- // Reset touches
97
- self->_infoObject->endDrawOperation();
98
-
99
- // Draw debug overlays
100
- if (self->_showDebugOverlay) {
101
-
102
- // Display average rendering timer
103
- auto jsAvg = self->_jsTimingInfo.getAverage();
104
- //auto jsFps = _jsTimingInfo.getFps();
105
-
106
- auto gpuAvg = self->_gpuTimingInfo.getAverage();
107
- //auto gpuFps = _gpuTimingInfo.getFps();
108
-
109
- auto total = jsAvg + gpuAvg;
110
-
111
- // Build string
112
- std::ostringstream stream;
113
- stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms";
114
-
115
- std::string debugString = stream.str();
116
-
117
- // Set up debug font/paints
118
- auto font = SkFont();
119
- font.setSize(14);
120
- auto paint = SkPaint();
121
- paint.setColor(SkColors::kRed);
122
- canvas->getCanvas()->drawSimpleText(
123
- debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8,
124
- 18, font, paint);
125
- }
126
- }
127
- });
121
+
122
+ // Save callback
123
+ _drawCallback = callback;
128
124
 
129
125
  // Request redraw
130
126
  requestRedraw();
@@ -144,7 +140,7 @@ void RNSkDrawView::drawInCanvas(std::shared_ptr<JsiSkCanvas> canvas,
144
140
  skCanvas->scale(pd, pd);
145
141
 
146
142
  // Call draw function.
147
- (*_drawCallback)(canvas, width / pd, height / pd, time, _platformContext);
143
+ callJsDrawCallback(width / pd, height / pd, time);
148
144
 
149
145
  // Restore and flush canvas
150
146
  skCanvas->restore();
@@ -203,6 +199,8 @@ void RNSkDrawView::performDraw() {
203
199
 
204
200
  // Finish drawing operations
205
201
  auto p = recorder.finishRecordingAsPicture();
202
+
203
+ _jsiCanvas->setCanvas(nullptr);
206
204
 
207
205
  // Calculate duration
208
206
  _jsTimingInfo.stopTiming();
@@ -217,7 +215,9 @@ void RNSkDrawView::performDraw() {
217
215
  if (self) {
218
216
  // Draw the picture recorded on the real GPU canvas
219
217
  self->_gpuTimingInfo.beginTiming();
220
- self->drawPicture(p);
218
+ self->renderToSkiaCanvas([p = std::move(p)](SkCanvas* canvas) {
219
+ canvas->drawPicture(p);
220
+ });
221
221
  self->_gpuTimingInfo.stopTiming();
222
222
  }
223
223
  // Unlock GPU drawing
@@ -16,7 +16,7 @@
16
16
  #pragma clang diagnostic push
17
17
  #pragma clang diagnostic ignored "-Wdocumentation"
18
18
 
19
- #include <SkRefCnt.h>
19
+ #include <SkCanvas.h>
20
20
 
21
21
  #pragma clang diagnostic pop
22
22
 
@@ -33,6 +33,16 @@ using RNSkDrawCallback =
33
33
 
34
34
  enum RNSkDrawingMode { Default, Continuous };
35
35
 
36
+ class FunctionWrapper {
37
+ public:
38
+ FunctionWrapper(jsi::Function &&func): _func(std::move(func)) {}
39
+ jsi::Value call(jsi::Runtime& runtime, const jsi::Value* args, size_t count) {
40
+ return _func.call(runtime, args, count);
41
+ }
42
+ private:
43
+ jsi::Function _func;
44
+ };
45
+
36
46
  class RNSkDrawView: public std::enable_shared_from_this<RNSkDrawView> {
37
47
  public:
38
48
  /**
@@ -60,7 +70,7 @@ public:
60
70
  /**
61
71
  * Installs the draw callback for the view
62
72
  */
63
- void setDrawCallback(std::shared_ptr<jsi::Function> callback);
73
+ void setDrawCallback(std::shared_ptr<FunctionWrapper> callback);
64
74
 
65
75
  /**
66
76
  Sets the native id of the view
@@ -105,9 +115,9 @@ protected:
105
115
  virtual float getScaledHeight() = 0;
106
116
 
107
117
  /**
108
- Override to render picture to GPU
118
+ Override to render to a canvas
109
119
  */
110
- virtual void drawPicture(const sk_sp<SkPicture> picture) = 0;
120
+ virtual void renderToSkiaCanvas(const std::function<void(SkCanvas*)>&) = 0;
111
121
 
112
122
  /**
113
123
  * @return The platformcontext
@@ -116,7 +126,13 @@ protected:
116
126
  return _platformContext;
117
127
  }
118
128
 
119
- private:
129
+ private:
130
+ /**
131
+ * Calls the JS draw callback. This is the JS function that does the actual drawing so this
132
+ * method must be called from the JS thread.
133
+ */
134
+ void callJsDrawCallback(int width, int height, double timestamp);
135
+
120
136
  /**
121
137
  Starts beginDrawCallback loop if the drawing mode is continuous
122
138
  */
@@ -143,7 +159,7 @@ private:
143
159
  /**
144
160
  * Stores the draw drawCallback
145
161
  */
146
- std::shared_ptr<RNSkDrawCallback> _drawCallback;
162
+ std::shared_ptr<FunctionWrapper> _drawCallback;
147
163
 
148
164
  /**
149
165
  * Stores a pointer to the jsi wrapper for the canvas. The reason for
@@ -19,7 +19,7 @@ using CallbackInfo = struct CallbackInfo {
19
19
  drawCallback = nullptr;
20
20
  view = nullptr;
21
21
  }
22
- std::shared_ptr<jsi::Function> drawCallback;
22
+ std::shared_ptr<FunctionWrapper> drawCallback;
23
23
  std::shared_ptr<RNSkDrawView> view;
24
24
  };
25
25
 
@@ -61,7 +61,7 @@ public:
61
61
  if (arguments[1].isUndefined()) {
62
62
  info->drawCallback = nullptr;
63
63
  } else {
64
- info->drawCallback = std::make_shared<jsi::Function>(
64
+ info->drawCallback = std::make_shared<FunctionWrapper>(
65
65
  arguments[1].asObject(runtime).asFunction(runtime));
66
66
  }
67
67
 
@@ -43,6 +43,16 @@ public:
43
43
  _callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
44
44
  }
45
45
 
46
+ void invalidate() override {
47
+ RNSkReadonlyValue::invalidate();
48
+
49
+ // Unregister listeners
50
+ for(const auto &unsubscribe: _unsubscribers) {
51
+ unsubscribe();
52
+ }
53
+ _unsubscribers.clear();
54
+ }
55
+
46
56
  void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) {
47
57
  // Save dependencies
48
58
  std::vector<std::shared_ptr<RNSkReadonlyValue>> dependencies;
@@ -80,13 +90,6 @@ public:
80
90
  dependencyUpdated(runtime);
81
91
  }
82
92
 
83
- virtual ~RNSkComputedValue() {
84
- // Unregister listeners
85
- for(const auto &unsubscribe: _unsubscribers) {
86
- unsubscribe();
87
- }
88
- }
89
-
90
93
  private:
91
94
  void dependencyUpdated(jsi::Runtime &runtime) {
92
95
  // Calculate new value
@@ -30,7 +30,9 @@ public:
30
30
  _valueHolder(std::make_unique<JsiSimpleValueWrapper>(*platformContext->getJsRuntime()))
31
31
  { }
32
32
 
33
- virtual ~RNSkReadonlyValue() { }
33
+ virtual ~RNSkReadonlyValue() {
34
+ invalidate();
35
+ }
34
36
 
35
37
  JSI_PROPERTY_GET(__typename__) {
36
38
  return jsi::String::createFromUtf8(runtime, "RNSkValue");
@@ -68,7 +70,15 @@ public:
68
70
  });
69
71
  }
70
72
 
71
- JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener))
73
+
74
+
75
+ JSI_HOST_FUNCTION(__invalidate) {
76
+ invalidate();
77
+ return jsi::Value::undefined();
78
+ }
79
+
80
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener),
81
+ JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate))
72
82
 
73
83
  /**
74
84
  * Adds a callback that will be called whenever the value changes
@@ -102,6 +112,15 @@ public:
102
112
  }
103
113
  }
104
114
 
115
+ /**
116
+ Override to implement invalidation logic for the value. In the base class this function
117
+ clears all subscribers.
118
+ */
119
+ virtual void invalidate() {
120
+ std::lock_guard<std::mutex> lock(_mutex);
121
+ _listeners.clear();
122
+ }
123
+
105
124
  jsi::Value getCurrent(jsi::Runtime &runtime) {
106
125
  return _valueHolder->getCurrent(runtime);
107
126
  }
@@ -72,6 +72,7 @@ public:
72
72
 
73
73
  JSI_EXPORT_FUNCTIONS(
74
74
  JSI_EXPORT_FUNC(RNSkValue, addListener),
75
+ JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate)
75
76
  )
76
77
 
77
78
  private:
@@ -32,7 +32,7 @@ protected:
32
32
  float getScaledHeight() override { return _height * _context->getPixelDensity(); };
33
33
 
34
34
  private:
35
- void drawPicture(const sk_sp<SkPicture> picture) override;
35
+ void renderToSkiaCanvas(const std::function<void(SkCanvas*)>& cb) override;
36
36
  bool createSkiaSurface();
37
37
 
38
38
  int _nativeId;
@@ -60,7 +60,7 @@ void RNSkDrawViewImpl::setSize(int width, int height) {
60
60
  requestRedraw();
61
61
  }
62
62
 
63
- void RNSkDrawViewImpl::drawPicture(const sk_sp<SkPicture> picture) {
63
+ void RNSkDrawViewImpl::renderToSkiaCanvas(const std::function<void(SkCanvas*)>& cb) {
64
64
  if(_width == -1 && _height == -1) {
65
65
  return;
66
66
  }
@@ -103,7 +103,7 @@ void RNSkDrawViewImpl::drawPicture(const sk_sp<SkPicture> picture) {
103
103
  }
104
104
 
105
105
  skSurface->getCanvas()->clear(SK_AlphaTRANSPARENT);
106
- skSurface->getCanvas()->drawPicture(picture);
106
+ cb(skSurface->getCanvas());
107
107
 
108
108
  id<MTLCommandBuffer> commandBuffer([_commandQueue commandBuffer]);
109
109
  [commandBuffer presentDrawable:currentDrawable];
@@ -73,6 +73,10 @@
73
73
  if(_manager != nullptr && _nativeId != 0) {
74
74
  _manager->unregisterSkiaDrawView(_nativeId);
75
75
  }
76
+
77
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil];
78
+
79
+ assert(_impl == nullptr);
76
80
  }
77
81
 
78
82
  #pragma mark Layout
@@ -9,6 +9,8 @@ var Values = _interopRequireWildcard(require("../values/web"));
9
9
 
10
10
  var ValuesHooks = _interopRequireWildcard(require("../values/hooks"));
11
11
 
12
+ var _selector = require("../values/selector");
13
+
12
14
  var BaseSkia = _interopRequireWildcard(require("../skia/types"));
13
15
 
14
16
  var _useSharedValueEffect = require("../external/reanimated/useSharedValueEffect");
@@ -64,7 +66,6 @@ const Mock = {
64
66
  Skia,
65
67
  ...BaseSkia,
66
68
  // 2. Hooks
67
- useDataCollection: Noop,
68
69
  useRawData: Noop,
69
70
  useData: Noop,
70
71
  useFont: Noop,
@@ -113,6 +114,7 @@ const Mock = {
113
114
  // ValueExports
114
115
  ...Values,
115
116
  ...ValuesHooks,
117
+ Selector: _selector.Selector,
116
118
  // Animations
117
119
  ...timingFunctions,
118
120
  ...springFunctions,