@shopify/react-native-skia 0.1.120 → 0.1.123

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. package/android/CMakeLists.txt +33 -17
  2. package/android/build.gradle +81 -34
  3. package/android/cpp/jni/JniSkiaDrawView.cpp +14 -71
  4. package/android/cpp/jni/JniSkiaManager.cpp +1 -1
  5. package/android/cpp/jni/include/JniSkiaDrawView.h +18 -22
  6. package/android/cpp/jni/include/JniSkiaManager.h +4 -4
  7. package/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp +68 -0
  8. package/android/cpp/rnskia-android/RNSkDrawViewImpl.h +48 -0
  9. package/android/cpp/{jni/include/JniPlatformContextWrapper.h → rnskia-android/RNSkPlatformContextImpl.h} +4 -4
  10. package/android/cpp/{jni → rnskia-android}/SkiaOpenGLRenderer.cpp +39 -54
  11. package/android/cpp/{jni/include → rnskia-android}/SkiaOpenGLRenderer.h +2 -31
  12. package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java +1 -1
  13. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java +1 -1
  14. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +21 -28
  15. package/cpp/api/JsiSkApi.h +2 -0
  16. package/cpp/api/JsiSkColor.h +49 -0
  17. package/cpp/api/JsiSkPath.h +31 -2
  18. package/cpp/api/JsiSkPathFactory.h +96 -1
  19. package/cpp/api/third_party/CSSColorParser.h +324 -0
  20. package/cpp/rnskia/RNSkAnimation.h +4 -7
  21. package/cpp/rnskia/RNSkDrawView.cpp +77 -116
  22. package/cpp/rnskia/RNSkDrawView.h +5 -35
  23. package/cpp/rnskia/RNSkJsiViewApi.h +8 -5
  24. package/cpp/rnskia/RNSkManager.cpp +2 -2
  25. package/cpp/rnskia/RNSkManager.h +2 -2
  26. package/cpp/rnskia/RNSkPlatformContext.h +1 -1
  27. package/cpp/rnskia/values/RNSkClockValue.h +19 -11
  28. package/cpp/rnskia/values/RNSkDerivedValue.h +1 -1
  29. package/cpp/rnskia/values/RNSkReadonlyValue.h +15 -15
  30. package/cpp/utils/RNSkTimingInfo.h +13 -1
  31. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +5 -7
  32. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +25 -10
  33. package/ios/RNSkia-iOS/SkiaDrawView.mm +21 -15
  34. package/lib/commonjs/renderer/Canvas.js +3 -3
  35. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  36. package/lib/commonjs/renderer/components/Paint.js +1 -1
  37. package/lib/commonjs/renderer/components/Paint.js.map +1 -1
  38. package/lib/commonjs/renderer/components/shapes/Path.js +10 -2
  39. package/lib/commonjs/renderer/components/shapes/Path.js.map +1 -1
  40. package/lib/commonjs/renderer/nodes/Node.js +3 -3
  41. package/lib/commonjs/renderer/nodes/Node.js.map +1 -1
  42. package/lib/commonjs/renderer/processors/Paint.js +6 -1
  43. package/lib/commonjs/renderer/processors/Paint.js.map +1 -1
  44. package/lib/commonjs/skia/Color.js +3 -25
  45. package/lib/commonjs/skia/Color.js.map +1 -1
  46. package/lib/commonjs/skia/Image/Image.js.map +1 -1
  47. package/lib/commonjs/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  48. package/lib/commonjs/skia/Paint/Paint.js +13 -1
  49. package/lib/commonjs/skia/Paint/Paint.js.map +1 -1
  50. package/lib/commonjs/skia/Paint/usePaint.js +2 -4
  51. package/lib/commonjs/skia/Paint/usePaint.js.map +1 -1
  52. package/lib/commonjs/skia/Path/Path.js +13 -1
  53. package/lib/commonjs/skia/Path/Path.js.map +1 -1
  54. package/lib/commonjs/skia/Shader/Shader.js.map +1 -1
  55. package/lib/commonjs/skia/Skia.js +43 -3
  56. package/lib/commonjs/skia/Skia.js.map +1 -1
  57. package/lib/module/renderer/Canvas.js +2 -2
  58. package/lib/module/renderer/Canvas.js.map +1 -1
  59. package/lib/module/renderer/components/Paint.js +2 -2
  60. package/lib/module/renderer/components/Paint.js.map +1 -1
  61. package/lib/module/renderer/components/shapes/Path.js +10 -3
  62. package/lib/module/renderer/components/shapes/Path.js.map +1 -1
  63. package/lib/module/renderer/nodes/Node.js +3 -3
  64. package/lib/module/renderer/nodes/Node.js.map +1 -1
  65. package/lib/module/renderer/processors/Paint.js +6 -1
  66. package/lib/module/renderer/processors/Paint.js.map +1 -1
  67. package/lib/module/skia/Color.js +2 -21
  68. package/lib/module/skia/Color.js.map +1 -1
  69. package/lib/module/skia/Image/Image.js.map +1 -1
  70. package/lib/module/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  71. package/lib/module/skia/Paint/Paint.js +6 -0
  72. package/lib/module/skia/Paint/Paint.js.map +1 -1
  73. package/lib/module/skia/Paint/usePaint.js +2 -3
  74. package/lib/module/skia/Paint/usePaint.js.map +1 -1
  75. package/lib/module/skia/Path/Path.js +11 -0
  76. package/lib/module/skia/Path/Path.js.map +1 -1
  77. package/lib/module/skia/Shader/Shader.js.map +1 -1
  78. package/lib/module/skia/Skia.js +45 -2
  79. package/lib/module/skia/Skia.js.map +1 -1
  80. package/lib/typescript/src/renderer/components/shapes/Path.d.ts +3 -1
  81. package/lib/typescript/src/renderer/processors/Paint.d.ts +2 -1
  82. package/lib/typescript/src/skia/Color.d.ts +0 -1
  83. package/lib/typescript/src/skia/Image/Image.d.ts +3 -3
  84. package/lib/typescript/src/skia/ImageFilter/ImageFilterFactory.d.ts +2 -2
  85. package/lib/typescript/src/skia/Paint/Paint.d.ts +3 -2
  86. package/lib/typescript/src/skia/Path/Path.d.ts +13 -0
  87. package/lib/typescript/src/skia/Path/PathFactory.d.ts +7 -1
  88. package/lib/typescript/src/skia/Picture/Picture.d.ts +2 -2
  89. package/lib/typescript/src/skia/RuntimeEffect/RuntimeEffect.d.ts +3 -3
  90. package/lib/typescript/src/skia/Shader/Shader.d.ts +2 -2
  91. package/lib/typescript/src/skia/Shader/ShaderFactory.d.ts +9 -9
  92. package/lib/typescript/src/skia/Skia.d.ts +5 -3
  93. package/package.json +1 -1
  94. package/scripts/install-npm.js +1 -1
  95. package/src/renderer/Canvas.tsx +2 -2
  96. package/src/renderer/components/Paint.tsx +2 -2
  97. package/src/renderer/components/shapes/Path.tsx +12 -4
  98. package/src/renderer/nodes/Node.ts +3 -3
  99. package/src/renderer/processors/Paint.ts +5 -0
  100. package/src/skia/Color.ts +3 -20
  101. package/src/skia/Image/Image.ts +3 -3
  102. package/src/skia/ImageFilter/ImageFilterFactory.ts +2 -2
  103. package/src/skia/Paint/Paint.ts +9 -2
  104. package/src/skia/Paint/usePaint.ts +2 -4
  105. package/src/skia/Path/Path.ts +16 -0
  106. package/src/skia/Path/PathFactory.ts +8 -1
  107. package/src/skia/Picture/Picture.ts +2 -2
  108. package/src/skia/RuntimeEffect/RuntimeEffect.ts +4 -4
  109. package/src/skia/Shader/Shader.ts +2 -2
  110. package/src/skia/Shader/ShaderFactory.ts +9 -9
  111. package/src/skia/Skia.ts +47 -3
