@shopify/react-native-skia 0.1.180 → 0.1.181

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;
@@ -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) {
@@ -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
  }
@@ -33,35 +33,33 @@ public:
33
33
  _prop = defineProperty<NodeProp>(name);
34
34
  }
35
35
 
36
- void updateDerivedValue() override {
37
- if (_prop->isSet()) {
38
- // Check for JsiSkRRect
39
- if (_prop->value().getType() == PropType::HostObject) {
40
- // Try reading as rect
41
- auto rectPtr = std::dynamic_pointer_cast<JsiSkRRect>(
42
- _prop->value().getAsHostObject());
43
- if (rectPtr != nullptr) {
44
- auto rrect = rectPtr->getObject();
45
- setDerivedValue(SkRRect::MakeRectXY(
46
- SkRect::MakeXYWH(rrect->rect().x(), rrect->rect().y(),
47
- rrect->rect().width(), rrect->rect().height()),
48
- rrect->getSimpleRadii().x(), rrect->getSimpleRadii().y()));
49
- }
50
- } else {
51
- if (_prop->isSet() && _prop->value().getType() == PropType::Object) {
52
- auto p = _prop->value();
53
- if (p.hasValue(PropNameX) && p.hasValue(PropNameY) &&
54
- p.hasValue(PropNameWidth) && p.hasValue(PropNameHeight) &&
55
- p.hasValue(PropNameRx) && p.hasValue(PropNameRy)) {
56
- auto x = _prop->value().getValue(PropNameX);
57
- auto y = _prop->value().getValue(PropNameY);
58
- auto width = _prop->value().getValue(PropNameWidth);
59
- auto height = _prop->value().getValue(PropNameHeight);
60
- auto rx = _prop->value().getValue(PropNameRx);
61
- auto ry = _prop->value().getValue(PropNameRy);
36
+ static std::shared_ptr<SkRRect> processRRect(const JsiValue &value) {
37
+ if (value.getType() == PropType::HostObject) {
38
+ // Try reading as rect
39
+ auto rectPtr =
40
+ std::dynamic_pointer_cast<JsiSkRRect>(value.getAsHostObject());
41
+ if (rectPtr != nullptr) {
42
+ auto rrect = rectPtr->getObject();
43
+ return std::make_shared<SkRRect>(
44
+ SkRRect::MakeRectXY(rrect->rect(), rrect->getSimpleRadii().x(),
45
+ rrect->getSimpleRadii().y()));
46
+ }
47
+ } else {
48
+ if (value.getType() == PropType::Object) {
49
+ if (value.hasValue(PropNameRect) && value.hasValue(PropNameRx) &&
50
+ value.hasValue(PropNameRy)) {
51
+ auto rect = value.getValue(PropNameRect);
52
+ if (rect.hasValue(PropNameX) && rect.hasValue(PropNameY) &&
53
+ rect.hasValue(PropNameWidth) && rect.hasValue(PropNameHeight)) {
54
+ auto x = rect.getValue(PropNameX);
55
+ auto y = rect.getValue(PropNameY);
56
+ auto width = rect.getValue(PropNameWidth);
57
+ auto height = rect.getValue(PropNameHeight);
58
+ auto rx = value.getValue(PropNameRx);
59
+ auto ry = value.getValue(PropNameRy);
62
60
 
63
61
  // Update cache from js object value
64
- setDerivedValue(SkRRect::MakeRectXY(
62
+ return std::make_shared<SkRRect>(SkRRect::MakeRectXY(
65
63
  SkRect::MakeXYWH(x.getAsNumber(), y.getAsNumber(),
66
64
  width.getAsNumber(), height.getAsNumber()),
67
65
  rx.getAsNumber(), ry.getAsNumber()));
@@ -69,6 +67,14 @@ public:
69
67
  }
70
68
  }
71
69
  }
70
+ return nullptr;
71
+ }
72
+
73
+ void updateDerivedValue() override {
74
+ if (_prop->isSet()) {
75
+ auto value = _prop->value();
76
+ setDerivedValue(RRectProp::processRRect(value));
77
+ }
72
78
  }
73
79
 
74
80
  private:
@@ -150,40 +156,12 @@ public:
150
156
  }
151
157
 
152
158
  void updateDerivedValue() override {
153
- if (_boxProp->value().getType() == PropType::HostObject) {
154
- auto rectPtr = std::dynamic_pointer_cast<JsiSkRect>(
155
- _boxProp->value().getAsHostObject());
156
- auto rrectPtr = std::dynamic_pointer_cast<JsiSkRRect>(
157
- _boxProp->value().getAsHostObject());
158
- // 1. box is SkRect
159
- if (rectPtr != nullptr) {
160
- auto rect = rectPtr->getObject();
161
- setDerivedValue(SkRRect::MakeRect(*rect));
162
- // 2. box is SkRRect
163
- } else if (rrectPtr != nullptr) {
164
- setDerivedValue(rrectPtr->getObject());
165
- }
166
- } else if (_boxProp->value().getType() == PropType::Object) {
167
- if (_boxProp->value().hasValue(PropNameRect)) {
168
- // 3. box is { rect: { x, y, width, height }, rx, ry }
169
- auto rectProp = _boxProp->value().getValue(PropNameRect);
170
- auto x = rectProp.getValue(PropNameX).getAsNumber();
171
- auto y = rectProp.getValue(PropNameY).getAsNumber();
172
- auto width = rectProp.getValue(PropNameWidth).getAsNumber();
173
- auto height = rectProp.getValue(PropNameHeight).getAsNumber();
174
- auto rx = _boxProp->value().getValue(PropNameRx).getAsNumber();
175
- auto ry = _boxProp->value().getValue(PropNameRy).getAsNumber();
176
- setDerivedValue(
177
- SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, width, height), rx, ry));
178
- } else {
179
- // 4. box is { x, y, width, height }
180
- auto x = _boxProp->value().getValue(PropNameX).getAsNumber();
181
- auto y = _boxProp->value().getValue(PropNameY).getAsNumber();
182
- auto width = _boxProp->value().getValue(PropNameWidth).getAsNumber();
183
- auto height = _boxProp->value().getValue(PropNameHeight).getAsNumber();
184
- setDerivedValue(
185
- SkRRect::MakeRect(SkRect::MakeXYWH(x, y, width, height)));
186
- }
159
+ auto value = _boxProp->value();
160
+ auto rect = RectProp::processRect(value);
161
+ if (rect) {
162
+ setDerivedValue(SkRRect::MakeRect(*rect));
163
+ } else {
164
+ setDerivedValue(RRectProp::processRRect(value));
187
165
  }
188
166
  }
189
167
 
@@ -31,33 +31,35 @@ public:
31
31
  _prop = defineProperty<NodeProp>(name);
32
32
  }
33
33
 
34
+ static std::shared_ptr<SkRect> processRect(const JsiValue &value) {
35
+ if (value.getType() == PropType::HostObject) {
36
+ auto rectPtr =
37
+ std::dynamic_pointer_cast<JsiSkRect>(value.getAsHostObject());
38
+ if (rectPtr != nullptr) {
39
+ return std::make_shared<SkRect>(SkRect::MakeXYWH(
40
+ rectPtr->getObject()->x(), rectPtr->getObject()->y(),
41
+ rectPtr->getObject()->width(), rectPtr->getObject()->height()));
42
+ }
43
+ } else if (value.getType() == PropType::Object &&
44
+ value.hasValue(PropNameX) && value.hasValue(PropNameY) &&
45
+ value.hasValue(PropNameWidth) &&
46
+ value.hasValue(PropNameHeight)) {
47
+ // Save props for fast access
48
+ auto x = value.getValue(PropNameX);
49
+ auto y = value.getValue(PropNameY);
50
+ auto width = value.getValue(PropNameWidth);
51
+ auto height = value.getValue(PropNameHeight);
52
+ // Update cache from js object value
53
+ return std::make_shared<SkRect>(
54
+ SkRect::MakeXYWH(x.getAsNumber(), y.getAsNumber(),
55
+ width.getAsNumber(), height.getAsNumber()));
56
+ }
57
+ return nullptr;
58
+ }
59
+
34
60
  void updateDerivedValue() override {
35
61
  if (_prop->isSet()) {
36
- // Check for JsiSkRect
37
- if (_prop->value().getType() == PropType::HostObject) {
38
- auto rectPtr = std::dynamic_pointer_cast<JsiSkRect>(
39
- _prop->value().getAsHostObject());
40
- if (rectPtr != nullptr) {
41
- setDerivedValue(SkRect::MakeXYWH(
42
- rectPtr->getObject()->x(), rectPtr->getObject()->y(),
43
- rectPtr->getObject()->width(), rectPtr->getObject()->height()));
44
- }
45
- } else {
46
- auto p = _prop->value();
47
- if (p.hasValue(PropNameX) && p.hasValue(PropNameY) &&
48
- p.hasValue(PropNameWidth) && p.hasValue(PropNameHeight)) {
49
- // Save props for fast access
50
- auto x = p.getValue(PropNameX);
51
- auto y = p.getValue(PropNameY);
52
- auto width = p.getValue(PropNameWidth);
53
- auto height = p.getValue(PropNameHeight);
54
-
55
- // Update cache from js object value
56
- setDerivedValue(SkRect::MakeXYWH(x.getAsNumber(), y.getAsNumber(),
57
- width.getAsNumber(),
58
- height.getAsNumber()));
59
- }
60
- }
62
+ setDerivedValue(RectProp::processRect(_prop->value()));
61
63
  }
62
64
  }
63
65
 
@@ -4,7 +4,6 @@
4
4
  #include <thread>
5
5
  #include <utility>
6
6
 
7
- #include <RNSkMeasureTime.h>
8
7
  #include <SkiaMetalRenderer.h>
9
8
 
10
9
  #pragma clang diagnostic push
@@ -20,7 +19,6 @@ void RNSkiOSPlatformContext::performStreamOperation(
20
19
  const std::string &sourceUri,
21
20
  const std::function<void(std::unique_ptr<SkStreamAsset>)> &op) {
22
21
 
23
- RNSkMeasureTime("PlatformContext::performStreamOperation");
24
22
  auto loader = [=]() {
25
23
  NSURL *url = [[NSURL alloc]
26
24
  initWithString:[NSString stringWithUTF8String:sourceUri.c_str()]];
@@ -103,8 +103,12 @@ class SkiaBaseWebView extends _react.default.Component {
103
103
  }
104
104
 
105
105
  componentWillUnmount() {
106
+ var _this$_canvasRef$curr, _this$_canvasRef$curr2, _this$_canvasRef$curr3;
107
+
106
108
  this.unsubscribeAll();
107
- cancelAnimationFrame(this.requestId);
109
+ cancelAnimationFrame(this.requestId); // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context
110
+
111
+ (_this$_canvasRef$curr = this._canvasRef.current) === null || _this$_canvasRef$curr === void 0 ? void 0 : (_this$_canvasRef$curr2 = _this$_canvasRef$curr.getContext("webgl2")) === null || _this$_canvasRef$curr2 === void 0 ? void 0 : (_this$_canvasRef$curr3 = _this$_canvasRef$curr2.getExtension("WEBGL_lose_context")) === null || _this$_canvasRef$curr3 === void 0 ? void 0 : _this$_canvasRef$curr3.loseContext();
108
112
  }
109
113
  /**
110
114
  * Creates a snapshot from the canvas in the surface
@@ -1 +1 @@
1
- {"version":3,"names":["pd","PixelRatio","get","SkiaBaseWebView","React","Component","constructor","props","createRef","_mode","mode","unsubscribeAll","_unsubscriptions","forEach","u","onLayout","evt","CanvasKit","global","width","height","nativeEvent","layout","_canvasRef","current","canvas","surface","MakeWebGLCanvasSurface","Error","_surface","JsiSkSurface","_canvas","getCanvas","redraw","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","makeImageSnapshot","rect","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","touches","_touches","Float32Array","of","save","scale","restore","requestAnimationFrame","bind","setDrawMode","registerValues","_values","v","push","addListener","handleTouchEvent","touchType","id","pointerId","x","clientX","currentTarget","getClientRects","left","y","clientY","top","force","pressure","type","timestamp","Date","now","createTouchHandler","render","debug","viewProps","display","flex","TouchType","Start","Active","End","Cancelled"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { PointerEvent } from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\nimport { PixelRatio, View } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport type { SkiaValue } from \"../values\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\n\nimport type { DrawMode, SkiaBaseViewProps, TouchInfo } from \"./types\";\nimport { TouchType } from \"./types\";\n\nconst pd = PixelRatio.get();\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n this._mode = props.mode ?? \"default\";\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _touches: Array<TouchInfo> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _mode: DrawMode;\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayout(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n const { width, height } = evt.nativeEvent.layout;\n this.width = width;\n this.height = height;\n // Reset canvas / surface on layout change\n if (this._canvasRef.current) {\n const canvas = this._canvasRef.current;\n canvas.width = width * pd;\n canvas.height = height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(this._canvasRef.current);\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n protected getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!, []);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(\n canvas: SkCanvas,\n touches: TouchInfo[]\n ): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._mode === \"continuous\" || this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const touches = [...this._touches];\n this._touches = [];\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas, touches);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n /**\n * Updates the drawing mode for the skia view. This is the same\n * as declaratively setting the mode property on the SkiaView.\n * There are two drawing modes, \"continuous\" and \"default\",\n * where the continuous mode will continuously redraw the view and\n * the default mode will only redraw when any of the regular react\n * properties are changed like size and margins.\n * @param mode Drawing mode to use.\n */\n public setDrawMode(mode: DrawMode) {\n this._mode = mode;\n this.tick();\n }\n\n /**\n * Registers one or move values as a dependant value of the Skia View. The view will\n * The view will redraw itself when any of the values change.\n * @param values Values to register\n */\n public registerValues(_values: SkiaValue<unknown>[]) {\n // Unsubscribe from dependency values\n this.unsubscribeAll();\n // Register redraw dependencies on values\n _values.forEach((v) => {\n this._unsubscriptions.push(\n v.addListener(() => {\n this.redraw();\n })\n );\n });\n }\n\n private handleTouchEvent(evt: PointerEvent, touchType: TouchType) {\n this._touches.push({\n id: evt.pointerId,\n x: evt.clientX - evt.currentTarget.getClientRects()[0].left,\n y: evt.clientY - evt.currentTarget.getClientRects()[0].top,\n force: evt.pressure,\n type: touchType,\n timestamp: Date.now(),\n });\n this.redraw();\n }\n\n createTouchHandler(touchType: TouchType) {\n return (evt: PointerEvent) => this.handleTouchEvent(evt, touchType);\n }\n\n render() {\n const { mode, debug = false, ...viewProps } = this.props;\n return (\n <View {...viewProps} onLayout={this.onLayout.bind(this)}>\n <canvas\n ref={this._canvasRef}\n style={{ display: \"flex\", flex: 1 }}\n onPointerDown={this.createTouchHandler(TouchType.Start)}\n onPointerMove={this.createTouchHandler(TouchType.Active)}\n onPointerUp={this.createTouchHandler(TouchType.End)}\n onPointerCancel={this.createTouchHandler(TouchType.Cancelled)}\n onPointerLeave={this.createTouchHandler(TouchType.End)}\n onPointerOut={this.createTouchHandler(TouchType.End)}\n />\n </View>\n );\n }\n}\n"],"mappings":";;;;;;;AACA;;AAGA;;AAIA;;AAGA;;;;;;;;AAEA,MAAMA,EAAE,GAAGC,uBAAA,CAAWC,GAAX,EAAX;;AAEO,MAAeC,eAAf,SAEGC,cAAA,CAAMC,SAFT,CAE2B;EAChCC,WAAW,CAACC,KAAD,EAAgB;IACzB,MAAMA,KAAN;;IADyB,kCAKa,IALb;;IAAA,0CAMmB,EANnB;;IAAA,kCAOU,EAPV;;IAAA,iCAQQ,IARR;;IAAA,iDASNH,cAAA,CAAMI,SAAN,EATM;;IAAA;;IAAA,yCAWD,CAXC;;IAAA,mCAYP,CAZO;;IAAA,+BAcT,CAdS;;IAAA,gCAeR,CAfQ;;IAEzB,KAAKC,KAAL,GAAaF,KAAK,CAACG,IAAN,IAAc,SAA3B;EACD;;EAcOC,cAAc,GAAG;IACvB,KAAKC,gBAAL,CAAsBC,OAAtB,CAA+BC,CAAD,IAAOA,CAAC,EAAtC;;IACA,KAAKF,gBAAL,GAAwB,EAAxB;EACD;;EAEOG,QAAQ,CAACC,GAAD,EAAyB;IACvC,MAAM;MAAEC;IAAF,IAAgBC,MAAtB;IACA,MAAM;MAAEC,KAAF;MAASC;IAAT,IAAoBJ,GAAG,CAACK,WAAJ,CAAgBC,MAA1C;IACA,KAAKH,KAAL,GAAaA,KAAb;IACA,KAAKC,MAAL,GAAcA,MAAd,CAJuC,CAKvC;;IACA,IAAI,KAAKG,UAAL,CAAgBC,OAApB,EAA6B;MAC3B,MAAMC,MAAM,GAAG,KAAKF,UAAL,CAAgBC,OAA/B;MACAC,MAAM,CAACN,KAAP,GAAeA,KAAK,GAAGnB,EAAvB;MACAyB,MAAM,CAACL,MAAP,GAAgBA,MAAM,GAAGpB,EAAzB;MACA,MAAM0B,OAAO,GAAGT,SAAS,CAACU,sBAAV,CAAiC,KAAKJ,UAAL,CAAgBC,OAAjD,CAAhB;;MACA,IAAI,CAACE,OAAL,EAAc;QACZ,MAAM,IAAIE,KAAJ,CAAU,0BAAV,CAAN;MACD;;MACD,KAAKC,QAAL,GAAgB,IAAIC,0BAAJ,CAAiBb,SAAjB,EAA4BS,OAA5B,CAAhB;MACA,KAAKK,OAAL,GAAe,KAAKF,QAAL,CAAcG,SAAd,EAAf;MACA,KAAKC,MAAL;IACD,CAjBsC,CAkBvC;;;IACA,IAAI,KAAK1B,KAAL,CAAWQ,QAAf,EAAyB;MACvB,KAAKR,KAAL,CAAWQ,QAAX,CAAoBC,GAApB;IACD;EACF;;EAESkB,OAAO,GAAG;IAClB,OAAO;MAAEf,KAAK,EAAE,KAAKA,KAAd;MAAqBC,MAAM,EAAE,KAAKA;IAAlC,CAAP;EACD;;EAEDe,iBAAiB,GAAG;IAClB;IACA,KAAKC,IAAL;EACD;;EAEDC,kBAAkB,GAAG;IACnB,KAAKJ,MAAL;EACD;;EAEDK,oBAAoB,GAAG;IACrB,KAAK3B,cAAL;IACA4B,oBAAoB,CAAC,KAAKC,SAAN,CAApB;EACD;EAED;AACF;AACA;AACA;AACA;;;EACSC,iBAAiB,CAACC,IAAD,EAAgB;IAAA;;IACtC,KAAKX,OAAL,CAAcY,KAAd,CAAoB1B,SAAS,CAAC2B,WAA9B;;IACA,KAAKC,cAAL,CAAoB,KAAKd,OAAzB,EAAmC,EAAnC;IACA,uBAAKF,QAAL,kEAAeiB,GAAf,CAAmBC,KAAnB;IACA,0BAAO,KAAKlB,QAAZ,oDAAO,gBAAeY,iBAAf,CAAiCC,IAAjC,CAAP;EACD;EAED;AACF;AACA;;;EAME;AACF;AACA;EACUN,IAAI,GAAG;IACb,IAAI,KAAK3B,KAAL,KAAe,YAAf,IAA+B,KAAKuC,eAAL,GAAuB,CAA1D,EAA6D;MAC3D,KAAKA,eAAL,GAAuB,CAAvB;;MACA,IAAI,KAAKjB,OAAT,EAAkB;QAAA;;QAChB,MAAMkB,OAAO,GAAG,CAAC,GAAG,KAAKC,QAAT,CAAhB;QACA,KAAKA,QAAL,GAAgB,EAAhB;QACA,MAAMzB,MAAM,GAAG,KAAKM,OAApB;QACAN,MAAM,CAACkB,KAAP,CAAaQ,YAAY,CAACC,EAAb,CAAgB,CAAhB,EAAmB,CAAnB,EAAsB,CAAtB,EAAyB,CAAzB,CAAb;QACA3B,MAAM,CAAC4B,IAAP;QACA5B,MAAM,CAAC6B,KAAP,CAAatD,EAAb,EAAiBA,EAAjB;QACA,KAAK6C,cAAL,CAAoBpB,MAApB,EAA4BwB,OAA5B;QACAxB,MAAM,CAAC8B,OAAP;QACA,wBAAK1B,QAAL,oEAAeiB,GAAf,CAAmBC,KAAnB;MACD;IACF;;IACD,KAAKP,SAAL,GAAiBgB,qBAAqB,CAAC,KAAKpB,IAAL,CAAUqB,IAAV,CAAe,IAAf,CAAD,CAAtC;EACD;;EAEMxB,MAAM,GAAG;IACd,KAAKe,eAAL;EACD;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;EACSU,WAAW,CAAChD,IAAD,EAAiB;IACjC,KAAKD,KAAL,GAAaC,IAAb;IACA,KAAK0B,IAAL;EACD;EAED;AACF;AACA;AACA;AACA;;;EACSuB,cAAc,CAACC,OAAD,EAAgC;IACnD;IACA,KAAKjD,cAAL,GAFmD,CAGnD;;IACAiD,OAAO,CAAC/C,OAAR,CAAiBgD,CAAD,IAAO;MACrB,KAAKjD,gBAAL,CAAsBkD,IAAtB,CACED,CAAC,CAACE,WAAF,CAAc,MAAM;QAClB,KAAK9B,MAAL;MACD,CAFD,CADF;IAKD,CAND;EAOD;;EAEO+B,gBAAgB,CAAChD,GAAD,EAAoBiD,SAApB,EAA0C;IAChE,KAAKf,QAAL,CAAcY,IAAd,CAAmB;MACjBI,EAAE,EAAElD,GAAG,CAACmD,SADS;MAEjBC,CAAC,EAAEpD,GAAG,CAACqD,OAAJ,GAAcrD,GAAG,CAACsD,aAAJ,CAAkBC,cAAlB,GAAmC,CAAnC,EAAsCC,IAFtC;MAGjBC,CAAC,EAAEzD,GAAG,CAAC0D,OAAJ,GAAc1D,GAAG,CAACsD,aAAJ,CAAkBC,cAAlB,GAAmC,CAAnC,EAAsCI,GAHtC;MAIjBC,KAAK,EAAE5D,GAAG,CAAC6D,QAJM;MAKjBC,IAAI,EAAEb,SALW;MAMjBc,SAAS,EAAEC,IAAI,CAACC,GAAL;IANM,CAAnB;;IAQA,KAAKhD,MAAL;EACD;;EAEDiD,kBAAkB,CAACjB,SAAD,EAAuB;IACvC,OAAQjD,GAAD,IAAuB,KAAKgD,gBAAL,CAAsBhD,GAAtB,EAA2BiD,SAA3B,CAA9B;EACD;;EAEDkB,MAAM,GAAG;IACP,MAAM;MAAEzE,IAAF;MAAQ0E,KAAK,GAAG,KAAhB;MAAuB,GAAGC;IAA1B,IAAwC,KAAK9E,KAAnD;IACA,oBACE,6BAAC,iBAAD,eAAU8E,SAAV;MAAqB,QAAQ,EAAE,KAAKtE,QAAL,CAAc0C,IAAd,CAAmB,IAAnB;IAA/B,iBACE;MACE,GAAG,EAAE,KAAKlC,UADZ;MAEE,KAAK,EAAE;QAAE+D,OAAO,EAAE,MAAX;QAAmBC,IAAI,EAAE;MAAzB,CAFT;MAGE,aAAa,EAAE,KAAKL,kBAAL,CAAwBM,gBAAA,CAAUC,KAAlC,CAHjB;MAIE,aAAa,EAAE,KAAKP,kBAAL,CAAwBM,gBAAA,CAAUE,MAAlC,CAJjB;MAKE,WAAW,EAAE,KAAKR,kBAAL,CAAwBM,gBAAA,CAAUG,GAAlC,CALf;MAME,eAAe,EAAE,KAAKT,kBAAL,CAAwBM,gBAAA,CAAUI,SAAlC,CANnB;MAOE,cAAc,EAAE,KAAKV,kBAAL,CAAwBM,gBAAA,CAAUG,GAAlC,CAPlB;MAQE,YAAY,EAAE,KAAKT,kBAAL,CAAwBM,gBAAA,CAAUG,GAAlC;IARhB,EADF,CADF;EAcD;;AA9K+B"}
1
+ {"version":3,"names":["pd","PixelRatio","get","SkiaBaseWebView","React","Component","constructor","props","createRef","_mode","mode","unsubscribeAll","_unsubscriptions","forEach","u","onLayout","evt","CanvasKit","global","width","height","nativeEvent","layout","_canvasRef","current","canvas","surface","MakeWebGLCanvasSurface","Error","_surface","JsiSkSurface","_canvas","getCanvas","redraw","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","getContext","getExtension","loseContext","makeImageSnapshot","rect","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","touches","_touches","Float32Array","of","save","scale","restore","requestAnimationFrame","bind","setDrawMode","registerValues","_values","v","push","addListener","handleTouchEvent","touchType","id","pointerId","x","clientX","currentTarget","getClientRects","left","y","clientY","top","force","pressure","type","timestamp","Date","now","createTouchHandler","render","debug","viewProps","display","flex","TouchType","Start","Active","End","Cancelled"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { PointerEvent } from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\nimport { PixelRatio, View } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport type { SkiaValue } from \"../values\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\n\nimport type { DrawMode, SkiaBaseViewProps, TouchInfo } from \"./types\";\nimport { TouchType } from \"./types\";\n\nconst pd = PixelRatio.get();\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n this._mode = props.mode ?? \"default\";\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _touches: Array<TouchInfo> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _mode: DrawMode;\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayout(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n const { width, height } = evt.nativeEvent.layout;\n this.width = width;\n this.height = height;\n // Reset canvas / surface on layout change\n if (this._canvasRef.current) {\n const canvas = this._canvasRef.current;\n canvas.width = width * pd;\n canvas.height = height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(this._canvasRef.current);\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n protected getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context\n this._canvasRef.current\n ?.getContext(\"webgl2\")\n ?.getExtension(\"WEBGL_lose_context\")\n ?.loseContext();\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!, []);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(\n canvas: SkCanvas,\n touches: TouchInfo[]\n ): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._mode === \"continuous\" || this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const touches = [...this._touches];\n this._touches = [];\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas, touches);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n /**\n * Updates the drawing mode for the skia view. This is the same\n * as declaratively setting the mode property on the SkiaView.\n * There are two drawing modes, \"continuous\" and \"default\",\n * where the continuous mode will continuously redraw the view and\n * the default mode will only redraw when any of the regular react\n * properties are changed like size and margins.\n * @param mode Drawing mode to use.\n */\n public setDrawMode(mode: DrawMode) {\n this._mode = mode;\n this.tick();\n }\n\n /**\n * Registers one or move values as a dependant value of the Skia View. The view will\n * The view will redraw itself when any of the values change.\n * @param values Values to register\n */\n public registerValues(_values: SkiaValue<unknown>[]) {\n // Unsubscribe from dependency values\n this.unsubscribeAll();\n // Register redraw dependencies on values\n _values.forEach((v) => {\n this._unsubscriptions.push(\n v.addListener(() => {\n this.redraw();\n })\n );\n });\n }\n\n private handleTouchEvent(evt: PointerEvent, touchType: TouchType) {\n this._touches.push({\n id: evt.pointerId,\n x: evt.clientX - evt.currentTarget.getClientRects()[0].left,\n y: evt.clientY - evt.currentTarget.getClientRects()[0].top,\n force: evt.pressure,\n type: touchType,\n timestamp: Date.now(),\n });\n this.redraw();\n }\n\n createTouchHandler(touchType: TouchType) {\n return (evt: PointerEvent) => this.handleTouchEvent(evt, touchType);\n }\n\n render() {\n const { mode, debug = false, ...viewProps } = this.props;\n return (\n <View {...viewProps} onLayout={this.onLayout.bind(this)}>\n <canvas\n ref={this._canvasRef}\n style={{ display: \"flex\", flex: 1 }}\n onPointerDown={this.createTouchHandler(TouchType.Start)}\n onPointerMove={this.createTouchHandler(TouchType.Active)}\n onPointerUp={this.createTouchHandler(TouchType.End)}\n onPointerCancel={this.createTouchHandler(TouchType.Cancelled)}\n onPointerLeave={this.createTouchHandler(TouchType.End)}\n onPointerOut={this.createTouchHandler(TouchType.End)}\n />\n </View>\n );\n }\n}\n"],"mappings":"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"}
@@ -92,8 +92,12 @@ export class SkiaBaseWebView extends React.Component {
92
92
  }
93
93
 
94
94
  componentWillUnmount() {
95
+ var _this$_canvasRef$curr, _this$_canvasRef$curr2, _this$_canvasRef$curr3;
96
+
95
97
  this.unsubscribeAll();
96
- cancelAnimationFrame(this.requestId);
98
+ cancelAnimationFrame(this.requestId); // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context
99
+
100
+ (_this$_canvasRef$curr = this._canvasRef.current) === null || _this$_canvasRef$curr === void 0 ? void 0 : (_this$_canvasRef$curr2 = _this$_canvasRef$curr.getContext("webgl2")) === null || _this$_canvasRef$curr2 === void 0 ? void 0 : (_this$_canvasRef$curr3 = _this$_canvasRef$curr2.getExtension("WEBGL_lose_context")) === null || _this$_canvasRef$curr3 === void 0 ? void 0 : _this$_canvasRef$curr3.loseContext();
97
101
  }
98
102
  /**
99
103
  * Creates a snapshot from the canvas in the surface
@@ -1 +1 @@
1
- {"version":3,"names":["React","PixelRatio","View","JsiSkSurface","TouchType","pd","get","SkiaBaseWebView","Component","constructor","props","createRef","_mode","mode","unsubscribeAll","_unsubscriptions","forEach","u","onLayout","evt","CanvasKit","global","width","height","nativeEvent","layout","_canvasRef","current","canvas","surface","MakeWebGLCanvasSurface","Error","_surface","_canvas","getCanvas","redraw","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","makeImageSnapshot","rect","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","touches","_touches","Float32Array","of","save","scale","restore","requestAnimationFrame","bind","setDrawMode","registerValues","_values","v","push","addListener","handleTouchEvent","touchType","id","pointerId","x","clientX","currentTarget","getClientRects","left","y","clientY","top","force","pressure","type","timestamp","Date","now","createTouchHandler","render","debug","viewProps","display","flex","Start","Active","End","Cancelled"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { PointerEvent } from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\nimport { PixelRatio, View } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport type { SkiaValue } from \"../values\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\n\nimport type { DrawMode, SkiaBaseViewProps, TouchInfo } from \"./types\";\nimport { TouchType } from \"./types\";\n\nconst pd = PixelRatio.get();\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n this._mode = props.mode ?? \"default\";\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _touches: Array<TouchInfo> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _mode: DrawMode;\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayout(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n const { width, height } = evt.nativeEvent.layout;\n this.width = width;\n this.height = height;\n // Reset canvas / surface on layout change\n if (this._canvasRef.current) {\n const canvas = this._canvasRef.current;\n canvas.width = width * pd;\n canvas.height = height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(this._canvasRef.current);\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n protected getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!, []);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(\n canvas: SkCanvas,\n touches: TouchInfo[]\n ): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._mode === \"continuous\" || this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const touches = [...this._touches];\n this._touches = [];\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas, touches);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n /**\n * Updates the drawing mode for the skia view. This is the same\n * as declaratively setting the mode property on the SkiaView.\n * There are two drawing modes, \"continuous\" and \"default\",\n * where the continuous mode will continuously redraw the view and\n * the default mode will only redraw when any of the regular react\n * properties are changed like size and margins.\n * @param mode Drawing mode to use.\n */\n public setDrawMode(mode: DrawMode) {\n this._mode = mode;\n this.tick();\n }\n\n /**\n * Registers one or move values as a dependant value of the Skia View. The view will\n * The view will redraw itself when any of the values change.\n * @param values Values to register\n */\n public registerValues(_values: SkiaValue<unknown>[]) {\n // Unsubscribe from dependency values\n this.unsubscribeAll();\n // Register redraw dependencies on values\n _values.forEach((v) => {\n this._unsubscriptions.push(\n v.addListener(() => {\n this.redraw();\n })\n );\n });\n }\n\n private handleTouchEvent(evt: PointerEvent, touchType: TouchType) {\n this._touches.push({\n id: evt.pointerId,\n x: evt.clientX - evt.currentTarget.getClientRects()[0].left,\n y: evt.clientY - evt.currentTarget.getClientRects()[0].top,\n force: evt.pressure,\n type: touchType,\n timestamp: Date.now(),\n });\n this.redraw();\n }\n\n createTouchHandler(touchType: TouchType) {\n return (evt: PointerEvent) => this.handleTouchEvent(evt, touchType);\n }\n\n render() {\n const { mode, debug = false, ...viewProps } = this.props;\n return (\n <View {...viewProps} onLayout={this.onLayout.bind(this)}>\n <canvas\n ref={this._canvasRef}\n style={{ display: \"flex\", flex: 1 }}\n onPointerDown={this.createTouchHandler(TouchType.Start)}\n onPointerMove={this.createTouchHandler(TouchType.Active)}\n onPointerUp={this.createTouchHandler(TouchType.End)}\n onPointerCancel={this.createTouchHandler(TouchType.Cancelled)}\n onPointerLeave={this.createTouchHandler(TouchType.End)}\n onPointerOut={this.createTouchHandler(TouchType.End)}\n />\n </View>\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","PixelRatio","View","JsiSkSurface","TouchType","pd","get","SkiaBaseWebView","Component","constructor","props","createRef","_mode","mode","unsubscribeAll","_unsubscriptions","forEach","u","onLayout","evt","CanvasKit","global","width","height","nativeEvent","layout","_canvasRef","current","canvas","surface","MakeWebGLCanvasSurface","Error","_surface","_canvas","getCanvas","redraw","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","getContext","getExtension","loseContext","makeImageSnapshot","rect","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","touches","_touches","Float32Array","of","save","scale","restore","requestAnimationFrame","bind","setDrawMode","registerValues","_values","v","push","addListener","handleTouchEvent","touchType","id","pointerId","x","clientX","currentTarget","getClientRects","left","y","clientY","top","force","pressure","type","timestamp","Date","now","createTouchHandler","render","debug","viewProps","display","flex","Start","Active","End","Cancelled"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { PointerEvent } from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\nimport { PixelRatio, View } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport type { SkiaValue } from \"../values\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\n\nimport type { DrawMode, SkiaBaseViewProps, TouchInfo } from \"./types\";\nimport { TouchType } from \"./types\";\n\nconst pd = PixelRatio.get();\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n this._mode = props.mode ?? \"default\";\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _touches: Array<TouchInfo> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _mode: DrawMode;\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayout(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n const { width, height } = evt.nativeEvent.layout;\n this.width = width;\n this.height = height;\n // Reset canvas / surface on layout change\n if (this._canvasRef.current) {\n const canvas = this._canvasRef.current;\n canvas.width = width * pd;\n canvas.height = height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(this._canvasRef.current);\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n protected getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context\n this._canvasRef.current\n ?.getContext(\"webgl2\")\n ?.getExtension(\"WEBGL_lose_context\")\n ?.loseContext();\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!, []);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(\n canvas: SkCanvas,\n touches: TouchInfo[]\n ): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._mode === \"continuous\" || this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const touches = [...this._touches];\n this._touches = [];\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas, touches);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n /**\n * Updates the drawing mode for the skia view. This is the same\n * as declaratively setting the mode property on the SkiaView.\n * There are two drawing modes, \"continuous\" and \"default\",\n * where the continuous mode will continuously redraw the view and\n * the default mode will only redraw when any of the regular react\n * properties are changed like size and margins.\n * @param mode Drawing mode to use.\n */\n public setDrawMode(mode: DrawMode) {\n this._mode = mode;\n this.tick();\n }\n\n /**\n * Registers one or move values as a dependant value of the Skia View. The view will\n * The view will redraw itself when any of the values change.\n * @param values Values to register\n */\n public registerValues(_values: SkiaValue<unknown>[]) {\n // Unsubscribe from dependency values\n this.unsubscribeAll();\n // Register redraw dependencies on values\n _values.forEach((v) => {\n this._unsubscriptions.push(\n v.addListener(() => {\n this.redraw();\n })\n );\n });\n }\n\n private handleTouchEvent(evt: PointerEvent, touchType: TouchType) {\n this._touches.push({\n id: evt.pointerId,\n x: evt.clientX - evt.currentTarget.getClientRects()[0].left,\n y: evt.clientY - evt.currentTarget.getClientRects()[0].top,\n force: evt.pressure,\n type: touchType,\n timestamp: Date.now(),\n });\n this.redraw();\n }\n\n createTouchHandler(touchType: TouchType) {\n return (evt: PointerEvent) => this.handleTouchEvent(evt, touchType);\n }\n\n render() {\n const { mode, debug = false, ...viewProps } = this.props;\n return (\n <View {...viewProps} onLayout={this.onLayout.bind(this)}>\n <canvas\n ref={this._canvasRef}\n style={{ display: \"flex\", flex: 1 }}\n onPointerDown={this.createTouchHandler(TouchType.Start)}\n onPointerMove={this.createTouchHandler(TouchType.Active)}\n onPointerUp={this.createTouchHandler(TouchType.End)}\n onPointerCancel={this.createTouchHandler(TouchType.Cancelled)}\n onPointerLeave={this.createTouchHandler(TouchType.End)}\n onPointerOut={this.createTouchHandler(TouchType.End)}\n />\n </View>\n );\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "setup-skia-web": "./scripts/setup-canvaskit.js"
8
8
  },
9
9
  "title": "React Native Skia",
10
- "version": "0.1.180",
10
+ "version": "0.1.181",
11
11
  "description": "High-performance React Native Graphics using Skia",
12
12
  "main": "lib/module/index.js",
13
13
  "files": [
@@ -78,6 +78,11 @@ export abstract class SkiaBaseWebView<
78
78
  componentWillUnmount() {
79
79
  this.unsubscribeAll();
80
80
  cancelAnimationFrame(this.requestId);
81
+ // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context
82
+ this._canvasRef.current
83
+ ?.getContext("webgl2")
84
+ ?.getExtension("WEBGL_lose_context")
85
+ ?.loseContext();
81
86
  }
82
87
 
83
88
  /**