@shopify/react-native-skia 0.1.178 → 0.1.181

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/android/build.gradle +6 -1
  2. package/cpp/jsi/RuntimeAwareCache.cpp +0 -2
  3. package/cpp/rnskia/RNSkDomView.cpp +2 -2
  4. package/cpp/rnskia/RNSkPlatformContext.h +2 -2
  5. package/cpp/rnskia/RNSkView.h +5 -3
  6. package/cpp/rnskia/dom/base/JsiDependencyManager.h +10 -6
  7. package/cpp/rnskia/dom/base/JsiDomNode.h +133 -78
  8. package/cpp/rnskia/dom/base/JsiDomRenderNode.h +8 -8
  9. package/cpp/rnskia/dom/base/NodeProp.h +5 -5
  10. package/cpp/rnskia/dom/base/NodePropsContainer.h +7 -1
  11. package/cpp/rnskia/dom/nodes/JsiImageFilterNodes.h +10 -9
  12. package/cpp/rnskia/dom/props/ClipProp.h +13 -20
  13. package/cpp/rnskia/dom/props/PathProp.h +16 -14
  14. package/cpp/rnskia/dom/props/PointProp.h +1 -1
  15. package/cpp/rnskia/dom/props/RRectProp.h +39 -61
  16. package/cpp/rnskia/dom/props/RectProp.h +27 -25
  17. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +0 -2
  18. package/lib/commonjs/dom/nodes/paint/ImageFilters.js +10 -2
  19. package/lib/commonjs/dom/nodes/paint/ImageFilters.js.map +1 -1
  20. package/lib/commonjs/external/reanimated/moduleWrapper.d.ts +2 -2
  21. package/lib/commonjs/external/reanimated/moduleWrapper.js +33 -37
  22. package/lib/commonjs/external/reanimated/moduleWrapper.js.map +1 -1
  23. package/lib/commonjs/external/reanimated/renderHelpers.js +2 -6
  24. package/lib/commonjs/external/reanimated/renderHelpers.js.map +1 -1
  25. package/lib/commonjs/external/reanimated/useSharedValueEffect.js +1 -1
  26. package/lib/commonjs/external/reanimated/useSharedValueEffect.js.map +1 -1
  27. package/lib/commonjs/views/SkiaBaseWebView.js +5 -1
  28. package/lib/commonjs/views/SkiaBaseWebView.js.map +1 -1
  29. package/lib/module/dom/nodes/paint/ImageFilters.js +10 -2
  30. package/lib/module/dom/nodes/paint/ImageFilters.js.map +1 -1
  31. package/lib/module/external/reanimated/moduleWrapper.d.ts +2 -2
  32. package/lib/module/external/reanimated/moduleWrapper.js +31 -32
  33. package/lib/module/external/reanimated/moduleWrapper.js.map +1 -1
  34. package/lib/module/external/reanimated/renderHelpers.js +3 -7
  35. package/lib/module/external/reanimated/renderHelpers.js.map +1 -1
  36. package/lib/module/external/reanimated/useSharedValueEffect.js +2 -2
  37. package/lib/module/external/reanimated/useSharedValueEffect.js.map +1 -1
  38. package/lib/module/views/SkiaBaseWebView.js +5 -1
  39. package/lib/module/views/SkiaBaseWebView.js.map +1 -1
  40. package/lib/typescript/src/external/reanimated/moduleWrapper.d.ts +2 -2
  41. package/package.json +1 -1
  42. package/src/dom/nodes/paint/ImageFilters.ts +8 -2
  43. package/src/external/reanimated/moduleWrapper.ts +36 -38
  44. package/src/external/reanimated/renderHelpers.ts +3 -7
  45. package/src/external/reanimated/useSharedValueEffect.ts +2 -2
  46. package/src/views/SkiaBaseWebView.tsx +5 -0