@@ -20,8 +20,6 @@
20
20
 
21
21
  #pragma clang diagnostic pop
22
22
 
23
- #define LOG_ALL_DRAWING 0
24
-
25
23
  class SkPicture;
26
24
  class SkRect;
27
25
  class SkImage;
@@ -35,7 +33,7 @@ using RNSkDrawCallback =
35
33
 
36
34
  enum RNSkDrawingMode { Default, Continuous };
37
35
 
38
- class RNSkDrawView {
36
+ class RNSkDrawView: public std::enable_shared_from_this<RNSkDrawView> {
39
37
  public:
40
38
  /**
41
39
  * Constructor
@@ -45,7 +43,7 @@ public:
45
43
  /**
46
44
  Destructor
47
45
  */
48
- ~RNSkDrawView();
46
+ virtual ~RNSkDrawView();
49
47
 
50
48
  /**
51
49
  * Repaints the Skia view using the underlying context and the drawcallback.
@@ -96,14 +94,6 @@ public:
96
94
  sk_sp<SkImage> makeImageSnapshot(std::shared_ptr<SkRect> bounds);
97
95
 
98
96
  protected:
99
- void setNativeDrawFunc(std::function<void(const sk_sp<SkPicture>)> drawFunc) {
100
- if(!_gpuDrawingLock->try_lock_for(250ms)) {
101
- RNSkLogger::logToConsole("Could not lock drawing when clearing drawing function - %i", _nativeId);
102
- }
103
- _nativeDrawFunc = drawFunc;
104
- _gpuDrawingLock->unlock();
105
- }
106
-
107
97
  /**
108
98
  Returns the scaled width of the view
109
99
  */
@@ -115,14 +105,9 @@ protected:
115
105
  virtual int getHeight() { return -1; };
116
106
 
117
107
  /**
118
- Returns true if the view is invalidated
119
- */
120
- volatile bool isInvalidated() { return _isInvalidated; }
121
-
122
- /**
123
- Override to be notified on invalidation
108
+ Override to render picture to GPU
124
109
  */
125
- virtual void onInvalidated() {}
110
+ virtual void drawPicture(const sk_sp<SkPicture> picture) = 0;
126
111
 
127
112
  /**
128
113
  * @return The platformcontext
@@ -210,12 +195,7 @@ private:
210
195
  /**
211
196
  Timing information for GPU rendering
212
197
  */
213
- RNSkTimingInfo _gpuTimingInfo;
214
-
215
- /**
216
- Measures vsync framerate
217
- */
218
- RNSkTimingInfo _vsyncTimingInfo;
198
+ RNSkTimingInfo _gpuTimingInfo;
219
199
 
220
200
  /**
221
201
  Redraw queue counter
@@ -227,16 +207,6 @@ private:
227
207
  */
228
208
  size_t _nativeId;
229
209
 
230
- /**
231
- Invalidation flag
232
- */
233
- std::atomic<bool> _isInvalidated = { false };
234
-
235
- /**
236
- Native draw handler
237
- */
238
- std::function<void(const sk_sp<SkPicture>)> _nativeDrawFunc;
239
-
240
210
  };
241
211
 
242
212
  } // namespace RNSkia
@@ -20,7 +20,7 @@ using CallbackInfo = struct CallbackInfo {
20
20
  view = nullptr;
21
21
  }
22
22
  std::shared_ptr<jsi::Function> drawCallback;
23
- RNSkDrawView *view;
23
+ std::shared_ptr<RNSkDrawView> view;
24
24
  };
25
25
 
