@shopify/react-native-skia 2.2.19 → 2.2.21
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/android/CMakeLists.txt +2 -0
- package/apple/SkiaCVPixelBufferUtils.mm +8 -4
- package/cpp/api/JsiSkCanvas.h +22 -0
- package/cpp/api/JsiSkDispatcher.cpp +9 -0
- package/cpp/api/JsiSkDispatcher.h +149 -0
- package/cpp/api/JsiSkImage.h +27 -9
- package/cpp/api/JsiSkPicture.h +22 -1
- package/cpp/api/JsiSkSurface.h +15 -10
- package/cpp/api/recorder/Drawings.h +43 -9
- package/cpp/api/recorder/JsiRecorder.h +3 -1
- package/cpp/api/recorder/RNRecorder.h +10 -4
- package/lib/commonjs/external/reanimated/textures.js +31 -28
- package/lib/commonjs/external/reanimated/textures.js.map +1 -1
- package/lib/commonjs/renderer/Offscreen.js +1 -7
- package/lib/commonjs/renderer/Offscreen.js.map +1 -1
- package/lib/commonjs/skia/core/SVG.web.d.ts +2 -2
- package/lib/commonjs/skia/core/SVG.web.js +23 -7
- package/lib/commonjs/skia/core/SVG.web.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkCanvas.d.ts +1 -1
- package/lib/commonjs/skia/web/JsiSkCanvas.js +7 -1
- package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +4 -0
- package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js +4 -0
- package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
- package/lib/module/external/reanimated/textures.js +33 -30
- package/lib/module/external/reanimated/textures.js.map +1 -1
- package/lib/module/renderer/Offscreen.js +1 -8
- package/lib/module/renderer/Offscreen.js.map +1 -1
- package/lib/module/skia/core/SVG.web.d.ts +2 -2
- package/lib/module/skia/core/SVG.web.js +23 -7
- package/lib/module/skia/core/SVG.web.js.map +1 -1
- package/lib/module/skia/web/JsiSkCanvas.d.ts +1 -1
- package/lib/module/skia/web/JsiSkCanvas.js +7 -1
- package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
- package/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +4 -0
- package/lib/module/sksg/Recorder/ReanimatedRecorder.js +5 -0
- package/lib/module/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
- package/lib/typescript/lib/commonjs/skia/core/SVG.web.d.ts +1 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiSkCanvas.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +4 -0
- package/lib/typescript/lib/module/skia/core/SVG.web.d.ts +1 -1
- package/lib/typescript/lib/module/skia/web/JsiSkCanvas.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +4 -0
- package/lib/typescript/src/skia/core/SVG.web.d.ts +2 -2
- package/lib/typescript/src/skia/web/JsiSkCanvas.d.ts +1 -1
- package/lib/typescript/src/sksg/Recorder/ReanimatedRecorder.d.ts +4 -0
- package/package.json +6 -1
- package/src/external/reanimated/textures.tsx +36 -27
- package/src/renderer/Offscreen.tsx +1 -7
- package/src/skia/core/SVG.web.ts +35 -21
- package/src/skia/web/JsiSkCanvas.ts +3 -1
- package/src/sksg/Recorder/ReanimatedRecorder.ts +4 -0
- package/cpp/api/JsiSkThreadSafeDeletion.h +0 -105
package/android/CMakeLists.txt
CHANGED
@@ -126,6 +126,8 @@ add_library(
|
|
126
126
|
"${PROJECT_SOURCE_DIR}/../cpp/api/third_party/CSSColorParser.cpp"
|
127
127
|
"${PROJECT_SOURCE_DIR}/../cpp/api/third_party/base64.cpp"
|
128
128
|
"${PROJECT_SOURCE_DIR}/../cpp/api/third_party/SkottieUtils.cpp"
|
129
|
+
|
130
|
+
"${PROJECT_SOURCE_DIR}/../cpp/api/JsiSkDispatcher.cpp"
|
129
131
|
${BACKEND_SOURCES}
|
130
132
|
)
|
131
133
|
|
@@ -30,12 +30,16 @@
|
|
30
30
|
#include <TargetConditionals.h>
|
31
31
|
#if TARGET_RT_BIG_ENDIAN
|
32
32
|
#define FourCC2Str(fourcc) \
|
33
|
-
(const char[]){
|
34
|
-
|
33
|
+
(const char[]) { \
|
34
|
+
*((char *)&fourcc), *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 2), \
|
35
|
+
*(((char *)&fourcc) + 3), 0 \
|
36
|
+
}
|
35
37
|
#else
|
36
38
|
#define FourCC2Str(fourcc) \
|
37
|
-
(const char[]){
|
38
|
-
|
39
|
+
(const char[]) { \
|
40
|
+
*(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
|
41
|
+
*(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0 \
|
42
|
+
}
|
39
43
|
#endif
|
40
44
|
|
41
45
|
// pragma MARK: TextureHolder
|
package/cpp/api/JsiSkCanvas.h
CHANGED
@@ -34,6 +34,7 @@
|
|
34
34
|
#include "include/core/SkRegion.h"
|
35
35
|
#include "include/core/SkSurface.h"
|
36
36
|
#include "include/core/SkTypeface.h"
|
37
|
+
#include "include/gpu/ganesh/GrDirectContext.h"
|
37
38
|
|
38
39
|
#pragma clang diagnostic pop
|
39
40
|
|
@@ -68,6 +69,7 @@ public:
|
|
68
69
|
|
69
70
|
JSI_HOST_FUNCTION(drawImage) {
|
70
71
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
72
|
+
validateImageForDrawing(runtime, image);
|
71
73
|
auto x = arguments[1].asNumber();
|
72
74
|
auto y = arguments[2].asNumber();
|
73
75
|
std::shared_ptr<SkPaint> paint;
|
@@ -80,6 +82,7 @@ public:
|
|
80
82
|
|
81
83
|
JSI_HOST_FUNCTION(drawImageRect) {
|
82
84
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
85
|
+
validateImageForDrawing(runtime, image);
|
83
86
|
auto src = JsiSkRect::fromValue(runtime, arguments[1]);
|
84
87
|
auto dest = JsiSkRect::fromValue(runtime, arguments[2]);
|
85
88
|
auto paint = JsiSkPaint::fromValue(runtime, arguments[3]);
|
@@ -92,6 +95,7 @@ public:
|
|
92
95
|
|
93
96
|
JSI_HOST_FUNCTION(drawImageCubic) {
|
94
97
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
98
|
+
validateImageForDrawing(runtime, image);
|
95
99
|
auto x = arguments[1].asNumber();
|
96
100
|
auto y = arguments[2].asNumber();
|
97
101
|
float B = arguments[3].asNumber();
|
@@ -108,6 +112,7 @@ public:
|
|
108
112
|
|
109
113
|
JSI_HOST_FUNCTION(drawImageOptions) {
|
110
114
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
115
|
+
validateImageForDrawing(runtime, image);
|
111
116
|
auto x = arguments[1].asNumber();
|
112
117
|
auto y = arguments[2].asNumber();
|
113
118
|
auto fm = (SkFilterMode)arguments[3].asNumber();
|
@@ -124,6 +129,7 @@ public:
|
|
124
129
|
|
125
130
|
JSI_HOST_FUNCTION(drawImageNine) {
|
126
131
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
132
|
+
validateImageForDrawing(runtime, image);
|
127
133
|
auto center = JsiSkRect::fromValue(runtime, arguments[1]);
|
128
134
|
auto dest = JsiSkRect::fromValue(runtime, arguments[2]);
|
129
135
|
auto fm = (SkFilterMode)arguments[3].asNumber();
|
@@ -140,6 +146,7 @@ public:
|
|
140
146
|
|
141
147
|
JSI_HOST_FUNCTION(drawImageRectCubic) {
|
142
148
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
149
|
+
validateImageForDrawing(runtime, image);
|
143
150
|
auto src = JsiSkRect::fromValue(runtime, arguments[1]);
|
144
151
|
auto dest = JsiSkRect::fromValue(runtime, arguments[2]);
|
145
152
|
float B = arguments[3].asNumber();
|
@@ -159,6 +166,7 @@ public:
|
|
159
166
|
|
160
167
|
JSI_HOST_FUNCTION(drawImageRectOptions) {
|
161
168
|
auto image = JsiSkImage::fromValue(runtime, arguments[0]);
|
169
|
+
validateImageForDrawing(runtime, image);
|
162
170
|
auto src = JsiSkRect::fromValue(runtime, arguments[1]);
|
163
171
|
auto dest = JsiSkRect::fromValue(runtime, arguments[2]);
|
164
172
|
auto filter = (SkFilterMode)arguments[3].asNumber();
|
@@ -695,6 +703,20 @@ public:
|
|
695
703
|
SkCanvas *getCanvas() { return _canvas; }
|
696
704
|
|
697
705
|
private:
|
706
|
+
void validateImageForDrawing(jsi::Runtime &runtime,
|
707
|
+
const sk_sp<SkImage> image) {
|
708
|
+
#if !defined(SK_GRAPHITE)
|
709
|
+
auto ctx = getContext()->getDirectContext();
|
710
|
+
if (!ctx) {
|
711
|
+
throw jsi::JSError(runtime, "No GPU context available");
|
712
|
+
}
|
713
|
+
if (image && !image->isValid(ctx->asRecorder())) {
|
714
|
+
throw jsi::JSError(
|
715
|
+
runtime, "image used in drawImage() does not belong to this context");
|
716
|
+
}
|
717
|
+
#endif
|
718
|
+
}
|
719
|
+
|
698
720
|
SkCanvas *_canvas;
|
699
721
|
};
|
700
722
|
} // namespace RNSkia
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <functional>
|
4
|
+
#include <memory>
|
5
|
+
#include <mutex>
|
6
|
+
#include <queue>
|
7
|
+
#include <thread>
|
8
|
+
#include <unordered_map>
|
9
|
+
|
10
|
+
namespace RNSkia {
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Thread-local dispatcher for managing deferred operations.
|
14
|
+
* Each thread gets its own dispatcher instance for queueing operations
|
15
|
+
* to be executed on that specific thread.
|
16
|
+
*/
|
17
|
+
class Dispatcher {
|
18
|
+
private:
|
19
|
+
using Operation = std::function<void()>;
|
20
|
+
|
21
|
+
struct DispatcherData {
|
22
|
+
std::queue<Operation> operationQueue;
|
23
|
+
std::mutex queueMutex;
|
24
|
+
};
|
25
|
+
|
26
|
+
// Thread-local storage for dispatcher data
|
27
|
+
static thread_local std::shared_ptr<DispatcherData> _threadDispatcher;
|
28
|
+
|
29
|
+
// Global registry of all dispatchers by thread ID
|
30
|
+
static inline std::mutex _registryMutex;
|
31
|
+
static inline std::unordered_map<std::thread::id,
|
32
|
+
std::weak_ptr<DispatcherData>>
|
33
|
+
_dispatcherRegistry;
|
34
|
+
|
35
|
+
std::shared_ptr<DispatcherData> _data;
|
36
|
+
std::thread::id _threadId;
|
37
|
+
|
38
|
+
public:
|
39
|
+
Dispatcher() : _threadId(std::this_thread::get_id()) {
|
40
|
+
// Get or create dispatcher data for current thread
|
41
|
+
if (!_threadDispatcher) {
|
42
|
+
_threadDispatcher = std::make_shared<DispatcherData>();
|
43
|
+
|
44
|
+
// Register in global registry
|
45
|
+
std::lock_guard<std::mutex> lock(_registryMutex);
|
46
|
+
_dispatcherRegistry[_threadId] = _threadDispatcher;
|
47
|
+
}
|
48
|
+
_data = _threadDispatcher;
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Get the dispatcher for the current thread.
|
53
|
+
* Creates one if it doesn't exist.
|
54
|
+
*/
|
55
|
+
static std::shared_ptr<Dispatcher> getDispatcher() {
|
56
|
+
return std::make_shared<Dispatcher>();
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Get the dispatcher for a specific thread.
|
61
|
+
* Returns nullptr if that thread doesn't have a dispatcher.
|
62
|
+
*/
|
63
|
+
static std::shared_ptr<Dispatcher> getDispatcher(std::thread::id threadId) {
|
64
|
+
std::lock_guard<std::mutex> lock(_registryMutex);
|
65
|
+
auto it = _dispatcherRegistry.find(threadId);
|
66
|
+
if (it != _dispatcherRegistry.end()) {
|
67
|
+
if (auto data = it->second.lock()) {
|
68
|
+
auto dispatcher = std::make_shared<Dispatcher>();
|
69
|
+
dispatcher->_data = data;
|
70
|
+
dispatcher->_threadId = threadId;
|
71
|
+
return dispatcher;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return nullptr;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Queue an operation to be executed on the dispatcher's thread.
|
79
|
+
* The operation will be executed when processQueue() is called on that
|
80
|
+
* thread.
|
81
|
+
*/
|
82
|
+
void run(Operation op) {
|
83
|
+
if (!_data)
|
84
|
+
return;
|
85
|
+
|
86
|
+
std::lock_guard<std::mutex> lock(_data->queueMutex);
|
87
|
+
_data->operationQueue.push(std::move(op));
|
88
|
+
}
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Process all pending operations for the current thread.
|
92
|
+
* Must be called from the thread that owns this dispatcher.
|
93
|
+
* Returns the number of operations processed.
|
94
|
+
*/
|
95
|
+
size_t processQueue() {
|
96
|
+
if (!_data)
|
97
|
+
return 0;
|
98
|
+
|
99
|
+
// Only process if we're on the correct thread
|
100
|
+
if (std::this_thread::get_id() != _threadId) {
|
101
|
+
return 0;
|
102
|
+
}
|
103
|
+
|
104
|
+
std::queue<Operation> operations;
|
105
|
+
{
|
106
|
+
std::lock_guard<std::mutex> lock(_data->queueMutex);
|
107
|
+
operations.swap(_data->operationQueue);
|
108
|
+
}
|
109
|
+
|
110
|
+
size_t count = operations.size();
|
111
|
+
while (!operations.empty()) {
|
112
|
+
auto &op = operations.front();
|
113
|
+
op();
|
114
|
+
operations.pop();
|
115
|
+
}
|
116
|
+
|
117
|
+
return count;
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Get the number of pending operations.
|
122
|
+
*/
|
123
|
+
size_t getPendingCount() const {
|
124
|
+
if (!_data)
|
125
|
+
return 0;
|
126
|
+
|
127
|
+
std::lock_guard<std::mutex> lock(_data->queueMutex);
|
128
|
+
return _data->operationQueue.size();
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Clean up dispatcher for a thread that's shutting down.
|
133
|
+
*/
|
134
|
+
static void cleanup() {
|
135
|
+
if (_threadDispatcher) {
|
136
|
+
// Process any remaining operations
|
137
|
+
auto dispatcher = getDispatcher();
|
138
|
+
dispatcher->processQueue();
|
139
|
+
|
140
|
+
// Remove from registry
|
141
|
+
std::lock_guard<std::mutex> lock(_registryMutex);
|
142
|
+
_dispatcherRegistry.erase(std::this_thread::get_id());
|
143
|
+
|
144
|
+
_threadDispatcher.reset();
|
145
|
+
}
|
146
|
+
}
|
147
|
+
};
|
148
|
+
|
149
|
+
} // namespace RNSkia
|
package/cpp/api/JsiSkImage.h
CHANGED
@@ -4,11 +4,11 @@
|
|
4
4
|
#include <string>
|
5
5
|
#include <utility>
|
6
6
|
|
7
|
+
#include "JsiSkDispatcher.h"
|
7
8
|
#include "JsiSkHostObjects.h"
|
8
9
|
#include "JsiSkImageInfo.h"
|
9
10
|
#include "JsiSkMatrix.h"
|
10
11
|
#include "JsiSkShader.h"
|
11
|
-
#include "JsiSkThreadSafeDeletion.h"
|
12
12
|
#include "third_party/base64.h"
|
13
13
|
|
14
14
|
#include "JsiTextureInfo.h"
|
@@ -63,7 +63,7 @@ inline SkSamplingOptions SamplingOptionsFromValue(jsi::Runtime &runtime,
|
|
63
63
|
|
64
64
|
class JsiSkImage : public JsiSkWrappingSkPtrHostObject<SkImage> {
|
65
65
|
private:
|
66
|
-
|
66
|
+
std::shared_ptr<Dispatcher> _dispatcher;
|
67
67
|
|
68
68
|
public:
|
69
69
|
// TODO-API: Properties?
|
@@ -258,6 +258,10 @@ public:
|
|
258
258
|
return JsiTextureInfo::toValue(runtime, texInfo);
|
259
259
|
}
|
260
260
|
|
261
|
+
JSI_HOST_FUNCTION(isTextureBacked) {
|
262
|
+
return jsi::Value(getObject()->isTextureBacked());
|
263
|
+
}
|
264
|
+
|
261
265
|
EXPORT_JSI_API_TYPENAME(JsiSkImage, Image)
|
262
266
|
|
263
267
|
JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkImage, width),
|
@@ -270,27 +274,41 @@ public:
|
|
270
274
|
JSI_EXPORT_FUNC(JsiSkImage, readPixels),
|
271
275
|
JSI_EXPORT_FUNC(JsiSkImage, makeNonTextureImage),
|
272
276
|
JSI_EXPORT_FUNC(JsiSkImage, getNativeTextureUnstable),
|
277
|
+
JSI_EXPORT_FUNC(JsiSkImage, isTextureBacked),
|
273
278
|
JSI_EXPORT_FUNC(JsiSkImage, dispose))
|
274
279
|
|
275
280
|
JsiSkImage(std::shared_ptr<RNSkPlatformContext> context,
|
276
281
|
const sk_sp<SkImage> image)
|
277
282
|
: JsiSkWrappingSkPtrHostObject<SkImage>(std::move(context),
|
278
283
|
std::move(image)) {
|
279
|
-
//
|
280
|
-
|
284
|
+
// Get the dispatcher for the current thread
|
285
|
+
_dispatcher = Dispatcher::getDispatcher();
|
286
|
+
// Process any pending operations
|
287
|
+
_dispatcher->processQueue();
|
281
288
|
}
|
282
289
|
|
283
290
|
~JsiSkImage() override {
|
284
|
-
//
|
285
|
-
|
286
|
-
|
287
|
-
|
291
|
+
// Queue deletion on the creation thread if needed
|
292
|
+
auto image = getObject();
|
293
|
+
if (image && _dispatcher) {
|
294
|
+
_dispatcher->run([image]() {
|
295
|
+
// Image will be deleted when this lambda is destroyed
|
296
|
+
});
|
297
|
+
}
|
298
|
+
// Clear the object to prevent base class destructor from deleting it
|
288
299
|
setObject(nullptr);
|
289
300
|
}
|
290
301
|
|
291
302
|
size_t getMemoryPressure() const override {
|
292
303
|
auto image = getObject();
|
293
|
-
|
304
|
+
if (image) {
|
305
|
+
if (image->isTextureBacked()) {
|
306
|
+
return image->textureSize();
|
307
|
+
} else {
|
308
|
+
return image->imageInfo().computeMinByteSize();
|
309
|
+
}
|
310
|
+
}
|
311
|
+
return 0;
|
294
312
|
}
|
295
313
|
};
|
296
314
|
|
package/cpp/api/JsiSkPicture.h
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#include <memory>
|
4
4
|
|
5
5
|
#include "JsiSkData.h"
|
6
|
+
#include "JsiSkDispatcher.h"
|
6
7
|
#include "JsiSkHostObjects.h"
|
7
8
|
#include "JsiSkMatrix.h"
|
8
9
|
#include "JsiSkRect.h"
|
@@ -20,10 +21,30 @@ namespace RNSkia {
|
|
20
21
|
namespace jsi = facebook::jsi;
|
21
22
|
|
22
23
|
class JsiSkPicture : public JsiSkWrappingSkPtrHostObject<SkPicture> {
|
24
|
+
private:
|
25
|
+
std::shared_ptr<Dispatcher> _dispatcher;
|
26
|
+
|
23
27
|
public:
|
24
28
|
JsiSkPicture(std::shared_ptr<RNSkPlatformContext> context,
|
25
29
|
const sk_sp<SkPicture> picture)
|
26
|
-
: JsiSkWrappingSkPtrHostObject<SkPicture>(context, picture) {
|
30
|
+
: JsiSkWrappingSkPtrHostObject<SkPicture>(context, picture) {
|
31
|
+
// Get the dispatcher for the current thread
|
32
|
+
_dispatcher = Dispatcher::getDispatcher();
|
33
|
+
// Process any pending operations
|
34
|
+
_dispatcher->processQueue();
|
35
|
+
}
|
36
|
+
|
37
|
+
~JsiSkPicture() override {
|
38
|
+
// Queue deletion on the creation thread if needed
|
39
|
+
auto picture = getObject();
|
40
|
+
if (picture && _dispatcher) {
|
41
|
+
_dispatcher->run([picture]() {
|
42
|
+
// Picture will be deleted when this lambda is destroyed
|
43
|
+
});
|
44
|
+
}
|
45
|
+
// Clear the object to prevent base class destructor from deleting it
|
46
|
+
setObject(nullptr);
|
47
|
+
}
|
27
48
|
|
28
49
|
JSI_HOST_FUNCTION(makeShader) {
|
29
50
|
auto tmx = (SkTileMode)arguments[0].asNumber();
|
package/cpp/api/JsiSkSurface.h
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
|
6
6
|
#include <jsi/jsi.h>
|
7
7
|
|
8
|
+
#include "JsiSkDispatcher.h"
|
8
9
|
#include "JsiSkHostObjects.h"
|
9
|
-
#include "JsiSkThreadSafeDeletion.h"
|
10
10
|
#include "JsiTextureInfo.h"
|
11
11
|
|
12
12
|
#include "JsiSkCanvas.h"
|
@@ -30,23 +30,28 @@ namespace jsi = facebook::jsi;
|
|
30
30
|
|
31
31
|
class JsiSkSurface : public JsiSkWrappingSkPtrHostObject<SkSurface> {
|
32
32
|
private:
|
33
|
-
|
33
|
+
std::shared_ptr<Dispatcher> _dispatcher;
|
34
34
|
|
35
35
|
public:
|
36
36
|
JsiSkSurface(std::shared_ptr<RNSkPlatformContext> context,
|
37
37
|
sk_sp<SkSurface> surface)
|
38
38
|
: JsiSkWrappingSkPtrHostObject<SkSurface>(std::move(context),
|
39
|
-
std::move(surface))
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
std::move(surface)) {
|
40
|
+
// Get the dispatcher for the current thread
|
41
|
+
_dispatcher = Dispatcher::getDispatcher();
|
42
|
+
// Process any pending operations
|
43
|
+
_dispatcher->processQueue();
|
43
44
|
}
|
44
45
|
|
45
46
|
~JsiSkSurface() override {
|
46
|
-
//
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
// Queue deletion on the creation thread if needed
|
48
|
+
auto surface = getObject();
|
49
|
+
if (surface && _dispatcher) {
|
50
|
+
_dispatcher->run([surface]() {
|
51
|
+
// Surface will be deleted when this lambda is destroyed
|
52
|
+
});
|
53
|
+
}
|
54
|
+
// Clear the object to prevent base class destructor from deleting it
|
50
55
|
setObject(nullptr);
|
51
56
|
}
|
52
57
|
|
@@ -6,6 +6,7 @@
|
|
6
6
|
#include "Convertor.h"
|
7
7
|
#include "DrawingCtx.h"
|
8
8
|
#include "ImageFit.h"
|
9
|
+
#include "RNSkPlatformContext.h"
|
9
10
|
|
10
11
|
namespace RNSkia {
|
11
12
|
|
@@ -468,10 +469,11 @@ struct ImageCmdProps {
|
|
468
469
|
class ImageCmd : public Command {
|
469
470
|
public:
|
470
471
|
ImageCmdProps props;
|
472
|
+
std::shared_ptr<RNSkPlatformContext> _context;
|
471
473
|
|
472
|
-
ImageCmd(
|
473
|
-
Variables &variables)
|
474
|
-
: Command(CommandType::DrawImage) {
|
474
|
+
ImageCmd(std::shared_ptr<RNSkPlatformContext> context, jsi::Runtime &runtime,
|
475
|
+
const jsi::Object &object, Variables &variables)
|
476
|
+
: Command(CommandType::DrawImage), _context(context) {
|
475
477
|
convertProperty(runtime, object, "rect", props.rect, variables);
|
476
478
|
convertProperty(runtime, object, "image", props.image, variables);
|
477
479
|
convertProperty(runtime, object, "sampling", props.sampling, variables);
|
@@ -484,6 +486,17 @@ public:
|
|
484
486
|
convertProperty(runtime, object, "rect", props.rect, variables);
|
485
487
|
}
|
486
488
|
|
489
|
+
~ImageCmd() {
|
490
|
+
if (props.image.has_value()) {
|
491
|
+
auto image = props.image.value();
|
492
|
+
if (image) {
|
493
|
+
_context->runOnMainThread([image]() {
|
494
|
+
// Image will be deleted when this lambda is destroyed on main thread
|
495
|
+
});
|
496
|
+
}
|
497
|
+
}
|
498
|
+
}
|
499
|
+
|
487
500
|
void draw(DrawingCtx *ctx) {
|
488
501
|
auto [x, y, width, height, rect, fit, image, sampling] = props;
|
489
502
|
if (image.has_value()) {
|
@@ -784,13 +797,24 @@ struct PictureCmdProps {
|
|
784
797
|
class PictureCmd : public Command {
|
785
798
|
public:
|
786
799
|
PictureCmdProps props;
|
800
|
+
std::shared_ptr<RNSkPlatformContext> _context;
|
787
801
|
|
788
|
-
PictureCmd(
|
802
|
+
PictureCmd(std::shared_ptr<RNSkPlatformContext> context,
|
803
|
+
jsi::Runtime &runtime, const jsi::Object &object,
|
789
804
|
Variables &variables)
|
790
|
-
: Command(CommandType::DrawPicture) {
|
805
|
+
: Command(CommandType::DrawPicture), _context(context) {
|
791
806
|
convertProperty(runtime, object, "picture", props.picture, variables);
|
792
807
|
}
|
793
808
|
|
809
|
+
~PictureCmd() {
|
810
|
+
auto picture = props.picture;
|
811
|
+
if (picture) {
|
812
|
+
_context->runOnMainThread([picture]() {
|
813
|
+
// Picture will be deleted when this lambda is destroyed on main thread
|
814
|
+
});
|
815
|
+
}
|
816
|
+
}
|
817
|
+
|
794
818
|
void draw(DrawingCtx *ctx) { ctx->canvas->drawPicture(props.picture); }
|
795
819
|
};
|
796
820
|
|
@@ -914,10 +938,11 @@ struct AtlasCmdProps {
|
|
914
938
|
class AtlasCmd : public Command {
|
915
939
|
public:
|
916
940
|
AtlasCmdProps props;
|
941
|
+
std::shared_ptr<RNSkPlatformContext> _context;
|
917
942
|
|
918
|
-
AtlasCmd(
|
919
|
-
Variables &variables)
|
920
|
-
: Command(CommandType::DrawAtlas) {
|
943
|
+
AtlasCmd(std::shared_ptr<RNSkPlatformContext> context, jsi::Runtime &runtime,
|
944
|
+
const jsi::Object &object, Variables &variables)
|
945
|
+
: Command(CommandType::DrawAtlas), _context(context) {
|
921
946
|
convertProperty(runtime, object, "image", props.image, variables);
|
922
947
|
convertProperty(runtime, object, "sprites", props.sprites, variables);
|
923
948
|
convertProperty(runtime, object, "transforms", props.transforms, variables);
|
@@ -926,6 +951,15 @@ public:
|
|
926
951
|
convertProperty(runtime, object, "sampling", props.sampling, variables);
|
927
952
|
}
|
928
953
|
|
954
|
+
~AtlasCmd() {
|
955
|
+
auto image = props.image;
|
956
|
+
if (image) {
|
957
|
+
_context->runOnMainThread([image]() {
|
958
|
+
// Image will be deleted when this lambda is destroyed on main thread
|
959
|
+
});
|
960
|
+
}
|
961
|
+
}
|
962
|
+
|
929
963
|
void draw(DrawingCtx *ctx) {
|
930
964
|
if (props.image) {
|
931
965
|
// Validate transforms and sprites have the same size
|
@@ -956,4 +990,4 @@ public:
|
|
956
990
|
}
|
957
991
|
};
|
958
992
|
|
959
|
-
} // namespace RNSkia
|
993
|
+
} // namespace RNSkia
|
@@ -22,7 +22,9 @@ class JsiRecorder : public JsiSkWrappingSharedPtrHostObject<Recorder> {
|
|
22
22
|
public:
|
23
23
|
JsiRecorder(std::shared_ptr<RNSkPlatformContext> context)
|
24
24
|
: JsiSkWrappingSharedPtrHostObject(std::move(context),
|
25
|
-
std::make_shared<Recorder>()) {
|
25
|
+
std::make_shared<Recorder>()) {
|
26
|
+
getObject()->_context = getContext();
|
27
|
+
}
|
26
28
|
|
27
29
|
JSI_HOST_FUNCTION(savePaint) {
|
28
30
|
getObject()->savePaint(runtime, arguments[0].asObject(runtime),
|
@@ -15,6 +15,7 @@
|
|
15
15
|
#include "ImageFilters.h"
|
16
16
|
#include "Paint.h"
|
17
17
|
#include "PathEffects.h"
|
18
|
+
#include "RNSkPlatformContext.h"
|
18
19
|
#include "Shaders.h"
|
19
20
|
|
20
21
|
namespace RNSkia {
|
@@ -24,8 +25,10 @@ private:
|
|
24
25
|
std::vector<std::unique_ptr<Command>> commands;
|
25
26
|
|
26
27
|
public:
|
28
|
+
std::shared_ptr<RNSkPlatformContext> _context;
|
27
29
|
Variables variables;
|
28
30
|
|
31
|
+
Recorder() = default;
|
29
32
|
~Recorder() = default;
|
30
33
|
|
31
34
|
void savePaint(jsi::Runtime &runtime, const jsi::Object &props,
|
@@ -216,7 +219,8 @@ public:
|
|
216
219
|
}
|
217
220
|
|
218
221
|
void drawImage(jsi::Runtime &runtime, const jsi::Object &props) {
|
219
|
-
commands.push_back(
|
222
|
+
commands.push_back(
|
223
|
+
std::make_unique<ImageCmd>(_context, runtime, props, variables));
|
220
224
|
}
|
221
225
|
|
222
226
|
void drawPoints(jsi::Runtime &runtime, const jsi::Object &props) {
|
@@ -255,7 +259,8 @@ public:
|
|
255
259
|
}
|
256
260
|
|
257
261
|
void drawPicture(jsi::Runtime &runtime, const jsi::Object &props) {
|
258
|
-
commands.push_back(
|
262
|
+
commands.push_back(
|
263
|
+
std::make_unique<PictureCmd>(_context, runtime, props, variables));
|
259
264
|
}
|
260
265
|
|
261
266
|
void drawImageSVG(jsi::Runtime &runtime, const jsi::Object &props) {
|
@@ -269,7 +274,8 @@ public:
|
|
269
274
|
}
|
270
275
|
|
271
276
|
void drawAtlas(jsi::Runtime &runtime, const jsi::Object &props) {
|
272
|
-
commands.push_back(
|
277
|
+
commands.push_back(
|
278
|
+
std::make_unique<AtlasCmd>(_context, runtime, props, variables));
|
273
279
|
}
|
274
280
|
|
275
281
|
void drawSkottie(jsi::Runtime &runtime, const jsi::Object &props) {
|
@@ -646,4 +652,4 @@ public:
|
|
646
652
|
}
|
647
653
|
};
|
648
654
|
|
649
|
-
} // namespace RNSkia
|
655
|
+
} // namespace RNSkia
|