@shopify/react-native-skia 0.1.241 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- package/android/CMakeLists.txt +32 -0
- package/android/build.gradle +12 -0
- package/android/cpp/jni/JniSkiaManager.cpp +38 -5
- package/android/cpp/jni/include/JniPlatformContext.h +0 -4
- package/android/cpp/jni/include/JniSkiaManager.h +3 -4
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +3 -2
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaManager.java +4 -4
- package/android/src/reactnative69/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +11 -0
- package/android/src/reactnative74/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +14 -0
- package/lib/commonjs/renderer/Offscreen.js +2 -2
- package/lib/commonjs/renderer/Offscreen.js.map +1 -1
- package/lib/module/renderer/Offscreen.js +2 -2
- package/lib/module/renderer/Offscreen.js.map +1 -1
- package/package.json +9 -7
- package/src/renderer/Offscreen.tsx +2 -2
package/android/CMakeLists.txt
CHANGED
@@ -73,6 +73,8 @@ target_include_directories(
|
|
73
73
|
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi"
|
74
74
|
"${NODE_MODULES_DIR}/react-native/ReactCommon"
|
75
75
|
"${NODE_MODULES_DIR}/react-native/ReactCommon/react/nativemodule/core"
|
76
|
+
"${NODE_MODULES_DIR}/react-native/ReactCommon/runtimeexecutor"
|
77
|
+
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/jni"
|
76
78
|
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni"
|
77
79
|
|
78
80
|
cpp/jni/include
|
@@ -178,6 +180,34 @@ else()
|
|
178
180
|
endif()
|
179
181
|
message("-- FBJNI : " ${FBJNI_LIBRARY})
|
180
182
|
|
183
|
+
unset(REACTNATIVEJNI_LIB CACHE)
|
184
|
+
if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71)
|
185
|
+
# RN 0.71 distributes prebuilt binaries.
|
186
|
+
set (REACTNATIVEJNI_LIB "ReactAndroid::reactnativejni")
|
187
|
+
else()
|
188
|
+
find_library(
|
189
|
+
REACTNATIVEJNI_LIB
|
190
|
+
reactnativejni
|
191
|
+
PATHS ${LIBRN_DIR}
|
192
|
+
NO_CMAKE_FIND_ROOT_PATH
|
193
|
+
)
|
194
|
+
endif()
|
195
|
+
message("-- REACTNATIVEJNI : " ${REACTNATIVEJNI_LIB})
|
196
|
+
|
197
|
+
unset(RUNTIMEEXECUTOR_LIB CACHE)
|
198
|
+
if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71)
|
199
|
+
# RN 0.71 distributes prebuilt binaries.
|
200
|
+
set (RUNTIMEEXECUTOR_LIB "ReactAndroid::runtimeexecutor")
|
201
|
+
else()
|
202
|
+
find_library(
|
203
|
+
RUNTIMEEXECUTOR_LIB
|
204
|
+
runtimeexecutor
|
205
|
+
PATHS ${LIBRN_DIR}
|
206
|
+
NO_CMAKE_FIND_ROOT_PATH
|
207
|
+
)
|
208
|
+
endif()
|
209
|
+
message("-- RUNTIMEEXECUTOR : " ${RUNTIMEEXECUTOR_LIB})
|
210
|
+
|
181
211
|
unset(TURBOMODULES_LIB CACHE)
|
182
212
|
if(${REACT_NATIVE_VERSION} GREATER_EQUAL 71)
|
183
213
|
# RN 0.71 distributes prebuilt binaries.
|
@@ -199,6 +229,8 @@ target_link_libraries(
|
|
199
229
|
${FBJNI_LIBRARY}
|
200
230
|
${REACT_LIB}
|
201
231
|
${JSI_LIB}
|
232
|
+
${REACTNATIVEJNI_LIB}
|
233
|
+
${RUNTIMEEXECUTOR_LIB}
|
202
234
|
${TURBOMODULES_LIB}
|
203
235
|
${SKIA_SVG_LIB}
|
204
236
|
${SKIA_SKSHAPER_LIB}
|
package/android/build.gradle
CHANGED
@@ -167,6 +167,16 @@ android {
|
|
167
167
|
"src/paper/java",
|
168
168
|
]
|
169
169
|
}
|
170
|
+
|
171
|
+
if (REACT_NATIVE_VERSION >= 74) {
|
172
|
+
srcDirs += [
|
173
|
+
"src/reactnative74/java"
|
174
|
+
]
|
175
|
+
} else {
|
176
|
+
srcDirs += [
|
177
|
+
"src/reactnative69/java"
|
178
|
+
]
|
179
|
+
}
|
170
180
|
}
|
171
181
|
}
|
172
182
|
|
@@ -182,6 +192,8 @@ android {
|
|
182
192
|
"**/libfbjni.so",
|
183
193
|
"**/libjsi.so",
|
184
194
|
"**/libreact_nativemodule_core.so",
|
195
|
+
"**/libreactnativejni.so",
|
196
|
+
"**/libruntimeexecutor.so",
|
185
197
|
"**/libturbomodulejsijni.so",
|
186
198
|
"META-INF/**"
|
187
199
|
]
|
@@ -7,6 +7,36 @@
|
|
7
7
|
|
8
8
|
#include <RNSkManager.h>
|
9
9
|
|
10
|
+
namespace {
|
11
|
+
|
12
|
+
// For bridgeless mode, currently we don't have a way to get the JSCallInvoker
|
13
|
+
// from Java. Workaround to use RuntimeExecutor to simulate the behavior of
|
14
|
+
// JSCallInvoker. In the future when bridgeless mode is a standard and no more
|
15
|
+
// backward compatible to be considered, we could just use RuntimeExecutor to
|
16
|
+
// run task on JS thread.
|
17
|
+
class BridgelessJSCallInvoker : public facebook::react::CallInvoker {
|
18
|
+
public:
|
19
|
+
explicit BridgelessJSCallInvoker(
|
20
|
+
facebook::react::RuntimeExecutor runtimeExecutor)
|
21
|
+
: runtimeExecutor_(std::move(runtimeExecutor)) {}
|
22
|
+
|
23
|
+
void invokeAsync(std::function<void()> &&func) noexcept override {
|
24
|
+
runtimeExecutor_(
|
25
|
+
[func = std::move(func)](facebook::jsi::Runtime &runtime) { func(); });
|
26
|
+
}
|
27
|
+
|
28
|
+
void invokeSync(std::function<void()> &&func) override {
|
29
|
+
throw std::runtime_error(
|
30
|
+
"Synchronous native -> JS calls are currently not supported.");
|
31
|
+
}
|
32
|
+
|
33
|
+
private:
|
34
|
+
facebook::react::RuntimeExecutor runtimeExecutor_;
|
35
|
+
|
36
|
+
}; // class BridgelessJSCallInvoker
|
37
|
+
|
38
|
+
} // namespace
|
39
|
+
|
10
40
|
namespace RNSkia {
|
11
41
|
|
12
42
|
namespace jsi = facebook::jsi;
|
@@ -22,14 +52,17 @@ void JniSkiaManager::registerNatives() {
|
|
22
52
|
|
23
53
|
// JNI init
|
24
54
|
jni::local_ref<jni::HybridClass<JniSkiaManager>::jhybriddata>
|
25
|
-
JniSkiaManager::initHybrid(
|
26
|
-
|
27
|
-
|
55
|
+
JniSkiaManager::initHybrid(
|
56
|
+
jni::alias_ref<jhybridobject> jThis, jlong jsContext,
|
57
|
+
jni::alias_ref<facebook::react::JRuntimeExecutor::javaobject>
|
58
|
+
jRuntimeExecutor,
|
59
|
+
JavaPlatformContext skiaContext) {
|
28
60
|
|
61
|
+
auto jsCallInvoker = std::make_shared<BridgelessJSCallInvoker>(
|
62
|
+
jRuntimeExecutor->cthis()->get());
|
29
63
|
// cast from JNI hybrid objects to C++ instances
|
30
64
|
return makeCxxInstance(jThis, reinterpret_cast<jsi::Runtime *>(jsContext),
|
31
|
-
|
32
|
-
skiaContext->cthis());
|
65
|
+
jsCallInvoker, skiaContext->cthis());
|
33
66
|
}
|
34
67
|
|
35
68
|
void JniSkiaManager::initializeRuntime() {
|
@@ -1,6 +1,5 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
-
#include <ReactCommon/CallInvokerHolder.h>
|
4
3
|
#include <fbjni/fbjni.h>
|
5
4
|
|
6
5
|
#include <exception>
|
@@ -18,9 +17,6 @@ namespace RNSkia {
|
|
18
17
|
namespace jsi = facebook::jsi;
|
19
18
|
namespace jni = facebook::jni;
|
20
19
|
|
21
|
-
using JSCallInvokerHolder =
|
22
|
-
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>;
|
23
|
-
|
24
20
|
class JniPlatformContext : public jni::HybridClass<JniPlatformContext> {
|
25
21
|
public:
|
26
22
|
static auto constexpr kJavaDescriptor =
|
@@ -5,6 +5,7 @@
|
|
5
5
|
#include <fbjni/fbjni.h>
|
6
6
|
#include <jsi/jsi.h>
|
7
7
|
#include <memory>
|
8
|
+
#include <react/jni/JRuntimeExecutor.h>
|
8
9
|
|
9
10
|
#include <JniPlatformContext.h>
|
10
11
|
#include <RNSkAndroidPlatformContext.h>
|
@@ -17,9 +18,6 @@ class RNSkManager;
|
|
17
18
|
|
18
19
|
namespace jsi = facebook::jsi;
|
19
20
|
|
20
|
-
using JSCallInvokerHolder =
|
21
|
-
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>;
|
22
|
-
|
23
21
|
using JavaPlatformContext = jni::alias_ref<JniPlatformContext::javaobject>;
|
24
22
|
|
25
23
|
class JniSkiaManager : public jni::HybridClass<JniSkiaManager> {
|
@@ -30,7 +28,8 @@ public:
|
|
30
28
|
|
31
29
|
static jni::local_ref<jni::HybridClass<JniSkiaManager>::jhybriddata>
|
32
30
|
initHybrid(jni::alias_ref<jhybridobject> jThis, jlong jsContext,
|
33
|
-
|
31
|
+
jni::alias_ref<facebook::react::JRuntimeExecutor::javaobject>
|
32
|
+
jRuntimeExecutor,
|
34
33
|
JavaPlatformContext platformContext);
|
35
34
|
|
36
35
|
static void registerNatives();
|
@@ -5,14 +5,15 @@ import android.content.Context;
|
|
5
5
|
import com.facebook.jni.HybridData;
|
6
6
|
import com.facebook.jni.annotations.DoNotStrip;
|
7
7
|
import com.facebook.react.bridge.ReactContext;
|
8
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
8
9
|
|
9
10
|
public class SkiaDomView extends SkiaBaseView {
|
10
11
|
@DoNotStrip
|
11
12
|
private HybridData mHybridData;
|
12
13
|
|
13
|
-
public SkiaDomView(
|
14
|
+
public SkiaDomView(ThemedReactContext context) {
|
14
15
|
super(context);
|
15
|
-
RNSkiaModule skiaModule = (
|
16
|
+
RNSkiaModule skiaModule = context.getReactApplicationContext().getNativeModule(RNSkiaModule.class);
|
16
17
|
mHybridData = initHybrid(skiaModule.getSkiaManager());
|
17
18
|
}
|
18
19
|
|
@@ -3,7 +3,7 @@ package com.shopify.reactnative.skia;
|
|
3
3
|
import com.facebook.jni.HybridData;
|
4
4
|
import com.facebook.proguard.annotations.DoNotStrip;
|
5
5
|
import com.facebook.react.bridge.ReactContext;
|
6
|
-
import com.facebook.react.
|
6
|
+
import com.facebook.react.bridge.RuntimeExecutor;
|
7
7
|
|
8
8
|
@DoNotStrip
|
9
9
|
public class SkiaManager {
|
@@ -22,11 +22,11 @@ public class SkiaManager {
|
|
22
22
|
super();
|
23
23
|
mContext = context;
|
24
24
|
|
25
|
-
|
25
|
+
RuntimeExecutor runtimeExecutor = ReactNativeCompatible.getRuntimeExecutor(context);
|
26
26
|
|
27
27
|
mPlatformContext = new PlatformContext(context);
|
28
28
|
|
29
|
-
mHybridData = initHybrid(context.getJavaScriptContextHolder().get(),
|
29
|
+
mHybridData = initHybrid(context.getJavaScriptContextHolder().get(), runtimeExecutor, mPlatformContext);
|
30
30
|
|
31
31
|
initializeRuntime();
|
32
32
|
}
|
@@ -48,7 +48,7 @@ public class SkiaManager {
|
|
48
48
|
public void onHostPause() { mPlatformContext.onPause(); }
|
49
49
|
|
50
50
|
// private C++ functions
|
51
|
-
private native HybridData initHybrid(long jsContext,
|
51
|
+
private native HybridData initHybrid(long jsContext, RuntimeExecutor runtimeExecutor,
|
52
52
|
PlatformContext platformContext);
|
53
53
|
|
54
54
|
private native void initializeRuntime();
|
package/android/src/reactnative69/java/com/shopify/reactnative/skia/ReactNativeCompatible.java
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
package com.shopify.reactnative.skia;
|
2
|
+
|
3
|
+
import com.facebook.react.bridge.ReactContext;
|
4
|
+
import com.facebook.react.bridge.RuntimeExecutor;
|
5
|
+
|
6
|
+
/* package */ final class ReactNativeCompatible {
|
7
|
+
public static RuntimeExecutor getRuntimeExecutor(ReactContext context) {
|
8
|
+
return context.getCatalystInstance().getRuntimeExecutor();
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
package/android/src/reactnative74/java/com/shopify/reactnative/skia/ReactNativeCompatible.java
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
package com.shopify.reactnative.skia;
|
2
|
+
|
3
|
+
import androidx.annotation.OptIn;
|
4
|
+
|
5
|
+
import com.facebook.react.bridge.ReactContext;
|
6
|
+
import com.facebook.react.bridge.RuntimeExecutor;
|
7
|
+
import com.facebook.react.common.annotations.FrameworkAPI;
|
8
|
+
|
9
|
+
/* package */ final class ReactNativeCompatible {
|
10
|
+
@OptIn(markerClass = FrameworkAPI.class)
|
11
|
+
public static RuntimeExecutor getRuntimeExecutor(ReactContext context) {
|
12
|
+
return context.getRuntimeExecutor();
|
13
|
+
}
|
14
|
+
}
|
@@ -42,8 +42,8 @@ const drawAsImageFromPicture = (picture, size) => {
|
|
42
42
|
canvas.drawPicture(picture);
|
43
43
|
surface.flush();
|
44
44
|
const image = surface.makeImageSnapshot();
|
45
|
-
// If we are not on the main thread, we need to make the image non-texture.
|
46
|
-
if (!isOnMainThread()) {
|
45
|
+
// If we are not on the main thread or if we are on Web, we need to make the image non-texture.
|
46
|
+
if (!isOnMainThread() || _Platform.Platform.OS === "web") {
|
47
47
|
return image.makeNonTextureImage();
|
48
48
|
} else {
|
49
49
|
return image;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["_types","require","_skia","_Platform","_Reconciler","isOnMainThread","_WORKLET","Platform","OS","exports","drawAsPicture","element","recorder","Skia","PictureRecorder","canvas","beginRecording","root","SkiaRoot","render","ctx","JsiDrawingContext","dom","picture","finishRecordingAsPicture","drawAsImage","size","drawAsImageFromPicture","pd","surface","Surface","MakeOffscreen","width","height","getCanvas","scale","drawPicture","flush","image","makeImageSnapshot","makeNonTextureImage"],"sources":["Offscreen.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nimport { JsiDrawingContext } from \"../dom/types\";\nimport type { SkPicture, SkSize } from \"../skia/types\";\nimport { Skia } from \"../skia\";\nimport { Platform } from \"../Platform\";\n\nimport { SkiaRoot } from \"./Reconciler\";\n\n// We call it main thread because on web main is JS thread\nexport const isOnMainThread = () => {\n \"worklet\";\n return (\n (typeof _WORKLET !== \"undefined\" && _WORKLET === true) ||\n Platform.OS === \"web\"\n );\n};\n\nexport const drawAsPicture = (element: ReactElement) => {\n const recorder = Skia.PictureRecorder();\n const canvas = recorder.beginRecording();\n const root = new SkiaRoot(Skia, false);\n root.render(element);\n const ctx = new JsiDrawingContext(Skia, canvas);\n root.dom.render(ctx);\n const picture = recorder.finishRecordingAsPicture();\n return picture;\n};\n\nexport const drawAsImage = (element: ReactElement, size: SkSize) => {\n return drawAsImageFromPicture(drawAsPicture(element), size);\n};\n\n// TODO: We're not sure yet why PixelRatio is not needed here.\nconst pd = 1;\nexport const drawAsImageFromPicture = (picture: SkPicture, size: SkSize) => {\n \"worklet\";\n const surface = Skia.Surface.MakeOffscreen(\n size.width * pd,\n size.height * pd\n )!;\n const canvas = surface.getCanvas();\n canvas.scale(pd, pd);\n canvas.drawPicture(picture);\n surface.flush();\n const image = surface.makeImageSnapshot();\n // If we are not on the main thread, we need to make the image non-texture.\n if (!isOnMainThread()) {\n return image.makeNonTextureImage();\n } else {\n return image;\n }\n};\n"],"mappings":";;;;;;AAEA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,SAAA,GAAAF,OAAA;AAEA,IAAAG,WAAA,GAAAH,OAAA;AAEA;AACO,MAAMI,cAAc,GAAGA,CAAA,KAAM;EAClC,SAAS;;EACT,OACG,OAAOC,QAAQ,KAAK,WAAW,IAAIA,QAAQ,KAAK,IAAI,IACrDC,kBAAQ,CAACC,EAAE,KAAK,KAAK;AAEzB,CAAC;AAACC,OAAA,CAAAJ,cAAA,GAAAA,cAAA;AAEK,MAAMK,aAAa,GAAIC,OAAqB,IAAK;EACtD,MAAMC,QAAQ,GAAGC,UAAI,CAACC,eAAe,CAAC,CAAC;EACvC,MAAMC,MAAM,GAAGH,QAAQ,CAACI,cAAc,CAAC,CAAC;EACxC,MAAMC,IAAI,GAAG,IAAIC,oBAAQ,CAACL,UAAI,EAAE,KAAK,CAAC;EACtCI,IAAI,CAACE,MAAM,CAACR,OAAO,CAAC;EACpB,MAAMS,GAAG,GAAG,IAAIC,wBAAiB,CAACR,UAAI,EAAEE,MAAM,CAAC;EAC/CE,IAAI,CAACK,GAAG,CAACH,MAAM,CAACC,GAAG,CAAC;EACpB,MAAMG,OAAO,GAAGX,QAAQ,CAACY,wBAAwB,CAAC,CAAC;EACnD,OAAOD,OAAO;AAChB,CAAC;AAACd,OAAA,CAAAC,aAAA,GAAAA,aAAA;AAEK,MAAMe,WAAW,GAAGA,CAACd,OAAqB,EAAEe,IAAY,KAAK;EAClE,OAAOC,sBAAsB,CAACjB,aAAa,CAACC,OAAO,CAAC,EAAEe,IAAI,CAAC;AAC7D,CAAC;;AAED;AAAAjB,OAAA,CAAAgB,WAAA,GAAAA,WAAA;AACA,MAAMG,EAAE,GAAG,CAAC;AACL,MAAMD,sBAAsB,GAAGA,CAACJ,OAAkB,EAAEG,IAAY,KAAK;EAC1E,SAAS;;EACT,MAAMG,OAAO,GAAGhB,UAAI,CAACiB,OAAO,CAACC,aAAa,CACxCL,IAAI,CAACM,KAAK,GAAGJ,EAAE,EACfF,IAAI,CAACO,MAAM,GAAGL,EAChB,CAAE;EACF,MAAMb,MAAM,GAAGc,OAAO,CAACK,SAAS,CAAC,CAAC;EAClCnB,MAAM,CAACoB,KAAK,CAACP,EAAE,EAAEA,EAAE,CAAC;EACpBb,MAAM,CAACqB,WAAW,CAACb,OAAO,CAAC;EAC3BM,OAAO,CAACQ,KAAK,CAAC,CAAC;EACf,MAAMC,KAAK,GAAGT,OAAO,CAACU,iBAAiB,CAAC,CAAC;EACzC;EACA,IAAI,CAAClC,cAAc,CAAC,CAAC,EAAE;
|
1
|
+
{"version":3,"names":["_types","require","_skia","_Platform","_Reconciler","isOnMainThread","_WORKLET","Platform","OS","exports","drawAsPicture","element","recorder","Skia","PictureRecorder","canvas","beginRecording","root","SkiaRoot","render","ctx","JsiDrawingContext","dom","picture","finishRecordingAsPicture","drawAsImage","size","drawAsImageFromPicture","pd","surface","Surface","MakeOffscreen","width","height","getCanvas","scale","drawPicture","flush","image","makeImageSnapshot","makeNonTextureImage"],"sources":["Offscreen.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nimport { JsiDrawingContext } from \"../dom/types\";\nimport type { SkPicture, SkSize } from \"../skia/types\";\nimport { Skia } from \"../skia\";\nimport { Platform } from \"../Platform\";\n\nimport { SkiaRoot } from \"./Reconciler\";\n\n// We call it main thread because on web main is JS thread\nexport const isOnMainThread = () => {\n \"worklet\";\n return (\n (typeof _WORKLET !== \"undefined\" && _WORKLET === true) ||\n Platform.OS === \"web\"\n );\n};\n\nexport const drawAsPicture = (element: ReactElement) => {\n const recorder = Skia.PictureRecorder();\n const canvas = recorder.beginRecording();\n const root = new SkiaRoot(Skia, false);\n root.render(element);\n const ctx = new JsiDrawingContext(Skia, canvas);\n root.dom.render(ctx);\n const picture = recorder.finishRecordingAsPicture();\n return picture;\n};\n\nexport const drawAsImage = (element: ReactElement, size: SkSize) => {\n return drawAsImageFromPicture(drawAsPicture(element), size);\n};\n\n// TODO: We're not sure yet why PixelRatio is not needed here.\nconst pd = 1;\nexport const drawAsImageFromPicture = (picture: SkPicture, size: SkSize) => {\n \"worklet\";\n const surface = Skia.Surface.MakeOffscreen(\n size.width * pd,\n size.height * pd\n )!;\n const canvas = surface.getCanvas();\n canvas.scale(pd, pd);\n canvas.drawPicture(picture);\n surface.flush();\n const image = surface.makeImageSnapshot();\n // If we are not on the main thread or if we are on Web, we need to make the image non-texture.\n if (!isOnMainThread() || Platform.OS === \"web\") {\n return image.makeNonTextureImage();\n } else {\n return image;\n }\n};\n"],"mappings":";;;;;;AAEA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,SAAA,GAAAF,OAAA;AAEA,IAAAG,WAAA,GAAAH,OAAA;AAEA;AACO,MAAMI,cAAc,GAAGA,CAAA,KAAM;EAClC,SAAS;;EACT,OACG,OAAOC,QAAQ,KAAK,WAAW,IAAIA,QAAQ,KAAK,IAAI,IACrDC,kBAAQ,CAACC,EAAE,KAAK,KAAK;AAEzB,CAAC;AAACC,OAAA,CAAAJ,cAAA,GAAAA,cAAA;AAEK,MAAMK,aAAa,GAAIC,OAAqB,IAAK;EACtD,MAAMC,QAAQ,GAAGC,UAAI,CAACC,eAAe,CAAC,CAAC;EACvC,MAAMC,MAAM,GAAGH,QAAQ,CAACI,cAAc,CAAC,CAAC;EACxC,MAAMC,IAAI,GAAG,IAAIC,oBAAQ,CAACL,UAAI,EAAE,KAAK,CAAC;EACtCI,IAAI,CAACE,MAAM,CAACR,OAAO,CAAC;EACpB,MAAMS,GAAG,GAAG,IAAIC,wBAAiB,CAACR,UAAI,EAAEE,MAAM,CAAC;EAC/CE,IAAI,CAACK,GAAG,CAACH,MAAM,CAACC,GAAG,CAAC;EACpB,MAAMG,OAAO,GAAGX,QAAQ,CAACY,wBAAwB,CAAC,CAAC;EACnD,OAAOD,OAAO;AAChB,CAAC;AAACd,OAAA,CAAAC,aAAA,GAAAA,aAAA;AAEK,MAAMe,WAAW,GAAGA,CAACd,OAAqB,EAAEe,IAAY,KAAK;EAClE,OAAOC,sBAAsB,CAACjB,aAAa,CAACC,OAAO,CAAC,EAAEe,IAAI,CAAC;AAC7D,CAAC;;AAED;AAAAjB,OAAA,CAAAgB,WAAA,GAAAA,WAAA;AACA,MAAMG,EAAE,GAAG,CAAC;AACL,MAAMD,sBAAsB,GAAGA,CAACJ,OAAkB,EAAEG,IAAY,KAAK;EAC1E,SAAS;;EACT,MAAMG,OAAO,GAAGhB,UAAI,CAACiB,OAAO,CAACC,aAAa,CACxCL,IAAI,CAACM,KAAK,GAAGJ,EAAE,EACfF,IAAI,CAACO,MAAM,GAAGL,EAChB,CAAE;EACF,MAAMb,MAAM,GAAGc,OAAO,CAACK,SAAS,CAAC,CAAC;EAClCnB,MAAM,CAACoB,KAAK,CAACP,EAAE,EAAEA,EAAE,CAAC;EACpBb,MAAM,CAACqB,WAAW,CAACb,OAAO,CAAC;EAC3BM,OAAO,CAACQ,KAAK,CAAC,CAAC;EACf,MAAMC,KAAK,GAAGT,OAAO,CAACU,iBAAiB,CAAC,CAAC;EACzC;EACA,IAAI,CAAClC,cAAc,CAAC,CAAC,IAAIE,kBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;IAC9C,OAAO8B,KAAK,CAACE,mBAAmB,CAAC,CAAC;EACpC,CAAC,MAAM;IACL,OAAOF,KAAK;EACd;AACF,CAAC;AAAC7B,OAAA,CAAAkB,sBAAA,GAAAA,sBAAA"}
|
@@ -34,8 +34,8 @@ export const drawAsImageFromPicture = (picture, size) => {
|
|
34
34
|
canvas.drawPicture(picture);
|
35
35
|
surface.flush();
|
36
36
|
const image = surface.makeImageSnapshot();
|
37
|
-
// If we are not on the main thread, we need to make the image non-texture.
|
38
|
-
if (!isOnMainThread()) {
|
37
|
+
// If we are not on the main thread or if we are on Web, we need to make the image non-texture.
|
38
|
+
if (!isOnMainThread() || Platform.OS === "web") {
|
39
39
|
return image.makeNonTextureImage();
|
40
40
|
} else {
|
41
41
|
return image;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["JsiDrawingContext","Skia","Platform","SkiaRoot","isOnMainThread","_WORKLET","OS","drawAsPicture","element","recorder","PictureRecorder","canvas","beginRecording","root","render","ctx","dom","picture","finishRecordingAsPicture","drawAsImage","size","drawAsImageFromPicture","pd","surface","Surface","MakeOffscreen","width","height","getCanvas","scale","drawPicture","flush","image","makeImageSnapshot","makeNonTextureImage"],"sources":["Offscreen.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nimport { JsiDrawingContext } from \"../dom/types\";\nimport type { SkPicture, SkSize } from \"../skia/types\";\nimport { Skia } from \"../skia\";\nimport { Platform } from \"../Platform\";\n\nimport { SkiaRoot } from \"./Reconciler\";\n\n// We call it main thread because on web main is JS thread\nexport const isOnMainThread = () => {\n \"worklet\";\n return (\n (typeof _WORKLET !== \"undefined\" && _WORKLET === true) ||\n Platform.OS === \"web\"\n );\n};\n\nexport const drawAsPicture = (element: ReactElement) => {\n const recorder = Skia.PictureRecorder();\n const canvas = recorder.beginRecording();\n const root = new SkiaRoot(Skia, false);\n root.render(element);\n const ctx = new JsiDrawingContext(Skia, canvas);\n root.dom.render(ctx);\n const picture = recorder.finishRecordingAsPicture();\n return picture;\n};\n\nexport const drawAsImage = (element: ReactElement, size: SkSize) => {\n return drawAsImageFromPicture(drawAsPicture(element), size);\n};\n\n// TODO: We're not sure yet why PixelRatio is not needed here.\nconst pd = 1;\nexport const drawAsImageFromPicture = (picture: SkPicture, size: SkSize) => {\n \"worklet\";\n const surface = Skia.Surface.MakeOffscreen(\n size.width * pd,\n size.height * pd\n )!;\n const canvas = surface.getCanvas();\n canvas.scale(pd, pd);\n canvas.drawPicture(picture);\n surface.flush();\n const image = surface.makeImageSnapshot();\n // If we are not on the main thread, we need to make the image non-texture.\n if (!isOnMainThread()) {\n return image.makeNonTextureImage();\n } else {\n return image;\n }\n};\n"],"mappings":"AAEA,SAASA,iBAAiB,QAAQ,cAAc;AAEhD,SAASC,IAAI,QAAQ,SAAS;AAC9B,SAASC,QAAQ,QAAQ,aAAa;AAEtC,SAASC,QAAQ,QAAQ,cAAc;;AAEvC;AACA,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAM;EAClC,SAAS;;EACT,OACG,OAAOC,QAAQ,KAAK,WAAW,IAAIA,QAAQ,KAAK,IAAI,IACrDH,QAAQ,CAACI,EAAE,KAAK,KAAK;AAEzB,CAAC;AAED,OAAO,MAAMC,aAAa,GAAIC,OAAqB,IAAK;EACtD,MAAMC,QAAQ,GAAGR,IAAI,CAACS,eAAe,CAAC,CAAC;EACvC,MAAMC,MAAM,GAAGF,QAAQ,CAACG,cAAc,CAAC,CAAC;EACxC,MAAMC,IAAI,GAAG,IAAIV,QAAQ,CAACF,IAAI,EAAE,KAAK,CAAC;EACtCY,IAAI,CAACC,MAAM,CAACN,OAAO,CAAC;EACpB,MAAMO,GAAG,GAAG,IAAIf,iBAAiB,CAACC,IAAI,EAAEU,MAAM,CAAC;EAC/CE,IAAI,CAACG,GAAG,CAACF,MAAM,CAACC,GAAG,CAAC;EACpB,MAAME,OAAO,GAAGR,QAAQ,CAACS,wBAAwB,CAAC,CAAC;EACnD,OAAOD,OAAO;AAChB,CAAC;AAED,OAAO,MAAME,WAAW,GAAGA,CAACX,OAAqB,EAAEY,IAAY,KAAK;EAClE,OAAOC,sBAAsB,CAACd,aAAa,CAACC,OAAO,CAAC,EAAEY,IAAI,CAAC;AAC7D,CAAC;;AAED;AACA,MAAME,EAAE,GAAG,CAAC;AACZ,OAAO,MAAMD,sBAAsB,GAAGA,CAACJ,OAAkB,EAAEG,IAAY,KAAK;EAC1E,SAAS;;EACT,MAAMG,OAAO,GAAGtB,IAAI,CAACuB,OAAO,CAACC,aAAa,CACxCL,IAAI,CAACM,KAAK,GAAGJ,EAAE,EACfF,IAAI,CAACO,MAAM,GAAGL,EAChB,CAAE;EACF,MAAMX,MAAM,GAAGY,OAAO,CAACK,SAAS,CAAC,CAAC;EAClCjB,MAAM,CAACkB,KAAK,CAACP,EAAE,EAAEA,EAAE,CAAC;EACpBX,MAAM,CAACmB,WAAW,CAACb,OAAO,CAAC;EAC3BM,OAAO,CAACQ,KAAK,CAAC,CAAC;EACf,MAAMC,KAAK,GAAGT,OAAO,CAACU,iBAAiB,CAAC,CAAC;EACzC;EACA,IAAI,CAAC7B,cAAc,CAAC,CAAC,EAAE;
|
1
|
+
{"version":3,"names":["JsiDrawingContext","Skia","Platform","SkiaRoot","isOnMainThread","_WORKLET","OS","drawAsPicture","element","recorder","PictureRecorder","canvas","beginRecording","root","render","ctx","dom","picture","finishRecordingAsPicture","drawAsImage","size","drawAsImageFromPicture","pd","surface","Surface","MakeOffscreen","width","height","getCanvas","scale","drawPicture","flush","image","makeImageSnapshot","makeNonTextureImage"],"sources":["Offscreen.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nimport { JsiDrawingContext } from \"../dom/types\";\nimport type { SkPicture, SkSize } from \"../skia/types\";\nimport { Skia } from \"../skia\";\nimport { Platform } from \"../Platform\";\n\nimport { SkiaRoot } from \"./Reconciler\";\n\n// We call it main thread because on web main is JS thread\nexport const isOnMainThread = () => {\n \"worklet\";\n return (\n (typeof _WORKLET !== \"undefined\" && _WORKLET === true) ||\n Platform.OS === \"web\"\n );\n};\n\nexport const drawAsPicture = (element: ReactElement) => {\n const recorder = Skia.PictureRecorder();\n const canvas = recorder.beginRecording();\n const root = new SkiaRoot(Skia, false);\n root.render(element);\n const ctx = new JsiDrawingContext(Skia, canvas);\n root.dom.render(ctx);\n const picture = recorder.finishRecordingAsPicture();\n return picture;\n};\n\nexport const drawAsImage = (element: ReactElement, size: SkSize) => {\n return drawAsImageFromPicture(drawAsPicture(element), size);\n};\n\n// TODO: We're not sure yet why PixelRatio is not needed here.\nconst pd = 1;\nexport const drawAsImageFromPicture = (picture: SkPicture, size: SkSize) => {\n \"worklet\";\n const surface = Skia.Surface.MakeOffscreen(\n size.width * pd,\n size.height * pd\n )!;\n const canvas = surface.getCanvas();\n canvas.scale(pd, pd);\n canvas.drawPicture(picture);\n surface.flush();\n const image = surface.makeImageSnapshot();\n // If we are not on the main thread or if we are on Web, we need to make the image non-texture.\n if (!isOnMainThread() || Platform.OS === \"web\") {\n return image.makeNonTextureImage();\n } else {\n return image;\n }\n};\n"],"mappings":"AAEA,SAASA,iBAAiB,QAAQ,cAAc;AAEhD,SAASC,IAAI,QAAQ,SAAS;AAC9B,SAASC,QAAQ,QAAQ,aAAa;AAEtC,SAASC,QAAQ,QAAQ,cAAc;;AAEvC;AACA,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAM;EAClC,SAAS;;EACT,OACG,OAAOC,QAAQ,KAAK,WAAW,IAAIA,QAAQ,KAAK,IAAI,IACrDH,QAAQ,CAACI,EAAE,KAAK,KAAK;AAEzB,CAAC;AAED,OAAO,MAAMC,aAAa,GAAIC,OAAqB,IAAK;EACtD,MAAMC,QAAQ,GAAGR,IAAI,CAACS,eAAe,CAAC,CAAC;EACvC,MAAMC,MAAM,GAAGF,QAAQ,CAACG,cAAc,CAAC,CAAC;EACxC,MAAMC,IAAI,GAAG,IAAIV,QAAQ,CAACF,IAAI,EAAE,KAAK,CAAC;EACtCY,IAAI,CAACC,MAAM,CAACN,OAAO,CAAC;EACpB,MAAMO,GAAG,GAAG,IAAIf,iBAAiB,CAACC,IAAI,EAAEU,MAAM,CAAC;EAC/CE,IAAI,CAACG,GAAG,CAACF,MAAM,CAACC,GAAG,CAAC;EACpB,MAAME,OAAO,GAAGR,QAAQ,CAACS,wBAAwB,CAAC,CAAC;EACnD,OAAOD,OAAO;AAChB,CAAC;AAED,OAAO,MAAME,WAAW,GAAGA,CAACX,OAAqB,EAAEY,IAAY,KAAK;EAClE,OAAOC,sBAAsB,CAACd,aAAa,CAACC,OAAO,CAAC,EAAEY,IAAI,CAAC;AAC7D,CAAC;;AAED;AACA,MAAME,EAAE,GAAG,CAAC;AACZ,OAAO,MAAMD,sBAAsB,GAAGA,CAACJ,OAAkB,EAAEG,IAAY,KAAK;EAC1E,SAAS;;EACT,MAAMG,OAAO,GAAGtB,IAAI,CAACuB,OAAO,CAACC,aAAa,CACxCL,IAAI,CAACM,KAAK,GAAGJ,EAAE,EACfF,IAAI,CAACO,MAAM,GAAGL,EAChB,CAAE;EACF,MAAMX,MAAM,GAAGY,OAAO,CAACK,SAAS,CAAC,CAAC;EAClCjB,MAAM,CAACkB,KAAK,CAACP,EAAE,EAAEA,EAAE,CAAC;EACpBX,MAAM,CAACmB,WAAW,CAACb,OAAO,CAAC;EAC3BM,OAAO,CAACQ,KAAK,CAAC,CAAC;EACf,MAAMC,KAAK,GAAGT,OAAO,CAACU,iBAAiB,CAAC,CAAC;EACzC;EACA,IAAI,CAAC7B,cAAc,CAAC,CAAC,IAAIF,QAAQ,CAACI,EAAE,KAAK,KAAK,EAAE;IAC9C,OAAO0B,KAAK,CAACE,mBAAmB,CAAC,CAAC;EACpC,CAAC,MAAM;IACL,OAAOF,KAAK;EACd;AACF,CAAC"}
|
package/package.json
CHANGED
@@ -7,9 +7,12 @@
|
|
7
7
|
"setup-skia-web": "./scripts/setup-canvaskit.js"
|
8
8
|
},
|
9
9
|
"title": "React Native Skia",
|
10
|
-
"version": "0.
|
10
|
+
"version": "1.0.2",
|
11
11
|
"description": "High-performance React Native Graphics using Skia",
|
12
12
|
"main": "lib/module/index.js",
|
13
|
+
"react-native": "src/index.ts",
|
14
|
+
"module": "lib/module/index.js",
|
15
|
+
"types": "lib/typescript/index.d.ts",
|
13
16
|
"files": [
|
14
17
|
"src",
|
15
18
|
"lib",
|
@@ -45,7 +48,8 @@
|
|
45
48
|
"lint": "eslint . --ext .ts,.tsx --max-warnings 0 --cache",
|
46
49
|
"test": "jest",
|
47
50
|
"e2e": "E2E=true yarn test -i e2e",
|
48
|
-
"build": "bob build && merge-dirs lib/typescript/src lib/commonjs && merge-dirs lib/typescript/src lib/module"
|
51
|
+
"build": "bob build && merge-dirs lib/typescript/src lib/commonjs && merge-dirs lib/typescript/src lib/module",
|
52
|
+
"release": "standard-version"
|
49
53
|
},
|
50
54
|
"repository": {
|
51
55
|
"type": "git",
|
@@ -102,6 +106,7 @@
|
|
102
106
|
"react-native": "0.72.6",
|
103
107
|
"react-native-builder-bob": "0.18.2",
|
104
108
|
"react-native-reanimated": "3.6.2",
|
109
|
+
"standard-version": "^9.5.0",
|
105
110
|
"ts-jest": "29.1.1",
|
106
111
|
"typescript": "5.1.6",
|
107
112
|
"ws": "8.11.0"
|
@@ -139,8 +144,5 @@
|
|
139
144
|
"resolutions": {
|
140
145
|
"@typescript-eslint/eslint-plugin": "6.10.0",
|
141
146
|
"@typescript-eslint/parser": "6.10.0"
|
142
|
-
}
|
143
|
-
|
144
|
-
"module": "lib/module/index.js",
|
145
|
-
"react-native": "src/index.ts"
|
146
|
-
}
|
147
|
+
}
|
148
|
+
}
|
@@ -44,8 +44,8 @@ export const drawAsImageFromPicture = (picture: SkPicture, size: SkSize) => {
|
|
44
44
|
canvas.drawPicture(picture);
|
45
45
|
surface.flush();
|
46
46
|
const image = surface.makeImageSnapshot();
|
47
|
-
// If we are not on the main thread, we need to make the image non-texture.
|
48
|
-
if (!isOnMainThread()) {
|
47
|
+
// If we are not on the main thread or if we are on Web, we need to make the image non-texture.
|
48
|
+
if (!isOnMainThread() || Platform.OS === "web") {
|
49
49
|
return image.makeNonTextureImage();
|
50
50
|
} else {
|
51
51
|
return image;
|