26
26
  class RNSkJsiViewApi : public JsiHostObject {
@@ -105,7 +105,7 @@ public:
105
105
  sk_sp<SkImage> image;
106
106
  auto info = getEnsuredCallbackInfo(nativeId);
107
107
  if (info->view != nullptr) {
108
- if(count > 1 && !arguments[1].isUndefined() && arguments[1].isNull()) {
108
+ if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) {
109
109
  auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
110
110
  image = info->view->makeImageSnapshot(rect);
111
111
  } else {
@@ -226,7 +226,7 @@ public:
226
226
  * @param nativeId Id of view to register
227
227
  * @param view View to register
228
228
  */
229
- void registerSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
229
+ void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
230
230
  auto info = getEnsuredCallbackInfo(nativeId);
231
231
  info->view = view;
232
232
  if (info->drawCallback != nullptr) {
@@ -260,15 +260,18 @@ public:
260
260
  a valid view is set, the setDrawCallback method is called on the
261
261
  view (if a valid callback exists).
262
262
  */
263
- void setSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
263
+ void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
264
264
  if (_callbackInfos.find(nativeId) == _callbackInfos.end()) {
265
265
  return;
266
266
  }
267
267
  auto info = getEnsuredCallbackInfo(nativeId);
268
- info->view = view;
269
268
  if (view != nullptr && info->drawCallback != nullptr) {
269
+ info->view = view;
270
270
  info->view->setNativeId(nativeId);
271
271
  info->view->setDrawCallback(info->drawCallback);
272
+ } else if(view == nullptr && info->drawCallback != nullptr) {
273
+ info->view->setDrawCallback(nullptr);
274
+ info->view = view;
272
275
  }
273
276
  }
274
277
 
@@ -45,7 +45,7 @@ void RNSkManager::invalidate() {
45
45
  _platformContext->invalidate();
46
46
  }
47
47
 
48
- void RNSkManager::registerSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
48
+ void RNSkManager::registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
49
49
  if (!_isInvalidated && _viewApi != nullptr)
50
50
  _viewApi->registerSkiaDrawView(nativeId, view);
51
51
  }
@@ -55,7 +55,7 @@ void RNSkManager::unregisterSkiaDrawView(size_t nativeId) {
55
55
  _viewApi->unregisterSkiaDrawView(nativeId);
56
56
  }
57
57
 
58
- void RNSkManager::setSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
58
+ void RNSkManager::setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
59
59
  if (!_isInvalidated && _viewApi != nullptr)
60
60
  _viewApi->setSkiaDrawView(nativeId, view);
61
61
  }
@@ -41,7 +41,7 @@ public:
41
41
  * @param nativeId Native view id
42
42
  * @param view View to register
43
43
  */
44
- void registerSkiaDrawView(size_t nativeId, RNSkDrawView *view);
44
+ void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view);
45
45
 
46
46
  /**
47
47
  * Unregisters the RNSkDrawView from the list of registered views
@@ -54,7 +54,7 @@ public:
54
54
  Used when we want to remove a view without unregistering it
55
55
  - this happens typically on iOS.
56
56
  */
57
- void setSkiaDrawView(size_t nativeId, RNSkDrawView *view);
57
+ void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view);
58
58
 
59
59
  /**
60
60
  * @return The platform context
@@ -43,7 +43,7 @@ public:
43
43
  /**
44
44
  * Destructor
45
45
  */
46
- ~RNSkPlatformContext() {
46
+ virtual ~RNSkPlatformContext() {
47
47
  invalidate();
48
48
  }
49
49
 
@@ -8,7 +8,6 @@
8
8
  #include <algorithm>
9
9
  #include <functional>
10
10
  #include <chrono>
11
- #include <mutex>
12
11
 
13
12
  namespace RNSkia
14
13
  {
@@ -38,7 +37,7 @@ public:
38
37
  update(_runtime, static_cast<double>(0));
39
38
  }
40
39
 
41
- ~RNSkClockValue() {
40
+ virtual ~RNSkClockValue() {
42
41
  stopClock();
43
42
  }
44
43
 
@@ -73,8 +72,12 @@ public:
73
72
  _start += timeSinceStop;
74
73
 
75
74
  _state = RNSkClockState::Running;
76
- auto dispatch = std::bind(&RNSkClockValue::notifyUpdate, this, std::placeholders::_1);
77
- getContext()->beginDrawLoop(_identifier, dispatch);
75
+ getContext()->beginDrawLoop(_identifier, [weakSelf = weak_from_this()](bool invalidated){
76
+ auto self = weakSelf.lock();
77
+ if(self) {
78
+ std::dynamic_pointer_cast<RNSkClockValue>(self)->notifyUpdate(invalidated);
79
+ }
80
+ });
78
81
  }
79
82
 
80
83
  virtual void stopClock() {
@@ -100,15 +103,20 @@ protected:
100
103
  return;
101
104
  }
102
105
 
103
- // Avoid moving on if we are being called after the dtor was started
104
106
  // Ensure we call any updates from the draw loop on the javascript thread
105
107
  getContext()->runOnJavascriptThread(
106
- [this]() {
107
- if(_state == RNSkClockState::Running) {
108
- auto now = std::chrono::high_resolution_clock::now();
109
- auto deltaFromStart = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start).count();
110
- tick(_runtime, static_cast<double>(deltaFromStart));
111
- }
108
+ // To ensure that this shared_ptr instance is not deallocated before we are done
109
+ // running the update lambda we pass a shared from this to the lambda scope.
110
+ [weakSelf = weak_from_this()]() {
111
+ auto self = weakSelf.lock();
112
+ if(self) {
113
+ auto selfClockValue = std::dynamic_pointer_cast<RNSkClockValue>(self);
114
+ if(selfClockValue->getState() == RNSkClockState::Running) {
115
+ auto now = std::chrono::high_resolution_clock::now();
116
+ auto deltaFromStart = std::chrono::duration_cast<std::chrono::milliseconds>(now - selfClockValue->_start).count();
117
+ selfClockValue->tick(selfClockValue->_runtime, static_cast<double>(deltaFromStart));
118
+ }
119
+ }
112
120
  });
113
121
  }
114
122
 
@@ -73,7 +73,7 @@ public:
73
73
  dependencyUpdated(runtime);
74
74
  }
75
75
 