@@ -28,6 +28,11 @@ def safeExtGet(prop, fallback) {
28
28
 
29
29
  apply plugin: 'com.android.library'
30
30
 
31
+ def reactNativeArchitectures() {
32
+ def value = project.getProperties().get("reactNativeArchitectures")
33
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
34
+ }
35
+
31
36
  static def findNodeModules(baseDir) {
32
37
  def basePath = baseDir.toPath().normalize()
33
38
  // Node's module resolution algorithm searches up to the root directory,
@@ -119,7 +124,7 @@ android {
119
124
  externalNativeBuild {
120
125
  cmake {
121
126
  cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID"
122
- abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
127
+ abiFilters (*reactNativeArchitectures())
123
128
  arguments '-DANDROID_STL=c++_shared',
124
129
  "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}",
125
130
  "-DNODE_MODULES_DIR=${nodeModules}",
@@ -1,5 +1,3 @@
1
- #pragma once
2
-
3
1
  #include "RuntimeAwareCache.h"
4
2
 
5
3
  namespace RNJsi {
@@ -22,7 +22,7 @@ RNSkDomRenderer::RNSkDomRenderer(std::function<void()> requestRedraw,
22
22
 
23
23
  RNSkDomRenderer::~RNSkDomRenderer() {
24
24
  if (_root != nullptr) {
25
- _root->dispose();
25
+ _root->dispose(true);
26
26
  _root = nullptr;
27
27
  }
28
28
  }
@@ -63,7 +63,7 @@ void RNSkDomRenderer::renderImmediate(
63
63
  void RNSkDomRenderer::setRoot(std::shared_ptr<JsiDomRenderNode> node) {
64
64
  std::lock_guard<std::mutex> lock(_rootLock);
65
65
  if (_root != nullptr) {
66
- _root->dispose();
66
+ _root->dispose(true);
67
67
  _root = nullptr;
68
68
  }
69
69
  _root = node;
@@ -112,8 +112,8 @@ public:
112
112
 
113
113
  /**
114
114
  * Creates an offscreen surface
115
- * @param width
116
- * @param height
115
+ * @param width width of the surface
116
+ * @param height height of the surface
117
117
  * @return sk_sp<SkSurface>
118
118
  */
119
119
  virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;
@@ -88,10 +88,11 @@ protected:
88
88
 
89
89
  class RNSkImageCanvasProvider : public RNSkCanvasProvider {
90
90
  public:
91
- RNSkImageCanvasProvider(std::function<void()> requestRedraw, float width,
91
+ RNSkImageCanvasProvider(std::shared_ptr<RNSkPlatformContext> context,
92
+ std::function<void()> requestRedraw, float width,
92
93
  float height)
93
94
  : RNSkCanvasProvider(requestRedraw), _width(width), _height(height) {
94
- _surface = SkSurface::MakeRasterN32Premul(_width, _height);
95
+ _surface = context->makeOffscreenSurface(_width, _height);
95
96
  }
96
97
 
97
98
  /**
@@ -261,8 +262,9 @@ public:
261
262
  Renders the view into an SkImage instead of the screen.
262
263
  */
263
264
  sk_sp<SkImage> makeImageSnapshot(std::shared_ptr<SkRect> bounds) {
265
+
264
266
  auto provider = std::make_shared<RNSkImageCanvasProvider>(
265
- std::bind(&RNSkView::requestRedraw, this),
267
+ getPlatformContext(), std::bind(&RNSkView::requestRedraw, this),
266
268
  _canvasProvider->getScaledWidth(), _canvasProvider->getScaledHeight());
267
269
 
268
270
  _renderer->renderImmediate(provider);
@@ -23,8 +23,10 @@ class JsiDependencyManager
23
23
  public std::enable_shared_from_this<JsiDependencyManager> {
24
24
  public:
25
25
  JsiDependencyManager(std::shared_ptr<RNSkPlatformContext> context,
26
- jsi::Object &&registerValuesCallback)
27
- : _registerValuesCallback(std::move(registerValuesCallback)),
26
+ jsi::Runtime &runtime,
27
+ const jsi::Value &registerValuesCallback)
28
+ : _registerValuesCallback(std::make_shared<jsi::Object>(
29
+ registerValuesCallback.asObject(runtime))),
28
30
  JsiHostObject() {}
29
31
 
30
32
  ~JsiDependencyManager() { unsubscribeAll(); }
@@ -158,7 +160,7 @@ public:
158
160
  }
159
161
 
160
162
  // Call JS registerValues callback
161
- auto func = _registerValuesCallback.asFunction(runtime);
163
+ auto func = _registerValuesCallback->asFunction(runtime);
162
164
  _unregisterValues = std::make_shared<jsi::Object>(
163
165
  func.call(runtime, array, 1).asObject(runtime));
164
166
 
@@ -187,6 +189,8 @@ public:
187
189
 
188
190
  unsubscribeAll();
189
191
 
192
+ _registerValuesCallback = nullptr;
193
+
190
194
  return jsi::Value::undefined();
191
195
  }
192
196
 
@@ -203,8 +207,8 @@ public:
203
207
  return JSI_HOST_FUNCTION_LAMBDA {
204
208
  // Params: registerValues: (values: Array<SkiaValue<unknown>>) => () =>
205
209
  // void
206
- auto obj = std::make_shared<JsiDependencyManager>(
207
- context, getArgumentAsObject(runtime, arguments, count, 0));
210
+ auto obj = std::make_shared<JsiDependencyManager>(context, runtime,
211
+ arguments[0]);
208
212
 
209
213
  return jsi::Object::createFromHostObject(runtime, std::move(obj));
210
214
  };
@@ -283,7 +287,7 @@ private:
283
287
  return false;
284
288
  }
285
289
 
286
- jsi::Object _registerValuesCallback;
290
+ std::shared_ptr<jsi::Object> _registerValuesCallback;
287
291
  std::shared_ptr<jsi::Object> _unregisterValues;
288
292
  std::map<JsiDomNode *,
289
293
  std::vector<std::pair<std::shared_ptr<RNSkReadonlyValue>,
@@ -49,7 +49,19 @@ public:
49
49
  JsiDomNode(std::shared_ptr<RNSkPlatformContext> context, const char *type,
50
50
  NodeClass nodeClass)
51
51
  : _type(type), _context(context), _nodeClass(nodeClass),
52
- _nodeId(NodeIdent++), JsiHostObject() {}
52
+ _nodeId(NodeIdent++), JsiHostObject() {
53
+ #if SKIA_DOM_DEBUG
54
+ printDebugInfo("JsiDomNode." + std::string(_type) +
55
+ " CTOR - nodeId: " + std::to_string(_nodeId));
56
+ #endif
57
+ }
58
+
59
+ virtual ~JsiDomNode() {
60
+ #if SKIA_DOM_DEBUG
61
+ printDebugInfo("JsiDomNode." + std::string(_type) +
62
+ " DTOR - nodeId: " + std::to_string(_nodeId));
63
+ #endif
64
+ }
53
65
 
54
66
  /**
55
67
  Called when creating the node, resolves properties from the node constructor.
@@ -65,7 +77,7 @@ public:
65
77
  JSI_HOST_FUNCTION(setProps) {
66
78
  if (count == 1) {
67
79
  // Initialize properties container
68
- setProps(runtime, getArgumentAsObject(runtime, arguments, count, 0));
80
+ setProps(runtime, arguments[0]);
69
81
  } else {
70
82
  setEmptyProps();
71
83
  }
@@ -102,7 +114,7 @@ public:
102
114
  tree. Use for cleaning up.
103
115
  */
104
116
  JSI_HOST_FUNCTION(dispose) {
105
- dispose();
117
+ dispose(false);
106
118
  return jsi::Value::undefined();
107
119
  }
108
120
 
@@ -247,36 +259,9 @@ public:
247
259
  _propsContainer->markAsResolved();
248
260
  }
249
261
 
250
- // Now let's dispose if needed
262
+ // Now let's invalidate if needed
251
263
  if (_isDisposing && !_isDisposed) {
252
- _isDisposed = true;
253
-
254
- this->setParent(nullptr);
255
-
256
- // Callback signaling that we're done
257
- if (_disposeCallback != nullptr) {
258
- _disposeCallback();
259
- _disposeCallback = nullptr;
260
- }
261
-
262
- // Clear props
263
- if (_propsContainer != nullptr) {
264
- _propsContainer->dispose();
265
- }
266
-
267
- // Remove children
268
- std::vector<std::shared_ptr<JsiDomNode>> tmp;
269
- {
270
- std::lock_guard<std::mutex> lock(_childrenLock);
271
- tmp.reserve(_children.size());
272
- for (auto &child : _children) {
273
- tmp.push_back(child);
274
- }
275
- _children.clear();
276
- }
277
- for (auto &child : tmp) {
278
- child->dispose();
279
- }
264
+ invalidate();
280
265
  }
281
266
 
282
267
  // Resolve children
@@ -292,6 +277,22 @@ public:
292
277
  // Empty implementation
293
278
  }
294
279
 
280
+ /**
281
+ Called when a node has been removed from the dom tree and needs to be cleaned
282
+ up. If the invalidate parameter is set, we will invalidate the node directly.
283
+ Calling dispose from the JS dispose function calls this with invalidate set
284
+ to false, while the dom render view calls this with true.
285
+ */
286
+ virtual void dispose(bool immediate) {
287
+ if (_isDisposing) {
288
+ return;
289
+ }
290
+ _isDisposing = true;
291
+ if (immediate) {
292
+ invalidate();
293
+ }
294
+ }
295
+
295
296
  protected:
296
297
  /**
297
298
  Adds an operation that will be executed when the render cycle is finished.
@@ -319,24 +320,17 @@ protected:
319
320
 
320
321
  /**
321
322
  Native implementation of the set properties method. This is called from the
322
- reconciler when properties are set due to changes in React. This method will
323
- always call the onPropsSet method as a signal that things have changed.
323
+ reconciler when properties are set due to changes in React.
324
324
  */
325
- void setProps(jsi::Runtime &runtime, jsi::Object &&props) {
325
+ void setProps(jsi::Runtime &runtime, const jsi::Value &maybeProps) {
326
326
  #if SKIA_DOM_DEBUG
327
327
  printDebugInfo("JS:setProps(nodeId: " + std::to_string(_nodeId) + ")");
328
328
  #endif
329
- if (_propsContainer == nullptr) {
329
+ // Initialize properties container
330
+ ensurePropertyContainer();
330
331
 
331
- // Initialize properties container
332
- _propsContainer = std::make_shared<NodePropsContainer>(
333
- getType(), [=](BaseNodeProp *p) { onPropertyChanged(p); });
334
-
335
- // Ask sub classes to define their properties
336
- defineProperties(_propsContainer.get());
337
- }
338
332
  // Update properties container
339
- _propsContainer->setProps(runtime, std::move(props));
333
+ _propsContainer->setProps(runtime, maybeProps);
340
334
 
341
335
  // Invalidate context
342
336
  invalidateContext();
@@ -349,15 +343,8 @@ protected:
349
343
  #if SKIA_DOM_DEBUG
350
344
  printDebugInfo("JS:setEmptyProps(nodeId: " + std::to_string(_nodeId) + ")");
351
345
  #endif
352
- if (_propsContainer == nullptr) {
353
-
354
- // Initialize properties container
355
- _propsContainer = std::make_shared<NodePropsContainer>(
356
- getType(), [=](BaseNodeProp *p) { onPropertyChanged(p); });
357
-
358
- // Ask sub classes to define their properties
359
- defineProperties(_propsContainer.get());
360
- }
346
+ // Initialize properties container
347
+ ensurePropertyContainer();
361
348
  }
362
349
 
363
350
  /**
@@ -381,9 +368,12 @@ protected:
381
368
  printDebugInfo("JS:addChild(childId: " + std::to_string(child->_nodeId) +
382
369
  ")");
383
370
  #endif
384
- enqueAsynOperation([child, this]() {
385
- _children.push_back(child);
386
- child->setParent(this);
371
+ enqueAsynOperation([child, weakSelf = weak_from_this()]() {
372
+ auto self = weakSelf.lock();
373
+ if (self) {
374
+ self->_children.push_back(child);
375
+ child->setParent(self.get());
376
+ }
387
377
  });
388
378
  }
389
379
 
@@ -398,10 +388,14 @@ protected:
398
388
  "JS:insertChildBefore(childId: " + std::to_string(child->_nodeId) +
399
389
  ", beforeId: " + std::to_string(before->_nodeId) + ")");
400
390
  #endif
401
- enqueAsynOperation([child, before, this]() {
402
- auto position = std::find(_children.begin(), _children.end(), before);
403
- _children.insert(position, child);
404
- child->setParent(this);
391
+ enqueAsynOperation([child, before, weakSelf = weak_from_this()]() {
392
+ auto self = weakSelf.lock();
393
+ if (self) {
394
+ auto position =
395
+ std::find(self->_children.begin(), self->_children.end(), before);
396
+ self->_children.insert(position, child);
397
+ child->setParent(self.get());
398
+ }
405
399
  });
406
400
  }
407
401
 
@@ -414,27 +408,25 @@ protected:
414
408
  printDebugInfo("JS:removeChild(childId: " + std::to_string(child->_nodeId) +
415
409
  ")");
416
410
  #endif
417
- enqueAsynOperation([child, this]() {
418
- // Delete child itself
419
- _children.erase(
420
- std::remove_if(_children.begin(), _children.end(),
421
- [child](const auto &node) { return node == child; }),
422
- _children.end());
423
-
424
- child->dispose();
425
- });
426
- }
411
+ auto removeChild = [child,
412
+ weakSelf = weak_from_this()](bool immediate = false) {
413
+ auto self = weakSelf.lock();
414
+ if (self) {
415
+ // Delete child itself
416
+ self->_children.erase(
417
+ std::remove_if(self->_children.begin(), self->_children.end(),
418
+ [child](const auto &node) { return node == child; }),
419
+ self->_children.end());
420
+
421
+ child->dispose(immediate);
422
+ }
423
+ };
427
424
 
428
- /**
429
- Called when a node has been removed from the dom tree and needs to be cleaned
430
- up.
431
- */
432
- virtual void dispose() {
433
425
  if (_isDisposing) {
434
- return;
426
+ removeChild(false);
427
+ } else {
428
+ enqueAsynOperation(removeChild);
435
429
  }
436
-
437
- _isDisposing = true;
438
430
  }
439
431
 
440
432
  #if SKIA_DOM_DEBUG
@@ -477,6 +469,69 @@ protected:
477
469
  }
478
470
 
479
471
  private:
472
+ /**
473
+ Invalidates the node - meaning removing and clearing children and properties
474
+ **/
475
+ void invalidate() {
476
+ if (_isDisposing && !_isDisposed) {
477
+ #if SKIA_DOM_DEBUG
478
+ printDebugInfo("JsiDomNode::invalidate: nodeid: " +
479
+ std::to_string(_nodeId));
480
+ #endif
481
+
482
+ _isDisposed = true;
483
+
484
+ // Clear parent
485
+ this->setParent(nullptr);
486
+
487
+ // Clear any async operations
488
+ _queuedNodeOps.clear();
489
+
490
+ // Callback signaling that we're done
491
+ if (_disposeCallback != nullptr) {
492
+ _disposeCallback();
493
+ _disposeCallback = nullptr;
494
+ }
495
+
496
+ // Clear props
497
+ if (_propsContainer != nullptr) {
498
+ _propsContainer->dispose();
499
+ }
500
+
501
+ // Remove children
502
+ std::vector<std::shared_ptr<JsiDomNode>> tmp;
503
+ {
504
+ std::lock_guard<std::mutex> lock(_childrenLock);
505
+ tmp.reserve(_children.size());
506
+ for (auto &child : _children) {
507
+ tmp.push_back(child);
508
+ }
509
+ _children.clear();
510
+ }
511
+ for (auto &child : tmp) {
512
+ child->dispose(true);
513
+ }
514
+ }
515
+ }
516
+
517
+ /**
518
+ Creates and sets up the property container
519
+ */
520
+ void ensurePropertyContainer() {
521
+ if (_propsContainer == nullptr) {
522
+ _propsContainer = std::make_shared<NodePropsContainer>(
523
+ getType(), [weakSelf = weak_from_this()](BaseNodeProp *p) {
524
+ auto self = weakSelf.lock();
525
+ if (self) {
526
+ self->onPropertyChanged(p);
527
+ }
528
+ });
529
+
530
+ // Ask sub classes to define their properties
531
+ defineProperties(_propsContainer.get());
532
+ }
533
+ }
534
+
480
535
  const char *_type;
481
536
  std::shared_ptr<RNSkPlatformContext> _context;
482
537
 
@@ -132,19 +132,19 @@ public:
132
132
  */
133
133
  void resetPendingChanges() override { JsiDomNode::resetPendingChanges(); }
134
134
 
135
- /**
136
- Signal from the JS side that the node is removed from the dom.
137
- */
138
- void dispose() override { JsiDomNode::dispose(); }
139
-
140
135
  protected:
141
136
  /**
142
137
  Invalidates and marks then context as changed.
143
138
  */
144
139
  void invalidateContext() override {
145
- enqueAsynOperation([=]() {
146
- _paintCache.parent = nullptr;
147
- _paintCache.child = nullptr;
140
+ enqueAsynOperation([weakSelf = weak_from_this()]() {
141
+ auto self = weakSelf.lock();
142
+ if (self) {
143
+ std::static_pointer_cast<JsiDomRenderNode>(self)->_paintCache.parent =
144
+ nullptr;
145
+ std::static_pointer_cast<JsiDomRenderNode>(self)->_paintCache.child =
146
+ nullptr;
147
+ }
148
148
  });
149
149
  }
150
150
 
@@ -33,7 +33,7 @@ public:
33
33
  // readValueFromJS Function (which comes from the reconciler
34
34
  // setting a new property value on the property
35
35
  if (_value == nullptr) {
36
- _value = std::make_shared<JsiValue>(runtime, read(runtime, _name, this));
36
+ _value = std::make_unique<JsiValue>(runtime, read(runtime, _name, this));
37
37
  _isChanged = true;
38
38
  _hasNewValue = false;
39
39
  } else {
@@ -41,7 +41,7 @@ public:
41
41
  std::lock_guard<std::mutex> lock(_swapMutex);
42
42
  if (_buffer == nullptr) {
43
43
  _buffer =
44
- std::make_shared<JsiValue>(runtime, read(runtime, _name, this));
44
+ std::make_unique<JsiValue>(runtime, read(runtime, _name, this));
45
45
  } else {
46
46
  _buffer->setCurrent(runtime, read(runtime, _name, this));
47
47
  }
@@ -60,7 +60,7 @@ public:
60
60
  // and we don't want to rip out the underlying value object.
61
61
  std::lock_guard<std::mutex> lock(_swapMutex);
62
62
  if (_buffer == nullptr) {
63
- _buffer = std::make_shared<JsiValue>(runtime, value);
63
+ _buffer = std::make_unique<JsiValue>(runtime, value);
64
64
  } else {
65
65
  _buffer->setCurrent(runtime, value);
66
66
  }
@@ -129,8 +129,8 @@ private:
129
129
 
130
130
  std::function<void(BaseNodeProp *)> _onChange;
131
131
 
132
- std::shared_ptr<JsiValue> _value;
133
- std::shared_ptr<JsiValue> _buffer;
132
+ std::unique_ptr<JsiValue> _value;
133
+ std::unique_ptr<JsiValue> _buffer;
134
134
  std::atomic<bool> _isChanged = {false};
135
135
  std::atomic<bool> _hasNewValue = {false};
136
136
  std::mutex _swapMutex;
@@ -82,10 +82,16 @@ public:
82
82
  /**
83
83
  Called when the React / JS side sets properties on a node
84
84
  */
85
- void setProps(jsi::Runtime &runtime, jsi::Object &&props) {
85
+ void setProps(jsi::Runtime &runtime, const jsi::Value &maybePropsObject) {
86
86
  // Clear property mapping
87
87
  _mappedProperties.clear();
88
88
 
89
+ if (!maybePropsObject.isObject()) {
90
+ throw jsi::JSError(runtime, "Expected property object.");
91
+ }
92
+
93
+ auto props = maybePropsObject.asObject(runtime);
94
+
89
95
  // Use specialized reader function to be able to intercept calls that
90
96
  // reads specific named values from the js property object.
91
97
  auto read = [&](jsi::Runtime &runtime, PropId name, NodeProp *prop) {
@@ -158,20 +158,21 @@ public:
158
158
  : JsiBaseImageFilterNode(context, "skDisplacementMapImageFilter") {}
159
159
 
160
160
  void decorate(DeclarationContext *context) override {
161
-
161
+ decorateChildren(context);
162
162
  auto channelX =
163
163
  getColorChannelFromStringValue(_channelXProp->value().getAsString());
164
164
  auto channelY =
165
165
  getColorChannelFromStringValue(_channelYProp->value().getAsString());
166
166
  auto scale = _scaleProp->value().getAsNumber();
167
-
168
- auto displacement = context->getImageFilters()->pop();
169
-
170
- auto color = context->getImageFilters()->pop();
171
-
172
- composeAndPush(context, SkImageFilters::DisplacementMap(
173
- channelX, channelY, scale, displacement,
174
- color ? color : nullptr));
167
+ auto shader = context->getShaders()->pop();
168
+ if (!shader) {
169
+ throw std::runtime_error("DisplacementMap expects a shader as child");
170
+ }
171
+ auto map = SkImageFilters::Shader(shader);
172
+ auto input = context->getImageFilters()->pop();
173
+ auto imgf = SkImageFilters::DisplacementMap(channelX, channelY, scale, map,
174
+ input ? input : nullptr);
175
+ context->getImageFilters()->push(imgf);
175
176
  }
176
177
 
177
178
  protected:
@@ -22,43 +22,36 @@ public:
22
22
  explicit ClipProp(PropId name,
23
23
  const std::function<void(BaseNodeProp *)> &onChange)
24
24
  : BaseDerivedProp(onChange) {
25
- _pathProp = defineProperty<PathProp>(name);
26
- _rectProp = defineProperty<RectProp>(name);
27
- _rrectProp = defineProperty<RRectProp>(name);
25
+ _clipProp = defineProperty<NodeProp>(name);
28
26
  }
29
27
 
30
28
  void updateDerivedValue() override {
31
- if (_pathProp->isSet()) {
32
- _rect = nullptr;
33
- _rrect = nullptr;
34
- _path = _pathProp->getDerivedValue();
35
- } else if (_rrectProp->isSet()) {
36
- _rect = nullptr;
37
- _rrect = _rrectProp->getDerivedValue();
38
- _path = nullptr;
39
- } else if (_rectProp->isSet()) {
40
- _rect = _rectProp->getDerivedValue();
29
+ if (_clipProp->isSet()) {
30
+ auto value = _clipProp->value();
31
+ _rect = RectProp::processRect(value);
41
32
  _rrect = nullptr;
42
33
  _path = nullptr;
34
+ if (!_rect) {
35
+ _path = PathProp::processPath(value);
36
+ if (!_path) {
37
+ _rrect = RRectProp::processRRect(value);
38
+ }
39
+ }
43
40
  }
44
41
  }
45
42
 
46
- bool isSet() override {
47
- return _pathProp->isSet() || _rectProp->isSet() || _rrectProp->isSet();
48
- }
43
+ bool isSet() override { return _clipProp->isSet(); }
49
44
 
50
45
  const SkPath *getPath() { return _path.get(); }
51
46
  const SkRect *getRect() { return _rect.get(); }
52
47
  const SkRRect *getRRect() { return _rrect.get(); }
53
48
 
54
49
  private:
55
- PathProp *_pathProp;
56
- RectProp *_rectProp;
57
- RRectProp *_rrectProp;
50
+ NodeProp *_clipProp;
58
51
 
59
52
  std::shared_ptr<const SkPath> _path;
60
53
  std::shared_ptr<const SkRect> _rect;
61
54
  std::shared_ptr<const SkRRect> _rrect;
62
55
  };
63
56
 
64
- } // namespace RNSkia
57
+ } // namespace RNSkia
@@ -22,32 +22,34 @@ public:
22
22
  _pathProp = defineProperty<NodeProp>(name);
23
23
  }
24
24
 
25
- void updateDerivedValue() override {
26
- if (!_pathProp->isSet()) {
27
- setDerivedValue(nullptr);
28
- return;
29
- }
30
-
31
- if (_pathProp->value().getType() == PropType::HostObject) {
25
+ static std::shared_ptr<SkPath> processPath(const JsiValue &value) {
26
+ if (value.getType() == PropType::HostObject) {
32
27
  // Try reading as Path
33
- auto ptr = std::dynamic_pointer_cast<JsiSkPath>(
34
- _pathProp->value().getAsHostObject());
28
+ auto ptr = std::dynamic_pointer_cast<JsiSkPath>(value.getAsHostObject());
35
29
  if (ptr != nullptr) {
36
- setDerivedValue(ptr->getObject());
30
+ return ptr->getObject();
37
31
  }
38
- } else if (_pathProp->value().getType() == PropType::String) {
32
+ } else if (value.getType() == PropType::String) {
39
33
  // Read as string
40
- auto pathString = _pathProp->value().getAsString();
34
+ auto pathString = value.getAsString();
41
35
  SkPath result;
42
36
 
43
37
  if (SkParsePath::FromSVGString(pathString.c_str(), &result)) {
44
- setDerivedValue(std::make_shared<SkPath>(result));
38
+ return std::make_shared<SkPath>(result);
45
39
  } else {
46
40
  throw std::runtime_error("Could not parse path from string.");
47
41
  }
48
- } else {
42
+ }
43
+ return nullptr;
44
+ }
45
+
46
+ void updateDerivedValue() override {
47
+ if (!_pathProp->isSet()) {
49
48
  setDerivedValue(nullptr);
49
+ return;
50
50
  }
51
+ auto value = _pathProp->value();
52
+ setDerivedValue(PathProp::processPath(value));
51
53
  }
52
54
 
53
55
  private:
@@ -29,7 +29,7 @@ public:
29
29
  void updateDerivedValue() override {
30
30
  if (_pointProp->isSet()) {
31
31
  // Check for JsiSkRect and JsiSkPoint
32
- setDerivedValue(std::move(processValue(_pointProp->value())));
32
+ setDerivedValue(processValue(_pointProp->value()));
33
33
  } else {
34
34
  setDerivedValue(nullptr);
35
35
  }