@shopify/react-native-skia 0.1.141 → 0.1.142

Sign up to get free protection for your applications and to get access to all the features.
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,