76
- ~RNSkDerivedValue() {
76
+ virtual ~RNSkDerivedValue() {
77
77
  // Unregister listeners
78
78
  for(const auto &unsubscribe: _unsubscribers) {
79
79
  unsubscribe();
@@ -4,9 +4,7 @@
4
4
  #include <algorithm>
5
5
  #include <functional>
6
6
  #include <chrono>
7
- #include <mutex>
8
7
  #include <unordered_map>
9
- #include <utility>
10
8
  #include <memory>
11
9
 
12
10
  #include <jsi/jsi.h>
@@ -22,16 +20,15 @@ using namespace facebook;
22
20
  Implements a readonly Value that is updated every time the screen is redrawn. Its value will be the
23
21
  number of milliseconds since the animation value was started.
24
22
  */
25
- class RNSkReadonlyValue : public JsiSkHostObject
23
+ class RNSkReadonlyValue : public JsiSkHostObject,
24
+ public std::enable_shared_from_this<RNSkReadonlyValue>
26
25
  {
27
26
  public:
28
27
  RNSkReadonlyValue(std::shared_ptr<RNSkPlatformContext> platformContext)
29
28
  : JsiSkHostObject(platformContext),
30
29
  _propNameId(jsi::PropNameID::forUtf8(*platformContext->getJsRuntime(), "value")) {}
31
30
 
32
- ~RNSkReadonlyValue() {
33
- _invalidated = true;
34
- }
31
+ virtual ~RNSkReadonlyValue() { }
35
32
 
36
33
  JSI_PROPERTY_GET(__typename__) {
37
34
  return jsi::String::createFromUtf8(runtime, "RNSkValue");
@@ -43,8 +40,7 @@ public:
43
40
 
44
41
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__),
45
42
  JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current))
46
-
47
-
43
+
48
44
  JSI_HOST_FUNCTION(addListener) {
49
45
  if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) {
50
46
  jsi::detail::throwJSError(runtime, "Expected function as first parameter.");
@@ -52,8 +48,13 @@ public:
52
48
  }
53
49
  auto callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
54
50
 
55
- auto unsubscribe = addListener([this, callback = std::move(callback)](jsi::Runtime& runtime){
56
- callback->call(runtime, get_current(runtime));
51
+ auto unsubscribe = addListener([weakSelf = weak_from_this(),
52
+ callback = std::move(callback)](jsi::Runtime& runtime){
53
+ auto self = weakSelf.lock();
54
+ if(self) {
55
+ auto selfReadonlyValue = std::dynamic_pointer_cast<RNSkReadonlyValue>(self);
56
+ callback->call(runtime, selfReadonlyValue->get_current(runtime));
57
+ }
57
58
  });
58
59
 
59
60
  return jsi::Function::createFromHostFunction(runtime,
@@ -76,9 +77,10 @@ public:
76
77
  std::lock_guard<std::mutex> lock(_mutex);
77
78
  auto listenerId = _listenerId++;
78
79
  _listeners.emplace(listenerId, cb);
79
- return [this, listenerId]() {
80
- if(!_invalidated) {
81
- removeListener(listenerId);
80
+ return [weakSelf = weak_from_this(), listenerId]() {
81
+ auto self = weakSelf.lock();
82
+ if(self) {
83
+ self->removeListener(listenerId);
82
84
  }
83
85
  };
84
86
  }
@@ -128,8 +130,6 @@ protected:
128
130
  _listeners.erase(listenerId);
129
131
  }
130
132
 
131
- std::atomic<bool> _invalidated = { false };
132
-
133
133
  private:
134
134
  jsi::PropNameID _propNameId;
135
135
  std::shared_ptr<jsi::Object> _valueHolder;
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <RNSkLog.h>
3
4
  #include <chrono>
4
5
 
5
6
  #define NUMBER_OF_DURATION_SAMPLES 10
@@ -12,7 +13,7 @@ using ms = duration<float, std::milli>;
12
13
 
13
14
  class RNSkTimingInfo {
14
15
  public:
15
- RNSkTimingInfo() {
16
+ RNSkTimingInfo(const std::string &name): _name(std::move(name)) {
16
17
  reset();
17
18
  }
18
19
 
@@ -25,6 +26,7 @@ public:
25
26
  _prevFpsTimer = -1;
26
27
  _frameCount = 0;
27
28
  _lastFrameCount = -1;
29
+ _didSkip = false;
28
30
  }
29
31
 
30
32
  void beginTiming() {
@@ -35,6 +37,14 @@ public:
35
37
  time_point<steady_clock> stop = high_resolution_clock::now();
36
38
  addLastDuration(duration_cast<milliseconds>(stop - _start).count());
37
39
  tick(stop);
40
+ if(_didSkip) {
41
+ _didSkip = false;
42
+ RNSkLogger::logToConsole("%s: Skipped frame. Previous frame time: %lldms", _name.c_str(), _lastDuration);
43
+ }
44
+ }
45
+
46
+ void markSkipped() {
47
+ _didSkip = true;
38
48
  }
39
49
 
40
50
  long getAverage() { return static_cast<long>(_average); }
@@ -86,6 +96,8 @@ private:
86
96
  long _prevFpsTimer;
87
97
  double _frameCount;
88
98
  double _lastFrameCount;
99
+ double _didSkip;
100
+ std::string _name;
89
101
  };
90
102
 
91
103
  } // namespace RNSkia
@@ -21,20 +21,18 @@
21
21
  class RNSkDrawViewImpl : public RNSkia::RNSkDrawView {
22
22
  public:
23
23
  RNSkDrawViewImpl(std::shared_ptr<RNSkia::RNSkPlatformContext> context);
24
+ ~RNSkDrawViewImpl();
24
25
 
25
- void setSize(int width, int height);
26
+ CALayer* getLayer() { return _layer; }
26
27
 
27
- CALayer* getLayer() { return _layer; };
28
+ void setSize(int width, int height);
28
29
 
29
30
  protected:
30
31
  int getWidth() override { return _width * _context->getPixelDensity(); };
31
- int getHeight() override { return _height * _context->getPixelDensity(); };
32
- void onInvalidated() override {
33
- setNativeDrawFunc(nullptr);
34
- };
32
+ int getHeight() override { return _height * _context->getPixelDensity(); };
35
33
 
36
34
  private:
37
- void drawFrame(const sk_sp<SkPicture> picture);
35
+ void drawPicture(const sk_sp<SkPicture> picture) override;
38
36
  bool createSkiaSurface();
39
37
 
40
38
  int _nativeId;
@@ -19,19 +19,34 @@ sk_sp<GrDirectContext> RNSkDrawViewImpl::_skContext = nullptr;
19
19
 
20
20
  RNSkDrawViewImpl::RNSkDrawViewImpl(std::shared_ptr<RNSkia::RNSkPlatformContext> context):
21
21
  _context(context), RNSkia::RNSkDrawView(context) {
22
-
23
22
  #pragma clang diagnostic push
24
23
  #pragma clang diagnostic ignored "-Wunguarded-availability-new"
25
- _layer = [CAMetalLayer layer];
24
+ _layer = [CAMetalLayer layer];
26
25
  #pragma clang diagnostic pop
27
26
 
28
- _layer.framebufferOnly = NO;
29
- _layer.device = _device;
30
- _layer.opaque = false;
31
- _layer.contentsScale = _context->getPixelDensity();
32
- _layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
33
-
34
- setNativeDrawFunc(std::bind(&RNSkDrawViewImpl::drawFrame, this, std::placeholders::_1));
27
+ _layer.framebufferOnly = NO;
28
+ _layer.device = _device;
29
+ _layer.opaque = false;
30
+ _layer.contentsScale = _context->getPixelDensity();
31
+ _layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
32
+ }
33
+
34
+ RNSkDrawViewImpl::~RNSkDrawViewImpl() {
35
+ if([[NSThread currentThread] isMainThread]) {
36
+ _layer = NULL;
37
+ } else {
38
+ __block auto tempLayer = _layer;
39
+ dispatch_async(dispatch_get_main_queue(), ^{
40
+ // By using the tempLayer variable in the block we capture it and it will be
41
+ // released after the block has finished. This way the CAMetalLayer dealloc will
42
+ // only be called on the main thread. Problem: this destructor might be called from
43
+ // releasing the RNSkDrawViewImpl from a thread capture (after dtor has started),
44
+ // which would cause the CAMetalLayer dealloc to be called on another thread which
45
+ // causes a crash.
46
+ // https://github.com/Shopify/react-native-skia/issues/398
47
+ tempLayer = tempLayer;
48
+ });
49
+ }
35
50
  }
36
51
 
37
52
  void RNSkDrawViewImpl::setSize(int width, int height) {
@@ -44,7 +59,7 @@ void RNSkDrawViewImpl::setSize(int width, int height) {
44
59
  requestRedraw();
45
60
  }
46
61
 
47
- void RNSkDrawViewImpl::drawFrame(const sk_sp<SkPicture> picture) {
62
+ void RNSkDrawViewImpl::drawPicture(const sk_sp<SkPicture> picture) {
48
63
  if(_width == -1 && _height == -1) {
49
64
  return;
50
65
  }
@@ -26,53 +26,59 @@
26
26
  _nativeId = 0;
27
27
  _debugMode = false;
28
28
  _drawingMode = RNSkia::RNSkDrawingMode::Default;
29
+
29
30
  // Listen to notifications about module invalidation
31
+ __unsafe_unretained SkiaDrawView *weakSelf = self;
30
32
  auto nc = [NSNotificationCenter defaultCenter];
31
33
  [nc addObserverForName:RCTBridgeWillInvalidateModulesNotification
32
34
  object:nil
33
35
  queue:nil
34
36
  usingBlock:^(NSNotification *notification){
35
37
  // Remove local variables
36
- self->_manager = nullptr;
38
+ if(weakSelf != nullptr) {
39
+ weakSelf->_manager = nullptr;
40
+ }
37
41
  }];
38
42
  }
39
43
  return self;
40
44
  }
41
45
 
42
- - (void)dealloc {
43
- if(_manager != nullptr) {
44
- _manager->unregisterSkiaDrawView(_nativeId);
45
- }
46
- }
47
-
48
46
  #pragma mark Lifecycle
49
47
 
50
- - (void) willMoveToWindow:(UIWindow *)newWindow {
51
- [super willMoveToWindow: newWindow];
52
-
48
+ - (void) willMoveToSuperview:(UIView *)newWindow {
53
49
  if (newWindow == NULL) {
54
50
  // Remove implementation view when the parent view is not set
55
51
  if(_impl != nullptr) {
52
+ [_impl->getLayer() removeFromSuperlayer];
53
+
56
54
  if(_nativeId != 0 && _manager != nullptr) {
57
55
  _manager->setSkiaDrawView(_nativeId, nullptr);
58
56
  }
59
- [_impl->getLayer() removeFromSuperlayer];
57
+
60
58
  _impl = nullptr;
61
59
  }
62
60
  } else {
63
61
  // Create implementation view when the parent view is set
64
62
  if(_impl == nullptr && _manager != nullptr) {
65
63
  _impl = std::make_shared<RNSkDrawViewImpl>(_manager->getPlatformContext());
66
- [self.layer addSublayer:_impl->getLayer()];
64
+ [self.layer addSublayer: _impl->getLayer()];
67
65
  if(_nativeId != 0) {
68
- _manager->setSkiaDrawView(_nativeId, _impl.get());
66
+ _manager->setSkiaDrawView(_nativeId, _impl);
69
67
  }
70
68
  _impl->setDrawingMode(_drawingMode);
71
- _impl->setShowDebugOverlays(_debugMode);
69
+ _impl->setShowDebugOverlays(_debugMode);
72
70
  }
73
71
  }
74
72
  }
75
73
 
74
+ - (void) dealloc {
75
+ auto nc = [NSNotificationCenter defaultCenter];
76
+ [nc removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil];
77
+ if(_manager != nullptr && _nativeId != 0) {
78
+ _manager->unregisterSkiaDrawView(_nativeId);
79
+ }
80
+ }
81
+
76
82
  #pragma mark Layout
77
83
 
78
84
  - (void) layoutSubviews {
@@ -103,7 +109,7 @@
103
109
  _nativeId = nativeId;
104
110
 
105
111
  if(_impl != nullptr) {
106
- _manager->registerSkiaDrawView(nativeId, _impl.get());
112
+ _manager->registerSkiaDrawView(nativeId, _impl);
107
113
  }
108
114
  }
109
115
 
@@ -15,6 +15,8 @@ var _skia = require("../skia");
15
15
 
16
16
  var _useValue = require("../values/hooks/useValue");
17
17
 
18
+ var _Paint = require("../skia/Paint/Paint");
19
+
18
20
  var _HostConfig = require("./HostConfig");
19
21
 
20
22
  var _processors = require("./processors");
@@ -109,9 +111,7 @@ const Canvas = /*#__PURE__*/(0, _react.forwardRef)((_ref, forwardedRef) => {
109
111
  };
110
112
  }
111
113
 
112
- const paint = _skia.Skia.Paint();
113
-
114
- paint.setAntiAlias(true);
114
+ const paint = (0, _Paint.SkiaPaint)();
115
115
  const ctx = {
116
116
  width,
117
117
  height,
@@ -1 +1 @@
1
- {"version":3,"sources":["Canvas.tsx"],"names":["CanvasContext","React","createContext","useCanvasSize","canvas","Error","skiaReconciler","skHostConfig","injectIntoDevTools","bundleType","version","rendererPackageName","render","element","root","container","updateContainer","depMgr","subscribe","useCanvasRef","defaultFontMgr","Skia","FontMgr","RefDefault","Canvas","forwardedRef","children","style","debug","mode","onTouch","fontMgr","canvasCtx","width","height","innerRef","ref","useCombinedRefs","tick","setTick","redraw","t","Container","DependencyManager","createContainer","onDraw","info","timestamp","touches","current","paint","Paint","setAntiAlias","ctx","opacity","center","draw","unsubscribe","refs","targetRef","useRef","useEffect","forEach"],"mappings":"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","sourcesContent":["import React, {\n useEffect,\n useState,\n useCallback,\n useMemo,\n useContext,\n forwardRef,\n useRef,\n} from \"react\";\nimport type {\n RefObject,\n ReactNode,\n ComponentProps,\n MutableRefObject,\n ForwardedRef,\n} from \"react\";\nimport type { OpaqueRoot } from \"react-reconciler\";\nimport ReactReconciler from \"react-reconciler\";\n\nimport { SkiaView, useDrawCallback } from \"../views\";\nimport type { TouchHandler } from \"../views\";\nimport { Skia } from \"../skia\";\nimport type { FontMgr } from \"../skia/FontMgr/FontMgr\";\nimport { useValue } from \"../values/hooks/useValue\";\nimport type { SkiaReadonlyValue } from \"../values/types\";\n\nimport { debug as hostDebug, skHostConfig } from \"./HostConfig\";\n// import { debugTree } from \"./nodes\";\nimport { vec } from \"./processors\";\nimport { Container } from \"./nodes\";\nimport { DependencyManager } from \"./DependencyManager\";\n\nconst CanvasContext = React.createContext<SkiaReadonlyValue<{\n width: number;\n height: number;\n}> | null>(null);\n\nexport const useCanvasSize = () => {\n const canvas = useContext(CanvasContext);\n if (!canvas) {\n throw new Error(\"Canvas context is not available\");\n }\n return canvas;\n};\n\nexport const skiaReconciler = ReactReconciler(skHostConfig);\n\nskiaReconciler.injectIntoDevTools({\n bundleType: 1,\n version: \"0.0.1\",\n rendererPackageName: \"react-native-skia\",\n});\n\nconst render = (element: ReactNode, root: OpaqueRoot, container: Container) => {\n skiaReconciler.updateContainer(element, root, null, () => {\n hostDebug(\"updateContainer\");\n\n container.depMgr.subscribe();\n });\n};\n\nexport const useCanvasRef = () => useRef<SkiaView>(null);\n\nexport interface CanvasProps extends ComponentProps<typeof SkiaView> {\n ref?: RefObject<SkiaView>;\n children: ReactNode;\n onTouch?: TouchHandler;\n fontMgr?: FontMgr;\n}\n\nconst defaultFontMgr = Skia.FontMgr.RefDefault();\n\nexport const Canvas = forwardRef<SkiaView, CanvasProps>(\n ({ children, style, debug, mode, onTouch, fontMgr }, forwardedRef) => {\n const canvasCtx = useValue({ width: 0, height: 0 });\n const innerRef = useCanvasRef();\n const ref = useCombinedRefs(forwardedRef, innerRef);\n const [tick, setTick] = useState(0);\n const redraw = useCallback(() => setTick((t) => t + 1), []);\n\n const container = useMemo(\n () => new Container(new DependencyManager(ref), redraw),\n [redraw, ref]\n );\n\n const root = useMemo(\n () => skiaReconciler.createContainer(container, 0, false, null),\n [container]\n );\n // Render effect\n useEffect(() => {\n render(\n <CanvasContext.Provider value={canvasCtx}>\n {children}\n </CanvasContext.Provider>,\n root,\n container\n );\n }, [children, root, redraw, container, canvasCtx]);\n\n // Draw callback\n const onDraw = useDrawCallback(\n (canvas, info) => {\n // TODO: if tree is empty (count === 1) maybe we should not render?\n const { width, height, timestamp } = info;\n if (onTouch) {\n onTouch(info.touches);\n }\n if (\n width !== canvasCtx.current.width ||\n height !== canvasCtx.current.height\n ) {\n canvasCtx.current = { width, height };\n }\n const paint = Skia.Paint();\n paint.setAntiAlias(true);\n const ctx = {\n width,\n height,\n timestamp,\n canvas,\n paint,\n opacity: 1,\n ref,\n center: vec(width / 2, height / 2),\n fontMgr: fontMgr ?? defaultFontMgr,\n };\n container.draw(ctx);\n },\n [tick, onTouch]\n );\n\n useEffect(() => {\n return () => {\n container.depMgr.unsubscribe();\n };\n }, [container]);\n\n return (\n <SkiaView\n ref={ref}\n style={style}\n onDraw={onDraw}\n mode={mode}\n debug={debug}\n />\n );\n }\n);\n\n/**\n * Combines a list of refs into a single ref. This can be used to provide\n * both a forwarded ref and an internal ref keeping the same functionality\n * on both of the refs.\n * @param refs Array of refs to combine\n * @returns A single ref that can be used in a ref prop.\n */\nconst useCombinedRefs = <T,>(\n ...refs: Array<MutableRefObject<T> | ForwardedRef<T>>\n) => {\n const targetRef = React.useRef<T>(null);\n React.useEffect(() => {\n refs.forEach((ref) => {\n if (ref) {\n if (typeof ref === \"function\") {\n ref(targetRef.current);\n } else {\n ref.current = targetRef.current;\n }\n }\n });\n }, [refs]);\n return targetRef;\n};\n"]}
1
+ {"version":3,"sources":["Canvas.tsx"],"names":["CanvasContext","React","createContext","useCanvasSize","canvas","Error","skiaReconciler","skHostConfig","injectIntoDevTools","bundleType","version","rendererPackageName","render","element","root","container","updateContainer","depMgr","subscribe","useCanvasRef","defaultFontMgr","Skia","FontMgr","RefDefault","Canvas","forwardedRef","children","style","debug","mode","onTouch","fontMgr","canvasCtx","width","height","innerRef","ref","useCombinedRefs","tick","setTick","redraw","t","Container","DependencyManager","createContainer","onDraw","info","timestamp","touches","current","paint","ctx","opacity","center","draw","unsubscribe","refs","targetRef","useRef","useEffect","forEach"],"mappings":"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","sourcesContent":["import React, {\n useEffect,\n useState,\n useCallback,\n useMemo,\n useContext,\n forwardRef,\n useRef,\n} from \"react\";\nimport type {\n RefObject,\n ReactNode,\n ComponentProps,\n MutableRefObject,\n ForwardedRef,\n} from \"react\";\nimport type { OpaqueRoot } from \"react-reconciler\";\nimport ReactReconciler from \"react-reconciler\";\n\nimport { SkiaView, useDrawCallback } from \"../views\";\nimport type { TouchHandler } from \"../views\";\nimport { Skia } from \"../skia\";\nimport type { FontMgr } from \"../skia/FontMgr/FontMgr\";\nimport { useValue } from \"../values/hooks/useValue\";\nimport type { SkiaReadonlyValue } from \"../values/types\";\nimport { SkiaPaint } from \"../skia/Paint/Paint\";\n\nimport { debug as hostDebug, skHostConfig } from \"./HostConfig\";\n// import { debugTree } from \"./nodes\";\nimport { vec } from \"./processors\";\nimport { Container } from \"./nodes\";\nimport { DependencyManager } from \"./DependencyManager\";\n\nconst CanvasContext = React.createContext<SkiaReadonlyValue<{\n width: number;\n height: number;\n}> | null>(null);\n\nexport const useCanvasSize = () => {\n const canvas = useContext(CanvasContext);\n if (!canvas) {\n throw new Error(\"Canvas context is not available\");\n }\n return canvas;\n};\n\nexport const skiaReconciler = ReactReconciler(skHostConfig);\n\nskiaReconciler.injectIntoDevTools({\n bundleType: 1,\n version: \"0.0.1\",\n rendererPackageName: \"react-native-skia\",\n});\n\nconst render = (element: ReactNode, root: OpaqueRoot, container: Container) => {\n skiaReconciler.updateContainer(element, root, null, () => {\n hostDebug(\"updateContainer\");\n\n container.depMgr.subscribe();\n });\n};\n\nexport const useCanvasRef = () => useRef<SkiaView>(null);\n\nexport interface CanvasProps extends ComponentProps<typeof SkiaView> {\n ref?: RefObject<SkiaView>;\n children: ReactNode;\n onTouch?: TouchHandler;\n fontMgr?: FontMgr;\n}\n\nconst defaultFontMgr = Skia.FontMgr.RefDefault();\n\nexport const Canvas = forwardRef<SkiaView, CanvasProps>(\n ({ children, style, debug, mode, onTouch, fontMgr }, forwardedRef) => {\n const canvasCtx = useValue({ width: 0, height: 0 });\n const innerRef = useCanvasRef();\n const ref = useCombinedRefs(forwardedRef, innerRef);\n const [tick, setTick] = useState(0);\n const redraw = useCallback(() => setTick((t) => t + 1), []);\n\n const container = useMemo(\n () => new Container(new DependencyManager(ref), redraw),\n [redraw, ref]\n );\n\n const root = useMemo(\n () => skiaReconciler.createContainer(container, 0, false, null),\n [container]\n );\n // Render effect\n useEffect(() => {\n render(\n <CanvasContext.Provider value={canvasCtx}>\n {children}\n </CanvasContext.Provider>,\n root,\n container\n );\n }, [children, root, redraw, container, canvasCtx]);\n\n // Draw callback\n const onDraw = useDrawCallback(\n (canvas, info) => {\n // TODO: if tree is empty (count === 1) maybe we should not render?\n const { width, height, timestamp } = info;\n if (onTouch) {\n onTouch(info.touches);\n }\n if (\n width !== canvasCtx.current.width ||\n height !== canvasCtx.current.height\n ) {\n canvasCtx.current = { width, height };\n }\n const paint = SkiaPaint();\n const ctx = {\n width,\n height,\n timestamp,\n canvas,\n paint,\n opacity: 1,\n ref,\n center: vec(width / 2, height / 2),\n fontMgr: fontMgr ?? defaultFontMgr,\n };\n container.draw(ctx);\n },\n [tick, onTouch]\n );\n\n useEffect(() => {\n return () => {\n container.depMgr.unsubscribe();\n };\n }, [container]);\n\n return (\n <SkiaView\n ref={ref}\n style={style}\n onDraw={onDraw}\n mode={mode}\n debug={debug}\n />\n );\n }\n);\n\n/**\n * Combines a list of refs into a single ref. This can be used to provide\n * both a forwarded ref and an internal ref keeping the same functionality\n * on both of the refs.\n * @param refs Array of refs to combine\n * @returns A single ref that can be used in a ref prop.\n */\nconst useCombinedRefs = <T,>(\n ...refs: Array<MutableRefObject<T> | ForwardedRef<T>>\n) => {\n const targetRef = React.useRef<T>(null);\n React.useEffect(() => {\n refs.forEach((ref) => {\n if (ref) {\n if (typeof ref === \"function\") {\n ref(targetRef.current);\n } else {\n ref.current = targetRef.current;\n }\n }\n });\n }, [refs]);\n return targetRef;\n};\n"]}
@@ -23,7 +23,7 @@ const usePaintRef = () => (0, _react.useRef)(null);
23
23
 
24
24
  exports.usePaintRef = usePaintRef;
25
25
  const Paint = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
26
- const paint = (0, _react.useMemo)(() => _skia.Skia.Paint(), []);
26
+ const paint = (0, _react.useMemo)(() => (0, _skia.SkiaPaint)(), []);
27
27
  (0, _react.useImperativeHandle)(ref, () => paint, [paint]);
28
28
  const onDeclare = (0, _react.useMemo)(() => (0, _nodes.createDeclaration)((paintProps, children, ctx) => (0, _processors.processPaint)(paint, ctx.opacity, paintProps, children)), [paint]);
29
29
  return /*#__PURE__*/_react.default.createElement("skDeclaration", _extends({
@@ -1 +1 @@
1
- {"version":3,"sources":["Paint.tsx"],"names":["usePaintRef","Paint","props","ref","paint","Skia","onDeclare","paintProps","children","ctx","opacity"],"mappings":";;;;;;;AACA;;AAGA;;AAEA;;AACA;;;;;;;;AAEO,MAAMA,WAAW,GAAG,MAAM,mBAAgB,IAAhB,CAA1B;;;AAMA,MAAMC,KAAK,gBAAG,uBACnB,CAACC,KAAD,EAAQC,GAAR,KAAgB;AACd,QAAMC,KAAK,GAAG,oBAAQ,MAAMC,WAAKJ,KAAL,EAAd,EAA4B,EAA5B,CAAd;AACA,kCAAoBE,GAApB,EAAyB,MAAMC,KAA/B,EAAsC,CAACA,KAAD,CAAtC;AACA,QAAME,SAAS,GAAG,oBAChB,MACE,8BAA8B,CAACC,UAAD,EAAaC,QAAb,EAAuBC,GAAvB,KAC5B,8BAAaL,KAAb,EAAoBK,GAAG,CAACC,OAAxB,EAAiCH,UAAjC,EAA6CC,QAA7C,CADF,CAFc,EAKhB,CAACJ,KAAD,CALgB,CAAlB;AAOA,sBAAO;AAAe,IAAA,SAAS,EAAEE;AAA1B,KAAyCJ,KAAzC,EAAP;AACD,CAZkB,CAAd","sourcesContent":["import type { ReactNode } from \"react\";\nimport React, { useRef, useMemo, forwardRef, useImperativeHandle } from \"react\";\n\nimport type { SkPaint } from \"../../skia\";\nimport { Skia } from \"../../skia\";\nimport type { CustomPaintProps, AnimatedProps } from \"../processors\";\nimport { processPaint } from \"../processors\";\nimport { createDeclaration } from \"../nodes\";\n\nexport const usePaintRef = () => useRef<SkPaint>(null);\n\nexport interface PaintProps extends Omit<CustomPaintProps, \"paint\"> {\n children?: ReactNode | ReactNode[];\n}\n\nexport const Paint = forwardRef<SkPaint, AnimatedProps<PaintProps>>(\n (props, ref) => {\n const paint = useMemo(() => Skia.Paint(), []);\n useImperativeHandle(ref, () => paint, [paint]);\n const onDeclare = useMemo(\n () =>\n createDeclaration<PaintProps>((paintProps, children, ctx) =>\n processPaint(paint, ctx.opacity, paintProps, children)\n ),\n [paint]\n );\n return <skDeclaration onDeclare={onDeclare} {...props} />;\n }\n);\n"]}
1
+ {"version":3,"sources":["Paint.tsx"],"names":["usePaintRef","Paint","props","ref","paint","onDeclare","paintProps","children","ctx","opacity"],"mappings":";;;;;;;AACA;;AAGA;;AAEA;;AACA;;;;;;;;AAEO,MAAMA,WAAW,GAAG,MAAM,mBAAgB,IAAhB,CAA1B;;;AAMA,MAAMC,KAAK,gBAAG,uBACnB,CAACC,KAAD,EAAQC,GAAR,KAAgB;AACd,QAAMC,KAAK,GAAG,oBAAQ,MAAM,sBAAd,EAA2B,EAA3B,CAAd;AACA,kCAAoBD,GAApB,EAAyB,MAAMC,KAA/B,EAAsC,CAACA,KAAD,CAAtC;AACA,QAAMC,SAAS,GAAG,oBAChB,MACE,8BAA8B,CAACC,UAAD,EAAaC,QAAb,EAAuBC,GAAvB,KAC5B,8BAAaJ,KAAb,EAAoBI,GAAG,CAACC,OAAxB,EAAiCH,UAAjC,EAA6CC,QAA7C,CADF,CAFc,EAKhB,CAACH,KAAD,CALgB,CAAlB;AAOA,sBAAO;AAAe,IAAA,SAAS,EAAEC;AAA1B,KAAyCH,KAAzC,EAAP;AACD,CAZkB,CAAd","sourcesContent":["import type { ReactNode } from \"react\";\nimport React, { useRef, useMemo, forwardRef, useImperativeHandle } from \"react\";\n\nimport type { SkPaint } from \"../../skia\";\nimport { SkiaPaint } from \"../../skia\";\nimport type { CustomPaintProps, AnimatedProps } from \"../processors\";\nimport { processPaint } from \"../processors\";\nimport { createDeclaration } from \"../nodes\";\n\nexport const usePaintRef = () => useRef<SkPaint>(null);\n\nexport interface PaintProps extends Omit<CustomPaintProps, \"paint\"> {\n children?: ReactNode | ReactNode[];\n}\n\nexport const Paint = forwardRef<SkPaint, AnimatedProps<PaintProps>>(\n (props, ref) => {\n const paint = useMemo(() => SkiaPaint(), []);\n useImperativeHandle(ref, () => paint, [paint]);\n const onDeclare = useMemo(\n () =>\n createDeclaration<PaintProps>((paintProps, children, ctx) =>\n processPaint(paint, ctx.opacity, paintProps, children)\n ),\n [paint]\n );\n return <skDeclaration onDeclare={onDeclare} {...props} />;\n }\n);\n"]}
@@ -11,6 +11,8 @@ var _nodes = require("../../nodes");
11
11
 
12
12
  var _processors = require("../../processors");
13
13
 
14
+ var _skia = require("../../../skia");
15
+
14
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
17
 
16
18
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
@@ -24,15 +26,21 @@ const onDraw = (0, _nodes.createDrawing)((_ref, _ref2) => {
24
26
  start,
25
27
  end,
26
28
  stroke,
29
+ fillType,
27
30
  ...pathProps
28
31
  } = _ref2;
29
32
  const hasStartOffset = start !== 0;
30
- const hasEndOffset = start !== 1;
33
+ const hasEndOffset = end !== 1;
31
34
  const hasStrokeOptions = stroke !== undefined;
32
- const willMutatePath = hasStartOffset || hasEndOffset || hasStrokeOptions;
35
+ const hasFillType = !!fillType;
36
+ const willMutatePath = hasStartOffset || hasEndOffset || hasStrokeOptions || hasFillType;
33
37
  const pristinePath = (0, _processors.processPath)(pathProps.path);
34
38
  const path = willMutatePath ? pristinePath.copy() : pristinePath;
35
39
 
40
+ if (hasFillType) {
41
+ path.setFillType(_skia.FillType[(0, _processors.enumKey)(fillType)]);
42
+ }
43
+
36
44
  if (hasStrokeOptions) {
37
45
  path.stroke(stroke);
38
46
  }