@shopify/react-native-skia 2.2.13 → 2.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apple/MetalContext.h +3 -25
- package/apple/MetalContext.mm +7 -3
- package/apple/MetalWindowContext.mm +1 -1
- package/apple/RNSkMetalCanvasProvider.mm +3 -6
- package/cpp/api/JsiSkImage.h +20 -1
- package/cpp/api/JsiSkSurface.h +20 -1
- package/cpp/api/JsiSkThreadSafeDeletion.h +105 -0
- package/cpp/api/recorder/Drawings.h +4 -4
- package/cpp/jsi/JsiHostObject.cpp +0 -27
- package/cpp/jsi/JsiHostObject.h +5 -5
- package/cpp/jsi/ViewProperty.h +34 -2
- package/cpp/rnskia/RNSkJsiViewApi.h +14 -24
- package/cpp/rnskia/RNSkPictureView.h +25 -2
- package/cpp/rnskia/RNSkView.h +7 -0
- package/lib/commonjs/Platform/Platform.js +2 -1
- package/lib/commonjs/Platform/Platform.js.map +1 -1
- package/lib/commonjs/Platform/Platform.web.js +3 -0
- package/lib/commonjs/Platform/Platform.web.js.map +1 -1
- package/lib/commonjs/renderer/Canvas.js +35 -1
- package/lib/commonjs/renderer/Canvas.js.map +1 -1
- package/lib/commonjs/skia/core/SVG.web.js +1 -1
- package/lib/commonjs/skia/core/SVG.web.js.map +1 -1
- package/lib/commonjs/skia/types/Data/Data.d.ts +6 -1
- package/lib/commonjs/skia/types/Data/Data.js.map +1 -1
- package/lib/commonjs/sksg/Container.d.ts +2 -3
- package/lib/commonjs/sksg/Container.js +1 -1
- package/lib/commonjs/sksg/Container.js.map +1 -1
- package/lib/commonjs/sksg/Container.native.d.ts +3 -5
- package/lib/commonjs/sksg/Container.native.js +8 -15
- package/lib/commonjs/sksg/Container.native.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.d.ts +2 -3
- package/lib/commonjs/sksg/Container.web.js +1 -1
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/sksg/Reconciler.d.ts +2 -3
- package/lib/commonjs/sksg/Reconciler.js +2 -2
- package/lib/commonjs/sksg/Reconciler.js.map +1 -1
- package/lib/module/Platform/Platform.js +2 -1
- package/lib/module/Platform/Platform.js.map +1 -1
- package/lib/module/Platform/Platform.web.js +3 -0
- package/lib/module/Platform/Platform.web.js.map +1 -1
- package/lib/module/renderer/Canvas.js +35 -1
- package/lib/module/renderer/Canvas.js.map +1 -1
- package/lib/module/skia/core/SVG.web.js +1 -1
- package/lib/module/skia/core/SVG.web.js.map +1 -1
- package/lib/module/skia/types/Data/Data.d.ts +6 -1
- package/lib/module/skia/types/Data/Data.js.map +1 -1
- package/lib/module/sksg/Container.d.ts +2 -3
- package/lib/module/sksg/Container.js +1 -1
- package/lib/module/sksg/Container.js.map +1 -1
- package/lib/module/sksg/Container.native.d.ts +3 -5
- package/lib/module/sksg/Container.native.js +8 -15
- package/lib/module/sksg/Container.native.js.map +1 -1
- package/lib/module/sksg/Container.web.d.ts +2 -3
- package/lib/module/sksg/Container.web.js +1 -1
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/sksg/Reconciler.d.ts +2 -3
- package/lib/module/sksg/Reconciler.js +2 -2
- package/lib/module/sksg/Reconciler.js.map +1 -1
- package/lib/typescript/lib/commonjs/sksg/Container.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Container.native.d.ts +2 -3
- package/lib/typescript/lib/commonjs/sksg/Container.web.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Reconciler.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Container.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Container.native.d.ts +2 -3
- package/lib/typescript/lib/module/sksg/Container.web.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Reconciler.d.ts +1 -1
- package/lib/typescript/src/skia/types/Data/Data.d.ts +6 -1
- package/lib/typescript/src/sksg/Container.d.ts +2 -3
- package/lib/typescript/src/sksg/Container.native.d.ts +3 -5
- package/lib/typescript/src/sksg/Container.web.d.ts +2 -3
- package/lib/typescript/src/sksg/Reconciler.d.ts +2 -3
- package/package.json +1 -1
- package/src/Platform/Platform.ts +3 -0
- package/src/Platform/Platform.web.tsx +3 -0
- package/src/renderer/Canvas.tsx +33 -3
- package/src/skia/core/SVG.web.ts +3 -0
- package/src/skia/types/Data/Data.ts +7 -1
- package/src/sksg/Container.native.ts +10 -27
- package/src/sksg/Container.ts +2 -8
- package/src/sksg/Container.web.ts +2 -8
- package/src/sksg/Reconciler.ts +3 -4
package/apple/MetalContext.h
CHANGED
@@ -14,29 +14,6 @@
|
|
14
14
|
#import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
|
15
15
|
#import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
|
16
16
|
|
17
|
-
class MetalSharedContext {
|
18
|
-
public:
|
19
|
-
static MetalSharedContext &getInstance() {
|
20
|
-
static MetalSharedContext instance;
|
21
|
-
return instance;
|
22
|
-
}
|
23
|
-
|
24
|
-
id<MTLDevice> getDevice() { return _device; }
|
25
|
-
|
26
|
-
private:
|
27
|
-
MetalSharedContext() {
|
28
|
-
_device = MTLCreateSystemDefaultDevice();
|
29
|
-
if (!_device) {
|
30
|
-
throw std::runtime_error("Failed to create Metal device");
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
MetalSharedContext(const MetalSharedContext &) = delete;
|
35
|
-
MetalSharedContext &operator=(const MetalSharedContext &) = delete;
|
36
|
-
|
37
|
-
id<MTLDevice> _device;
|
38
|
-
};
|
39
|
-
|
40
17
|
struct OffscreenRenderContext {
|
41
18
|
id<MTLTexture> texture;
|
42
19
|
|
@@ -68,7 +45,7 @@ public:
|
|
68
45
|
}
|
69
46
|
|
70
47
|
sk_sp<SkSurface> MakeOffscreen(int width, int height) {
|
71
|
-
auto device =
|
48
|
+
auto device = _device;
|
72
49
|
auto ctx = new OffscreenRenderContext(device, _directContext, _commandQueue,
|
73
50
|
width, height);
|
74
51
|
|
@@ -115,7 +92,7 @@ public:
|
|
115
92
|
std::unique_ptr<RNSkia::WindowContext>
|
116
93
|
MakeWindow(CALayer *window, int width, int height,
|
117
94
|
bool useP3ColorSpace = true) {
|
118
|
-
auto device =
|
95
|
+
auto device = _device;
|
119
96
|
return std::make_unique<MetalWindowContext>(_directContext.get(), device,
|
120
97
|
_commandQueue, window, width,
|
121
98
|
height, useP3ColorSpace);
|
@@ -124,6 +101,7 @@ public:
|
|
124
101
|
GrDirectContext *getDirectContext() { return _directContext.get(); }
|
125
102
|
|
126
103
|
private:
|
104
|
+
id<MTLDevice> _device = nullptr;
|
127
105
|
id<MTLCommandQueue> _commandQueue = nullptr;
|
128
106
|
sk_sp<GrDirectContext> _directContext = nullptr;
|
129
107
|
|
package/apple/MetalContext.mm
CHANGED
@@ -18,11 +18,15 @@
|
|
18
18
|
#pragma clang diagnostic pop
|
19
19
|
|
20
20
|
MetalContext::MetalContext() {
|
21
|
-
|
21
|
+
_device = MTLCreateSystemDefaultDevice();
|
22
|
+
if (!_device) {
|
23
|
+
throw std::runtime_error("Failed to create Metal device");
|
24
|
+
}
|
25
|
+
|
22
26
|
_commandQueue =
|
23
|
-
id<MTLCommandQueue>(CFRetain((GrMTLHandle)[
|
27
|
+
id<MTLCommandQueue>(CFRetain((GrMTLHandle)[_device newCommandQueue]));
|
24
28
|
GrMtlBackendContext backendContext = {};
|
25
|
-
backendContext.fDevice.reset((__bridge void *)
|
29
|
+
backendContext.fDevice.reset((__bridge void *)_device);
|
26
30
|
backendContext.fQueue.reset((__bridge void *)_commandQueue);
|
27
31
|
GrContextOptions grContextOptions; // set different options here.
|
28
32
|
|
@@ -77,11 +77,7 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
|
|
77
77
|
// we try to render while in the background. (see above issue)
|
78
78
|
return false;
|
79
79
|
}
|
80
|
-
|
81
|
-
// Wrap in auto release pool since we want the system to clean up after
|
82
|
-
// rendering and not wait until later - we've seen some example of memory
|
83
|
-
// usage growing very fast in the simulator without this.
|
84
|
-
@autoreleasepool {
|
80
|
+
|
85
81
|
auto surface = _ctx->getSurface();
|
86
82
|
if (!surface) {
|
87
83
|
return false;
|
@@ -89,8 +85,9 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
|
|
89
85
|
auto canvas = surface->getCanvas();
|
90
86
|
cb(canvas);
|
91
87
|
_ctx->present();
|
88
|
+
return true;
|
92
89
|
}
|
93
|
-
return
|
90
|
+
return false;
|
94
91
|
};
|
95
92
|
|
96
93
|
void RNSkMetalCanvasProvider::setSize(int width, int height) {
|
package/cpp/api/JsiSkImage.h
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include "JsiSkImageInfo.h"
|
9
9
|
#include "JsiSkMatrix.h"
|
10
10
|
#include "JsiSkShader.h"
|
11
|
+
#include "JsiSkThreadSafeDeletion.h"
|
11
12
|
#include "third_party/base64.h"
|
12
13
|
|
13
14
|
#include "JsiTextureInfo.h"
|
@@ -61,6 +62,9 @@ inline SkSamplingOptions SamplingOptionsFromValue(jsi::Runtime &runtime,
|
|
61
62
|
}
|
62
63
|
|
63
64
|
class JsiSkImage : public JsiSkWrappingSkPtrHostObject<SkImage> {
|
65
|
+
private:
|
66
|
+
ThreadSafeDeletion<SkImage> _deletionHandler;
|
67
|
+
|
64
68
|
public:
|
65
69
|
// TODO-API: Properties?
|
66
70
|
JSI_HOST_FUNCTION(width) { return static_cast<double>(getObject()->width()); }
|
@@ -271,7 +275,22 @@ public:
|
|
271
275
|
JsiSkImage(std::shared_ptr<RNSkPlatformContext> context,
|
272
276
|
const sk_sp<SkImage> image)
|
273
277
|
: JsiSkWrappingSkPtrHostObject<SkImage>(std::move(context),
|
274
|
-
std::move(image))
|
278
|
+
std::move(image)),
|
279
|
+
_deletionHandler() {
|
280
|
+
// Drain any pending deletions when creating new images
|
281
|
+
ThreadSafeDeletion<SkImage>::drainDeletionQueue();
|
282
|
+
}
|
283
|
+
|
284
|
+
~JsiSkImage() override {
|
285
|
+
// Handle thread-safe deletion
|
286
|
+
auto objectToDelete = _deletionHandler.handleDeletion(getObject());
|
287
|
+
if (!objectToDelete) {
|
288
|
+
// Object was queued for deletion on another thread
|
289
|
+
// Clear it to prevent base class destructor from deleting it
|
290
|
+
setObject(nullptr);
|
291
|
+
}
|
292
|
+
// If objectToDelete is not null, base destructor will handle cleanup
|
293
|
+
}
|
275
294
|
|
276
295
|
size_t getMemoryPressure() const override {
|
277
296
|
auto image = getObject();
|
package/cpp/api/JsiSkSurface.h
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
#include <jsi/jsi.h>
|
7
7
|
|
8
8
|
#include "JsiSkHostObjects.h"
|
9
|
+
#include "JsiSkThreadSafeDeletion.h"
|
9
10
|
#include "JsiTextureInfo.h"
|
10
11
|
|
11
12
|
#include "JsiSkCanvas.h"
|
@@ -28,11 +29,29 @@ namespace RNSkia {
|
|
28
29
|
namespace jsi = facebook::jsi;
|
29
30
|
|
30
31
|
class JsiSkSurface : public JsiSkWrappingSkPtrHostObject<SkSurface> {
|
32
|
+
private:
|
33
|
+
ThreadSafeDeletion<SkSurface> _deletionHandler;
|
34
|
+
|
31
35
|
public:
|
32
36
|
JsiSkSurface(std::shared_ptr<RNSkPlatformContext> context,
|
33
37
|
sk_sp<SkSurface> surface)
|
34
38
|
: JsiSkWrappingSkPtrHostObject<SkSurface>(std::move(context),
|
35
|
-
std::move(surface))
|
39
|
+
std::move(surface)),
|
40
|
+
_deletionHandler() {
|
41
|
+
// Drain any pending deletions when creating new surfaces
|
42
|
+
ThreadSafeDeletion<SkSurface>::drainDeletionQueue();
|
43
|
+
}
|
44
|
+
|
45
|
+
~JsiSkSurface() override {
|
46
|
+
// Handle thread-safe deletion
|
47
|
+
auto objectToDelete = _deletionHandler.handleDeletion(getObject());
|
48
|
+
if (!objectToDelete) {
|
49
|
+
// Object was queued for deletion on another thread
|
50
|
+
// Clear it to prevent base class destructor from deleting it
|
51
|
+
setObject(nullptr);
|
52
|
+
}
|
53
|
+
// If objectToDelete is not null, base destructor will handle cleanup
|
54
|
+
}
|
36
55
|
|
37
56
|
EXPORT_JSI_API_TYPENAME(JsiSkSurface, Surface)
|
38
57
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <functional>
|
4
|
+
#include <memory>
|
5
|
+
#include <mutex>
|
6
|
+
#include <queue>
|
7
|
+
#include <thread>
|
8
|
+
|
9
|
+
// Define this to disable thread-safe deletion (for testing purposes)
|
10
|
+
// #define DISABLE_THREAD_SAFE_DELETION
|
11
|
+
|
12
|
+
namespace RNSkia {
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Utility class for managing thread-safe deletion of Skia objects.
|
16
|
+
* Ensures objects are deleted on the thread that created them.
|
17
|
+
*/
|
18
|
+
template <typename T> class ThreadSafeDeletion {
|
19
|
+
private:
|
20
|
+
struct DeletionItem {
|
21
|
+
sk_sp<T> object;
|
22
|
+
std::thread::id creationThreadId;
|
23
|
+
};
|
24
|
+
|
25
|
+
static inline std::mutex _queueMutex;
|
26
|
+
static inline std::queue<DeletionItem> _deletionQueue;
|
27
|
+
|
28
|
+
std::thread::id _creationThreadId;
|
29
|
+
|
30
|
+
public:
|
31
|
+
ThreadSafeDeletion() : _creationThreadId(std::this_thread::get_id()) {}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Handles deletion of the object. If we're on the wrong thread,
|
35
|
+
* queues it for later deletion. Returns nullptr if object was queued,
|
36
|
+
* or the object itself if it should be deleted immediately.
|
37
|
+
*/
|
38
|
+
sk_sp<T> handleDeletion(sk_sp<T> object) {
|
39
|
+
if (!object) {
|
40
|
+
return nullptr;
|
41
|
+
}
|
42
|
+
|
43
|
+
#ifdef DISABLE_THREAD_SAFE_DELETION
|
44
|
+
// When disabled, always return the object for immediate deletion
|
45
|
+
// This will likely cause crashes when objects are deleted on wrong thread
|
46
|
+
return object;
|
47
|
+
#else
|
48
|
+
// Always try to drain the queue when handling deletions
|
49
|
+
drainDeletionQueue();
|
50
|
+
|
51
|
+
// Check if we're on the creation thread
|
52
|
+
if (std::this_thread::get_id() != _creationThreadId) {
|
53
|
+
// Queue for deletion on the correct thread
|
54
|
+
std::lock_guard<std::mutex> lock(_queueMutex);
|
55
|
+
_deletionQueue.push({object, _creationThreadId});
|
56
|
+
return nullptr; // Signal that object was queued
|
57
|
+
}
|
58
|
+
|
59
|
+
// We're on the correct thread, return object for immediate deletion
|
60
|
+
return object;
|
61
|
+
#endif
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Drains the deletion queue for objects created on the current thread.
|
66
|
+
* Should be called periodically (e.g., when creating new objects).
|
67
|
+
*/
|
68
|
+
static void drainDeletionQueue() {
|
69
|
+
#ifndef DISABLE_THREAD_SAFE_DELETION
|
70
|
+
auto currentThreadId = std::this_thread::get_id();
|
71
|
+
std::queue<DeletionItem> remainingItems;
|
72
|
+
|
73
|
+
std::lock_guard<std::mutex> lock(_queueMutex);
|
74
|
+
|
75
|
+
// Process all items in the queue
|
76
|
+
while (!_deletionQueue.empty()) {
|
77
|
+
auto item = _deletionQueue.front();
|
78
|
+
_deletionQueue.pop();
|
79
|
+
|
80
|
+
// If this item belongs to the current thread, let it be deleted
|
81
|
+
if (item.creationThreadId == currentThreadId) {
|
82
|
+
// The sk_sp destructor will handle the cleanup
|
83
|
+
// Just let it go out of scope
|
84
|
+
} else {
|
85
|
+
// Keep items that belong to other threads
|
86
|
+
remainingItems.push(item);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
// Put back items that couldn't be deleted
|
91
|
+
_deletionQueue = std::move(remainingItems);
|
92
|
+
#endif
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Returns the number of items waiting for deletion.
|
97
|
+
* Useful for debugging and testing.
|
98
|
+
*/
|
99
|
+
static size_t getPendingDeletionCount() {
|
100
|
+
std::lock_guard<std::mutex> lock(_queueMutex);
|
101
|
+
return _deletionQueue.size();
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
} // namespace RNSkia
|
@@ -337,7 +337,6 @@ public:
|
|
337
337
|
}
|
338
338
|
};
|
339
339
|
|
340
|
-
// Add to Drawings.h after existing command structures
|
341
340
|
struct BoxShadowCmdProps {
|
342
341
|
float dx = 0;
|
343
342
|
float dy = 0;
|
@@ -386,7 +385,10 @@ public:
|
|
386
385
|
for (size_t i = 0; i < shadowCount; i++) {
|
387
386
|
auto shadowObj =
|
388
387
|
shadowsArray.getValueAtIndex(runtime, i).asObject(runtime);
|
389
|
-
|
388
|
+
|
389
|
+
// Create shadow directly in vector to avoid copy
|
390
|
+
shadows.emplace_back();
|
391
|
+
BoxShadowCmdProps &shadow = shadows.back();
|
390
392
|
|
391
393
|
convertProperty(runtime, shadowObj, "dx", shadow.dx, variables);
|
392
394
|
convertProperty(runtime, shadowObj, "dy", shadow.dy, variables);
|
@@ -394,8 +396,6 @@ public:
|
|
394
396
|
convertProperty(runtime, shadowObj, "blur", shadow.blur, variables);
|
395
397
|
convertProperty(runtime, shadowObj, "color", shadow.color, variables);
|
396
398
|
convertProperty(runtime, shadowObj, "inner", shadow.inner, variables);
|
397
|
-
|
398
|
-
shadows.push_back(shadow);
|
399
399
|
}
|
400
400
|
}
|
401
401
|
|
@@ -2,35 +2,8 @@
|
|
2
2
|
#include <functional>
|
3
3
|
#include <vector>
|
4
4
|
|
5
|
-
// To be able to find objects that aren't cleaned up correctly,
|
6
|
-
// we can set this value to 1 and debug the constructor/destructor
|
7
|
-
#define JSI_DEBUG_ALLOCATIONS 0
|
8
|
-
|
9
5
|
namespace RNJsi {
|
10
6
|
|
11
|
-
#if JSI_DEBUG_ALLOCATIONS
|
12
|
-
int objCounter = 0;
|
13
|
-
std::vector<JsiHostObject *> objects;
|
14
|
-
#endif
|
15
|
-
|
16
|
-
JsiHostObject::JsiHostObject() {
|
17
|
-
#if JSI_DEBUG_ALLOCATIONS
|
18
|
-
objects.push_back(this);
|
19
|
-
objCounter++;
|
20
|
-
#endif
|
21
|
-
}
|
22
|
-
JsiHostObject::~JsiHostObject() {
|
23
|
-
#if JSI_DEBUG_ALLOCATIONS
|
24
|
-
for (size_t i = 0; i < objects.size(); ++i) {
|
25
|
-
if (objects.at(i) == this) {
|
26
|
-
objects.erase(objects.begin() + i);
|
27
|
-
break;
|
28
|
-
}
|
29
|
-
}
|
30
|
-
objCounter--;
|
31
|
-
#endif
|
32
|
-
}
|
33
|
-
|
34
7
|
void JsiHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
|
35
8
|
const jsi::Value &value) {
|
36
9
|
|
package/cpp/jsi/JsiHostObject.h
CHANGED
@@ -47,7 +47,7 @@
|
|
47
47
|
* Creates a JSI export function declaration
|
48
48
|
*/
|
49
49
|
#define JSI_EXPORT_FUNC(CLASS, FUNCTION) \
|
50
|
-
{#FUNCTION, (jsi::Value
|
50
|
+
{#FUNCTION, (jsi::Value(JsiHostObject::*)( \
|
51
51
|
jsi::Runtime & runtime, const jsi::Value &thisValue, \
|
52
52
|
const jsi::Value *arguments, size_t)) & \
|
53
53
|
CLASS::FUNCTION}
|
@@ -65,7 +65,7 @@
|
|
65
65
|
* Creates a JSI export getter declaration
|
66
66
|
*/
|
67
67
|
#define JSI_EXPORT_PROP_GET(CLASS, FUNCTION) \
|
68
|
-
{#FUNCTION, (jsi::Value
|
68
|
+
{#FUNCTION, (jsi::Value(JsiHostObject::*)(jsi::Runtime & runtime)) & \
|
69
69
|
CLASS::STR_CAT(STR_GET, FUNCTION)}
|
70
70
|
|
71
71
|
/**
|
@@ -83,7 +83,7 @@
|
|
83
83
|
*/
|
84
84
|
#define JSI_EXPORT_PROP_SET(CLASS, FUNCTION) \
|
85
85
|
{#FUNCTION, \
|
86
|
-
(void
|
86
|
+
(void(JsiHostObject::*)(jsi::Runtime & runtime, const jsi::Value &)) & \
|
87
87
|
CLASS::STR_CAT(STR_SET, FUNCTION)}
|
88
88
|
|
89
89
|
/**
|
@@ -125,8 +125,8 @@ using JsiPropertySettersMap =
|
|
125
125
|
*/
|
126
126
|
class JsiHostObject : public jsi::HostObject {
|
127
127
|
public:
|
128
|
-
JsiHostObject();
|
129
|
-
~JsiHostObject();
|
128
|
+
JsiHostObject() = default;
|
129
|
+
~JsiHostObject() = default;
|
130
130
|
|
131
131
|
/**
|
132
132
|
* Overridden jsi::HostObject set property method
|
package/cpp/jsi/ViewProperty.h
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
+
#include <functional>
|
3
4
|
#include <jsi/jsi.h>
|
4
5
|
#include <memory>
|
5
6
|
#include <string>
|
@@ -26,11 +27,42 @@ public:
|
|
26
27
|
}
|
27
28
|
}
|
28
29
|
|
29
|
-
|
30
|
+
template <typename PlatformContext>
|
31
|
+
ViewProperty(jsi::Runtime &runtime, const jsi::Value &value,
|
32
|
+
PlatformContext platformContext, size_t nativeId) {
|
33
|
+
// Set the onSize callback with all the necessary context
|
34
|
+
_value = std::function<void(int, int)>(
|
35
|
+
[&runtime, platformContext, nativeId](int width, int height) {
|
36
|
+
jsi::Object size(runtime);
|
37
|
+
auto pd = platformContext->getPixelDensity();
|
38
|
+
size.setProperty(runtime, "width", jsi::Value(width / pd));
|
39
|
+
size.setProperty(runtime, "height", jsi::Value(height / pd));
|
40
|
+
|
41
|
+
// Get the stored shared value from global
|
42
|
+
std::string globalKey =
|
43
|
+
"__onSize_" + std::to_string(static_cast<int>(nativeId));
|
44
|
+
auto globalProp =
|
45
|
+
runtime.global().getProperty(runtime, globalKey.c_str());
|
46
|
+
if (!globalProp.isUndefined()) {
|
47
|
+
globalProp.asObject(runtime).setProperty(runtime, "value", size);
|
48
|
+
}
|
49
|
+
});
|
50
|
+
}
|
51
|
+
|
52
|
+
bool isNull() { return std::holds_alternative<std::nullptr_t>(_value); }
|
30
53
|
|
31
54
|
sk_sp<SkPicture> getPicture() { return std::get<sk_sp<SkPicture>>(_value); }
|
32
55
|
|
56
|
+
std::variant<std::nullptr_t, std::function<void(int, int)>>
|
57
|
+
getOnSize() const {
|
58
|
+
if (std::holds_alternative<std::function<void(int, int)>>(_value)) {
|
59
|
+
return std::get<std::function<void(int, int)>>(_value);
|
60
|
+
}
|
61
|
+
return nullptr;
|
62
|
+
}
|
63
|
+
|
33
64
|
private:
|
34
|
-
std::variant<nullptr_t, sk_sp<SkPicture
|
65
|
+
std::variant<std::nullptr_t, sk_sp<SkPicture>, std::function<void(int, int)>>
|
66
|
+
_value = nullptr;
|
35
67
|
};
|
36
68
|
} // namespace RNJsi
|
@@ -10,6 +10,7 @@
|
|
10
10
|
#include <vector>
|
11
11
|
|
12
12
|
#include "JsiHostObject.h"
|
13
|
+
#include "RNSkPictureView.h"
|
13
14
|
#include "RNSkPlatformContext.h"
|
14
15
|
#include "RNSkView.h"
|
15
16
|
#include "ViewProperty.h"
|
@@ -102,31 +103,20 @@ public:
|
|
102
103
|
ViewRegistry::getInstance().withViewInfo(
|
103
104
|
nativeId, [&](std::shared_ptr<RNSkViewInfo> info) {
|
104
105
|
auto name = arguments[1].asString(runtime).utf8(runtime);
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
? std::max(info->view->getScaledWidth(), 0)
|
110
|
-
: 0;
|
111
|
-
auto h = info->view != nullptr
|
112
|
-
? std::max(info->view->getScaledHeight(), 0)
|
113
|
-
: 0;
|
114
|
-
|
115
|
-
size.setProperty(runtime, "width", w / pd);
|
116
|
-
size.setProperty(runtime, "height", h / pd);
|
117
|
-
arguments[2].asObject(runtime).setProperty(runtime, "value", size);
|
118
|
-
} else {
|
106
|
+
info->props.insert_or_assign(
|
107
|
+
arguments[1].asString(runtime).utf8(runtime),
|
108
|
+
RNJsi::ViewProperty(runtime, arguments[2]));
|
109
|
+
if (info->props.find("onSize") == info->props.end()) {
|
119
110
|
info->props.insert_or_assign(
|
120
|
-
arguments[
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
}
|
111
|
+
"onSize", RNJsi::ViewProperty(runtime, arguments[2],
|
112
|
+
_platformContext, nativeId));
|
113
|
+
}
|
114
|
+
// Now let's see if we have a view that we can update
|
115
|
+
if (info->view != nullptr) {
|
116
|
+
// Update view!
|
117
|
+
info->view->setNativeId(nativeId);
|
118
|
+
info->view->setJsiProperties(info->props);
|
119
|
+
info->props.clear();
|
130
120
|
}
|
131
121
|
return nullptr; // Return type for template deduction
|
132
122
|
});
|
@@ -5,6 +5,7 @@
|
|
5
5
|
#include <mutex>
|
6
6
|
#include <string>
|
7
7
|
#include <unordered_map>
|
8
|
+
#include <variant>
|
8
9
|
#include <vector>
|
9
10
|
|
10
11
|
#include <jsi/jsi.h>
|
@@ -55,8 +56,25 @@ public:
|
|
55
56
|
_requestRedraw();
|
56
57
|
}
|
57
58
|
|
59
|
+
void setOnSize(
|
60
|
+
std::variant<std::nullptr_t, std::function<void(int, int)>> onSize) {
|
61
|
+
_onSize = onSize;
|
62
|
+
}
|
63
|
+
|
58
64
|
private:
|
59
65
|
bool performDraw(std::shared_ptr<RNSkCanvasProvider> canvasProvider) {
|
66
|
+
// Call onSize callback only if the size has changed
|
67
|
+
int currentWidth = canvasProvider->getWidth();
|
68
|
+
int currentHeight = canvasProvider->getHeight();
|
69
|
+
|
70
|
+
if (std::holds_alternative<std::function<void(int, int)>>(_onSize)) {
|
71
|
+
if (_lastWidth != currentWidth || _lastHeight != currentHeight) {
|
72
|
+
_lastWidth = currentWidth;
|
73
|
+
_lastHeight = currentHeight;
|
74
|
+
std::get<std::function<void(int, int)>>(_onSize)(currentWidth,
|
75
|
+
currentHeight);
|
76
|
+
}
|
77
|
+
}
|
60
78
|
return canvasProvider->renderToCanvas([=, this](SkCanvas *canvas) {
|
61
79
|
// Make sure to scale correctly
|
62
80
|
auto pd = _platformContext->getPixelDensity();
|
@@ -72,6 +90,9 @@ private:
|
|
72
90
|
|
73
91
|
std::shared_ptr<RNSkPlatformContext> _platformContext;
|
74
92
|
sk_sp<SkPicture> _picture;
|
93
|
+
std::variant<std::nullptr_t, std::function<void(int, int)>> _onSize = nullptr;
|
94
|
+
int _lastWidth = -1;
|
95
|
+
int _lastHeight = -1;
|
75
96
|
};
|
76
97
|
|
77
98
|
class RNSkPictureView : public RNSkView {
|
@@ -88,7 +109,7 @@ public:
|
|
88
109
|
|
89
110
|
void setJsiProperties(
|
90
111
|
std::unordered_map<std::string, RNJsi::ViewProperty> &props) override {
|
91
|
-
|
112
|
+
// Base implementation - no onSize callback
|
92
113
|
for (auto &prop : props) {
|
93
114
|
if (prop.first == "picture") {
|
94
115
|
if (prop.second.isNull()) {
|
@@ -97,10 +118,12 @@ public:
|
|
97
118
|
->setPicture(nullptr);
|
98
119
|
continue;
|
99
120
|
}
|
100
|
-
|
101
121
|
// Save picture
|
102
122
|
std::static_pointer_cast<RNSkPictureRenderer>(getRenderer())
|
103
123
|
->setPicture(prop.second.getPicture());
|
124
|
+
} else if (prop.first == "onSize") {
|
125
|
+
std::static_pointer_cast<RNSkPictureRenderer>(getRenderer())
|
126
|
+
->setOnSize(prop.second.getOnSize());
|
104
127
|
}
|
105
128
|
}
|
106
129
|
}
|
package/cpp/rnskia/RNSkView.h
CHANGED
@@ -148,6 +148,13 @@ public:
|
|
148
148
|
virtual void setJsiProperties(
|
149
149
|
std::unordered_map<std::string, RNJsi::ViewProperty> &props) = 0;
|
150
150
|
|
151
|
+
virtual void
|
152
|
+
setJsiProperties(std::unordered_map<std::string, RNJsi::ViewProperty> &props,
|
153
|
+
std::function<jsi::Object(int, int)> onSize) {
|
154
|
+
// Default implementation just calls the base method, ignoring onSize
|
155
|
+
setJsiProperties(props);
|
156
|
+
}
|
157
|
+
|
151
158
|
void requestRedraw() {
|
152
159
|
if (!_redrawRequested) {
|
153
160
|
_redrawRequested = true;
|
@@ -10,7 +10,8 @@ const Platform = exports.Platform = {
|
|
10
10
|
OS: _reactNative.Platform.OS,
|
11
11
|
PixelRatio: _reactNative.PixelRatio.get(),
|
12
12
|
resolveAsset: source => {
|
13
|
-
|
13
|
+
// eslint-disable-next-line no-nested-ternary
|
14
|
+
return (0, _types.isRNModule)(source) ? _reactNative.Image.resolveAssetSource(source).uri : "uri" in source ? source.uri : source.default;
|
14
15
|
},
|
15
16
|
findNodeHandle: _reactNative.findNodeHandle,
|
16
17
|
View: _reactNative.View
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_types","Platform","exports","OS","RNPlatform","PixelRatio","get","resolveAsset","source","isRNModule","Image","resolveAssetSource","uri","default","findNodeHandle","View"],"sources":["Platform.ts"],"sourcesContent":["import {\n Image,\n PixelRatio,\n Platform as RNPlatform,\n findNodeHandle,\n View,\n} from \"react-native\";\n\nimport type { DataModule } from \"../skia/types\";\nimport { isRNModule } from \"../skia/types\";\n\nimport type { IPlatform } from \"./IPlatform\";\n\nexport const Platform: IPlatform = {\n OS: RNPlatform.OS,\n PixelRatio: PixelRatio.get(),\n resolveAsset: (source: DataModule) => {\n return isRNModule(source)\n ? Image.resolveAssetSource(source).uri\n : source.default;\n },\n findNodeHandle,\n View,\n};\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AASA,IAAAC,MAAA,GAAAD,OAAA;AAIO,MAAME,QAAmB,GAAAC,OAAA,CAAAD,QAAA,GAAG;EACjCE,EAAE,EAAEC,qBAAU,CAACD,EAAE;EACjBE,UAAU,EAAEA,uBAAU,CAACC,GAAG,CAAC,CAAC;EAC5BC,YAAY,EAAGC,MAAkB,IAAK;IACpC,OAAO,IAAAC,iBAAU,EAACD,MAAM,CAAC,GACrBE,kBAAK,CAACC,kBAAkB,CAACH,MAAM,CAAC,CAACI,GAAG,
|
1
|
+
{"version":3,"names":["_reactNative","require","_types","Platform","exports","OS","RNPlatform","PixelRatio","get","resolveAsset","source","isRNModule","Image","resolveAssetSource","uri","default","findNodeHandle","View"],"sources":["Platform.ts"],"sourcesContent":["import {\n Image,\n PixelRatio,\n Platform as RNPlatform,\n findNodeHandle,\n View,\n} from \"react-native\";\n\nimport type { DataModule } from \"../skia/types\";\nimport { isRNModule } from \"../skia/types\";\n\nimport type { IPlatform } from \"./IPlatform\";\n\nexport const Platform: IPlatform = {\n OS: RNPlatform.OS,\n PixelRatio: PixelRatio.get(),\n resolveAsset: (source: DataModule) => {\n // eslint-disable-next-line no-nested-ternary\n return isRNModule(source)\n ? Image.resolveAssetSource(source).uri\n : \"uri\" in source\n ? source.uri\n : source.default;\n },\n findNodeHandle,\n View,\n};\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AASA,IAAAC,MAAA,GAAAD,OAAA;AAIO,MAAME,QAAmB,GAAAC,OAAA,CAAAD,QAAA,GAAG;EACjCE,EAAE,EAAEC,qBAAU,CAACD,EAAE;EACjBE,UAAU,EAAEA,uBAAU,CAACC,GAAG,CAAC,CAAC;EAC5BC,YAAY,EAAGC,MAAkB,IAAK;IACpC;IACA,OAAO,IAAAC,iBAAU,EAACD,MAAM,CAAC,GACrBE,kBAAK,CAACC,kBAAkB,CAACH,MAAM,CAAC,CAACI,GAAG,GACpC,KAAK,IAAIJ,MAAM,GACfA,MAAM,CAACI,GAAG,GACVJ,MAAM,CAACK,OAAO;EACpB,CAAC;EACDC,cAAc,EAAdA,2BAAc;EACdC,IAAI,EAAJA;AACF,CAAC","ignoreList":[]}
|
@@ -149,6 +149,9 @@ const Platform = exports.Platform = {
|
|
149
149
|
}
|
150
150
|
throw new Error("Asset source is a number - this is not supported on the web");
|
151
151
|
}
|
152
|
+
if ("uri" in source) {
|
153
|
+
return source.uri;
|
154
|
+
}
|
152
155
|
return source.default;
|
153
156
|
},
|
154
157
|
findNodeHandle: () => {
|