From 6deb069a453a77b4635c5a1cf1904104a2704e4f Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:14:03 +0800 Subject: [PATCH 1/7] [tools] Update react-native-skia.patch --- .../vendoring/config/react-native-skia.patch | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tools/src/vendoring/config/react-native-skia.patch b/tools/src/vendoring/config/react-native-skia.patch index e438fcf4278cf..791665af557a7 100644 --- a/tools/src/vendoring/config/react-native-skia.patch +++ b/tools/src/vendoring/config/react-native-skia.patch @@ -1,26 +1,25 @@ --- android/CMakeLists.txt +++ android/CMakeLists.txt -@@ -34,14 +34,14 @@ add_library( - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkDrawViewImpl.cpp" +@@ -40,13 +40,13 @@ + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLRenderer.cpp" - + - "${PROJECT_SOURCE_DIR}/cpp/jsi/JsiHostObject.cpp" + "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkManager.cpp" -- "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkDrawView.cpp" +- "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkJsView.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkDispatchQueue.cpp" + "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkManager.cpp" -+ "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkDrawView.cpp" ++ "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkJsView.cpp" + "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkDispatchQueue.cpp" - - "${PROJECT_SOURCE_DIR}/cpp/api/third_party/CSSColorParser.cpp" + "${PROJECT_SOURCE_DIR}/../cpp/api/third_party/CSSColorParser.cpp" ) -@@ -56,28 +56,28 @@ target_include_directories( +@@ -60,28 +60,28 @@ "${NODE_MODULES_DIR}/react-native/ReactCommon/react/nativemodule/core" "${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni" @@ -68,7 +67,7 @@ --- android/build.gradle +++ android/build.gradle -@@ -43,13 +43,17 @@ static def findNodeModules(baseDir) { +@@ -43,13 +43,17 @@ throw new GradleException("React-Native-Skia: Failed to find node_modules/ path!") } @@ -87,7 +86,7 @@ def buildType = "debug" tasks.all({ task -> -@@ -77,7 +81,7 @@ if (!defaultDir.exists()) { +@@ -77,7 +81,7 @@ } def prebuiltDir = sourceBuild @@ -96,7 +95,7 @@ : "$buildDir/react-native-0*/jni" -@@ -119,7 +123,7 @@ android { +@@ -119,7 +123,7 @@ externalNativeBuild { cmake { cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" @@ -105,7 +104,7 @@ arguments '-DANDROID_STL=c++_shared', "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", "-DNODE_MODULES_DIR=${nodeModules}", -@@ -189,8 +193,10 @@ dependencies { +@@ -190,8 +194,10 @@ } else { // React Native >= 0.69 def rnAarMatcher = "**/react-native/**/*${buildType}.aar" @@ -118,7 +117,7 @@ } } -@@ -255,4 +261,16 @@ def nativeBuildDependsOn(dependsOnTask, variant) { +@@ -256,4 +262,16 @@ afterEvaluate { nativeBuildDependsOn(extractAARHeaders, null) nativeBuildDependsOn(extractJNIFiles, null) From 2d267f0e582d6a7b76f5c759c808eea556cc2644 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:15:50 +0800 Subject: [PATCH 2/7] et uvm -m @shopify/react-native-skia -c 0.1.153 --- .../react-native-skia/android/CMakeLists.txt | 16 +- .../react-native-skia/android/README.md | 14 - .../react-native-skia/android/build.gradle | 9 +- .../android/cpp/jni/JniLoad.cpp | 12 +- .../android/cpp/jni/JniSkiaDrawView.cpp | 113 ------ .../android/cpp/jni/JniSkiaManager.cpp | 17 +- .../android/cpp/jni/include/JniSkiaBaseView.h | 68 ++++ .../android/cpp/jni/include/JniSkiaDrawView.h | 111 +++--- .../android/cpp/jni/include/JniSkiaManager.h | 18 +- .../cpp/jni/include/JniSkiaPictureView.h | 96 +++++ ...extImpl.h => RNSkAndroidPlatformContext.h} | 8 +- .../cpp/rnskia-android/RNSkAndroidView.h | 100 +++++ .../cpp/rnskia-android/RNSkDrawViewImpl.cpp | 73 ---- .../cpp/rnskia-android/RNSkDrawViewImpl.h | 48 --- .../RNSkOpenGLCanvasProvider.cpp | 91 +++++ .../rnskia-android/RNSkOpenGLCanvasProvider.h | 39 ++ .../cpp/rnskia-android/SkiaOpenGLRenderer.cpp | 44 ++- .../cpp/rnskia-android/SkiaOpenGLRenderer.h | 13 +- .../reactnative/skia/PlatformContext.java | 16 +- .../reactnative/skia/RNSkiaPackage.java | 3 +- .../reactnative/skia/SkiaBaseView.java | 143 +++++++ .../reactnative/skia/SkiaDrawView.java | 120 +----- ...wManager.java => SkiaDrawViewManager.java} | 19 +- .../shopify/reactnative/skia/SkiaManager.java | 11 +- .../reactnative/skia/SkiaPictureView.java | 45 +++ .../skia/SkiaPictureViewManager.java | 64 ++++ .../react-native-skia/cpp/api/JsiSkApi.h | 4 - .../cpp/api/JsiSkContourMeasure.h | 2 +- .../cpp/api/JsiSkDataFactory.h | 2 +- .../react-native-skia/cpp/api/JsiSkFont.h | 27 +- .../react-native-skia/cpp/api/JsiSkFontMgr.h | 84 ----- .../cpp/api/JsiSkFontMgrFactory.h | 48 --- .../react-native-skia/cpp/api/JsiSkMatrix.h | 21 ++ .../react-native-skia/cpp/api/JsiSkPaint.h | 6 + .../react-native-skia/cpp/api/JsiSkPath.h | 4 +- .../cpp/api/JsiSkPathFactory.h | 2 +- .../react-native-skia/cpp/api/JsiSkPicture.h | 8 +- .../cpp/api/JsiSkRuntimeEffect.h | 6 +- .../react-native-skia/cpp/api/JsiSkTypeface.h | 30 +- .../cpp/jsi/JsiSimpleValueWrapper.h | 54 +-- .../cpp/jsi/JsiValueWrapper.h | 138 +++++++ .../cpp/rnskia/RNSkDrawView.cpp | 291 -------------- .../cpp/rnskia/RNSkDrawView.h | 212 ----------- .../cpp/rnskia/RNSkInfoParameter.h | 18 +- .../cpp/rnskia/RNSkJsView.cpp | 211 +++++++++++ .../react-native-skia/cpp/rnskia/RNSkJsView.h | 115 ++++++ .../cpp/rnskia/RNSkJsiViewApi.h | 354 +++++++++--------- .../cpp/rnskia/RNSkManager.cpp | 14 +- .../cpp/rnskia/RNSkManager.h | 14 +- .../cpp/rnskia/RNSkPictureView.h | 124 ++++++ .../react-native-skia/cpp/rnskia/RNSkView.h | 287 ++++++++++++++ .../cpp/rnskia/values/RNSkComputedValue.h | 31 +- .../cpp/rnskia/values/RNSkReadonlyValue.h | 51 ++- .../cpp/rnskia/values/RNSkValue.h | 25 +- .../skia/include/third_party/skcms/LICENSE | 29 -- .../skia/include/third_party/vulkan/LICENSE | 29 -- .../react-native-skia/cpp/skia/readme.txt | 1 - .../react-native-skia/cpp/utils/RNSkLog.h | 6 +- apps/native-component-list/package.json | 2 +- .../react-native-skia/cpp/api/JsiSkApi.h | 4 - .../cpp/api/JsiSkContourMeasure.h | 2 +- .../cpp/api/JsiSkDataFactory.h | 2 +- .../react-native-skia/cpp/api/JsiSkFont.h | 27 +- .../react-native-skia/cpp/api/JsiSkFontMgr.h | 84 ----- .../cpp/api/JsiSkFontMgrFactory.h | 48 --- .../react-native-skia/cpp/api/JsiSkMatrix.h | 21 ++ .../react-native-skia/cpp/api/JsiSkPaint.h | 6 + .../react-native-skia/cpp/api/JsiSkPath.h | 4 +- .../cpp/api/JsiSkPathFactory.h | 2 +- .../react-native-skia/cpp/api/JsiSkPicture.h | 8 +- .../cpp/api/JsiSkRuntimeEffect.h | 6 +- .../react-native-skia/cpp/api/JsiSkTypeface.h | 30 +- .../cpp/jsi/JsiSimpleValueWrapper.h | 54 +-- .../cpp/jsi/JsiValueWrapper.h | 138 +++++++ .../cpp/rnskia/RNSkDrawView.cpp | 291 -------------- .../cpp/rnskia/RNSkDrawView.h | 212 ----------- .../cpp/rnskia/RNSkInfoParameter.h | 18 +- .../cpp/rnskia/RNSkJsView.cpp | 211 +++++++++++ .../react-native-skia/cpp/rnskia/RNSkJsView.h | 115 ++++++ .../cpp/rnskia/RNSkJsiViewApi.h | 354 +++++++++--------- .../cpp/rnskia/RNSkManager.cpp | 14 +- .../cpp/rnskia/RNSkManager.h | 14 +- .../cpp/rnskia/RNSkPictureView.h | 124 ++++++ .../react-native-skia/cpp/rnskia/RNSkView.h | 287 ++++++++++++++ .../cpp/rnskia/values/RNSkComputedValue.h | 31 +- .../cpp/rnskia/values/RNSkReadonlyValue.h | 51 ++- .../cpp/rnskia/values/RNSkValue.h | 25 +- .../react-native-skia/cpp/utils/RNSkLog.h | 6 +- .../ios/RNSkia-iOS/RNSkDrawViewImpl.h | 52 --- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.h | 38 ++ ...ViewImpl.mm => RNSkMetalCanvasProvider.mm} | 71 ++-- ...formContext.h => RNSkiOSPlatformContext.h} | 8 +- ...rmContext.mm => RNSkiOSPlatformContext.mm} | 10 +- .../ios/RNSkia-iOS/RNSkiOSView.h | 34 ++ .../ios/RNSkia-iOS/SkiaDrawView.h | 23 -- .../ios/RNSkia-iOS/SkiaDrawViewManager.mm | 30 +- .../ios/RNSkia-iOS/SkiaManager.mm | 6 +- .../ios/RNSkia-iOS/SkiaPictureViewManager.h | 8 + .../ios/RNSkia-iOS/SkiaPictureViewManager.mm | 51 +++ .../ios/RNSkia-iOS/SkiaUIView.h | 26 ++ .../{SkiaDrawView.mm => SkiaUIView.mm} | 56 +-- .../react-native-skia.podspec.json | 4 +- packages/expo/bundledNativeModules.json | 2 +- 103 files changed, 3517 insertions(+), 2652 deletions(-) delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/README.md delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaDrawView.cpp create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaBaseView.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaPictureView.h rename android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/{RNSkPlatformContextImpl.h => RNSkAndroidPlatformContext.h} (80%) create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java rename android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/{RNSkiaViewManager.java => SkiaDrawViewManager.java} (65%) create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureViewManager.java delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h create mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/skcms/LICENSE delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/vulkan/LICENSE delete mode 100644 android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/readme.txt delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h rename ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/{RNSkDrawViewImpl.mm => RNSkMetalCanvasProvider.mm} (69%) rename ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/{PlatformContext.h => RNSkiOSPlatformContext.h} (89%) rename ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/{PlatformContext.mm => RNSkiOSPlatformContext.mm} (80%) create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSView.h delete mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.h create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.mm create mode 100644 ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.h rename ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/{SkiaDrawView.mm => SkiaUIView.mm} (64%) diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/CMakeLists.txt b/android/vendored/unversioned/@shopify/react-native-skia/android/CMakeLists.txt index 9f4f65ce40cce..e4d14073585ab 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/CMakeLists.txt +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/CMakeLists.txt @@ -1,5 +1,11 @@ +project(RNSkia) cmake_minimum_required(VERSION 3.4.1) +if(${BUILD_TYPE} STREQUAL "debug") + set (CMAKE_BUILD_TYPE Debug) + message("-- Building with Debug Symbols") +endif() + set (CMAKE_VERBOSE_MAKEFILE ON) set (CMAKE_CXX_STANDARD 17) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSK_GL -DSK_BUILD_FOR_ANDROID -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_HAVE_MEMRCHR=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DON_ANDROID -DONANDROID") @@ -29,23 +35,21 @@ add_library( SHARED "${PROJECT_SOURCE_DIR}/cpp/jni/JniLoad.cpp" "${PROJECT_SOURCE_DIR}/cpp/jni/JniSkiaManager.cpp" - "${PROJECT_SOURCE_DIR}/cpp/jni/JniSkiaDrawView.cpp" + "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkDrawViewImpl.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLRenderer.cpp" - + "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp" "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkManager.cpp" - "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkDrawView.cpp" + "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkJsView.cpp" "${PROJECT_SOURCE_DIR}/../cpp/rnskia/RNSkDispatchQueue.cpp" - "${PROJECT_SOURCE_DIR}/../cpp/api/third_party/CSSColorParser.cpp" ) - target_include_directories( ${PACKAGE_NAME} PRIVATE diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/README.md b/android/vendored/unversioned/@shopify/react-native-skia/android/README.md deleted file mode 100644 index ac2fbda377ad1..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/README.md +++ /dev/null @@ -1,14 +0,0 @@ -README -====== - -If you want to publish the lib as a maven dependency, follow these steps before publishing a new version to npm: - -1. Be sure to have the Android [SDK](https://developer.android.com/studio/index.html) and [NDK](https://developer.android.com/ndk/guides/index.html) installed -2. Be sure to have a `local.properties` file in this folder that points to the Android SDK and NDK -``` -ndk.dir=/Users/{username}/Library/Android/sdk/ndk-bundle -sdk.dir=/Users/{username}/Library/Android/sdk -``` -3. Delete the `maven` folder -4. Run `./gradlew installArchives` -5. Verify that latest set of generated files is in the maven folder with the correct version number diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/build.gradle b/android/vendored/unversioned/@shopify/react-native-skia/android/build.gradle index aa4aca7ba8a5d..58dc51ae3ab1b 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/build.gradle +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/build.gradle @@ -127,7 +127,9 @@ android { arguments '-DANDROID_STL=c++_shared', "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", "-DNODE_MODULES_DIR=${nodeModules}", - "-DPREBUILT_DIR=${prebuiltDir}" + "-DPREBUILT_DIR=${prebuiltDir}", + "-DBUILD_TYPE=${buildType}" + } } } @@ -137,8 +139,7 @@ android { externalNativeBuild { cmake { - path file('CMakeLists.txt') - version '3.10.2' + path file('CMakeLists.txt') } } @@ -260,7 +261,7 @@ def nativeBuildDependsOn(dependsOnTask, variant) { afterEvaluate { nativeBuildDependsOn(extractAARHeaders, null) - nativeBuildDependsOn(extractJNIFiles, null) + nativeBuildDependsOn(extractJNIFiles, null) } tasks.whenTaskAdded { task -> diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniLoad.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniLoad.cpp index b5c51484d61b6..a31f229171cee 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniLoad.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniLoad.cpp @@ -1,13 +1,15 @@ #include "JniPlatformContext.h" #include "JniSkiaDrawView.h" +#include "JniSkiaPictureView.h" #include "JniSkiaManager.h" #include #include JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { - return facebook::jni::initialize(vm, [] { - RNSkia::JniSkiaManager::registerNatives(); - RNSkia::JniSkiaDrawView::registerNatives(); - RNSkia::JniPlatformContext::registerNatives(); - }); + return facebook::jni::initialize(vm, [] { + RNSkia::JniSkiaManager::registerNatives(); + RNSkia::JniSkiaDrawView::registerNatives(); + RNSkia::JniSkiaPictureView::registerNatives(); + RNSkia::JniPlatformContext::registerNatives(); + }); } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaDrawView.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaDrawView.cpp deleted file mode 100644 index 1b8ed5cd08fca..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaDrawView.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "JniSkiaDrawView.h" -#include "RNSkLog.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace RNSkia -{ - using namespace facebook; - using namespace jni; - - using TSelf = local_ref::jhybriddata>; - - /**** DTOR ***/ - JniSkiaDrawView::~JniSkiaDrawView() - { - } - - /**** JNI ****/ - - TSelf JniSkiaDrawView::initHybrid( - alias_ref jThis, - JavaSkiaManager skiaManager) - { - return makeCxxInstance(jThis, skiaManager); - } - - void JniSkiaDrawView::registerNatives() - { - registerHybrid({makeNativeMethod("initHybrid", JniSkiaDrawView::initHybrid), - makeNativeMethod("surfaceAvailable", JniSkiaDrawView::surfaceAvailable), - makeNativeMethod("surfaceDestroyed", JniSkiaDrawView::surfaceDestroyed), - makeNativeMethod("surfaceSizeChanged", JniSkiaDrawView::surfaceSizeChanged), - makeNativeMethod("setMode", JniSkiaDrawView::setMode), - makeNativeMethod("setDebugMode", JniSkiaDrawView::setDebugMode), - makeNativeMethod("updateTouchPoints", JniSkiaDrawView::updateTouchPoints)}); - } - - void JniSkiaDrawView::setMode(std::string mode) - { - if (mode.compare("continuous") == 0) - { - _drawView->setDrawingMode(RNSkDrawingMode::Continuous); - } - else - { - _drawView->setDrawingMode(RNSkDrawingMode::Default); - } - } - - void JniSkiaDrawView::setDebugMode(bool show) - { - _drawView->setShowDebugOverlays(show); - } - - void JniSkiaDrawView::updateTouchPoints(jni::JArrayDouble touches) - { - // Create touch points - std::vector points; - auto pin = touches.pin(); - auto scale = _drawView->getPixelDensity(); - points.reserve(pin.size() / 5); - for (size_t i = 0; i < pin.size(); i += 5) - { - RNSkTouchPoint point; - point.x = pin[i] / scale; - point.y = pin[i + 1] / scale; - point.force = pin[i + 2]; - point.type = (RNSkia::RNSkTouchType)pin[i + 3]; - point.id = pin[i + 4]; - points.push_back(point); - } - _drawView->updateTouchState(std::move(points)); - } - - void JniSkiaDrawView::surfaceAvailable(jobject surface, int width, int height) - { - _drawView->surfaceAvailable(ANativeWindow_fromSurface(Environment::current(), surface), width, height); - } - - void JniSkiaDrawView::surfaceSizeChanged(int width, int height) - { - _drawView->surfaceSizeChanged(width, height); - } - - void JniSkiaDrawView::surfaceDestroyed() - { - _drawView->surfaceDestroyed(); - } - - void JniSkiaDrawView::releaseSurface() { - jni::ThreadScope ts; - static auto method = javaPart_->getClass()->getMethod("releaseSurface"); - method(javaPart_.get()); - } -} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaManager.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaManager.cpp index e2b590d5be685..76dca49964b4d 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaManager.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/JniSkiaManager.cpp @@ -16,13 +16,8 @@ using namespace facebook; void JniSkiaManager::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", JniSkiaManager::initHybrid), - makeNativeMethod( - "initializeRuntime", JniSkiaManager::initializeRuntime), - makeNativeMethod("registerSkiaView", JniSkiaManager::registerSkiaView), - makeNativeMethod( - "unregisterSkiaView", JniSkiaManager::unregisterSkiaView), - makeNativeMethod( - "invalidate", JniSkiaManager::invalidate), + makeNativeMethod("initializeRuntime", JniSkiaManager::initializeRuntime), + makeNativeMethod("invalidate", JniSkiaManager::invalidate), }); } @@ -46,12 +41,4 @@ void JniSkiaManager::initializeRuntime() { _skManager = std::make_shared(_jsRuntime, _jsCallInvoker, _context); } -void JniSkiaManager::registerSkiaView(int viewTag, JniSkiaDrawView *skiaView) { - _skManager->registerSkiaDrawView(viewTag, skiaView->getDrawViewImpl()); -} - -void JniSkiaManager::unregisterSkiaView(int viewTag) { - _skManager->unregisterSkiaDrawView(viewTag); -} - } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaBaseView.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaBaseView.h new file mode 100644 index 0000000000000..8d1a077384449 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaBaseView.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +#include +#include +#include + +#include + +namespace RNSkia { + using namespace facebook; + using namespace jni; + + class JniSkiaBaseView { + public: + JniSkiaBaseView(jni::alias_ref skiaManager, + std::shared_ptr skiaView) : + _manager(skiaManager->cthis()), + _skiaView(skiaView) {} + + ~JniSkiaBaseView() {} + + std::shared_ptr getSkiaManager() { return _manager->getSkiaManager(); }; + + protected: + virtual void updateTouchPoints(jni::JArrayDouble touches) { + _skiaView->updateTouchPoints(touches); + } + + virtual void surfaceAvailable(jobject surface, int width, int height) { + _skiaView->surfaceAvailable(surface, width, height); + } + + virtual void surfaceSizeChanged(int width, int height) { + _skiaView->surfaceSizeChanged(width, height); + } + + virtual void surfaceDestroyed() { + _skiaView->surfaceDestroyed(); + } + + virtual void setMode(std::string mode) { + _skiaView->setMode(mode); + } + + virtual void setDebugMode(bool show) { + _skiaView->setShowDebugInfo(show); + } + + virtual void registerView(int nativeId) { + getSkiaManager()->registerSkiaView(nativeId, + _skiaView->getSkiaView()); + } + + virtual void unregisterView() { + getSkiaManager()->setSkiaView(_skiaView->getSkiaView()->getNativeId(), nullptr); + getSkiaManager()->unregisterSkiaView( + _skiaView->getSkiaView()->getNativeId()); + _skiaView->viewDidUnmount(); + } + + private: + JniSkiaManager *_manager; + std::shared_ptr _skiaView; + }; + +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaDrawView.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaDrawView.h index 5a04661732667..f61f746519c21 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaDrawView.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaDrawView.h @@ -1,78 +1,95 @@ #pragma once -#include #include -#include -#include #include #include #include -#include -#include +#include +#include +#include #include -#include -#include +#include +#include +#include -#include -#include -#include -#include - -class SkPicture; -class ANativeWindow; - -namespace RNSkia -{ +namespace RNSkia { using namespace facebook; + using namespace jni; - using JavaSkiaManager = jni::alias_ref; - - class JniSkiaDrawView : public jni::HybridClass - { + class JniSkiaDrawView + : public HybridClass, public JniSkiaBaseView { public: static auto constexpr kJavaDescriptor = "Lcom/shopify/reactnative/skia/SkiaDrawView;"; - static auto constexpr TAG = "ReactNativeSkia"; - static jni::local_ref initHybrid( - jni::alias_ref, - JavaSkiaManager); + static jni::local_ref + initHybrid(jni::alias_ref jThis, + jni::alias_ref skiaManager) { + return makeCxxInstance(jThis, skiaManager); + } - static void registerNatives(); + static void registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JniSkiaDrawView::initHybrid), + makeNativeMethod("surfaceAvailable", + JniSkiaDrawView::surfaceAvailable), + makeNativeMethod("surfaceDestroyed", + JniSkiaDrawView::surfaceDestroyed), + makeNativeMethod("surfaceSizeChanged", + JniSkiaDrawView::surfaceSizeChanged), + makeNativeMethod("setMode", JniSkiaDrawView::setMode), + makeNativeMethod("setDebugMode", JniSkiaDrawView::setDebugMode), + makeNativeMethod("updateTouchPoints", + JniSkiaDrawView::updateTouchPoints), + makeNativeMethod("registerView", JniSkiaDrawView::registerView), + makeNativeMethod("unregisterView", JniSkiaDrawView::unregisterView) + }); + } - void surfaceAvailable(jobject, int, int); - void surfaceDestroyed(); - void surfaceSizeChanged(int, int); + protected: + void updateTouchPoints(jni::JArrayDouble touches) override { + JniSkiaBaseView::updateTouchPoints(touches); + } - void updateTouchPoints(jni::JArrayDouble touches); + void surfaceAvailable(jobject surface, int width, int height) override { + JniSkiaBaseView::surfaceAvailable(surface, width, height); + } - ~JniSkiaDrawView(); + void surfaceSizeChanged(int width, int height) override { + JniSkiaBaseView::surfaceSizeChanged(width, height); + } - std::shared_ptr getDrawViewImpl() { return _drawView; } + void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); } - void releaseSurface(); + void setMode(std::string mode) override { + JniSkiaBaseView::setMode(mode); + } - protected: - void setMode(std::string mode); - void setDebugMode(bool show); + void setDebugMode(bool show) override { + JniSkiaBaseView::setDebugMode(show); + } - private: - friend HybridBase; + void registerView(int nativeId) override { + JniSkiaBaseView::registerView(nativeId); + } - std::shared_ptr _drawView; + void unregisterView() override { + JniSkiaBaseView::unregisterView(); + } - jni::global_ref javaPart_; + private: + friend HybridBase; - explicit JniSkiaDrawView( - jni::alias_ref jThis, - JavaSkiaManager skiaManager) - : javaPart_(jni::make_global(jThis)), - _drawView(std::make_shared(skiaManager->cthis()->getPlatformContext(), [this]() { - releaseSurface(); - })) { + explicit JniSkiaDrawView(jni::alias_ref jThis, + jni::alias_ref skiaManager) : + JniSkiaBaseView(skiaManager, + std::make_shared>( + skiaManager->cthis()->getPlatformContext())) { } + + jni::global_ref javaPart_; }; } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaManager.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaManager.h index 76246867747b8..218832f00055c 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaManager.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaManager.h @@ -7,12 +7,14 @@ #include #include -#include - +#include +#include #include namespace RNSkia { + class RNSkManager; + using namespace facebook; using JSCallInvokerHolder = @@ -20,8 +22,6 @@ using JSCallInvokerHolder = using JavaPlatformContext = jni::alias_ref; -class JniSkiaDrawView; - class JniSkiaManager : public jni::HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/shopify/reactnative/skia/SkiaManager;"; @@ -48,14 +48,12 @@ class JniSkiaManager : public jni::HybridClass { : _javaPart(jni::make_global(jThis)), _jsRuntime(runtime), _jsCallInvoker(jsCallInvoker), - _context(std::make_shared(platformContext, runtime, jsCallInvoker)) { + _context(std::make_shared(platformContext, runtime, jsCallInvoker)) { } - void registerSkiaView(int viewTag, JniSkiaDrawView *skiaView); - void unregisterSkiaView(int viewTag); - - std::shared_ptr getPlatformContext() { return _context; } + std::shared_ptr getPlatformContext() { return _context; } + std::shared_ptr getSkiaManager() { return _skManager; } void invalidate() { _context->stopDrawLoop(); @@ -73,7 +71,7 @@ class JniSkiaManager : public jni::HybridClass { jsi::Runtime *_jsRuntime; std::shared_ptr _jsCallInvoker; - std::shared_ptr _context; + std::shared_ptr _context; void initializeRuntime(); }; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaPictureView.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaPictureView.h new file mode 100644 index 0000000000000..bc7244ab193b3 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/jni/include/JniSkiaPictureView.h @@ -0,0 +1,96 @@ +#pragma once + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace RNSkia { + using namespace facebook; + using namespace jni; + + class JniSkiaPictureView + : public HybridClass, public JniSkiaBaseView { + public: + static auto constexpr kJavaDescriptor = "Lcom/shopify/reactnative/skia/SkiaPictureView;"; + + static jni::local_ref + initHybrid(jni::alias_ref jThis, + jni::alias_ref skiaManager) { + return makeCxxInstance(jThis, skiaManager); + } + + static void registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JniSkiaPictureView::initHybrid), + makeNativeMethod("surfaceAvailable", + JniSkiaPictureView::surfaceAvailable), + makeNativeMethod("surfaceDestroyed", + JniSkiaPictureView::surfaceDestroyed), + makeNativeMethod("surfaceSizeChanged", + JniSkiaPictureView::surfaceSizeChanged), + makeNativeMethod("setMode", JniSkiaPictureView::setMode), + makeNativeMethod("setDebugMode", JniSkiaPictureView::setDebugMode), + makeNativeMethod("updateTouchPoints", + JniSkiaPictureView::updateTouchPoints), + makeNativeMethod("registerView", JniSkiaPictureView::registerView), + makeNativeMethod("unregisterView", + JniSkiaPictureView::unregisterView) + }); + } + + protected: + void updateTouchPoints(jni::JArrayDouble touches) override { + JniSkiaBaseView::updateTouchPoints(touches); + } + + void surfaceAvailable(jobject surface, int width, int height) override { + JniSkiaBaseView::surfaceAvailable(surface, width, height); + } + + void surfaceSizeChanged(int width, int height) override { + JniSkiaBaseView::surfaceSizeChanged(width, height); + } + + void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); } + + void setMode(std::string mode) override { + JniSkiaBaseView::setMode(mode); + } + + void setDebugMode(bool show) override { + JniSkiaBaseView::setDebugMode(show); + } + + void registerView(int nativeId) override { + JniSkiaBaseView::registerView(nativeId); + } + + void unregisterView() override { + JniSkiaBaseView::unregisterView(); + } + + private: + friend HybridBase; + + explicit JniSkiaPictureView(jni::alias_ref jThis, + jni::alias_ref skiaManager) : + JniSkiaBaseView(skiaManager, + std::make_shared>( + skiaManager->cthis()->getPlatformContext())) { + } + + jni::global_ref javaPart_; + }; + +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkPlatformContextImpl.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h similarity index 80% rename from android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkPlatformContextImpl.h rename to android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h index 4ab7e12668f84..94adf66abb480 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkPlatformContextImpl.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h @@ -11,11 +11,11 @@ namespace RNSkia { using namespace facebook; - class RNSkPlatformContextImpl: public RNSkPlatformContext { + class RNSkAndroidPlatformContext: public RNSkPlatformContext { public: - RNSkPlatformContextImpl(JniPlatformContext* jniPlatformContext, - jsi::Runtime *runtime, - std::shared_ptr jsCallInvoker) : + RNSkAndroidPlatformContext(JniPlatformContext* jniPlatformContext, + jsi::Runtime *runtime, + std::shared_ptr jsCallInvoker) : RNSkPlatformContext(runtime, jsCallInvoker, jniPlatformContext->getPixelDensity()), diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h new file mode 100644 index 0000000000000..32ce1f1b47d37 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include + +namespace RNSkia { + + class RNSkBaseAndroidView { + public: + virtual void surfaceAvailable(jobject surface, int width, int height) = 0; + + virtual void surfaceDestroyed() = 0; + + virtual void surfaceSizeChanged(int width, int height) = 0; + + virtual float getPixelDensity() = 0; + + virtual void updateTouchPoints(jni::JArrayDouble touches) = 0; + + virtual void setMode(std::string mode) = 0; + + virtual void setShowDebugInfo(bool show) = 0; + + virtual void viewDidUnmount() = 0; + + virtual std::shared_ptr getSkiaView() = 0; + }; + + template + class RNSkAndroidView + : public T, public RNSkBaseAndroidView { + public: + RNSkAndroidView( + std::shared_ptr context) : + T(context, + std::make_shared( + std::bind(&RNSkia::RNSkView::requestRedraw, this), + context) + ) {} + + void surfaceAvailable(jobject surface, int width, int height) override { + std::static_pointer_cast( + T::getCanvasProvider())->surfaceAvailable(surface, width, height); + } + + void surfaceDestroyed() override { + std::static_pointer_cast( + T::getCanvasProvider())->surfaceDestroyed(); + } + + void surfaceSizeChanged(int width, int height) override { + std::static_pointer_cast( + T::getCanvasProvider())->surfaceSizeChanged(width, height); + } + + float getPixelDensity() override { + return T::getPlatformContext()->getPixelDensity(); + } + + void setMode(std::string mode) override { + if (mode.compare("continuous") == 0) { + T::setDrawingMode(RNSkDrawingMode::Continuous); + } else { + T::setDrawingMode(RNSkDrawingMode::Default); + } + } + + void setShowDebugInfo(bool show) override { + T::setShowDebugOverlays(show); + } + + void viewDidUnmount() override { + T::endDrawingLoop(); + } + + void updateTouchPoints(jni::JArrayDouble touches) override { + // Create touch points + std::vector points; + auto pin = touches.pin(); + auto scale = getPixelDensity(); + points.reserve(pin.size() / 5); + for (size_t i = 0; i < pin.size(); i += 5) { + RNSkTouchInfo point; + point.x = pin[i] / scale; + point.y = pin[i + 1] / scale; + point.force = pin[i + 2]; + point.type = (RNSkia::RNSkTouchInfo::TouchType) pin[i + 3]; + point.id = pin[i + 4]; + points.push_back(point); + } + T::updateTouchState(points); + } + + std::shared_ptr getSkiaView() override { + return T::shared_from_this(); + } + + }; +} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp deleted file mode 100644 index 5be180627bf44..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include - -#pragma clang diagnostic pop - -#include - -namespace RNSkia { - RNSkDrawViewImpl::RNSkDrawViewImpl(std::shared_ptr context, std::function releaseSurfaceCallback) : - RNSkia::RNSkDrawView(context), - _releaseSurfaceCallback(std::move(releaseSurfaceCallback)) {} - - void RNSkDrawViewImpl::surfaceAvailable(ANativeWindow* surface, int width, int height) { - _scaledWidth = width; - _scaledHeight = height; - - if (_renderer == nullptr) - { - // Create renderer! - _renderer = std::make_unique(surface, getNativeId()); - - // Redraw - requestRedraw(); - } - } - - void RNSkDrawViewImpl::surfaceDestroyed() { - if (_renderer != nullptr) - { - // Start teardown - _renderer->teardown(); - - // Teardown renderer on the render thread since OpenGL demands - // same thread access for OpenGL contexts. - getPlatformContext()->runOnRenderThread([weakSelf = weak_from_this()]() { - auto self = weakSelf.lock(); - if(self) { - auto drawViewImpl = std::dynamic_pointer_cast(self); - if(drawViewImpl->_renderer != nullptr) { - drawViewImpl->_renderer->run(nullptr, 0, 0); - } - // Remove renderer - drawViewImpl->_renderer = nullptr; - drawViewImpl->_releaseSurfaceCallback(); - } - }); - } - } - - void RNSkDrawViewImpl::surfaceSizeChanged(int width, int height) { - if(width == 0 && height == 0) { - // Setting width/height to zero is nothing we need to care about when - // it comes to invalidating the surface. - return; - } - _scaledWidth = width; - _scaledHeight = height; - - // Redraw after size change - requestRedraw(); - } - - void RNSkDrawViewImpl::drawPicture(const sk_sp picture) { - if(_renderer != nullptr) { - _renderer->run(picture, _scaledWidth, _scaledHeight); - } - } -} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.h deleted file mode 100644 index bce4d8cdf6704..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkDrawViewImpl.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include - -#pragma clang diagnostic pop - -namespace RNSkia { - class RNSkDrawViewImpl : public RNSkia::RNSkDrawView { - public: - RNSkDrawViewImpl(std::shared_ptr context, - std::function releaseSurfaceCallback); - - void surfaceAvailable(ANativeWindow* surface, int, int); - void surfaceDestroyed(); - void surfaceSizeChanged(int, int); - - float getPixelDensity() { - return getPlatformContext()->getPixelDensity(); - } - - protected: - float getScaledWidth() override { return _scaledWidth; }; - - float getScaledHeight() override { return _scaledHeight; }; - - void drawPicture(const sk_sp picture) override; - - private: - bool createSkiaSurface(); - - std::unique_ptr _renderer = nullptr; - - int _nativeId; - float _scaledWidth = -1; - float _scaledHeight = -1; - - std::function _releaseSurfaceCallback; - }; -} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp new file mode 100644 index 0000000000000..64e49bd3469ce --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -0,0 +1,91 @@ +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include + +#pragma clang diagnostic pop + +namespace RNSkia { + + RNSkOpenGLCanvasProvider::RNSkOpenGLCanvasProvider( + std::function requestRedraw, + std::shared_ptr context): + RNSkCanvasProvider(requestRedraw), + _context(context) {} + + RNSkOpenGLCanvasProvider::~RNSkOpenGLCanvasProvider() {} + + float RNSkOpenGLCanvasProvider::getScaledWidth() { + return _width; + } + + float RNSkOpenGLCanvasProvider::getScaledHeight() { + return _height; + } + + void RNSkOpenGLCanvasProvider::renderToCanvas(const std::function &cb) { + if(_renderer != nullptr) { + _renderer->run(cb, _width, _height); + } + } + + void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject surface, int width, int height) { + _width = width; + _height = height; + + if (_renderer == nullptr) + { + // Create renderer! + _renderer = std::make_unique(surface); + + // Redraw + _requestRedraw(); + } + } + void RNSkOpenGLCanvasProvider::surfaceDestroyed() { + if (_renderer != nullptr) + { + // teardown + _renderer->teardown(); + + // Teardown renderer on the render thread since OpenGL demands + // same thread access for OpenGL contexts. + std::condition_variable cv; + std::mutex m; + std::unique_lock lock(m); + + _context->runOnRenderThread([&cv, &m, weakSelf = weak_from_this()]() { + // Lock + std::unique_lock lock(m); + + auto self = weakSelf.lock(); + if(self) { + if(self->_renderer != nullptr) { + self->_renderer->run(nullptr, 0, 0); + } + // Remove renderer + self->_renderer = nullptr; + } + cv.notify_one(); + }); + + cv.wait(lock); + } + } + + void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) { + if(width == 0 && height == 0) { + // Setting width/height to zero is nothing we need to care about when + // it comes to invalidating the surface. + return; + } + _width = width; + _height = height; + + // Redraw after size change + _requestRedraw(); + } +} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h new file mode 100644 index 0000000000000..9b8e49c8f3ffe --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include + +#include +#include + +namespace RNSkia { + +class RNSkOpenGLCanvasProvider : + public RNSkia::RNSkCanvasProvider, + public std::enable_shared_from_this { +public: + RNSkOpenGLCanvasProvider(std::function requestRedraw, + std::shared_ptr context); + + ~RNSkOpenGLCanvasProvider(); + + float getScaledWidth() override; + + float getScaledHeight() override; + + void renderToCanvas(const std::function &cb) override; + + void surfaceAvailable(jobject surface, int width, int height); + + void surfaceDestroyed(); + + void surfaceSizeChanged(int width, int height); + +private: + std::unique_ptr _renderer = nullptr; + std::shared_ptr _context; + float _width = -1; + float _height = -1; +}; +} \ No newline at end of file diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp index 97d148ecd4782..288fd2d4e0a3b 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp @@ -1,6 +1,8 @@ #include "SkiaOpenGLRenderer.h" #include +#include +#include namespace RNSkia { @@ -20,12 +22,17 @@ namespace RNSkia return threadContexts.at(threadId); } - SkiaOpenGLRenderer::SkiaOpenGLRenderer(ANativeWindow *surface, size_t renderId): - _surfaceTexture(surface), - _renderId(renderId) { + SkiaOpenGLRenderer::SkiaOpenGLRenderer(jobject surface) { + _nativeWindow = ANativeWindow_fromSurface(facebook::jni::Environment::current(), surface); } - void SkiaOpenGLRenderer::run(const sk_sp picture, int width, int height) + SkiaOpenGLRenderer::~SkiaOpenGLRenderer() { + // Release surface + ANativeWindow_release(_nativeWindow); + _nativeWindow = nullptr; + } + + void SkiaOpenGLRenderer::run(const std::function &cb, int width, int height) { switch (_renderState) { @@ -51,7 +58,7 @@ namespace RNSkia return; } - if (picture != nullptr) + if (cb != nullptr) { // Reset Skia Context since it might be modified by another Skia View during // rendering. @@ -62,11 +69,10 @@ namespace RNSkia glClear(GL_COLOR_BUFFER_BIT); // Draw picture into surface - _skSurface->getCanvas()->drawPicture(picture); + cb(_skSurface->getCanvas()); // Flush - _skSurface->getCanvas()->flush(); - getThreadDrawingContext()->skContext->flush(); + _skSurface->flush(); if (!eglSwapBuffers(getThreadDrawingContext()->glDisplay, _glSurface)) { @@ -80,13 +86,15 @@ namespace RNSkia { _renderState = RenderState::Done; + // Release GL surface if (_glSurface != EGL_NO_SURFACE && getThreadDrawingContext()->glDisplay != EGL_NO_DISPLAY) { eglDestroySurface(getThreadDrawingContext()->glDisplay, _glSurface); + _glSurface = EGL_NO_SURFACE; } + // Release Skia Surface _skSurface = nullptr; - _surfaceTexture = nullptr; break; } @@ -180,10 +188,10 @@ namespace RNSkia EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; getThreadDrawingContext()->glContext = eglCreateContext( - getThreadDrawingContext()->glDisplay, - getThreadDrawingContext()->glConfig, - NULL, - contextAttribs); + getThreadDrawingContext()->glDisplay, + getThreadDrawingContext()->glConfig, + NULL, + contextAttribs); if (getThreadDrawingContext()->glContext == EGL_NO_CONTEXT) { @@ -216,7 +224,7 @@ namespace RNSkia bool SkiaOpenGLRenderer::initGLSurface() { - if (_surfaceTexture == nullptr) + if (_nativeWindow == nullptr) { return false; } @@ -239,10 +247,10 @@ namespace RNSkia // Create the opengl surface _glSurface = eglCreateWindowSurface( - getThreadDrawingContext()->glDisplay, - getThreadDrawingContext()->glConfig, - _surfaceTexture, - nullptr); + getThreadDrawingContext()->glDisplay, + getThreadDrawingContext()->glConfig, + _nativeWindow, + nullptr); if (_glSurface == EGL_NO_SURFACE) { diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h index 546f25f0d8334..28c16e4df5a3d 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h @@ -3,6 +3,8 @@ #include #include "android/native_window.h" +#include +#include #include "EGL/egl.h" #include "GLES2/gl2.h" @@ -45,18 +47,19 @@ namespace RNSkia class SkiaOpenGLRenderer { public: - SkiaOpenGLRenderer(ANativeWindow *surface, size_t renderId); + SkiaOpenGLRenderer(jobject surface); + ~SkiaOpenGLRenderer(); /** * Initializes, renders and tears down the render pipeline depending on the state of the * renderer. All OpenGL/Skia context operations are done on a separate thread which must * be the same for all calls to the render method. * - * @param picture Picture to render, can be nullptr, then no rendering will be performed + * @param callback Render callback * @param width Width of surface to render if there is a picture * @param height Height of surface to render if there is a picture */ - void run(const sk_sp picture, int width, int height); + void run(const std::function &cb, int width, int height); /** * Sets the state to finishing. Next time the renderer will be called it @@ -116,15 +119,13 @@ namespace RNSkia EGLSurface _glSurface = EGL_NO_SURFACE; - ANativeWindow *_surfaceTexture = nullptr; + ANativeWindow *_nativeWindow = nullptr; GrBackendRenderTarget _skRenderTarget; sk_sp _skSurface; int _prevWidth = 0; int _prevHeight = 0; - size_t _renderId; - std::atomic _renderState = { RenderState::Initializing }; }; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java index 61bde6f275ed8..c3a71a2e4eae4 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java @@ -26,8 +26,8 @@ public class PlatformContext { @DoNotStrip private final HybridData mHybridData; + private final ReactContext mContext; - private ExecutorService mDrawCallbackThread = Executors.newSingleThreadExecutor(); private boolean _drawLoopActive = false; private boolean _isPaused = false; @@ -37,7 +37,6 @@ public class PlatformContext { public PlatformContext(ReactContext reactContext) { mContext = reactContext; mHybridData = initHybrid(reactContext.getResources().getDisplayMetrics().density); - } private byte[] getStreamAsBytes(InputStream is) throws IOException { @@ -66,6 +65,7 @@ public void doFrame(long frameTimeNanos) { Choreographer.getInstance().postFrameCallback(frameCallback); } + @DoNotStrip public void raise(final String message) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override @@ -75,6 +75,7 @@ public void run() { }); } + @DoNotStrip public void beginDrawLoop() { if (_drawLoopActive) { return; @@ -88,21 +89,14 @@ public void run() { }); } + @DoNotStrip public void endDrawLoop() { if (_drawLoopActive) { _drawLoopActive = false; } } - public void triggerOnRenderThread() { - mDrawCallbackThread.execute(new Runnable() { - @Override - public void run() { - notifyTaskReady(); - } - }); - } - + @DoNotStrip public byte[] getJniStreamFromSource(String sourceUri) throws IOException { // First try loading the input as a resource directly int resourceId = mContext.getResources().getIdentifier(sourceUri, "drawable", mContext.getPackageName()); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java index 17ce708fef6b3..3552abe02de97 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java @@ -3,7 +3,6 @@ package com.shopify.reactnative.skia; import java.util.Arrays; -import java.util.Collections; import java.util.List; import com.facebook.react.ReactPackage; @@ -19,6 +18,6 @@ public List createNativeModules(ReactApplicationContext reactConte @Override public List createViewManagers(ReactApplicationContext reactContext) { - return Arrays.asList(new RNSkiaViewManager()); + return Arrays.asList(new SkiaDrawViewManager(), new SkiaPictureViewManager()); } } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java new file mode 100644 index 0000000000000..a470be0c62119 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -0,0 +1,143 @@ +package com.shopify.reactnative.skia; + +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.view.MotionEvent; +import android.view.Surface; +import android.view.TextureView; + +import com.facebook.jni.annotations.DoNotStrip; + +public abstract class SkiaBaseView extends TextureView implements TextureView.SurfaceTextureListener { + + @DoNotStrip + private Surface mSurface; + + public SkiaBaseView(Context context) { + super(context); + setSurfaceTextureListener(this); + setOpaque(false); + } + + @Override + public void setBackgroundColor(int color) { + // Texture view does not support setting the background color. + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + // https://developer.android.com/training/gestures/multi + int action = ev.getActionMasked(); + + MotionEvent.PointerCoords r = new MotionEvent.PointerCoords(); + + double[] points; + + // If this is a pointer_up/down event we need to handle it a bit specialized + switch (action) { + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: { + points = new double[5]; + int pointerIndex = ev.getActionIndex(); + ev.getPointerCoords(pointerIndex, r); + points[0] = r.x; + points[1] = r.y; + points[2] = ev.getPressure(pointerIndex); + points[3] = motionActionToType(action); + points[4] = ev.getPointerId(pointerIndex); + + updateTouchPoints(points); + + break; + } + default: { + // For the rest we can just handle it like expected + int count = ev.getPointerCount(); + int pointerIndex = 0; + points = new double[5 * count]; + for (int i = 0; i < count; i++) { + ev.getPointerCoords(i, r); + points[pointerIndex++] = r.x; + points[pointerIndex++] = r.y; + points[pointerIndex++] = ev.getPressure(i); + points[pointerIndex++] = motionActionToType(action); + points[pointerIndex++] = ev.getPointerId(i); + } + + updateTouchPoints(points); + + break; + } + } + + return true; + } + + private static int motionActionToType(int action) { + int actionType = 3; + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + actionType = 0; + break; + case MotionEvent.ACTION_MOVE: + actionType = 1; + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + actionType = 2; + break; + case MotionEvent.ACTION_CANCEL: + actionType = 3; + break; + } + return actionType; + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mSurface = new Surface(surface); + surfaceAvailable(mSurface, width, height); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + surfaceSizeChanged(width, height); + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + // Notify the native side + surfaceDestroyed(); + // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) + // Invoked when the specified SurfaceTexture is about to be destroyed. If returns true, + // no rendering should happen inside the surface texture after this method is invoked. + // We've measured this and it seems like we need to call release and return true - and + // then handle the issue with this being ripped out underneath the native layer in the C++ + // code. + mSurface.release(); + // Return true - we promise that no more rendering will be done now. + return true; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + // Nothing special to do here + } + + protected abstract void surfaceAvailable(Object surface, int width, int height); + + protected abstract void surfaceSizeChanged(int width, int height); + + protected abstract void surfaceDestroyed(); + + protected abstract void setMode(String mode); + + protected abstract void setDebugMode(boolean show); + + protected abstract void updateTouchPoints(double[] points); + + protected abstract void registerView(int nativeId); + + protected abstract void unregisterView(); +} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java index 4df19305a39d3..533285ec8cbb0 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java @@ -1,131 +1,45 @@ package com.shopify.reactnative.skia; import android.content.Context; -import android.graphics.SurfaceTexture; -import android.util.Log; -import android.view.Surface; -import android.view.TextureView; -import android.view.MotionEvent; import com.facebook.jni.HybridData; import com.facebook.jni.annotations.DoNotStrip; import com.facebook.react.bridge.ReactContext; -public class SkiaDrawView extends TextureView implements TextureView.SurfaceTextureListener { - - private static final String TAG = "Java::JniSkiaDrawView"; - +public class SkiaDrawView extends SkiaBaseView { @DoNotStrip private HybridData mHybridData; - @DoNotStrip - private boolean mViewRemoved; - - @DoNotStrip - private Surface mSurface; - - public SkiaDrawView(Context ctx) { - super(ctx); - RNSkiaModule skiaModule = ((ReactContext)ctx).getNativeModule(RNSkiaModule.class); + public SkiaDrawView(Context context) { + super(context); + RNSkiaModule skiaModule = ((ReactContext) context).getNativeModule(RNSkiaModule.class); mHybridData = initHybrid(skiaModule.getSkiaManager()); - setSurfaceTextureListener(this); - setOpaque(false); - } - - @Override - public void setBackgroundColor(int color) { - // Texture view does not support setting the background color. - } - - public void releaseSurface() { - if(mSurface != null) { - mSurface.release(); - mSurface = null; - } - // We can only reset the native side when the view was removed from screen. - // releasing the surface can also be done when the view is hidden and then - // we should only release the surface - and keep the native part around. - if(mViewRemoved) { - mHybridData.resetNative(); - } - } - - void onViewRemoved() { - mViewRemoved = true; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - int action = ev.getAction(); - int count = ev.getPointerCount(); - MotionEvent.PointerCoords r = new MotionEvent.PointerCoords(); - double[] points = new double[count*5]; - for (int i = 0; i < count; i++) { - ev.getPointerCoords(i, r); - points[i] = r.x; - points[i+1] = r.y; - points[i+2] = ev.getPressure(i); - switch (action) { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_POINTER_DOWN: - points[i+3] = 0; - break; - case MotionEvent.ACTION_MOVE: - points[i+3] = 1; - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_POINTER_UP: - points[i+3] = 2; - break; - case MotionEvent.ACTION_CANCEL: - points[i+3] = 3; - break; - } - points[i+4] = ev.getPointerId(i); - } - updateTouchPoints(points); - return true; } @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - mSurface = new Surface(surface); - surfaceAvailable(mSurface, width, height); + protected void finalize() throws Throwable { + super.finalize(); + mHybridData.resetNative(); } - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - surfaceSizeChanged(width, height); - } + private native HybridData initHybrid(SkiaManager skiaManager); - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - surfaceDestroyed(); - // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) - // Invoked when the specified SurfaceTexture is about to be destroyed. If returns true, - // no rendering should happen inside the surface texture after this method is invoked. - // If returns false, the client needs to call SurfaceTexture#release(). - return false; - } + protected native void surfaceAvailable(Object surface, int width, int height); - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - // Nothing special to do here - } + protected native void surfaceSizeChanged(int width, int height); - private native HybridData initHybrid(SkiaManager skiaManager); + protected native void surfaceDestroyed(); - private native void surfaceAvailable(Object surface, int width, int height); + protected native void setBgColor(int color); - private native void surfaceSizeChanged(int width, int height); + protected native void setMode(String mode); - private native void surfaceDestroyed(); + protected native void setDebugMode(boolean show); - private native void setBgColor(int color); + protected native void updateTouchPoints(double[] points); - public native void setMode(String mode); + protected native void registerView(int nativeId); - public native void setDebugMode(boolean show); + protected native void unregisterView(); - public native void updateTouchPoints(double[] points); } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawViewManager.java similarity index 65% rename from android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java rename to android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawViewManager.java index 11f37c51a5020..4b6fe7ab40e18 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawViewManager.java @@ -1,6 +1,5 @@ package com.shopify.reactnative.skia; -import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.BaseViewManager; import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.ThemedReactContext; @@ -9,16 +8,12 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import java.util.HashMap; - -public class RNSkiaViewManager extends BaseViewManager { - - final private HashMap mViewMapping = new HashMap(); +public class SkiaDrawViewManager extends BaseViewManager { @NonNull @Override public String getName() { - return "ReactNativeSkiaView"; + return "SkiaDrawView"; } @Override @@ -39,9 +34,7 @@ public void updateExtraData(SkiaDrawView root, Object extraData) { public void setNativeId(@NonNull SkiaDrawView view, @Nullable String nativeId) { super.setNativeId(view, nativeId); int nativeIdResolved = Integer.parseInt(nativeId); - RNSkiaModule skiaModule = ((ReactContext)view.getContext()).getNativeModule(RNSkiaModule.class); - skiaModule.getSkiaManager().register(nativeIdResolved, view); - mViewMapping.put(view, nativeIdResolved); + view.registerView(nativeIdResolved); } @ReactProp(name = "mode") @@ -57,11 +50,7 @@ public void setDebug(SkiaDrawView view, boolean show) { @Override public void onDropViewInstance(@NonNull SkiaDrawView view) { super.onDropViewInstance(view); - RNSkiaModule skiaModule = ((ReactContext)view.getContext()).getNativeModule(RNSkiaModule.class); - Integer nativeId = mViewMapping.get(view); - skiaModule.getSkiaManager().unregister(nativeId); - mViewMapping.remove(view); - view.onViewRemoved(); + view.unregisterView(); } @NonNull diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaManager.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaManager.java index 1aea5e77ff382..fd00fb5a3b17f 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaManager.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaManager.java @@ -43,14 +43,6 @@ public PlatformContext getPlatformContext() { return mPlatformContext; } - public void register(int nativeId, SkiaDrawView view) { - registerSkiaView(nativeId, view); - } - - public void unregister(int nativeId) { - unregisterSkiaView(nativeId); - } - public void onHostResume() { mPlatformContext.onResume(); } public void onHostPause() { mPlatformContext.onPause(); } @@ -58,9 +50,8 @@ public void unregister(int nativeId) { // private C++ functions private native HybridData initHybrid(long jsContext, CallInvokerHolderImpl jsCallInvokerHolder, PlatformContext platformContext); + private native void initializeRuntime(); - private native void registerSkiaView(int nativeId, SkiaDrawView view); - private native void unregisterSkiaView(int nativeId); public native void invalidate(); } \ No newline at end of file diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java new file mode 100644 index 0000000000000..7c1b9b5b3baa8 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java @@ -0,0 +1,45 @@ +package com.shopify.reactnative.skia; + +import android.content.Context; + +import com.facebook.jni.HybridData; +import com.facebook.jni.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactContext; + +public class SkiaPictureView extends SkiaBaseView { + @DoNotStrip + private HybridData mHybridData; + + public SkiaPictureView(Context context) { + super(context); + RNSkiaModule skiaModule = ((ReactContext) context).getNativeModule(RNSkiaModule.class); + mHybridData = initHybrid(skiaModule.getSkiaManager()); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + mHybridData.resetNative(); + } + + private native HybridData initHybrid(SkiaManager skiaManager); + + protected native void surfaceAvailable(Object surface, int width, int height); + + protected native void surfaceSizeChanged(int width, int height); + + protected native void surfaceDestroyed(); + + protected native void setBgColor(int color); + + protected native void setMode(String mode); + + protected native void setDebugMode(boolean show); + + protected native void updateTouchPoints(double[] points); + + protected native void registerView(int nativeId); + + protected native void unregisterView(); + +} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureViewManager.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureViewManager.java new file mode 100644 index 0000000000000..5184dd8aba98b --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureViewManager.java @@ -0,0 +1,64 @@ +package com.shopify.reactnative.skia; + +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.uimanager.BaseViewManager; +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.annotations.ReactProp; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.HashMap; + +public class SkiaPictureViewManager extends BaseViewManager { + + @NonNull + @Override + public String getName() { + return "SkiaPictureView"; + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + return new LayoutShadowNode(); + } + + @Override + public Class getShadowNodeClass() { + return LayoutShadowNode.class; + } + + @Override + public void updateExtraData(SkiaPictureView root, Object extraData) { + } + + @Override + public void setNativeId(@NonNull SkiaPictureView view, @Nullable String nativeId) { + super.setNativeId(view, nativeId); + int nativeIdResolved = Integer.parseInt(nativeId); + view.registerView(nativeIdResolved); + } + + @ReactProp(name = "mode") + public void setMode(SkiaPictureView view, String mode) { + view.setMode(mode); + } + + @ReactProp(name = "debug") + public void setDebug(SkiaPictureView view, boolean show) { + view.setDebugMode(show); + } + + @Override + public void onDropViewInstance(@NonNull SkiaPictureView view) { + super.onDropViewInstance(view); + view.unregisterView(); + } + + @NonNull + @Override + protected SkiaPictureView createViewInstance(@NonNull ThemedReactContext reactContext) { + return new SkiaPictureView(reactContext); + } +} \ No newline at end of file diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h index 8ba7f4513722f..a50c37b875bd0 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h @@ -33,7 +33,6 @@ #include "JsiSkVertices.h" #include "JsiSkTypefaceFactory.h" #include "JsiSkDataFactory.h" -#include "JsiSkFontMgrFactory.h" #include "JsiSkSurfaceFactory.h" #include "JsiSkTextBlobFactory.h" #include "JsiSkContourMeasureIter.h" @@ -72,9 +71,6 @@ namespace RNSkia installFunction("PictureRecorder", JsiSkPictureRecorder::createCtor(context)); installFunction("Color", JsiSkColor::createCtor()); - // Static members - installReadonlyProperty("FontMgr", - std::make_shared(context)); installReadonlyProperty("SVG", std::make_shared(context)); installReadonlyProperty("Image", diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h index 4d2d01fd712a2..4b5673f520e48 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h @@ -99,4 +99,4 @@ namespace RNSkia ->getObject(); } }; -} // namespace RNSkia \ No newline at end of file +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h index dc07e4674dcf7..8dc298c8f686a 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h @@ -75,7 +75,7 @@ namespace RNSkia { throw jsi::JSError(runtime, "Error decoding base64 string"); return jsi::Value::undefined(); } - + return jsi::Object::createFromHostObject(runtime, std::make_shared( getContext(), std::move(data))); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h index 15c9f7dad9cdd..094dbb636fbdb 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h @@ -38,24 +38,6 @@ namespace RNSkia return jsi::String::createFromUtf8(runtime, "Font"); } - JSI_HOST_FUNCTION(measureText) - { - RNSkLogger::warnToJavascriptConsole(runtime, "measureText() is deprecated. Clients should use 'Font.getGlyphWidths' instead (the latter does no shaping)"); - auto textVal = arguments[0].asString(runtime).utf8(runtime); - auto text = textVal.c_str(); - SkRect rect; - std::shared_ptr paint = nullptr; - // Check if a paint argument was provided - if (count == 2) - { - paint = JsiSkPaint::fromValue(runtime, arguments[1]); - } - getObject()->measureText(text, strlen(text), SkTextEncoding::kUTF8, &rect, - paint.get()); - rect.setXYWH(0, 0, rect.width(), rect.height()); - return JsiSkRect::toValue(runtime, getContext(), std::move(rect)); - } - JSI_HOST_FUNCTION(getGlyphWidths) { auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); @@ -89,7 +71,7 @@ namespace RNSkia JSI_HOST_FUNCTION(getTextWidth) { auto str = arguments[0].asString(runtime).utf8(runtime); - auto numGlyphIDs = str.length(); + auto numGlyphIDs = getObject()->countText(str.c_str(), str.length(), SkTextEncoding::kUTF8); std::vector glyphs; glyphs.resize(numGlyphIDs); int glyphsSize = static_cast(numGlyphIDs); @@ -129,9 +111,9 @@ namespace RNSkia JSI_HOST_FUNCTION(getGlyphIDs) { auto str = arguments[0].asString(runtime).utf8(runtime); - auto numGlyphIDs = count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() - ? arguments[1].asNumber() - : str.length(); + int numGlyphIDs = count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() + ? static_cast(arguments[1].asNumber()) + : getObject()->countText(str.c_str(), str.length(), SkTextEncoding::kUTF8); std::vector glyphIDs; glyphIDs.resize(numGlyphIDs); getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8, @@ -279,7 +261,6 @@ namespace RNSkia JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(JsiSkFont, getSize), - JSI_EXPORT_FUNC(JsiSkFont, measureText), JSI_EXPORT_FUNC(JsiSkFont, getMetrics), JSI_EXPORT_FUNC(JsiSkFont, getGlyphIDs), JSI_EXPORT_FUNC(JsiSkFont, getGlyphIntercepts), diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h deleted file mode 100644 index 02687da5fdf72..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "JsiSkHostObjects.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include -#include - -#pragma clang diagnostic pop - - -namespace RNSkia { - - using namespace facebook; - - class JsiSkFontMgr : public JsiSkWrappingSkPtrHostObject { - public: - - // TODO: declare in JsiSkWrappingSkPtrHostObject via extra template parameter? - JSI_PROPERTY_GET(__typename__) { - return jsi::String::createFromUtf8(runtime, "FontMgr"); - } - - JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkFontMgr, __typename__)) - - JsiSkFontMgr(std::shared_ptr context, - sk_sp fontMgr) - : JsiSkWrappingSkPtrHostObject(std::move(context), std::move(fontMgr)) {} - - JSI_HOST_FUNCTION(countFamilies) { - auto families = getObject()->countFamilies(); - return jsi::Value(families); - } - - JSI_HOST_FUNCTION(getFamilyName) { - auto i = arguments[0].asNumber(); - SkString familyName; - getObject()->getFamilyName(i, &familyName); - return jsi::String::createFromUtf8(runtime, familyName.c_str()); - } - - JSI_HOST_FUNCTION(matchFamilyStyle) { - auto familyName = arguments[0].asString(runtime).utf8(runtime); - auto fontStyle = SkFontStyle::Normal(); - if (count >= 2) { - auto object = arguments[1].asObject(runtime); - int weight = object.getProperty(runtime, "weight").asNumber(); - int width = object.getProperty(runtime, "width").asNumber(); - SkFontStyle::Slant slant = (SkFontStyle::Slant)object.getProperty(runtime, "slant").asNumber(); - fontStyle = SkFontStyle(width, weight, slant); - } - auto typeface = getObject()->matchFamilyStyle(familyName.c_str(), std::move(fontStyle)); - if (typeface == nullptr) { - return jsi::Value::null(); - } - return jsi::Object::createFromHostObject( - runtime, std::make_shared(getContext(), sk_sp(std::move(typeface))));; - } - - JSI_EXPORT_FUNCTIONS( - JSI_EXPORT_FUNC(JsiSkFontMgr, countFamilies), - JSI_EXPORT_FUNC(JsiSkFontMgr, getFamilyName), - JSI_EXPORT_FUNC(JsiSkFontMgr, matchFamilyStyle) - ) - - /** - Returns the underlying object from a host object of this type - */ - static sk_sp fromValue(jsi::Runtime &runtime, - const jsi::Value &obj) { - return obj.asObject(runtime) - .asHostObject(runtime) - ->getObject(); - } - }; -} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h deleted file mode 100644 index 165c5e77e4c52..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "JsiSkHostObjects.h" -#include "JsiSkFontMgr.h" -#include "JsiSkData.h" -#include - - -namespace RNSkia { - - using namespace facebook; - - class JsiSkFontMgrFactory : public JsiSkHostObject { - public: -// JSI_HOST_FUNCTION(FromData) { -// std::vector> data; -// for (int i = 0; i < count; i++) { -// auto d = JsiSkData::fromValue( -// runtime, arguments[i]); -// data.push_back(d); -// } -// -// auto fontMgr = SkFontMgr_New_Custom_Data(data.data(), data.size()); -// return jsi::Object::createFromHostObject( -// runtime, std::make_shared(getContext(), fontMgr)); -// } - - JSI_HOST_FUNCTION(RefDefault) { - auto fontMgr = SkFontMgr::RefDefault(); - return jsi::Object::createFromHostObject( - runtime, std::make_shared(getContext(), std::move(fontMgr))); - } - - JSI_EXPORT_FUNCTIONS( - //JSI_EXPORT_FUNC(JsiSkFontMgrFactory, FromData), - JSI_EXPORT_FUNC(JsiSkFontMgrFactory, RefDefault) - ) - - JsiSkFontMgrFactory(std::shared_ptr context) - : JsiSkHostObject(std::move(context)) {} - }; - -} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h index d19671f0d8928..d17093bbfcac6 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h @@ -46,6 +46,10 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { ); } + JSI_PROPERTY_GET(__typename__) { + return jsi::String::createFromUtf8(runtime, "Matrix"); + } + JSI_HOST_FUNCTION(concat) { auto m3 = JsiSkMatrix::fromValue(runtime, arguments[0]); getObject()->preConcat(*m3); @@ -78,6 +82,21 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { getObject()->preRotate(SkRadiansToDegrees(a)); return jsi::Value::undefined(); } + + JSI_HOST_FUNCTION(identity) { + getObject()->setIdentity(); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(get) { + auto values = jsi::Array(runtime, 9); + for (auto i = 0; i < 9; i++) { + values.setValueAtIndex(runtime, i, getObject()->get(i)); + } + return values; + } + + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkMatrix, __typename__)) JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(JsiSkMatrix, concat), @@ -85,6 +104,8 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { JSI_EXPORT_FUNC(JsiSkMatrix, scale), JSI_EXPORT_FUNC(JsiSkMatrix, skew), JSI_EXPORT_FUNC(JsiSkMatrix, rotate), + JSI_EXPORT_FUNC(JsiSkMatrix, identity), + JSI_EXPORT_FUNC(JsiSkMatrix, get), ) /** diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h index 8ce147a68444b..8c4efe7f9ee2c 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h @@ -39,6 +39,11 @@ class JsiSkPaint : public JsiSkWrappingSharedPtrHostObject { runtime, std::make_shared(getContext(), SkPaint(*paint))); } + JSI_HOST_FUNCTION(reset) { + getObject()->reset(); + return jsi::Value::undefined(); + } + JSI_HOST_FUNCTION(getColor) { return JsiSkColor::toValue(runtime, getObject()->getColor()); } @@ -144,6 +149,7 @@ class JsiSkPaint : public JsiSkWrappingSharedPtrHostObject { } JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkPaint, copy), + JSI_EXPORT_FUNC(JsiSkPaint, reset), JSI_EXPORT_FUNC(JsiSkPaint, getColor), JSI_EXPORT_FUNC(JsiSkPaint, getStrokeCap), JSI_EXPORT_FUNC(JsiSkPaint, getStrokeJoin), diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h index 92b02f5d651b0..0fe830b4205c6 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h @@ -348,7 +348,7 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rlineTo) { + JSI_HOST_FUNCTION(rLineTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); getObject()->rLineTo(x, y); @@ -536,7 +536,7 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { JSI_EXPORT_FUNC(JsiSkPath, moveTo), JSI_EXPORT_FUNC(JsiSkPath, rMoveTo), JSI_EXPORT_FUNC(JsiSkPath, lineTo), - JSI_EXPORT_FUNC(JsiSkPath, rlineTo), + JSI_EXPORT_FUNC(JsiSkPath, rLineTo), JSI_EXPORT_FUNC(JsiSkPath, cubicTo), JSI_EXPORT_FUNC(JsiSkPath, rCubicTo), JSI_EXPORT_FUNC(JsiSkPath, reset), diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h index 0591280ce2937..50510f114ff39 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h @@ -165,7 +165,7 @@ class JsiSkPathFactory : public JsiSkHostObject { JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromCmds), JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromText)) - JsiSkPathFactory(std::shared_ptr context) + JsiSkPathFactory(std::shared_ptr context) : JsiSkHostObject(std::move(context)) {} }; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h index b16d7f84034a5..ec94ab986fa2a 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h @@ -21,7 +21,13 @@ class JsiSkPicture : public JsiSkWrappingSkPtrHostObject { JsiSkPicture(std::shared_ptr context, const sk_sp picture) : JsiSkWrappingSkPtrHostObject(context, picture) {}; - + + JSI_PROPERTY_GET(__typename__) { + return jsi::String::createFromUtf8(runtime, "Picture"); + } + + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkPicture, __typename__)) + JSI_HOST_FUNCTION(makeShader) { auto tmx = (SkTileMode)arguments[0].asNumber(); auto tmy = (SkTileMode)arguments[1].asNumber(); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h index 7a22d4c3509ee..e4a638adfe963 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h @@ -35,7 +35,7 @@ namespace RNSkia : public JsiSkWrappingSkPtrHostObject { public: - + static sk_sp fromValue(jsi::Runtime &runtime, const jsi::Value &obj) { const auto& object = obj.asObject(runtime); return object.asHostObject(runtime)->getObject(); @@ -44,7 +44,7 @@ namespace RNSkia JSI_HOST_FUNCTION(makeShader) { auto uniforms = castUniforms(runtime, arguments[0]); - + auto matrix = count >= 2 && !arguments[1].isUndefined() && !arguments[1].isNull() ? JsiSkMatrix::fromValue(runtime, arguments[1]).get() : nullptr; // Create and return shader as host object @@ -57,7 +57,7 @@ namespace RNSkia JSI_HOST_FUNCTION(makeShaderWithChildren) { auto uniforms = castUniforms(runtime, arguments[0]); - + // Children std::vector> children; auto jsiChildren = arguments[1].asObject(runtime).asArray(runtime); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h index 685ac0969477e..edfcf63c4e6bd 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h @@ -22,24 +22,12 @@ using namespace facebook; class JsiSkTypeface : public JsiSkWrappingSkPtrHostObject { public: - JSI_PROPERTY_GET(bold) { - RNSkLogger::warnToJavascriptConsole(runtime, "Typeface.bold is deprecated and will be removed in a future release."); - return jsi::Value(getObject()->isBold()); - } - - JSI_PROPERTY_GET(italic) { - RNSkLogger::warnToJavascriptConsole(runtime, "Typeface.italic is deprecated and will be removed in a future release."); - return jsi::Value(getObject()->isItalic()); - } - // TODO: declare in JsiSkWrappingSkPtrHostObject via extra template parameter? JSI_PROPERTY_GET(__typename__) { return jsi::String::createFromUtf8(runtime, "Typeface"); } - JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkTypeface, bold), - JSI_EXPORT_PROP_GET(JsiSkTypeface, italic), - JSI_EXPORT_PROP_GET(JsiSkTypeface, __typename__)) + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkTypeface, __typename__)) JsiSkTypeface(std::shared_ptr context, sk_sp typeface) @@ -64,22 +52,6 @@ class JsiSkTypeface : public JsiSkWrappingSkPtrHostObject { return jsi::Object::createFromHostObject( runtime, std::make_shared(std::move(context), std::move(tf))); } - -private: - static SkFontStyle getFontStyleFromNumber(int fontStyle) { - switch (fontStyle) { - case 0: - return SkFontStyle::Normal(); - case 1: - return SkFontStyle::Bold(); - case 2: - return SkFontStyle::Italic(); - case 3: - return SkFontStyle::BoldItalic(); - default: - return SkFontStyle::Normal(); - }; - } }; } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h index 2d39a2d05718e..1d1c9220b1eda 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h @@ -7,26 +7,26 @@ namespace RNJsi { using namespace facebook; -enum JsiWrapperValueType +/** + Implements a simple wrapper class for JSI primitives like numbers and boolean values. Objects, + strings and arrays are stored as values inside a property holder. The class also provides a method + for comparing values that will compare numbers, booleans and strings. + */ +class JsiSimpleValueWrapper { +private: + enum ValueType { NonInitialized, Undefined, Null, Bool, Number, JsiValue -}; + }; -/** - Implements a simple wrapper class for JSI primitives like numbers and boolean values. Objects, - strings and arrays are stored as values inside a property holder. The class also provides a method - for comparing values that will compare numbers, booleans and strings. - */ -class JsiSimpleValueWrapper -{ public: JsiSimpleValueWrapper(jsi::Runtime& runtime) : - _type(JsiWrapperValueType::NonInitialized), + _type(ValueType::NonInitialized), _propNameId(jsi::PropNameID::forUtf8(runtime, "value")) {} @@ -34,17 +34,17 @@ class JsiSimpleValueWrapper { switch (_type) { - case JsiWrapperValueType::NonInitialized: + case ValueType::NonInitialized: return nullptr; - case JsiWrapperValueType::Undefined: + case ValueType::Undefined: return jsi::Value::undefined(); - case JsiWrapperValueType::Null: + case ValueType::Null: return jsi::Value::null(); - case JsiWrapperValueType::Bool: + case ValueType::Bool: return _boolValue; - case JsiWrapperValueType::Number: + case ValueType::Number: return _numberValue; - case JsiWrapperValueType::JsiValue: + case ValueType::JsiValue: if (_valueHolder == nullptr) { return jsi::Value::undefined(); } @@ -55,17 +55,17 @@ class JsiSimpleValueWrapper void setCurrent(jsi::Runtime &runtime, const jsi::Value &value) { if(value.isNumber()) { - _type = JsiWrapperValueType::Number; + _type = ValueType::Number; _numberValue = value.asNumber(); } else if(value.isBool()) { - _type = JsiWrapperValueType::Bool; + _type = ValueType::Bool; _boolValue = value.getBool(); } else if(value.isUndefined()) { - _type = JsiWrapperValueType::Undefined; + _type = ValueType::Undefined; } else if(value.isNull()) { - _type = JsiWrapperValueType::Null; + _type = ValueType::Null; } else { - _type = JsiWrapperValueType::JsiValue; + _type = ValueType::JsiValue; // Save as javascript object - we don't want to have to copy strings, objects and values if(_valueHolder == nullptr) { _valueHolder = std::make_shared(runtime); @@ -75,17 +75,17 @@ class JsiSimpleValueWrapper } bool equals(jsi::Runtime& runtime, const jsi::Value &value) { - if (_type == JsiWrapperValueType::NonInitialized) { + if (_type == ValueType::NonInitialized) { return false; } - if(value.isNumber() && _type == JsiWrapperValueType::Number) { + if(value.isNumber() && _type == ValueType::Number) { return _numberValue == value.asNumber(); - } else if(value.isBool() && _type == JsiWrapperValueType::Bool) { + } else if(value.isBool() && _type == ValueType::Bool) { return _boolValue == value.getBool(); } else if(value.isUndefined()) { - return _type == JsiWrapperValueType::Undefined; + return _type == ValueType::Undefined; } else if(value.isNull()) { - return _type == JsiWrapperValueType::Null; + return _type == ValueType::Null; } else if(value.isString()) { auto current = getCurrent(runtime); if (current.isString()) { @@ -103,6 +103,6 @@ class JsiSimpleValueWrapper bool _boolValue; double _numberValue; - JsiWrapperValueType _type; + ValueType _type; }; } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h new file mode 100644 index 0000000000000..18ec2d376d9ae --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h @@ -0,0 +1,138 @@ + +#pragma once + +#include + +namespace RNJsi +{ +using namespace facebook; + +enum JsiWrapperValueType +{ + NonInitialized, + Undefined, + Null, + Bool, + Number, + String, + Object, + Function, + Array, + HostObject, + Unknown +}; + +/** + Implements a simple wrapper class for JSI values where the value can be read without asking the runtime for any assistance + Meaning that we can access members without being on the JS thread. + */ +class JsiValueWrapper +{ +public: + JsiValueWrapper(jsi::Runtime& runtime) : + _type(JsiWrapperValueType::NonInitialized) + {} + + JsiValueWrapper(jsi::Runtime& runtime, const jsi::Value &value) : + _type(JsiWrapperValueType::NonInitialized) + { + setCurrent(runtime, value); + } + + void setCurrent(jsi::Runtime &runtime, const jsi::Value &value) + { + if (value.isNumber()) { + _type = JsiWrapperValueType::Number; + _numberValue = value.asNumber(); + } else if (value.isBool()) { + _type = JsiWrapperValueType::Bool; + _boolValue = value.getBool(); + } else if (value.isString()) { + _type = JsiWrapperValueType::String; + _stringValue = value.asString(runtime).utf8(runtime); + } else if (value.isUndefined()) { + _type = JsiWrapperValueType::Undefined; + } else if (value.isNull()) { + _type = JsiWrapperValueType::Null; + } else if (value.isObject()) { + _type = JsiWrapperValueType::Object; + _objectValue = std::make_shared(value.asObject(runtime)); + if (_objectValue->isFunction(runtime)) { + _type = JsiWrapperValueType::Function; + _functionValue = std::make_shared(_objectValue->asFunction(runtime)); + _objectValue = nullptr; + } else if (_objectValue->isArray(runtime)) { + _type = JsiWrapperValueType::Array; + _arrayValue = std::make_shared(_objectValue->asArray(runtime)); + _objectValue = nullptr; + } else if (_objectValue->isHostObject(runtime)) { + _type = JsiWrapperValueType::HostObject; + _hostObjectValue = _objectValue->asHostObject(runtime); + _objectValue = nullptr; + } + } else { + throw std::runtime_error("Could not store jsi::Value of provided type"); + } + // Save in value holder as well so that we can return current + if(_valueHolder == nullptr) { + _valueHolder = std::make_shared(runtime); + } + _valueHolder->setProperty(runtime, "current", value); + } + + bool isUndefinedOrNull() { + return _type == JsiWrapperValueType::Undefined || + _type == JsiWrapperValueType::Null; + } + + bool getAsBool() { + assert(_type == JsiWrapperValueType::Bool); + return _boolValue; + } + + double getAsNumber() { + assert(_type == JsiWrapperValueType::Number); + return _numberValue; + } + + const std::string& getAsString() { + assert(_type == JsiWrapperValueType::String); + return _stringValue; + } + + std::shared_ptr getAsFunction() { + assert(_type == JsiWrapperValueType::Function); + return _functionValue; + } + + std::shared_ptr getAsArray() { + assert(_type == JsiWrapperValueType::Array); + return _arrayValue; + } + + std::shared_ptr getAsObject() { + assert(_type == JsiWrapperValueType::Object); + return _objectValue; + } + + std::shared_ptr getAsHostObject() { + assert(_type == JsiWrapperValueType::HostObject); + return _hostObjectValue; + } + + JsiWrapperValueType getType() { return _type; } + +private: + std::shared_ptr _valueHolder; + + bool _boolValue; + double _numberValue; + std::string _stringValue; + std::shared_ptr _objectValue; + std::shared_ptr _functionValue; + std::shared_ptr _arrayValue; + std::shared_ptr _hostObjectValue; + + JsiWrapperValueType _type; +}; +} diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp deleted file mode 100644 index 4c29fa8b814f2..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp +++ /dev/null @@ -1,291 +0,0 @@ -// -// Created by Christian Falch on 23/08/2021. -// - -#include "RNSkDrawView.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma clang diagnostic pop - -namespace RNSkia { - -using namespace std::chrono; - -RNSkDrawView::RNSkDrawView(std::shared_ptr context) - : _jsiCanvas(std::make_shared(context)), - _platformContext(std::move(context)), - _infoObject(std::make_shared()), - _jsDrawingLock(std::make_shared()), - _gpuDrawingLock(std::make_shared()), - _jsTimingInfo("SKIA/JS"), - _gpuTimingInfo("SKIA/GPU") - {} - -RNSkDrawView::~RNSkDrawView() { - endDrawingLoop(); -} - -void RNSkDrawView::setNativeId(size_t nativeId) { - _nativeId = nativeId; - beginDrawingLoop(); -} - -void RNSkDrawView::setDrawCallback(std::shared_ptr callback) { - - if (callback == nullptr) { - _drawCallback = nullptr; - // We can just reset everything - this is a signal that we're done. - endDrawingLoop(); - return; - } - - // Reset timing info - _jsTimingInfo.reset(); - _gpuTimingInfo.reset(); - - // Create draw drawCallback wrapper - _drawCallback = std::make_shared( - [weakSelf = weak_from_this(), - callback = std::move(callback)](std::shared_ptr canvas, - int width, - int height, - double timestamp, - std::shared_ptr context) { - - auto self = weakSelf.lock(); - if(self) { - auto runtime = context->getJsRuntime(); - - // Update info parameter - self->_infoObject->beginDrawOperation(width, height, timestamp); - - // Set up arguments array - std::vector args(2); - args[0] = jsi::Object::createFromHostObject(*runtime, canvas); - args[1] = jsi::Object::createFromHostObject(*runtime, self->_infoObject); - - // To be able to call the drawing function we'll wrap it once again - callback->call(*runtime, - static_cast(args.data()), - (size_t)2); - - // Reset touches - self->_infoObject->endDrawOperation(); - - // Draw debug overlays - if (self->_showDebugOverlay) { - - // Display average rendering timer - auto jsAvg = self->_jsTimingInfo.getAverage(); - //auto jsFps = _jsTimingInfo.getFps(); - - auto gpuAvg = self->_gpuTimingInfo.getAverage(); - //auto gpuFps = _gpuTimingInfo.getFps(); - - auto total = jsAvg + gpuAvg; - - // Build string - std::ostringstream stream; - stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms"; - - std::string debugString = stream.str(); - - // Set up debug font/paints - auto font = SkFont(); - font.setSize(14); - auto paint = SkPaint(); - paint.setColor(SkColors::kRed); - canvas->getCanvas()->drawSimpleText( - debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8, - 18, font, paint); - } - } - }); - - // Request redraw - requestRedraw(); -} - -void RNSkDrawView::drawInCanvas(std::shared_ptr canvas, - int width, - int height, - double time) { - - // Call the draw drawCallback and perform js based drawing - auto skCanvas = canvas->getCanvas(); - if (_drawCallback != nullptr && skCanvas != nullptr) { - // Make sure to scale correctly - auto pd = _platformContext->getPixelDensity(); - skCanvas->save(); - skCanvas->scale(pd, pd); - - // Call draw function. - (*_drawCallback)(canvas, width / pd, height / pd, time, _platformContext); - - // Restore and flush canvas - skCanvas->restore(); - skCanvas->flush(); - } -} - -sk_sp RNSkDrawView::makeImageSnapshot(std::shared_ptr bounds) { - // Assert width/height - auto surface = SkSurface::MakeRasterN32Premul(getScaledWidth(), getScaledHeight()); - auto canvas = surface->getCanvas(); - auto jsiCanvas = std::make_shared(_platformContext); - jsiCanvas->setCanvas(canvas); - - milliseconds ms = duration_cast( - system_clock::now().time_since_epoch()); - - drawInCanvas(jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000); - - if(bounds != nullptr) { - SkIRect b = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(), bounds->height()); - return surface->makeImageSnapshot(b); - } else { - return surface->makeImageSnapshot(); - } -} - -void RNSkDrawView::updateTouchState(std::vector&& points) { - _infoObject->updateTouches(std::move(points)); - requestRedraw(); -} - -void RNSkDrawView::performDraw() { - // Start timing - _jsTimingInfo.beginTiming(); - - // Record the drawing operations on the JS thread so that we can - // move the actual drawing onto the render thread later - SkPictureRecorder recorder; - SkRTreeFactory factory; - SkCanvas* canvas = recorder.beginRecording(getScaledWidth(), getScaledHeight(), &factory); - _jsiCanvas->setCanvas(canvas); - - // Get current milliseconds - milliseconds ms = duration_cast( - system_clock::now().time_since_epoch()); - - try { - // Perform the javascript drawing - drawInCanvas(_jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000.0); - } catch(...) { - _jsTimingInfo.stopTiming(); - _jsDrawingLock->unlock(); - throw; - } - - // Finish drawing operations - auto p = recorder.finishRecordingAsPicture(); - - // Calculate duration - _jsTimingInfo.stopTiming(); - - if(_gpuDrawingLock->try_lock()) { - - // Post drawing message to the render thread where the picture recorded - // will be sent to the GPU/backend for rendering to screen. - auto gpuLock = _gpuDrawingLock; - _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock]() { - auto self = weakSelf.lock(); - if (self) { - // Draw the picture recorded on the real GPU canvas - self->_gpuTimingInfo.beginTiming(); - self->drawPicture(p); - self->_gpuTimingInfo.stopTiming(); - } - // Unlock GPU drawing - gpuLock->unlock(); - }); - } else { -#ifdef DEBUG - _gpuTimingInfo.markSkipped(); -#endif - // Request a new redraw since the last frame was skipped. - requestRedraw(); - } - - // Unlock JS drawing - _jsDrawingLock->unlock(); -} - -void RNSkDrawView::requestRedraw() { - _redrawRequestCounter++; -} - -void RNSkDrawView::beginDrawingLoop() { - if (_drawingLoopId != 0 || _nativeId == 0) { - return; - } - // Set to zero to avoid calling beginDrawLoop before we return - _drawingLoopId = _platformContext->beginDrawLoop(_nativeId, - [weakSelf = weak_from_this()](bool invalidated) { - auto self = weakSelf.lock(); - if(self) { - self->drawLoopCallback(invalidated); - } - }); -} - -void RNSkDrawView::drawLoopCallback(bool invalidated) { - if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) { - _redrawRequestCounter = 0; - - // We render on the javascript thread. - if(_jsDrawingLock->try_lock()) { - _platformContext->runOnJavascriptThread([weakSelf = weak_from_this()](){ - auto self = weakSelf.lock(); - if(self) { - self->performDraw(); - } - }); - } else { -#ifdef DEBUG - _jsTimingInfo.markSkipped(); -#endif - requestRedraw(); - } - } -} - -void RNSkDrawView::endDrawingLoop() { - if(_drawingLoopId != 0) { - _drawingLoopId = 0; - _platformContext->endDrawLoop(_nativeId); - } -} - -void RNSkDrawView::setDrawingMode(RNSkDrawingMode mode) { - if(mode == _drawingMode || _nativeId == 0) { - return; - } - _drawingMode = mode; -} - -} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h deleted file mode 100644 index 01cf33903e064..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h +++ /dev/null @@ -1,212 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include - -#pragma clang diagnostic pop - -class SkPicture; -class SkRect; -class SkImage; - -namespace RNSkia { -class JsiSkCanvas; -using namespace facebook; -using RNSkDrawCallback = - std::function, int, int, double, - std::shared_ptr)>; - -enum RNSkDrawingMode { Default, Continuous }; - -class RNSkDrawView: public std::enable_shared_from_this { -public: - /** - * Constructor - */ - RNSkDrawView(std::shared_ptr context); - - /** - Destructor - */ - virtual ~RNSkDrawView(); - - /** - * Repaints the Skia view using the underlying context and the drawcallback. - * This method schedules a draw request that will be run on the correct - * thread and js runtime. - */ - void requestRedraw(); - - /** - Calls the drawing callback on the javascript thread - */ - void performDraw(); - - /** - * Installs the draw callback for the view - */ - void setDrawCallback(std::shared_ptr callback); - - /** - Sets the native id of the view - */ - void setNativeId(size_t nativeId); - - /** - Returns the native id - */ - size_t getNativeId() { return _nativeId; } - - /** - Sets the drawing mode for the view - */ - void setDrawingMode(RNSkDrawingMode mode); - - /** - * Set to true to show the debug overlays on render - */ - void setShowDebugOverlays(bool show) { _showDebugOverlay = show; } - - /** - Update touch state with new touch points - */ - void updateTouchState(std::vector&& points); - - /** - Draws the view's surface into an image - return an SkImage - */ - sk_sp makeImageSnapshot(std::shared_ptr bounds); - -protected: - /** - Returns the scaled width of the view - */ - virtual float getScaledWidth() = 0; - - /** - Returns the scaled height of the view - */ - virtual float getScaledHeight() = 0; - - /** - Override to render picture to GPU - */ - virtual void drawPicture(const sk_sp picture) = 0; - - /** - * @return The platformcontext - */ - std::shared_ptr getPlatformContext() { - return _platformContext; - } - -private: - /** - Starts beginDrawCallback loop if the drawing mode is continuous - */ - void beginDrawingLoop(); - - /** - Ends an ongoing beginDrawCallback loop for this view - */ - void endDrawingLoop(); - - /** - Draw loop callback - */ - void drawLoopCallback(bool invalidated); - - /** - Draw in canvas - */ - void drawInCanvas(std::shared_ptr canvas, - int width, - int height, - double time); - - /** - * Stores the draw drawCallback - */ - std::shared_ptr _drawCallback; - - /** - * Stores a pointer to the jsi wrapper for the canvas. The reason for - * storing this pointer and not recreate it is that it creates a set of - * functions that we don't want to recreate on each render - */ - std::shared_ptr _jsiCanvas; - - /** - * JS Drawing mutex - */ - std::shared_ptr _jsDrawingLock; - - /** - * SKIA Drawing mutex - */ - std::shared_ptr _gpuDrawingLock; - - /** - * Pointer to the platform context - */ - std::shared_ptr _platformContext; - - /** - Drawing mode - */ - RNSkDrawingMode _drawingMode; - - /** - * Show debug overlays - */ - bool _showDebugOverlay = false; - - /** - * True if the drawing loop has been requested - */ - size_t _drawingLoopId = 0; - - /** - * Info object parameter - */ - std::shared_ptr _infoObject; - - /** - Timing information for javascript drawing - */ - RNSkTimingInfo _jsTimingInfo; - - /** - Timing information for GPU rendering - */ - RNSkTimingInfo _gpuTimingInfo; - - /** - Redraw queue counter - */ - std::atomic _redrawRequestCounter = { 1 }; - - /** - * Native id - */ - size_t _nativeId; - -}; - -} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h index f322b65dc22b2..a87eff12d7615 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h @@ -9,6 +9,7 @@ #include #include +#include namespace RNSkia { @@ -16,17 +17,6 @@ using namespace facebook; using namespace RNJsi; using namespace std::chrono; -enum RNSkTouchType { Start, Active, End, Cancelled }; - -using RNSkTouchPoint = struct { - double x; - double y; - double force; - RNSkTouchType type; - size_t id; - long timestamp; -}; - class RNSkInfoObject : public JsiHostObject { public: JSI_PROPERTY_GET(width) { return _width; } @@ -77,7 +67,7 @@ class RNSkInfoObject : public JsiHostObject { void endDrawOperation() { _touchesCache.clear(); } - void updateTouches(std::vector&& touches) { + void updateTouches(std::vector& touches) { std::lock_guard lock(_mutex); // Add timestamp auto ms = std::chrono::duration_cast( @@ -95,8 +85,8 @@ class RNSkInfoObject : public JsiHostObject { int _width; int _height; double _timestamp; - std::vector> _currentTouches; - std::vector> _touchesCache; + std::vector> _currentTouches; + std::vector> _touchesCache; std::mutex _mutex; }; } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp new file mode 100644 index 0000000000000..47c53dacb322f --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp @@ -0,0 +1,211 @@ +#include "RNSkJsView.h" + +namespace RNSkia +{ + +RNSkJsRenderer::RNSkJsRenderer(std::function requestRedraw, + std::shared_ptr context) : + RNSkRenderer(requestRedraw), + _jsiCanvas(std::make_shared(context)), + _platformContext(std::move(context)), + _infoObject(std::make_shared()), + _jsDrawingLock(std::make_shared()), + _gpuDrawingLock(std::make_shared()), + _jsTimingInfo("SKIA/JS"), + _gpuTimingInfo("SKIA/GPU") { +} + +bool RNSkJsRenderer::tryRender(std::shared_ptr canvasProvider) { + // We render on the javascript thread. + if(_jsDrawingLock->try_lock()) { + _platformContext->runOnJavascriptThread([weakSelf = weak_from_this(), canvasProvider](){ + auto self = weakSelf.lock(); + if(self) { + self->performDraw(canvasProvider); + } + }); + return true; + } else { +#ifdef DEBUG + _jsTimingInfo.markSkipped(); +#endif + return false; + } +}; + +void RNSkJsRenderer::renderImmediate(std::shared_ptr canvasProvider) { + milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); + canvasProvider->renderToCanvas([&](SkCanvas* canvas) { + // Create jsi canvas + auto jsiCanvas = std::make_shared(_platformContext); + jsiCanvas->setCanvas(canvas); + + drawInJsiCanvas(std::move(jsiCanvas), + canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + ms.count() / 1000); + }); +}; + +void RNSkJsRenderer::setDrawCallback(std::shared_ptr drawCallback) { + _drawCallback = drawCallback; +} + +std::shared_ptr RNSkJsRenderer::getInfoObject() { + return _infoObject; +} + +void RNSkJsRenderer::performDraw(std::shared_ptr canvasProvider) { + // Start timing + _jsTimingInfo.beginTiming(); + + // Record the drawing operations on the JS thread so that we can + // move the actual drawing onto the render thread later + SkPictureRecorder recorder; + SkRTreeFactory factory; + SkCanvas* canvas = recorder.beginRecording(canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + &factory); + + _jsiCanvas->setCanvas(canvas); + + // Get current milliseconds + milliseconds ms = duration_cast( + system_clock::now().time_since_epoch()); + + try { + // Perform the javascript drawing + drawInJsiCanvas(_jsiCanvas, + canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + ms.count() / 1000.0); + + } catch(...) { + _jsTimingInfo.stopTiming(); + _jsDrawingLock->unlock(); + throw; + } + + // Finish drawing operations + auto p = recorder.finishRecordingAsPicture(); + + _jsiCanvas->setCanvas(nullptr); + + // Calculate duration + _jsTimingInfo.stopTiming(); + + if(_gpuDrawingLock->try_lock()) { + + // Post drawing message to the render thread where the picture recorded + // will be sent to the GPU/backend for rendering to screen. + auto gpuLock = _gpuDrawingLock; + _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock, canvasProvider]() { + auto self = weakSelf.lock(); + if (self) { + // Draw the picture recorded on the real GPU canvas + self->_gpuTimingInfo.beginTiming(); + + canvasProvider->renderToCanvas([p = std::move(p)](SkCanvas* canvas) { + canvas->drawPicture(p); + }); + + self->_gpuTimingInfo.stopTiming(); + } + // Unlock GPU drawing + gpuLock->unlock(); + }); + } else { +#ifdef DEBUG + _gpuTimingInfo.markSkipped(); +#endif + // Request a new redraw since the last frame was skipped. + _requestRedraw(); + } + + // Unlock JS drawing + _jsDrawingLock->unlock(); +} + +void RNSkJsRenderer::callJsDrawCallback(std::shared_ptr jsiCanvas, + int width, + int height, + double timestamp) { + + if(_drawCallback == nullptr) { + return; + } + + // Reset timing info + _jsTimingInfo.reset(); + _gpuTimingInfo.reset(); + + auto runtime = _platformContext->getJsRuntime(); + + // Update info parameter + _infoObject->beginDrawOperation(width, height, timestamp); + + // Set up arguments array + std::vector args(2); + args[0] = jsi::Object::createFromHostObject(*runtime, jsiCanvas); + args[1] = jsi::Object::createFromHostObject(*runtime, _infoObject); + + // To be able to call the drawing function we'll wrap it once again + _drawCallback->call(*runtime, + static_cast(args.data()), + (size_t)2); + + // Reset touches + _infoObject->endDrawOperation(); + + // Draw debug overlays + if (getShowDebugOverlays()) { + + // Display average rendering timer + auto jsAvg = _jsTimingInfo.getAverage(); + //auto jsFps = _jsTimingInfo.getFps(); + + auto gpuAvg = _gpuTimingInfo.getAverage(); + //auto gpuFps = _gpuTimingInfo.getFps(); + + auto total = jsAvg + gpuAvg; + + // Build string + std::ostringstream stream; + stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms"; + + std::string debugString = stream.str(); + + // Set up debug font/paints + auto font = SkFont(); + font.setSize(14); + auto paint = SkPaint(); + paint.setColor(SkColors::kRed); + jsiCanvas->getCanvas()->drawSimpleText( + debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8, + 18, font, paint); + } +} + +void RNSkJsRenderer::drawInJsiCanvas(std::shared_ptr jsiCanvas, + int width, + int height, + double time) { + + // Call the draw drawCallback and perform js based drawing + auto skCanvas = jsiCanvas->getCanvas(); + if (_drawCallback != nullptr && skCanvas != nullptr) { + // Make sure to scale correctly + auto pd = _platformContext->getPixelDensity(); + skCanvas->save(); + skCanvas->scale(pd, pd); + + // Call draw function. + callJsDrawCallback(jsiCanvas, width / pd, height / pd, time); + + // Restore and flush canvas + skCanvas->restore(); + skCanvas->flush(); + } +} + +} // Namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h new file mode 100644 index 0000000000000..93000483ee381 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h @@ -0,0 +1,115 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include +#include + +#pragma clang diagnostic pop + +class SkPicture; +class SkRect; +class SkImage; + +namespace RNSkia { +class JsiSkCanvas; +using namespace facebook; + +class RNSkJsRenderer: + public RNSkRenderer, + public std::enable_shared_from_this { +public: + RNSkJsRenderer(std::function requestRedraw, + std::shared_ptr context); + + bool tryRender(std::shared_ptr canvasProvider) override; + + void renderImmediate(std::shared_ptr canvasProvider) override; + + void setDrawCallback(std::shared_ptr drawCallback); + + std::shared_ptr getInfoObject(); + +private: + void performDraw(std::shared_ptr canvasProvider); + + void callJsDrawCallback(std::shared_ptr jsiCanvas, + int width, + int height, + double timestamp); + + void drawInJsiCanvas(std::shared_ptr jsiCanvas, + int width, + int height, + double time); + + std::shared_ptr _platformContext; + std::shared_ptr _drawCallback; + std::shared_ptr _jsiCanvas; + std::shared_ptr _jsDrawingLock; + std::shared_ptr _gpuDrawingLock; + std::shared_ptr _infoObject; + RNSkTimingInfo _jsTimingInfo; + RNSkTimingInfo _gpuTimingInfo; +}; + +class RNSkJsView: public RNSkView { +public: + /** + * Constructor + */ + RNSkJsView(std::shared_ptr context, + std::shared_ptr canvasProvider): + RNSkView(context, + canvasProvider, + std::make_shared(std::bind(&RNSkJsView::requestRedraw, this), context)) {} + + void updateTouchState(std::vector& touches) override { + std::static_pointer_cast(getRenderer())->getInfoObject()->updateTouches(touches); + RNSkView::updateTouchState(touches); + } + + void setJsiProperties(std::unordered_map &props) override { + for(auto& prop: props) { + if(prop.first == "drawCallback") { + if(prop.second.isUndefinedOrNull()) { + // Clear drawcallback + std::static_pointer_cast(getRenderer())->setDrawCallback(nullptr); + return; + } else if (prop.second.getType() != JsiWrapperValueType::Function) { + // We expect a function for the draw callback custom property + throw std::runtime_error("Expected a function for the drawCallback custom property."); + } + + // Save callback + std::static_pointer_cast(getRenderer())->setDrawCallback(prop.second.getAsFunction()); + + // Request redraw + requestRedraw(); + + } else { + RNSkView::setJsiProperties(props); + } + } + } +}; +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h index 9dcb97e746732..23610ba79fec5 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h @@ -2,11 +2,13 @@ #include #include +#include #include #include #include -#include +#include +#include #include #include #include @@ -14,96 +16,143 @@ namespace RNSkia { using namespace facebook; -using CallbackInfo = struct CallbackInfo { - CallbackInfo() { - drawCallback = nullptr; +using RNSkViewInfo = struct RNSkViewInfo { + RNSkViewInfo() { view = nullptr; } - std::shared_ptr drawCallback; - std::shared_ptr view; + std::shared_ptr view; + std::unordered_map props; }; -class RNSkJsiViewApi : public JsiHostObject { +class RNSkJsiViewApi : public JsiHostObject, public std::enable_shared_from_this { public: - JSI_HOST_FUNCTION(setDrawCallback) { - if (count != 2) { + /** + Sets a custom property on a view given a view id. The property name/value will + be stored in a map alongside the id of the view and propagated to the view when + needed. + */ + JSI_HOST_FUNCTION(setJsiProperty) { + if (count != 3) { _platformContext->raiseError( - std::string("setDrawCallback: Expected 2 arguments, got " + + std::string("setJsiProperty: Expected 3 arguments, got " + std::to_string(count) + ".")); return jsi::Value::undefined(); } if (!arguments[0].isNumber()) { _platformContext->raiseError( - "setDrawCallback: First argument must be a number"); + "setJsiProperty: First argument must be a number"); return jsi::Value::undefined(); } - // We accept undefined to zero out the drawCallback - if (!arguments[1].isUndefined()) { - if (!arguments[1].isObject()) { - _platformContext->raiseError( - "setDrawCallback: Second argument must be a function"); - return jsi::Value::undefined(); - } - if (!arguments[1].asObject(runtime).isFunction(runtime)) { - _platformContext->raiseError( - "setDrawCallback: Second argument must be a function"); - return jsi::Value::undefined(); - } - } - - // find skia draw view - int nativeId = arguments[0].asNumber(); + if (!arguments[1].isString()) { + _platformContext->raiseError( + "setJsiProperty: Second argument must be the name of the property to set."); - // and function to install as the draw drawCallback - auto info = getEnsuredCallbackInfo(nativeId); - if (arguments[1].isUndefined()) { - info->drawCallback = nullptr; - } else { - info->drawCallback = std::make_shared( - arguments[1].asObject(runtime).asFunction(runtime)); + return jsi::Value::undefined(); } + auto nativeId = arguments[0].asNumber(); + auto info = getEnsuredViewInfo(nativeId); - // Update view if set - if (info->view != nullptr && info->drawCallback != nullptr) { + std::lock_guard lock(_mutex); + info->props.emplace(arguments[1].asString(runtime).utf8(runtime), JsiValueWrapper(runtime, arguments[2])); + + // Now let's see if we have a view that we can update + if(info->view != nullptr) { + // Update view! info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); + info->view->setJsiProperties(info->props); + info->props.clear(); } return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(invalidateSkiaView) { - if (count != 1) { + /** + Calls a custom command / method on a view by the view id. + */ + JSI_HOST_FUNCTION(callJsiMethod) { + if (count < 2) { _platformContext->raiseError( - std::string("invalidateSkiaView: Expected 2 arguments, got " + + std::string("callCustomCommand: Expected at least 2 arguments, got " + std::to_string(count) + ".")); + return jsi::Value::undefined(); } if (!arguments[0].isNumber()) { _platformContext->raiseError( - "invalidateSkiaView: First argument must be a number"); + "callCustomCommand: First argument must be a number"); + return jsi::Value::undefined(); } - // find skia draw view - int nativeId = arguments[0].asNumber(); + if (!arguments[1].isString()) { + _platformContext->raiseError( + "callCustomCommand: Second argument must be the name of the action to call."); - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - info->view->requestRedraw(); + return jsi::Value::undefined(); } - return jsi::Value::undefined(); + + auto nativeId = arguments[0].asNumber(); + auto action = arguments[1].asString(runtime).utf8(runtime); + + auto info = getEnsuredViewInfo(nativeId); + + if(info->view == nullptr) { + throw jsi::JSError(runtime, + std::string("callCustomCommand: Could not call action " + action + + " on view - view not ready.").c_str()); + + return jsi::Value::undefined(); + } + + // Get arguments + size_t paramsCount = count - 2; + const jsi::Value* params = paramsCount > 0 ? &arguments[2] : nullptr; + return info->view->callJsiMethod(runtime, action, params, paramsCount); + } + + JSI_HOST_FUNCTION(requestRedraw) { + if (count != 1) { + _platformContext->raiseError( + std::string("requestRedraw: Expected 1 arguments, got " + std::to_string(count) + ".")); + + return jsi::Value::undefined(); + } + + if (!arguments[0].isNumber()) { + _platformContext->raiseError( + "requestRedraw: First argument must be a number"); + + return jsi::Value::undefined(); + } + + // find Skia View + int nativeId = arguments[0].asNumber(); + + auto info = getEnsuredViewInfo(nativeId); + if (info->view != nullptr) { + info->view->requestRedraw(); + } + return jsi::Value::undefined(); } - + JSI_HOST_FUNCTION(makeImageSnapshot) { - - // find skia draw view + if (count < 1) { + _platformContext->raiseError(std::string("makeImageSnapshot: Expected at least 1 argument, got " + std::to_string(count) + ".")); + return jsi::Value::undefined(); + } + + if (!arguments[0].isNumber()) { + _platformContext->raiseError("makeImageSnapshot: First argument must be a number"); + return jsi::Value::undefined(); + } + + // find Skia view int nativeId = arguments[0].asNumber(); sk_sp image; - auto info = getEnsuredCallbackInfo(nativeId); + auto info = getEnsuredViewInfo(nativeId); if (info->view != nullptr) { if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) { auto rect = JsiSkRect::fromValue(runtime, arguments[1]); @@ -120,80 +169,58 @@ class RNSkJsiViewApi : public JsiHostObject { throw jsi::JSError(runtime, "No Skia View currently available."); return jsi::Value::undefined(); } - - JSI_HOST_FUNCTION(setDrawMode) { - if (count != 2) { - _platformContext->raiseError( - std::string("setDrawMode: Expected 2 arguments, got " + - std::to_string(count) + ".")); - return jsi::Value::undefined(); - } - - if (!arguments[0].isNumber()) { - _platformContext->raiseError( - "setDrawMode: First argument must be a number"); - return jsi::Value::undefined(); - } - // find skia draw view - int nativeId = arguments[0].asNumber(); - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - auto nextMode = arguments[1].asString(runtime).utf8(runtime); - if(nextMode.compare("continuous") == 0) { - info->view->setDrawingMode(RNSkDrawingMode::Continuous); - } else { - info->view->setDrawingMode(RNSkDrawingMode::Default); - } - } - return jsi::Value::undefined(); - } - JSI_HOST_FUNCTION(registerValuesInView) { - // Check params - if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { - throw jsi::JSError(runtime, "Expected array of Values as second parameter"); - return jsi::Value::undefined(); - } - - // Get identifier of native SkiaView - int nativeId = arguments[0].asNumber(); - - // Get values that should be added as dependencies - auto values = arguments[1].asObject(runtime).asArray(runtime); - std::vector> unsubscribers; - const std::size_t size = values.size(runtime); - unsubscribers.reserve(size); - for(size_t i=0; i(runtime); - - if(value != nullptr) { - // Add change listener - unsubscribers.push_back(value->addListener([this, nativeId](jsi::Runtime&){ - requestRedrawView(nativeId); - })); + // Check params + if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { + throw jsi::JSError(runtime, "Expected array of Values as second parameter"); + return jsi::Value::undefined(); } - } - - // Return unsubscribe method that unsubscribes to all values - // that we subscribed to. - return jsi::Function::createFromHostFunction(runtime, - jsi::PropNameID::forUtf8(runtime, "unsubscribe"), - 0, - JSI_HOST_FUNCTION_LAMBDA { - // decrease dependency count on the Skia View - for(auto &unsub : unsubscribers) { - unsub(); + + // Get identifier of native SkiaView + int nativeId = arguments[0].asNumber(); + + // Get values that should be added as dependencies + auto values = arguments[1].asObject(runtime).asArray(runtime); + std::vector> unsubscribers; + const std::size_t size = values.size(runtime); + unsubscribers.reserve(size); + for(size_t i=0; i(runtime); + + if(value != nullptr) { + // Add change listener + unsubscribers.push_back(value->addListener([weakSelf = weak_from_this(), nativeId](jsi::Runtime&){ + auto self = weakSelf.lock(); + if(self) { + auto info = self->getEnsuredViewInfo(nativeId); + if(info->view != nullptr) { + info->view->requestRedraw(); + } + } + })); + } } - return jsi::Value::undefined(); - }); - } - - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawCallback), - JSI_EXPORT_FUNC(RNSkJsiViewApi, invalidateSkiaView), - JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot), - JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawMode), - JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView)) + + // Return unsubscribe method that unsubscribes to all values + // that we subscribed to. + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "unsubscribe"), + 0, + JSI_HOST_FUNCTION_LAMBDA { + // decrease dependency count on the Skia View + for(auto &unsub : unsubscribers) { + unsub(); + } + return jsi::Value::undefined(); + }); + } + + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setJsiProperty), + JSI_EXPORT_FUNC(RNSkJsiViewApi, callJsiMethod), + JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView), + JSI_EXPORT_FUNC(RNSkJsiViewApi, requestRedraw), + JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot)) /** * Constructor @@ -203,7 +230,7 @@ class RNSkJsiViewApi : public JsiHostObject { : JsiHostObject(), _platformContext(platformContext) {} /** - * Invalidates the api object + * Invalidates the Skia View Api object */ void invalidate() { unregisterAll(); @@ -214,11 +241,12 @@ class RNSkJsiViewApi : public JsiHostObject { */ void unregisterAll() { // Unregister all views - auto tempList = _callbackInfos; + auto tempList = _viewInfos; for (const auto& info : tempList) { - unregisterSkiaDrawView(info.first); + unregisterSkiaView(info.first); } - _callbackInfos.clear(); + std::lock_guard lock(_mutex); + _viewInfos.clear(); } /** @@ -226,51 +254,48 @@ class RNSkJsiViewApi : public JsiHostObject { * @param nativeId Id of view to register * @param view View to register */ - void registerSkiaDrawView(size_t nativeId, std::shared_ptr view) { - auto info = getEnsuredCallbackInfo(nativeId); + void registerSkiaView(size_t nativeId, std::shared_ptr view) { + auto info = getEnsuredViewInfo(nativeId); + std::lock_guard lock(_mutex); info->view = view; - if (info->drawCallback != nullptr) { - info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); - } + info->view->setNativeId(nativeId); + info->view->setJsiProperties(info->props); + info->props.clear(); } /** * Unregisters a Skia draw view * @param nativeId View id */ - void unregisterSkiaDrawView(size_t nativeId) { - if (_callbackInfos.count(nativeId) == 0) { + void unregisterSkiaView(size_t nativeId) { + if (_viewInfos.count(nativeId) == 0) { return; } - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - info->view->setDrawCallback(nullptr); - } + auto info = getEnsuredViewInfo(nativeId); + + std::lock_guard lock(_mutex); info->view = nullptr; - info->drawCallback = nullptr; - _callbackInfos.erase(nativeId); + _viewInfos.erase(nativeId); } - + /** Sets a skia draw view for the given id. This function can be used to mark that an underlying SkiaView is not available (it could be removed due to ex. a transition). The view can be set to a nullptr - or a valid view, effectively toggling the view's availability. If - a valid view is set, the setDrawCallback method is called on the - view (if a valid callback exists). + or a valid view, effectively toggling the view's availability. */ - void setSkiaDrawView(size_t nativeId, std::shared_ptr view) { - if (_callbackInfos.find(nativeId) == _callbackInfos.end()) { + void setSkiaView(size_t nativeId, std::shared_ptr view) { + if (_viewInfos.find(nativeId) == _viewInfos.end()) { return; } - auto info = getEnsuredCallbackInfo(nativeId); - if (view != nullptr && info->drawCallback != nullptr) { + auto info = getEnsuredViewInfo(nativeId); + std::lock_guard lock(_mutex); + if (view != nullptr) { info->view = view; info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); - } else if(view == nullptr && info->drawCallback != nullptr) { - info->view->setDrawCallback(nullptr); + info->view->setJsiProperties(info->props); + info->props.clear(); + } else if(view == nullptr) { info->view = view; } } @@ -281,28 +306,17 @@ class RNSkJsiViewApi : public JsiHostObject { * @param nativeId View id * @return The callback info object for the requested view */ - CallbackInfo *getEnsuredCallbackInfo(size_t nativeId) { - if (_callbackInfos.count(nativeId) == 0) { - CallbackInfo info; - _callbackInfos.emplace(nativeId, info); + RNSkViewInfo *getEnsuredViewInfo(size_t nativeId) { + if (_viewInfos.count(nativeId) == 0) { + RNSkViewInfo info; + std::lock_guard lock(_mutex); + _viewInfos.emplace(nativeId, info); } - return &_callbackInfos.at(nativeId); + return &_viewInfos.at(nativeId); } - - /** - Send a redraw request to the view - */ - void requestRedrawView(size_t nativeId) { - auto info = getEnsuredCallbackInfo(nativeId); - if(info->view != nullptr) { - info->view->requestRedraw(); - } - } - - // List of callbacks - std::unordered_map _callbackInfos; - - // Platform context + + std::unordered_map _viewInfos; std::shared_ptr _platformContext; + std::mutex _mutex; }; } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp index b273e054389e3..e103885437ca2 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace RNSkia { @@ -45,19 +45,19 @@ void RNSkManager::invalidate() { _platformContext->invalidate(); } -void RNSkManager::registerSkiaDrawView(size_t nativeId, std::shared_ptr view) { +void RNSkManager::registerSkiaView(size_t nativeId, std::shared_ptr view) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->registerSkiaDrawView(nativeId, view); + _viewApi->registerSkiaView(nativeId, view); } -void RNSkManager::unregisterSkiaDrawView(size_t nativeId) { +void RNSkManager::unregisterSkiaView(size_t nativeId) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->unregisterSkiaDrawView(nativeId); + _viewApi->unregisterSkiaView(nativeId); } -void RNSkManager::setSkiaDrawView(size_t nativeId, std::shared_ptr view) { +void RNSkManager::setSkiaView(size_t nativeId, std::shared_ptr view) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->setSkiaDrawView(nativeId, view); + _viewApi->setSkiaView(nativeId, view); } void RNSkManager::installBindings() { diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h index 8e86eeb65f337..7b07a32f2476b 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h @@ -12,7 +12,7 @@ namespace facebook { } namespace RNSkia { -class RNSkDrawView; +class RNSkView; class RNSkJsiViewApi; using namespace facebook; @@ -37,24 +37,24 @@ class RNSkManager { void invalidate(); /** - * Registers a RNSkDrawView with the given native id + * Registers a RNSkView with the given native id * @param nativeId Native view id * @param view View to register */ - void registerSkiaDrawView(size_t nativeId, std::shared_ptr view); + void registerSkiaView(size_t nativeId, std::shared_ptr view); /** - * Unregisters the RNSkDrawView from the list of registered views + * Unregisters the RNSkView from the list of registered views * @param nativeId Native view Id */ - void unregisterSkiaDrawView(size_t nativeId); + void unregisterSkiaView(size_t nativeId); /** Sets the view pointed to by nativeId to the provided value. Used when we want to remove a view without unregistering it - this happens typically on iOS. */ - void setSkiaDrawView(size_t nativeId, std::shared_ptr view); + void setSkiaView(size_t nativeId, std::shared_ptr view); /** * @return The platform context @@ -66,7 +66,7 @@ class RNSkManager { private: /** * Installs the javascript methods for registering/unregistering draw - * callbacks for RNSkDrawViews. Called on installation of the parent native + * callbacks for RNSkViews. Called on installation of the parent native * module. */ void installBindings(); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h new file mode 100644 index 0000000000000..d71eb171d0214 --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include +#include + +#pragma clang diagnostic pop + +class SkPicture; +class SkRect; +class SkImage; + +namespace RNSkia { + +using namespace facebook; + +class RNSkPictureRenderer: + public RNSkRenderer, + public std::enable_shared_from_this { +public: + RNSkPictureRenderer(std::function requestRedraw, + std::shared_ptr context): + RNSkRenderer(requestRedraw), + _platformContext(context) {} + + bool tryRender(std::shared_ptr canvasProvider) override { + performDraw(canvasProvider); + return true; + } + + void renderImmediate(std::shared_ptr canvasProvider) override { + performDraw(canvasProvider); + } + + void setPicture(std::shared_ptr picture) { + if(picture == nullptr) { + _picture = nullptr; + return; + } + + _picture = std::dynamic_pointer_cast(picture); + _requestRedraw(); + } + +private: + void performDraw(std::shared_ptr canvasProvider) { + if(_picture == nullptr) { + return; + } + + canvasProvider->renderToCanvas([=](SkCanvas* canvas){ + // Make sure to scale correctly + auto pd = _platformContext->getPixelDensity(); + canvas->save(); + canvas->scale(pd, pd); + + canvas->drawPicture(_picture->getObject()); + + // Restore and flush canvas + canvas->restore(); + canvas->flush(); + }); + } + + std::shared_ptr _platformContext; + std::shared_ptr _picture; +}; + +class RNSkPictureView: public RNSkView { +public: + /** + * Constructor + */ + RNSkPictureView(std::shared_ptr context, + std::shared_ptr canvasProvider): + RNSkView(context, + canvasProvider, + std::make_shared(std::bind(&RNSkPictureView::requestRedraw, this), context)) {} + + void setJsiProperties(std::unordered_map &props) override { + for(auto& prop: props) { + if(prop.first == "picture") { + if(prop.second.isUndefinedOrNull()) { + // Clear picture + std::static_pointer_cast(getRenderer())->setPicture(nullptr); + return; + } else if (prop.second.getType() != JsiWrapperValueType::HostObject) { + // We expect a function for the picture custom property + throw std::runtime_error("Expected an object for the picture custom property."); + } + + // Save picture + std::static_pointer_cast(getRenderer())->setPicture(prop.second.getAsHostObject()); + + // Request redraw + requestRedraw(); + + } else { + RNSkView::setJsiProperties(props); + } + } + } +}; +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h new file mode 100644 index 0000000000000..5a6c6b2613e6f --- /dev/null +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h @@ -0,0 +1,287 @@ + +#pragma once + +#include + +#include + +#include + +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include + +#pragma clang diagnostic pop + +namespace RNSkia { + +using namespace facebook; + +class RNSkCanvasProvider { +public: + RNSkCanvasProvider(std::function requestRedraw): _requestRedraw(requestRedraw) {} + + /** + Returns the scaled width of the view + */ + virtual float getScaledWidth() = 0; + + /** + Returns the scaled height of the view + */ + virtual float getScaledHeight() = 0; + + /** + Render to a canvas + */ + virtual void renderToCanvas(const std::function&) = 0; +protected: + std::function _requestRedraw; +}; + +class RNSkRenderer { +public: + RNSkRenderer(std::function requestRedraw): _requestRedraw(requestRedraw) {} + + /** + Tries to render the current set of drawing operations. If we're busy we'll return false so that the calling RNSkBaseDrawView + can request a new render next frame. The tryRender method is typically called on each frame if there are any redraw + requests. The method will be called from the main thread, so the implementor must make sure any thread requirements are + met before rendering. This method will also allow the rendering to be dispatched to another thread. + */ + virtual bool tryRender(std::shared_ptr canvasProvider) = 0; + + /** + Renders directly to the canvas in the canvas provider. This method is called from a Javascript call to render a + snapshot of the SkiaView to an image, and can therefore run outside the tryRender loop and directly in the + javascript thread. + */ + virtual void renderImmediate(std::shared_ptr canvasProvider) = 0; + + void setShowDebugOverlays(bool showDebugOverlays) { _showDebugOverlays = showDebugOverlays; } + bool getShowDebugOverlays() { return _showDebugOverlays; } + +protected: + std::function _requestRedraw; + bool _showDebugOverlays; +}; + +class RNSkImageCanvasProvider: public RNSkCanvasProvider { +public: + RNSkImageCanvasProvider(std::function requestRedraw, + float width, + float height): + RNSkCanvasProvider(requestRedraw), + _width(width), + _height(height) { + _surface = SkSurface::MakeRasterN32Premul(_width, _height); + } + + /** + Returns a snapshot of the current surface/canvas + */ + sk_sp makeSnapshot(std::shared_ptr bounds) { + if(bounds != nullptr) { + SkIRect b = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(), bounds->height()); + return _surface->makeImageSnapshot(b); + } else { + return _surface->makeImageSnapshot(); + } + } + + /** + Returns the scaled width of the view + */ + float getScaledWidth() override { return _width; }; + + /** + Returns the scaled height of the view + */ + float getScaledHeight() override { return _height; }; + + /** + Render to a canvas + */ + void renderToCanvas(const std::function& cb) override { + cb(_surface->getCanvas()); + }; + +private: + float _width; + float _height; + sk_sp _surface; +}; + +enum RNSkDrawingMode { Default, Continuous }; + +using RNSkTouchInfo = struct { + enum TouchType { Start, Active, End, Cancelled }; + double x; + double y; + double force; + TouchType type; + size_t id; + long timestamp; +}; + +class RNSkView: public std::enable_shared_from_this { +public: + /** + * Constructor + */ + RNSkView(std::shared_ptr context, + std::shared_ptr canvasProvider, + std::shared_ptr renderer): + _platformContext(context), + _canvasProvider(canvasProvider), + _renderer(renderer) {} + + /** + Destructor + */ + virtual ~RNSkView() { + endDrawingLoop(); + } + + /** + Sets custom properties. Custom properties are properties that are set directly from Javascript without having + to go through the async bridge. + */ + virtual void setJsiProperties(std::unordered_map &props) { + throw std::runtime_error("The base Skia View does not support any custom properties."); + }; + + /** + Calls a custom action. + */ + virtual jsi::Value callJsiMethod(jsi::Runtime& runtime, + const std::string& name, + const jsi::Value *arguments, + size_t count) { + throw std::runtime_error("The base Skia View does not support any commands. Command " + name + " not found."); + }; + + /** + * Repaints the Skia view using the underlying context and the drawcallback. + * This method schedules a draw request that will be run on the correct + * thread and js runtime. + */ + void requestRedraw() { + _redrawRequestCounter++; + } + + /** + Sets the native id of the view + */ + virtual void setNativeId(size_t nativeId) { + _nativeId = nativeId; + beginDrawingLoop(); + } + + /** + Returns the native id + */ + size_t getNativeId() { return _nativeId; } + + /** + Sets the drawing mode for the view + */ + void setDrawingMode(RNSkDrawingMode mode) { + _drawingMode = mode; + requestRedraw(); + } + + /** + * Set to true to show the debug overlays on render + */ + void setShowDebugOverlays(bool show) { + _renderer->setShowDebugOverlays(show); + requestRedraw(); + } + + /** + Update touch state with new touch points + */ + virtual void updateTouchState(std::vector&) { + requestRedraw(); + } + + /** + Renders the view into an SkImage instead of the screen. + */ + sk_sp makeImageSnapshot(std::shared_ptr bounds) { + auto provider = std::make_shared(std::bind(&RNSkView::requestRedraw, this), + _canvasProvider->getScaledWidth(), + _canvasProvider->getScaledHeight()); + + _renderer->renderImmediate(provider); + return provider->makeSnapshot(bounds); + } + +protected: + std::shared_ptr getPlatformContext() { return _platformContext; } + std::shared_ptr getCanvasProvider() { return _canvasProvider; } + std::shared_ptr getRenderer() { return _renderer; } + + /** + Ends an ongoing beginDrawCallback loop for this view. This method is made protected if + the drawing loop should be stopped before reaching the destructor (like we do for Android + views) + */ + void endDrawingLoop() { + if(_drawingLoopId != 0) { + _drawingLoopId = 0; + _platformContext->endDrawLoop(_nativeId); + } + } + +private: + /** + Starts beginDrawCallback loop if the drawing mode is continuous + */ + void beginDrawingLoop() { + if (_drawingLoopId != 0 || _nativeId == 0) { + return; + } + // Set to zero to avoid calling beginDrawLoop before we return + _drawingLoopId = _platformContext->beginDrawLoop(_nativeId, + [weakSelf = weak_from_this()](bool invalidated) { + auto self = weakSelf.lock(); + if(self) { + self->drawLoopCallback(invalidated); + } + }); + } + + /** + Draw loop callback + */ + void drawLoopCallback(bool invalidated) { + if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) { + _redrawRequestCounter = 0; + + if(!_renderer->tryRender(_canvasProvider)) { + // The renderer could not render cause it was busy, just schedule redrawing + // on the next frame. + requestRedraw(); + } + } + } + + std::shared_ptr _platformContext; + std::shared_ptr _canvasProvider; + std::shared_ptr _renderer; + + RNSkDrawingMode _drawingMode; + size_t _nativeId; + + size_t _drawingLoopId = 0; + std::atomic _redrawRequestCounter = { 1 }; +}; + +} // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h index 3dec3bf655443..b871b70bb286d 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h @@ -33,20 +33,30 @@ class RNSkComputedValue : public RNSkReadonlyValue !arguments[0].asObject(runtime).isFunction(runtime)) { throw jsi::JSError(runtime, "Expected callback function as first parameter"); } - + if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { throw jsi::JSError(runtime, "Expected array of dependencies as second parameter"); } - + // Get callback for calculating result _callback = std::make_shared(arguments[0].asObject(runtime).asFunction(runtime)); } - + + void invalidate() override { + RNSkReadonlyValue::invalidate(); + + // Unregister listeners + for(const auto &unsubscribe: _unsubscribers) { + unsubscribe(); + } + _unsubscribers.clear(); + } + void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) { // Save dependencies std::vector> dependencies; - + // Ensure that all dependencies are Values auto deps = arguments[1].asObject(runtime).asArray(runtime); const std::size_t size = deps.size(runtime); @@ -63,7 +73,7 @@ class RNSkComputedValue : public RNSkReadonlyValue } dependencies.push_back(value); } - + // register change handler on dependencies _unsubscribers.reserve(_unsubscribers.size() + size); for(const auto &dep: dependencies) { @@ -75,18 +85,11 @@ class RNSkComputedValue : public RNSkReadonlyValue } })); } - + // Set initial value dependencyUpdated(runtime); } - - virtual ~RNSkComputedValue() { - // Unregister listeners - for(const auto &unsubscribe: _unsubscribers) { - unsubscribe(); - } - } - + private: void dependencyUpdated(jsi::Runtime &runtime) { // Calculate new value diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h index 2211344d7a228..a779bbd1058c4 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h @@ -29,27 +29,29 @@ class RNSkReadonlyValue : public JsiSkHostObject, : JsiSkHostObject(platformContext), _valueHolder(std::make_unique(*platformContext->getJsRuntime())) { } - - virtual ~RNSkReadonlyValue() { } + + virtual ~RNSkReadonlyValue() { + invalidate(); + } JSI_PROPERTY_GET(__typename__) { return jsi::String::createFromUtf8(runtime, "RNSkValue"); } - + JSI_PROPERTY_GET(current) { return getCurrent(runtime); } - + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__), JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current)) - + JSI_HOST_FUNCTION(addListener) { if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) { throw jsi::JSError(runtime, "Expected function as first parameter."); return jsi::Value::undefined(); } auto callback = std::make_shared(arguments[0].asObject(runtime).asFunction(runtime)); - + auto unsubscribe = addListener([weakSelf = weak_from_this(), callback = std::move(callback)](jsi::Runtime& runtime){ auto self = weakSelf.lock(); @@ -58,7 +60,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, callback->call(runtime, selfReadonlyValue->get_current(runtime)); } }); - + return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "unsubscribe"), 0, @@ -67,9 +69,17 @@ class RNSkReadonlyValue : public JsiSkHostObject, return jsi::Value::undefined(); }); } - - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener)) - + + + + JSI_HOST_FUNCTION(__invalidate) { + invalidate(); + return jsi::Value::undefined(); + } + + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener), + JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate)) + /** * Adds a callback that will be called whenever the value changes * @param cb Callback @@ -86,7 +96,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, } }; } - + /** Updates the underlying value and notifies all listeners about the change. Listeners are only notified if the value was actually changed for numeric, boolean and string @@ -101,13 +111,22 @@ class RNSkReadonlyValue : public JsiSkHostObject, notifyListeners(runtime); } } - + + /** + Override to implement invalidation logic for the value. In the base class this function + clears all subscribers. + */ + virtual void invalidate() { + std::lock_guard lock(_mutex); + _listeners.clear(); + } + jsi::Value getCurrent(jsi::Runtime &runtime) { return _valueHolder->getCurrent(runtime); } - + protected: - + /** Notifies listeners about changes @param runtime Current JS Runtime @@ -122,7 +141,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, listener.second(runtime); } } - + /** Removes a subscription listeners @param listenerId identifier of listener to remove @@ -134,7 +153,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, private: std::unique_ptr _valueHolder; - + long _listenerId = 0; std::unordered_map> _listeners; std::mutex _mutex; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h index b168c33f6e7b3..141632a5ecc80 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h @@ -26,22 +26,22 @@ class RNSkValue : public RNSkReadonlyValue update(runtime, arguments[0]); } } - + ~RNSkValue() { unsubscribe(); } - + JSI_PROPERTY_SET(current) { // When someone else is setting the value we need to stop any ongoing // animations unsubscribe(); update(runtime, value); } - + JSI_PROPERTY_SET(animation) { // Cancel existing animation unsubscribe(); - + // Verify input if(value.isObject() && value.asObject(runtime).isHostObject(runtime)) { auto animation = value.asObject(runtime).getHostObject(runtime); @@ -55,23 +55,24 @@ class RNSkValue : public RNSkReadonlyValue throw jsi::JSError(runtime, "Animation expected."); } } - + JSI_PROPERTY_GET(animation) { if(_animation != nullptr) { return jsi::Object::createFromHostObject(runtime, _animation); } return jsi::Value::undefined(); } - + JSI_EXPORT_PROPERTY_SETTERS(JSI_EXPORT_PROP_SET(RNSkValue, current), JSI_EXPORT_PROP_SET(RNSkValue, animation)) - + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__), JSI_EXPORT_PROP_GET(RNSkValue, current), JSI_EXPORT_PROP_GET(RNSkValue, animation)) - + JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(RNSkValue, addListener), + JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate) ) private: @@ -90,26 +91,26 @@ class RNSkValue : public RNSkReadonlyValue _animation->startClock(); } } - + void animationDidUpdate(jsi::Runtime& runtime) { if(_animation != nullptr) { // Update ourselves from the current animation value update(runtime, _animation->get_current(runtime)); } } - + void unsubscribe() { if(_unsubscribe != nullptr) { (*_unsubscribe)(); _unsubscribe = nullptr; } - + if(_animation != nullptr) { _animation->stopClock(); _animation = nullptr; } } - + std::shared_ptr _animation; std::shared_ptr> _unsubscribe; }; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/skcms/LICENSE b/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/skcms/LICENSE deleted file mode 100644 index 6c7c5be360194..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/skcms/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2018 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/vulkan/LICENSE b/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/vulkan/LICENSE deleted file mode 100644 index 6c7c5be360194..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/include/third_party/vulkan/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2018 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/readme.txt b/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/readme.txt deleted file mode 100644 index 6d4442e021a62..0000000000000 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/skia/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Placeholder for the Skia include files. \ No newline at end of file diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h index 92485ec75f5af..8bd1ee0daacec 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h @@ -54,19 +54,19 @@ class RNSkLogger { #endif va_end(args); } - + static void logToJavascriptConsole(jsi::Runtime& runtime, const std::string& message) { auto console = RNSkLogger::getJavascriptConsole(runtime).asObject(runtime); auto log = console.getPropertyAsFunction(runtime, "log"); log.call(runtime, jsi::String::createFromUtf8(runtime, message)); } - + static void warnToJavascriptConsole(jsi::Runtime& runtime, const std::string& message) { auto console = RNSkLogger::getJavascriptConsole(runtime).asObject(runtime); auto warn = console.getPropertyAsFunction(runtime, "warn"); warn.call(runtime, jsi::String::createFromUtf8(runtime, message)); } - + private: static jsi::Value getJavascriptConsole(jsi::Runtime& runtime) { auto console = runtime.global().getProperty(runtime, "console"); diff --git a/apps/native-component-list/package.json b/apps/native-component-list/package.json index 1f1025717ca44..1f49723b5196c 100644 --- a/apps/native-component-list/package.json +++ b/apps/native-component-list/package.json @@ -54,7 +54,7 @@ "@react-navigation/native": "~5.9.8", "@react-navigation/stack": "~5.12.6", "@shopify/flash-list": "1.3.0", - "@shopify/react-native-skia": "0.1.137", + "@shopify/react-native-skia": "0.1.153", "@use-expo/permissions": "^2.0.0", "date-format": "^2.0.0", "deep-object-diff": "^1.1.0", diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h index 8ba7f4513722f..a50c37b875bd0 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkApi.h @@ -33,7 +33,6 @@ #include "JsiSkVertices.h" #include "JsiSkTypefaceFactory.h" #include "JsiSkDataFactory.h" -#include "JsiSkFontMgrFactory.h" #include "JsiSkSurfaceFactory.h" #include "JsiSkTextBlobFactory.h" #include "JsiSkContourMeasureIter.h" @@ -72,9 +71,6 @@ namespace RNSkia installFunction("PictureRecorder", JsiSkPictureRecorder::createCtor(context)); installFunction("Color", JsiSkColor::createCtor()); - // Static members - installReadonlyProperty("FontMgr", - std::make_shared(context)); installReadonlyProperty("SVG", std::make_shared(context)); installReadonlyProperty("Image", diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h index 4d2d01fd712a2..4b5673f520e48 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkContourMeasure.h @@ -99,4 +99,4 @@ namespace RNSkia ->getObject(); } }; -} // namespace RNSkia \ No newline at end of file +} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h index dc07e4674dcf7..8dc298c8f686a 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkDataFactory.h @@ -75,7 +75,7 @@ namespace RNSkia { throw jsi::JSError(runtime, "Error decoding base64 string"); return jsi::Value::undefined(); } - + return jsi::Object::createFromHostObject(runtime, std::make_shared( getContext(), std::move(data))); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h index 15c9f7dad9cdd..094dbb636fbdb 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFont.h @@ -38,24 +38,6 @@ namespace RNSkia return jsi::String::createFromUtf8(runtime, "Font"); } - JSI_HOST_FUNCTION(measureText) - { - RNSkLogger::warnToJavascriptConsole(runtime, "measureText() is deprecated. Clients should use 'Font.getGlyphWidths' instead (the latter does no shaping)"); - auto textVal = arguments[0].asString(runtime).utf8(runtime); - auto text = textVal.c_str(); - SkRect rect; - std::shared_ptr paint = nullptr; - // Check if a paint argument was provided - if (count == 2) - { - paint = JsiSkPaint::fromValue(runtime, arguments[1]); - } - getObject()->measureText(text, strlen(text), SkTextEncoding::kUTF8, &rect, - paint.get()); - rect.setXYWH(0, 0, rect.width(), rect.height()); - return JsiSkRect::toValue(runtime, getContext(), std::move(rect)); - } - JSI_HOST_FUNCTION(getGlyphWidths) { auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); @@ -89,7 +71,7 @@ namespace RNSkia JSI_HOST_FUNCTION(getTextWidth) { auto str = arguments[0].asString(runtime).utf8(runtime); - auto numGlyphIDs = str.length(); + auto numGlyphIDs = getObject()->countText(str.c_str(), str.length(), SkTextEncoding::kUTF8); std::vector glyphs; glyphs.resize(numGlyphIDs); int glyphsSize = static_cast(numGlyphIDs); @@ -129,9 +111,9 @@ namespace RNSkia JSI_HOST_FUNCTION(getGlyphIDs) { auto str = arguments[0].asString(runtime).utf8(runtime); - auto numGlyphIDs = count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() - ? arguments[1].asNumber() - : str.length(); + int numGlyphIDs = count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() + ? static_cast(arguments[1].asNumber()) + : getObject()->countText(str.c_str(), str.length(), SkTextEncoding::kUTF8); std::vector glyphIDs; glyphIDs.resize(numGlyphIDs); getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8, @@ -279,7 +261,6 @@ namespace RNSkia JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(JsiSkFont, getSize), - JSI_EXPORT_FUNC(JsiSkFont, measureText), JSI_EXPORT_FUNC(JsiSkFont, getMetrics), JSI_EXPORT_FUNC(JsiSkFont, getGlyphIDs), JSI_EXPORT_FUNC(JsiSkFont, getGlyphIntercepts), diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h deleted file mode 100644 index 02687da5fdf72..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgr.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "JsiSkHostObjects.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include -#include - -#pragma clang diagnostic pop - - -namespace RNSkia { - - using namespace facebook; - - class JsiSkFontMgr : public JsiSkWrappingSkPtrHostObject { - public: - - // TODO: declare in JsiSkWrappingSkPtrHostObject via extra template parameter? - JSI_PROPERTY_GET(__typename__) { - return jsi::String::createFromUtf8(runtime, "FontMgr"); - } - - JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkFontMgr, __typename__)) - - JsiSkFontMgr(std::shared_ptr context, - sk_sp fontMgr) - : JsiSkWrappingSkPtrHostObject(std::move(context), std::move(fontMgr)) {} - - JSI_HOST_FUNCTION(countFamilies) { - auto families = getObject()->countFamilies(); - return jsi::Value(families); - } - - JSI_HOST_FUNCTION(getFamilyName) { - auto i = arguments[0].asNumber(); - SkString familyName; - getObject()->getFamilyName(i, &familyName); - return jsi::String::createFromUtf8(runtime, familyName.c_str()); - } - - JSI_HOST_FUNCTION(matchFamilyStyle) { - auto familyName = arguments[0].asString(runtime).utf8(runtime); - auto fontStyle = SkFontStyle::Normal(); - if (count >= 2) { - auto object = arguments[1].asObject(runtime); - int weight = object.getProperty(runtime, "weight").asNumber(); - int width = object.getProperty(runtime, "width").asNumber(); - SkFontStyle::Slant slant = (SkFontStyle::Slant)object.getProperty(runtime, "slant").asNumber(); - fontStyle = SkFontStyle(width, weight, slant); - } - auto typeface = getObject()->matchFamilyStyle(familyName.c_str(), std::move(fontStyle)); - if (typeface == nullptr) { - return jsi::Value::null(); - } - return jsi::Object::createFromHostObject( - runtime, std::make_shared(getContext(), sk_sp(std::move(typeface))));; - } - - JSI_EXPORT_FUNCTIONS( - JSI_EXPORT_FUNC(JsiSkFontMgr, countFamilies), - JSI_EXPORT_FUNC(JsiSkFontMgr, getFamilyName), - JSI_EXPORT_FUNC(JsiSkFontMgr, matchFamilyStyle) - ) - - /** - Returns the underlying object from a host object of this type - */ - static sk_sp fromValue(jsi::Runtime &runtime, - const jsi::Value &obj) { - return obj.asObject(runtime) - .asHostObject(runtime) - ->getObject(); - } - }; -} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h deleted file mode 100644 index 165c5e77e4c52..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkFontMgrFactory.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "JsiSkHostObjects.h" -#include "JsiSkFontMgr.h" -#include "JsiSkData.h" -#include - - -namespace RNSkia { - - using namespace facebook; - - class JsiSkFontMgrFactory : public JsiSkHostObject { - public: -// JSI_HOST_FUNCTION(FromData) { -// std::vector> data; -// for (int i = 0; i < count; i++) { -// auto d = JsiSkData::fromValue( -// runtime, arguments[i]); -// data.push_back(d); -// } -// -// auto fontMgr = SkFontMgr_New_Custom_Data(data.data(), data.size()); -// return jsi::Object::createFromHostObject( -// runtime, std::make_shared(getContext(), fontMgr)); -// } - - JSI_HOST_FUNCTION(RefDefault) { - auto fontMgr = SkFontMgr::RefDefault(); - return jsi::Object::createFromHostObject( - runtime, std::make_shared(getContext(), std::move(fontMgr))); - } - - JSI_EXPORT_FUNCTIONS( - //JSI_EXPORT_FUNC(JsiSkFontMgrFactory, FromData), - JSI_EXPORT_FUNC(JsiSkFontMgrFactory, RefDefault) - ) - - JsiSkFontMgrFactory(std::shared_ptr context) - : JsiSkHostObject(std::move(context)) {} - }; - -} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h index d19671f0d8928..d17093bbfcac6 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkMatrix.h @@ -46,6 +46,10 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { ); } + JSI_PROPERTY_GET(__typename__) { + return jsi::String::createFromUtf8(runtime, "Matrix"); + } + JSI_HOST_FUNCTION(concat) { auto m3 = JsiSkMatrix::fromValue(runtime, arguments[0]); getObject()->preConcat(*m3); @@ -78,6 +82,21 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { getObject()->preRotate(SkRadiansToDegrees(a)); return jsi::Value::undefined(); } + + JSI_HOST_FUNCTION(identity) { + getObject()->setIdentity(); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(get) { + auto values = jsi::Array(runtime, 9); + for (auto i = 0; i < 9; i++) { + values.setValueAtIndex(runtime, i, getObject()->get(i)); + } + return values; + } + + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkMatrix, __typename__)) JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(JsiSkMatrix, concat), @@ -85,6 +104,8 @@ class JsiSkMatrix : public JsiSkWrappingSharedPtrHostObject { JSI_EXPORT_FUNC(JsiSkMatrix, scale), JSI_EXPORT_FUNC(JsiSkMatrix, skew), JSI_EXPORT_FUNC(JsiSkMatrix, rotate), + JSI_EXPORT_FUNC(JsiSkMatrix, identity), + JSI_EXPORT_FUNC(JsiSkMatrix, get), ) /** diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h index 8ce147a68444b..8c4efe7f9ee2c 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPaint.h @@ -39,6 +39,11 @@ class JsiSkPaint : public JsiSkWrappingSharedPtrHostObject { runtime, std::make_shared(getContext(), SkPaint(*paint))); } + JSI_HOST_FUNCTION(reset) { + getObject()->reset(); + return jsi::Value::undefined(); + } + JSI_HOST_FUNCTION(getColor) { return JsiSkColor::toValue(runtime, getObject()->getColor()); } @@ -144,6 +149,7 @@ class JsiSkPaint : public JsiSkWrappingSharedPtrHostObject { } JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkPaint, copy), + JSI_EXPORT_FUNC(JsiSkPaint, reset), JSI_EXPORT_FUNC(JsiSkPaint, getColor), JSI_EXPORT_FUNC(JsiSkPaint, getStrokeCap), JSI_EXPORT_FUNC(JsiSkPaint, getStrokeJoin), diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h index 92b02f5d651b0..0fe830b4205c6 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPath.h @@ -348,7 +348,7 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rlineTo) { + JSI_HOST_FUNCTION(rLineTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); getObject()->rLineTo(x, y); @@ -536,7 +536,7 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { JSI_EXPORT_FUNC(JsiSkPath, moveTo), JSI_EXPORT_FUNC(JsiSkPath, rMoveTo), JSI_EXPORT_FUNC(JsiSkPath, lineTo), - JSI_EXPORT_FUNC(JsiSkPath, rlineTo), + JSI_EXPORT_FUNC(JsiSkPath, rLineTo), JSI_EXPORT_FUNC(JsiSkPath, cubicTo), JSI_EXPORT_FUNC(JsiSkPath, rCubicTo), JSI_EXPORT_FUNC(JsiSkPath, reset), diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h index 0591280ce2937..50510f114ff39 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPathFactory.h @@ -165,7 +165,7 @@ class JsiSkPathFactory : public JsiSkHostObject { JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromCmds), JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromText)) - JsiSkPathFactory(std::shared_ptr context) + JsiSkPathFactory(std::shared_ptr context) : JsiSkHostObject(std::move(context)) {} }; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h index b16d7f84034a5..ec94ab986fa2a 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkPicture.h @@ -21,7 +21,13 @@ class JsiSkPicture : public JsiSkWrappingSkPtrHostObject { JsiSkPicture(std::shared_ptr context, const sk_sp picture) : JsiSkWrappingSkPtrHostObject(context, picture) {}; - + + JSI_PROPERTY_GET(__typename__) { + return jsi::String::createFromUtf8(runtime, "Picture"); + } + + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkPicture, __typename__)) + JSI_HOST_FUNCTION(makeShader) { auto tmx = (SkTileMode)arguments[0].asNumber(); auto tmy = (SkTileMode)arguments[1].asNumber(); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h index 7a22d4c3509ee..e4a638adfe963 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkRuntimeEffect.h @@ -35,7 +35,7 @@ namespace RNSkia : public JsiSkWrappingSkPtrHostObject { public: - + static sk_sp fromValue(jsi::Runtime &runtime, const jsi::Value &obj) { const auto& object = obj.asObject(runtime); return object.asHostObject(runtime)->getObject(); @@ -44,7 +44,7 @@ namespace RNSkia JSI_HOST_FUNCTION(makeShader) { auto uniforms = castUniforms(runtime, arguments[0]); - + auto matrix = count >= 2 && !arguments[1].isUndefined() && !arguments[1].isNull() ? JsiSkMatrix::fromValue(runtime, arguments[1]).get() : nullptr; // Create and return shader as host object @@ -57,7 +57,7 @@ namespace RNSkia JSI_HOST_FUNCTION(makeShaderWithChildren) { auto uniforms = castUniforms(runtime, arguments[0]); - + // Children std::vector> children; auto jsiChildren = arguments[1].asObject(runtime).asArray(runtime); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h index 685ac0969477e..edfcf63c4e6bd 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/api/JsiSkTypeface.h @@ -22,24 +22,12 @@ using namespace facebook; class JsiSkTypeface : public JsiSkWrappingSkPtrHostObject { public: - JSI_PROPERTY_GET(bold) { - RNSkLogger::warnToJavascriptConsole(runtime, "Typeface.bold is deprecated and will be removed in a future release."); - return jsi::Value(getObject()->isBold()); - } - - JSI_PROPERTY_GET(italic) { - RNSkLogger::warnToJavascriptConsole(runtime, "Typeface.italic is deprecated and will be removed in a future release."); - return jsi::Value(getObject()->isItalic()); - } - // TODO: declare in JsiSkWrappingSkPtrHostObject via extra template parameter? JSI_PROPERTY_GET(__typename__) { return jsi::String::createFromUtf8(runtime, "Typeface"); } - JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkTypeface, bold), - JSI_EXPORT_PROP_GET(JsiSkTypeface, italic), - JSI_EXPORT_PROP_GET(JsiSkTypeface, __typename__)) + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkTypeface, __typename__)) JsiSkTypeface(std::shared_ptr context, sk_sp typeface) @@ -64,22 +52,6 @@ class JsiSkTypeface : public JsiSkWrappingSkPtrHostObject { return jsi::Object::createFromHostObject( runtime, std::make_shared(std::move(context), std::move(tf))); } - -private: - static SkFontStyle getFontStyleFromNumber(int fontStyle) { - switch (fontStyle) { - case 0: - return SkFontStyle::Normal(); - case 1: - return SkFontStyle::Bold(); - case 2: - return SkFontStyle::Italic(); - case 3: - return SkFontStyle::BoldItalic(); - default: - return SkFontStyle::Normal(); - }; - } }; } // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h index 2d39a2d05718e..1d1c9220b1eda 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiSimpleValueWrapper.h @@ -7,26 +7,26 @@ namespace RNJsi { using namespace facebook; -enum JsiWrapperValueType +/** + Implements a simple wrapper class for JSI primitives like numbers and boolean values. Objects, + strings and arrays are stored as values inside a property holder. The class also provides a method + for comparing values that will compare numbers, booleans and strings. + */ +class JsiSimpleValueWrapper { +private: + enum ValueType { NonInitialized, Undefined, Null, Bool, Number, JsiValue -}; + }; -/** - Implements a simple wrapper class for JSI primitives like numbers and boolean values. Objects, - strings and arrays are stored as values inside a property holder. The class also provides a method - for comparing values that will compare numbers, booleans and strings. - */ -class JsiSimpleValueWrapper -{ public: JsiSimpleValueWrapper(jsi::Runtime& runtime) : - _type(JsiWrapperValueType::NonInitialized), + _type(ValueType::NonInitialized), _propNameId(jsi::PropNameID::forUtf8(runtime, "value")) {} @@ -34,17 +34,17 @@ class JsiSimpleValueWrapper { switch (_type) { - case JsiWrapperValueType::NonInitialized: + case ValueType::NonInitialized: return nullptr; - case JsiWrapperValueType::Undefined: + case ValueType::Undefined: return jsi::Value::undefined(); - case JsiWrapperValueType::Null: + case ValueType::Null: return jsi::Value::null(); - case JsiWrapperValueType::Bool: + case ValueType::Bool: return _boolValue; - case JsiWrapperValueType::Number: + case ValueType::Number: return _numberValue; - case JsiWrapperValueType::JsiValue: + case ValueType::JsiValue: if (_valueHolder == nullptr) { return jsi::Value::undefined(); } @@ -55,17 +55,17 @@ class JsiSimpleValueWrapper void setCurrent(jsi::Runtime &runtime, const jsi::Value &value) { if(value.isNumber()) { - _type = JsiWrapperValueType::Number; + _type = ValueType::Number; _numberValue = value.asNumber(); } else if(value.isBool()) { - _type = JsiWrapperValueType::Bool; + _type = ValueType::Bool; _boolValue = value.getBool(); } else if(value.isUndefined()) { - _type = JsiWrapperValueType::Undefined; + _type = ValueType::Undefined; } else if(value.isNull()) { - _type = JsiWrapperValueType::Null; + _type = ValueType::Null; } else { - _type = JsiWrapperValueType::JsiValue; + _type = ValueType::JsiValue; // Save as javascript object - we don't want to have to copy strings, objects and values if(_valueHolder == nullptr) { _valueHolder = std::make_shared(runtime); @@ -75,17 +75,17 @@ class JsiSimpleValueWrapper } bool equals(jsi::Runtime& runtime, const jsi::Value &value) { - if (_type == JsiWrapperValueType::NonInitialized) { + if (_type == ValueType::NonInitialized) { return false; } - if(value.isNumber() && _type == JsiWrapperValueType::Number) { + if(value.isNumber() && _type == ValueType::Number) { return _numberValue == value.asNumber(); - } else if(value.isBool() && _type == JsiWrapperValueType::Bool) { + } else if(value.isBool() && _type == ValueType::Bool) { return _boolValue == value.getBool(); } else if(value.isUndefined()) { - return _type == JsiWrapperValueType::Undefined; + return _type == ValueType::Undefined; } else if(value.isNull()) { - return _type == JsiWrapperValueType::Null; + return _type == ValueType::Null; } else if(value.isString()) { auto current = getCurrent(runtime); if (current.isString()) { @@ -103,6 +103,6 @@ class JsiSimpleValueWrapper bool _boolValue; double _numberValue; - JsiWrapperValueType _type; + ValueType _type; }; } diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h new file mode 100644 index 0000000000000..18ec2d376d9ae --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/jsi/JsiValueWrapper.h @@ -0,0 +1,138 @@ + +#pragma once + +#include + +namespace RNJsi +{ +using namespace facebook; + +enum JsiWrapperValueType +{ + NonInitialized, + Undefined, + Null, + Bool, + Number, + String, + Object, + Function, + Array, + HostObject, + Unknown +}; + +/** + Implements a simple wrapper class for JSI values where the value can be read without asking the runtime for any assistance + Meaning that we can access members without being on the JS thread. + */ +class JsiValueWrapper +{ +public: + JsiValueWrapper(jsi::Runtime& runtime) : + _type(JsiWrapperValueType::NonInitialized) + {} + + JsiValueWrapper(jsi::Runtime& runtime, const jsi::Value &value) : + _type(JsiWrapperValueType::NonInitialized) + { + setCurrent(runtime, value); + } + + void setCurrent(jsi::Runtime &runtime, const jsi::Value &value) + { + if (value.isNumber()) { + _type = JsiWrapperValueType::Number; + _numberValue = value.asNumber(); + } else if (value.isBool()) { + _type = JsiWrapperValueType::Bool; + _boolValue = value.getBool(); + } else if (value.isString()) { + _type = JsiWrapperValueType::String; + _stringValue = value.asString(runtime).utf8(runtime); + } else if (value.isUndefined()) { + _type = JsiWrapperValueType::Undefined; + } else if (value.isNull()) { + _type = JsiWrapperValueType::Null; + } else if (value.isObject()) { + _type = JsiWrapperValueType::Object; + _objectValue = std::make_shared(value.asObject(runtime)); + if (_objectValue->isFunction(runtime)) { + _type = JsiWrapperValueType::Function; + _functionValue = std::make_shared(_objectValue->asFunction(runtime)); + _objectValue = nullptr; + } else if (_objectValue->isArray(runtime)) { + _type = JsiWrapperValueType::Array; + _arrayValue = std::make_shared(_objectValue->asArray(runtime)); + _objectValue = nullptr; + } else if (_objectValue->isHostObject(runtime)) { + _type = JsiWrapperValueType::HostObject; + _hostObjectValue = _objectValue->asHostObject(runtime); + _objectValue = nullptr; + } + } else { + throw std::runtime_error("Could not store jsi::Value of provided type"); + } + // Save in value holder as well so that we can return current + if(_valueHolder == nullptr) { + _valueHolder = std::make_shared(runtime); + } + _valueHolder->setProperty(runtime, "current", value); + } + + bool isUndefinedOrNull() { + return _type == JsiWrapperValueType::Undefined || + _type == JsiWrapperValueType::Null; + } + + bool getAsBool() { + assert(_type == JsiWrapperValueType::Bool); + return _boolValue; + } + + double getAsNumber() { + assert(_type == JsiWrapperValueType::Number); + return _numberValue; + } + + const std::string& getAsString() { + assert(_type == JsiWrapperValueType::String); + return _stringValue; + } + + std::shared_ptr getAsFunction() { + assert(_type == JsiWrapperValueType::Function); + return _functionValue; + } + + std::shared_ptr getAsArray() { + assert(_type == JsiWrapperValueType::Array); + return _arrayValue; + } + + std::shared_ptr getAsObject() { + assert(_type == JsiWrapperValueType::Object); + return _objectValue; + } + + std::shared_ptr getAsHostObject() { + assert(_type == JsiWrapperValueType::HostObject); + return _hostObjectValue; + } + + JsiWrapperValueType getType() { return _type; } + +private: + std::shared_ptr _valueHolder; + + bool _boolValue; + double _numberValue; + std::string _stringValue; + std::shared_ptr _objectValue; + std::shared_ptr _functionValue; + std::shared_ptr _arrayValue; + std::shared_ptr _hostObjectValue; + + JsiWrapperValueType _type; +}; +} diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp deleted file mode 100644 index 4c29fa8b814f2..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.cpp +++ /dev/null @@ -1,291 +0,0 @@ -// -// Created by Christian Falch on 23/08/2021. -// - -#include "RNSkDrawView.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma clang diagnostic pop - -namespace RNSkia { - -using namespace std::chrono; - -RNSkDrawView::RNSkDrawView(std::shared_ptr context) - : _jsiCanvas(std::make_shared(context)), - _platformContext(std::move(context)), - _infoObject(std::make_shared()), - _jsDrawingLock(std::make_shared()), - _gpuDrawingLock(std::make_shared()), - _jsTimingInfo("SKIA/JS"), - _gpuTimingInfo("SKIA/GPU") - {} - -RNSkDrawView::~RNSkDrawView() { - endDrawingLoop(); -} - -void RNSkDrawView::setNativeId(size_t nativeId) { - _nativeId = nativeId; - beginDrawingLoop(); -} - -void RNSkDrawView::setDrawCallback(std::shared_ptr callback) { - - if (callback == nullptr) { - _drawCallback = nullptr; - // We can just reset everything - this is a signal that we're done. - endDrawingLoop(); - return; - } - - // Reset timing info - _jsTimingInfo.reset(); - _gpuTimingInfo.reset(); - - // Create draw drawCallback wrapper - _drawCallback = std::make_shared( - [weakSelf = weak_from_this(), - callback = std::move(callback)](std::shared_ptr canvas, - int width, - int height, - double timestamp, - std::shared_ptr context) { - - auto self = weakSelf.lock(); - if(self) { - auto runtime = context->getJsRuntime(); - - // Update info parameter - self->_infoObject->beginDrawOperation(width, height, timestamp); - - // Set up arguments array - std::vector args(2); - args[0] = jsi::Object::createFromHostObject(*runtime, canvas); - args[1] = jsi::Object::createFromHostObject(*runtime, self->_infoObject); - - // To be able to call the drawing function we'll wrap it once again - callback->call(*runtime, - static_cast(args.data()), - (size_t)2); - - // Reset touches - self->_infoObject->endDrawOperation(); - - // Draw debug overlays - if (self->_showDebugOverlay) { - - // Display average rendering timer - auto jsAvg = self->_jsTimingInfo.getAverage(); - //auto jsFps = _jsTimingInfo.getFps(); - - auto gpuAvg = self->_gpuTimingInfo.getAverage(); - //auto gpuFps = _gpuTimingInfo.getFps(); - - auto total = jsAvg + gpuAvg; - - // Build string - std::ostringstream stream; - stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms"; - - std::string debugString = stream.str(); - - // Set up debug font/paints - auto font = SkFont(); - font.setSize(14); - auto paint = SkPaint(); - paint.setColor(SkColors::kRed); - canvas->getCanvas()->drawSimpleText( - debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8, - 18, font, paint); - } - } - }); - - // Request redraw - requestRedraw(); -} - -void RNSkDrawView::drawInCanvas(std::shared_ptr canvas, - int width, - int height, - double time) { - - // Call the draw drawCallback and perform js based drawing - auto skCanvas = canvas->getCanvas(); - if (_drawCallback != nullptr && skCanvas != nullptr) { - // Make sure to scale correctly - auto pd = _platformContext->getPixelDensity(); - skCanvas->save(); - skCanvas->scale(pd, pd); - - // Call draw function. - (*_drawCallback)(canvas, width / pd, height / pd, time, _platformContext); - - // Restore and flush canvas - skCanvas->restore(); - skCanvas->flush(); - } -} - -sk_sp RNSkDrawView::makeImageSnapshot(std::shared_ptr bounds) { - // Assert width/height - auto surface = SkSurface::MakeRasterN32Premul(getScaledWidth(), getScaledHeight()); - auto canvas = surface->getCanvas(); - auto jsiCanvas = std::make_shared(_platformContext); - jsiCanvas->setCanvas(canvas); - - milliseconds ms = duration_cast( - system_clock::now().time_since_epoch()); - - drawInCanvas(jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000); - - if(bounds != nullptr) { - SkIRect b = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(), bounds->height()); - return surface->makeImageSnapshot(b); - } else { - return surface->makeImageSnapshot(); - } -} - -void RNSkDrawView::updateTouchState(std::vector&& points) { - _infoObject->updateTouches(std::move(points)); - requestRedraw(); -} - -void RNSkDrawView::performDraw() { - // Start timing - _jsTimingInfo.beginTiming(); - - // Record the drawing operations on the JS thread so that we can - // move the actual drawing onto the render thread later - SkPictureRecorder recorder; - SkRTreeFactory factory; - SkCanvas* canvas = recorder.beginRecording(getScaledWidth(), getScaledHeight(), &factory); - _jsiCanvas->setCanvas(canvas); - - // Get current milliseconds - milliseconds ms = duration_cast( - system_clock::now().time_since_epoch()); - - try { - // Perform the javascript drawing - drawInCanvas(_jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000.0); - } catch(...) { - _jsTimingInfo.stopTiming(); - _jsDrawingLock->unlock(); - throw; - } - - // Finish drawing operations - auto p = recorder.finishRecordingAsPicture(); - - // Calculate duration - _jsTimingInfo.stopTiming(); - - if(_gpuDrawingLock->try_lock()) { - - // Post drawing message to the render thread where the picture recorded - // will be sent to the GPU/backend for rendering to screen. - auto gpuLock = _gpuDrawingLock; - _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock]() { - auto self = weakSelf.lock(); - if (self) { - // Draw the picture recorded on the real GPU canvas - self->_gpuTimingInfo.beginTiming(); - self->drawPicture(p); - self->_gpuTimingInfo.stopTiming(); - } - // Unlock GPU drawing - gpuLock->unlock(); - }); - } else { -#ifdef DEBUG - _gpuTimingInfo.markSkipped(); -#endif - // Request a new redraw since the last frame was skipped. - requestRedraw(); - } - - // Unlock JS drawing - _jsDrawingLock->unlock(); -} - -void RNSkDrawView::requestRedraw() { - _redrawRequestCounter++; -} - -void RNSkDrawView::beginDrawingLoop() { - if (_drawingLoopId != 0 || _nativeId == 0) { - return; - } - // Set to zero to avoid calling beginDrawLoop before we return - _drawingLoopId = _platformContext->beginDrawLoop(_nativeId, - [weakSelf = weak_from_this()](bool invalidated) { - auto self = weakSelf.lock(); - if(self) { - self->drawLoopCallback(invalidated); - } - }); -} - -void RNSkDrawView::drawLoopCallback(bool invalidated) { - if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) { - _redrawRequestCounter = 0; - - // We render on the javascript thread. - if(_jsDrawingLock->try_lock()) { - _platformContext->runOnJavascriptThread([weakSelf = weak_from_this()](){ - auto self = weakSelf.lock(); - if(self) { - self->performDraw(); - } - }); - } else { -#ifdef DEBUG - _jsTimingInfo.markSkipped(); -#endif - requestRedraw(); - } - } -} - -void RNSkDrawView::endDrawingLoop() { - if(_drawingLoopId != 0) { - _drawingLoopId = 0; - _platformContext->endDrawLoop(_nativeId); - } -} - -void RNSkDrawView::setDrawingMode(RNSkDrawingMode mode) { - if(mode == _drawingMode || _nativeId == 0) { - return; - } - _drawingMode = mode; -} - -} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h deleted file mode 100644 index 01cf33903e064..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDrawView.h +++ /dev/null @@ -1,212 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include - -#pragma clang diagnostic pop - -class SkPicture; -class SkRect; -class SkImage; - -namespace RNSkia { -class JsiSkCanvas; -using namespace facebook; -using RNSkDrawCallback = - std::function, int, int, double, - std::shared_ptr)>; - -enum RNSkDrawingMode { Default, Continuous }; - -class RNSkDrawView: public std::enable_shared_from_this { -public: - /** - * Constructor - */ - RNSkDrawView(std::shared_ptr context); - - /** - Destructor - */ - virtual ~RNSkDrawView(); - - /** - * Repaints the Skia view using the underlying context and the drawcallback. - * This method schedules a draw request that will be run on the correct - * thread and js runtime. - */ - void requestRedraw(); - - /** - Calls the drawing callback on the javascript thread - */ - void performDraw(); - - /** - * Installs the draw callback for the view - */ - void setDrawCallback(std::shared_ptr callback); - - /** - Sets the native id of the view - */ - void setNativeId(size_t nativeId); - - /** - Returns the native id - */ - size_t getNativeId() { return _nativeId; } - - /** - Sets the drawing mode for the view - */ - void setDrawingMode(RNSkDrawingMode mode); - - /** - * Set to true to show the debug overlays on render - */ - void setShowDebugOverlays(bool show) { _showDebugOverlay = show; } - - /** - Update touch state with new touch points - */ - void updateTouchState(std::vector&& points); - - /** - Draws the view's surface into an image - return an SkImage - */ - sk_sp makeImageSnapshot(std::shared_ptr bounds); - -protected: - /** - Returns the scaled width of the view - */ - virtual float getScaledWidth() = 0; - - /** - Returns the scaled height of the view - */ - virtual float getScaledHeight() = 0; - - /** - Override to render picture to GPU - */ - virtual void drawPicture(const sk_sp picture) = 0; - - /** - * @return The platformcontext - */ - std::shared_ptr getPlatformContext() { - return _platformContext; - } - -private: - /** - Starts beginDrawCallback loop if the drawing mode is continuous - */ - void beginDrawingLoop(); - - /** - Ends an ongoing beginDrawCallback loop for this view - */ - void endDrawingLoop(); - - /** - Draw loop callback - */ - void drawLoopCallback(bool invalidated); - - /** - Draw in canvas - */ - void drawInCanvas(std::shared_ptr canvas, - int width, - int height, - double time); - - /** - * Stores the draw drawCallback - */ - std::shared_ptr _drawCallback; - - /** - * Stores a pointer to the jsi wrapper for the canvas. The reason for - * storing this pointer and not recreate it is that it creates a set of - * functions that we don't want to recreate on each render - */ - std::shared_ptr _jsiCanvas; - - /** - * JS Drawing mutex - */ - std::shared_ptr _jsDrawingLock; - - /** - * SKIA Drawing mutex - */ - std::shared_ptr _gpuDrawingLock; - - /** - * Pointer to the platform context - */ - std::shared_ptr _platformContext; - - /** - Drawing mode - */ - RNSkDrawingMode _drawingMode; - - /** - * Show debug overlays - */ - bool _showDebugOverlay = false; - - /** - * True if the drawing loop has been requested - */ - size_t _drawingLoopId = 0; - - /** - * Info object parameter - */ - std::shared_ptr _infoObject; - - /** - Timing information for javascript drawing - */ - RNSkTimingInfo _jsTimingInfo; - - /** - Timing information for GPU rendering - */ - RNSkTimingInfo _gpuTimingInfo; - - /** - Redraw queue counter - */ - std::atomic _redrawRequestCounter = { 1 }; - - /** - * Native id - */ - size_t _nativeId; - -}; - -} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h index f322b65dc22b2..a87eff12d7615 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkInfoParameter.h @@ -9,6 +9,7 @@ #include #include +#include namespace RNSkia { @@ -16,17 +17,6 @@ using namespace facebook; using namespace RNJsi; using namespace std::chrono; -enum RNSkTouchType { Start, Active, End, Cancelled }; - -using RNSkTouchPoint = struct { - double x; - double y; - double force; - RNSkTouchType type; - size_t id; - long timestamp; -}; - class RNSkInfoObject : public JsiHostObject { public: JSI_PROPERTY_GET(width) { return _width; } @@ -77,7 +67,7 @@ class RNSkInfoObject : public JsiHostObject { void endDrawOperation() { _touchesCache.clear(); } - void updateTouches(std::vector&& touches) { + void updateTouches(std::vector& touches) { std::lock_guard lock(_mutex); // Add timestamp auto ms = std::chrono::duration_cast( @@ -95,8 +85,8 @@ class RNSkInfoObject : public JsiHostObject { int _width; int _height; double _timestamp; - std::vector> _currentTouches; - std::vector> _touchesCache; + std::vector> _currentTouches; + std::vector> _touchesCache; std::mutex _mutex; }; } // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp new file mode 100644 index 0000000000000..47c53dacb322f --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.cpp @@ -0,0 +1,211 @@ +#include "RNSkJsView.h" + +namespace RNSkia +{ + +RNSkJsRenderer::RNSkJsRenderer(std::function requestRedraw, + std::shared_ptr context) : + RNSkRenderer(requestRedraw), + _jsiCanvas(std::make_shared(context)), + _platformContext(std::move(context)), + _infoObject(std::make_shared()), + _jsDrawingLock(std::make_shared()), + _gpuDrawingLock(std::make_shared()), + _jsTimingInfo("SKIA/JS"), + _gpuTimingInfo("SKIA/GPU") { +} + +bool RNSkJsRenderer::tryRender(std::shared_ptr canvasProvider) { + // We render on the javascript thread. + if(_jsDrawingLock->try_lock()) { + _platformContext->runOnJavascriptThread([weakSelf = weak_from_this(), canvasProvider](){ + auto self = weakSelf.lock(); + if(self) { + self->performDraw(canvasProvider); + } + }); + return true; + } else { +#ifdef DEBUG + _jsTimingInfo.markSkipped(); +#endif + return false; + } +}; + +void RNSkJsRenderer::renderImmediate(std::shared_ptr canvasProvider) { + milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); + canvasProvider->renderToCanvas([&](SkCanvas* canvas) { + // Create jsi canvas + auto jsiCanvas = std::make_shared(_platformContext); + jsiCanvas->setCanvas(canvas); + + drawInJsiCanvas(std::move(jsiCanvas), + canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + ms.count() / 1000); + }); +}; + +void RNSkJsRenderer::setDrawCallback(std::shared_ptr drawCallback) { + _drawCallback = drawCallback; +} + +std::shared_ptr RNSkJsRenderer::getInfoObject() { + return _infoObject; +} + +void RNSkJsRenderer::performDraw(std::shared_ptr canvasProvider) { + // Start timing + _jsTimingInfo.beginTiming(); + + // Record the drawing operations on the JS thread so that we can + // move the actual drawing onto the render thread later + SkPictureRecorder recorder; + SkRTreeFactory factory; + SkCanvas* canvas = recorder.beginRecording(canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + &factory); + + _jsiCanvas->setCanvas(canvas); + + // Get current milliseconds + milliseconds ms = duration_cast( + system_clock::now().time_since_epoch()); + + try { + // Perform the javascript drawing + drawInJsiCanvas(_jsiCanvas, + canvasProvider->getScaledWidth(), + canvasProvider->getScaledHeight(), + ms.count() / 1000.0); + + } catch(...) { + _jsTimingInfo.stopTiming(); + _jsDrawingLock->unlock(); + throw; + } + + // Finish drawing operations + auto p = recorder.finishRecordingAsPicture(); + + _jsiCanvas->setCanvas(nullptr); + + // Calculate duration + _jsTimingInfo.stopTiming(); + + if(_gpuDrawingLock->try_lock()) { + + // Post drawing message to the render thread where the picture recorded + // will be sent to the GPU/backend for rendering to screen. + auto gpuLock = _gpuDrawingLock; + _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock, canvasProvider]() { + auto self = weakSelf.lock(); + if (self) { + // Draw the picture recorded on the real GPU canvas + self->_gpuTimingInfo.beginTiming(); + + canvasProvider->renderToCanvas([p = std::move(p)](SkCanvas* canvas) { + canvas->drawPicture(p); + }); + + self->_gpuTimingInfo.stopTiming(); + } + // Unlock GPU drawing + gpuLock->unlock(); + }); + } else { +#ifdef DEBUG + _gpuTimingInfo.markSkipped(); +#endif + // Request a new redraw since the last frame was skipped. + _requestRedraw(); + } + + // Unlock JS drawing + _jsDrawingLock->unlock(); +} + +void RNSkJsRenderer::callJsDrawCallback(std::shared_ptr jsiCanvas, + int width, + int height, + double timestamp) { + + if(_drawCallback == nullptr) { + return; + } + + // Reset timing info + _jsTimingInfo.reset(); + _gpuTimingInfo.reset(); + + auto runtime = _platformContext->getJsRuntime(); + + // Update info parameter + _infoObject->beginDrawOperation(width, height, timestamp); + + // Set up arguments array + std::vector args(2); + args[0] = jsi::Object::createFromHostObject(*runtime, jsiCanvas); + args[1] = jsi::Object::createFromHostObject(*runtime, _infoObject); + + // To be able to call the drawing function we'll wrap it once again + _drawCallback->call(*runtime, + static_cast(args.data()), + (size_t)2); + + // Reset touches + _infoObject->endDrawOperation(); + + // Draw debug overlays + if (getShowDebugOverlays()) { + + // Display average rendering timer + auto jsAvg = _jsTimingInfo.getAverage(); + //auto jsFps = _jsTimingInfo.getFps(); + + auto gpuAvg = _gpuTimingInfo.getAverage(); + //auto gpuFps = _gpuTimingInfo.getFps(); + + auto total = jsAvg + gpuAvg; + + // Build string + std::ostringstream stream; + stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms"; + + std::string debugString = stream.str(); + + // Set up debug font/paints + auto font = SkFont(); + font.setSize(14); + auto paint = SkPaint(); + paint.setColor(SkColors::kRed); + jsiCanvas->getCanvas()->drawSimpleText( + debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8, + 18, font, paint); + } +} + +void RNSkJsRenderer::drawInJsiCanvas(std::shared_ptr jsiCanvas, + int width, + int height, + double time) { + + // Call the draw drawCallback and perform js based drawing + auto skCanvas = jsiCanvas->getCanvas(); + if (_drawCallback != nullptr && skCanvas != nullptr) { + // Make sure to scale correctly + auto pd = _platformContext->getPixelDensity(); + skCanvas->save(); + skCanvas->scale(pd, pd); + + // Call draw function. + callJsDrawCallback(jsiCanvas, width / pd, height / pd, time); + + // Restore and flush canvas + skCanvas->restore(); + skCanvas->flush(); + } +} + +} // Namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h new file mode 100644 index 0000000000000..93000483ee381 --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsView.h @@ -0,0 +1,115 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include +#include + +#pragma clang diagnostic pop + +class SkPicture; +class SkRect; +class SkImage; + +namespace RNSkia { +class JsiSkCanvas; +using namespace facebook; + +class RNSkJsRenderer: + public RNSkRenderer, + public std::enable_shared_from_this { +public: + RNSkJsRenderer(std::function requestRedraw, + std::shared_ptr context); + + bool tryRender(std::shared_ptr canvasProvider) override; + + void renderImmediate(std::shared_ptr canvasProvider) override; + + void setDrawCallback(std::shared_ptr drawCallback); + + std::shared_ptr getInfoObject(); + +private: + void performDraw(std::shared_ptr canvasProvider); + + void callJsDrawCallback(std::shared_ptr jsiCanvas, + int width, + int height, + double timestamp); + + void drawInJsiCanvas(std::shared_ptr jsiCanvas, + int width, + int height, + double time); + + std::shared_ptr _platformContext; + std::shared_ptr _drawCallback; + std::shared_ptr _jsiCanvas; + std::shared_ptr _jsDrawingLock; + std::shared_ptr _gpuDrawingLock; + std::shared_ptr _infoObject; + RNSkTimingInfo _jsTimingInfo; + RNSkTimingInfo _gpuTimingInfo; +}; + +class RNSkJsView: public RNSkView { +public: + /** + * Constructor + */ + RNSkJsView(std::shared_ptr context, + std::shared_ptr canvasProvider): + RNSkView(context, + canvasProvider, + std::make_shared(std::bind(&RNSkJsView::requestRedraw, this), context)) {} + + void updateTouchState(std::vector& touches) override { + std::static_pointer_cast(getRenderer())->getInfoObject()->updateTouches(touches); + RNSkView::updateTouchState(touches); + } + + void setJsiProperties(std::unordered_map &props) override { + for(auto& prop: props) { + if(prop.first == "drawCallback") { + if(prop.second.isUndefinedOrNull()) { + // Clear drawcallback + std::static_pointer_cast(getRenderer())->setDrawCallback(nullptr); + return; + } else if (prop.second.getType() != JsiWrapperValueType::Function) { + // We expect a function for the draw callback custom property + throw std::runtime_error("Expected a function for the drawCallback custom property."); + } + + // Save callback + std::static_pointer_cast(getRenderer())->setDrawCallback(prop.second.getAsFunction()); + + // Request redraw + requestRedraw(); + + } else { + RNSkView::setJsiProperties(props); + } + } + } +}; +} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h index 9dcb97e746732..23610ba79fec5 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkJsiViewApi.h @@ -2,11 +2,13 @@ #include #include +#include #include #include #include -#include +#include +#include #include #include #include @@ -14,96 +16,143 @@ namespace RNSkia { using namespace facebook; -using CallbackInfo = struct CallbackInfo { - CallbackInfo() { - drawCallback = nullptr; +using RNSkViewInfo = struct RNSkViewInfo { + RNSkViewInfo() { view = nullptr; } - std::shared_ptr drawCallback; - std::shared_ptr view; + std::shared_ptr view; + std::unordered_map props; }; -class RNSkJsiViewApi : public JsiHostObject { +class RNSkJsiViewApi : public JsiHostObject, public std::enable_shared_from_this { public: - JSI_HOST_FUNCTION(setDrawCallback) { - if (count != 2) { + /** + Sets a custom property on a view given a view id. The property name/value will + be stored in a map alongside the id of the view and propagated to the view when + needed. + */ + JSI_HOST_FUNCTION(setJsiProperty) { + if (count != 3) { _platformContext->raiseError( - std::string("setDrawCallback: Expected 2 arguments, got " + + std::string("setJsiProperty: Expected 3 arguments, got " + std::to_string(count) + ".")); return jsi::Value::undefined(); } if (!arguments[0].isNumber()) { _platformContext->raiseError( - "setDrawCallback: First argument must be a number"); + "setJsiProperty: First argument must be a number"); return jsi::Value::undefined(); } - // We accept undefined to zero out the drawCallback - if (!arguments[1].isUndefined()) { - if (!arguments[1].isObject()) { - _platformContext->raiseError( - "setDrawCallback: Second argument must be a function"); - return jsi::Value::undefined(); - } - if (!arguments[1].asObject(runtime).isFunction(runtime)) { - _platformContext->raiseError( - "setDrawCallback: Second argument must be a function"); - return jsi::Value::undefined(); - } - } - - // find skia draw view - int nativeId = arguments[0].asNumber(); + if (!arguments[1].isString()) { + _platformContext->raiseError( + "setJsiProperty: Second argument must be the name of the property to set."); - // and function to install as the draw drawCallback - auto info = getEnsuredCallbackInfo(nativeId); - if (arguments[1].isUndefined()) { - info->drawCallback = nullptr; - } else { - info->drawCallback = std::make_shared( - arguments[1].asObject(runtime).asFunction(runtime)); + return jsi::Value::undefined(); } + auto nativeId = arguments[0].asNumber(); + auto info = getEnsuredViewInfo(nativeId); - // Update view if set - if (info->view != nullptr && info->drawCallback != nullptr) { + std::lock_guard lock(_mutex); + info->props.emplace(arguments[1].asString(runtime).utf8(runtime), JsiValueWrapper(runtime, arguments[2])); + + // Now let's see if we have a view that we can update + if(info->view != nullptr) { + // Update view! info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); + info->view->setJsiProperties(info->props); + info->props.clear(); } return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(invalidateSkiaView) { - if (count != 1) { + /** + Calls a custom command / method on a view by the view id. + */ + JSI_HOST_FUNCTION(callJsiMethod) { + if (count < 2) { _platformContext->raiseError( - std::string("invalidateSkiaView: Expected 2 arguments, got " + + std::string("callCustomCommand: Expected at least 2 arguments, got " + std::to_string(count) + ".")); + return jsi::Value::undefined(); } if (!arguments[0].isNumber()) { _platformContext->raiseError( - "invalidateSkiaView: First argument must be a number"); + "callCustomCommand: First argument must be a number"); + return jsi::Value::undefined(); } - // find skia draw view - int nativeId = arguments[0].asNumber(); + if (!arguments[1].isString()) { + _platformContext->raiseError( + "callCustomCommand: Second argument must be the name of the action to call."); - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - info->view->requestRedraw(); + return jsi::Value::undefined(); } - return jsi::Value::undefined(); + + auto nativeId = arguments[0].asNumber(); + auto action = arguments[1].asString(runtime).utf8(runtime); + + auto info = getEnsuredViewInfo(nativeId); + + if(info->view == nullptr) { + throw jsi::JSError(runtime, + std::string("callCustomCommand: Could not call action " + action + + " on view - view not ready.").c_str()); + + return jsi::Value::undefined(); + } + + // Get arguments + size_t paramsCount = count - 2; + const jsi::Value* params = paramsCount > 0 ? &arguments[2] : nullptr; + return info->view->callJsiMethod(runtime, action, params, paramsCount); + } + + JSI_HOST_FUNCTION(requestRedraw) { + if (count != 1) { + _platformContext->raiseError( + std::string("requestRedraw: Expected 1 arguments, got " + std::to_string(count) + ".")); + + return jsi::Value::undefined(); + } + + if (!arguments[0].isNumber()) { + _platformContext->raiseError( + "requestRedraw: First argument must be a number"); + + return jsi::Value::undefined(); + } + + // find Skia View + int nativeId = arguments[0].asNumber(); + + auto info = getEnsuredViewInfo(nativeId); + if (info->view != nullptr) { + info->view->requestRedraw(); + } + return jsi::Value::undefined(); } - + JSI_HOST_FUNCTION(makeImageSnapshot) { - - // find skia draw view + if (count < 1) { + _platformContext->raiseError(std::string("makeImageSnapshot: Expected at least 1 argument, got " + std::to_string(count) + ".")); + return jsi::Value::undefined(); + } + + if (!arguments[0].isNumber()) { + _platformContext->raiseError("makeImageSnapshot: First argument must be a number"); + return jsi::Value::undefined(); + } + + // find Skia view int nativeId = arguments[0].asNumber(); sk_sp image; - auto info = getEnsuredCallbackInfo(nativeId); + auto info = getEnsuredViewInfo(nativeId); if (info->view != nullptr) { if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) { auto rect = JsiSkRect::fromValue(runtime, arguments[1]); @@ -120,80 +169,58 @@ class RNSkJsiViewApi : public JsiHostObject { throw jsi::JSError(runtime, "No Skia View currently available."); return jsi::Value::undefined(); } - - JSI_HOST_FUNCTION(setDrawMode) { - if (count != 2) { - _platformContext->raiseError( - std::string("setDrawMode: Expected 2 arguments, got " + - std::to_string(count) + ".")); - return jsi::Value::undefined(); - } - - if (!arguments[0].isNumber()) { - _platformContext->raiseError( - "setDrawMode: First argument must be a number"); - return jsi::Value::undefined(); - } - // find skia draw view - int nativeId = arguments[0].asNumber(); - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - auto nextMode = arguments[1].asString(runtime).utf8(runtime); - if(nextMode.compare("continuous") == 0) { - info->view->setDrawingMode(RNSkDrawingMode::Continuous); - } else { - info->view->setDrawingMode(RNSkDrawingMode::Default); - } - } - return jsi::Value::undefined(); - } - JSI_HOST_FUNCTION(registerValuesInView) { - // Check params - if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { - throw jsi::JSError(runtime, "Expected array of Values as second parameter"); - return jsi::Value::undefined(); - } - - // Get identifier of native SkiaView - int nativeId = arguments[0].asNumber(); - - // Get values that should be added as dependencies - auto values = arguments[1].asObject(runtime).asArray(runtime); - std::vector> unsubscribers; - const std::size_t size = values.size(runtime); - unsubscribers.reserve(size); - for(size_t i=0; i(runtime); - - if(value != nullptr) { - // Add change listener - unsubscribers.push_back(value->addListener([this, nativeId](jsi::Runtime&){ - requestRedrawView(nativeId); - })); + // Check params + if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { + throw jsi::JSError(runtime, "Expected array of Values as second parameter"); + return jsi::Value::undefined(); } - } - - // Return unsubscribe method that unsubscribes to all values - // that we subscribed to. - return jsi::Function::createFromHostFunction(runtime, - jsi::PropNameID::forUtf8(runtime, "unsubscribe"), - 0, - JSI_HOST_FUNCTION_LAMBDA { - // decrease dependency count on the Skia View - for(auto &unsub : unsubscribers) { - unsub(); + + // Get identifier of native SkiaView + int nativeId = arguments[0].asNumber(); + + // Get values that should be added as dependencies + auto values = arguments[1].asObject(runtime).asArray(runtime); + std::vector> unsubscribers; + const std::size_t size = values.size(runtime); + unsubscribers.reserve(size); + for(size_t i=0; i(runtime); + + if(value != nullptr) { + // Add change listener + unsubscribers.push_back(value->addListener([weakSelf = weak_from_this(), nativeId](jsi::Runtime&){ + auto self = weakSelf.lock(); + if(self) { + auto info = self->getEnsuredViewInfo(nativeId); + if(info->view != nullptr) { + info->view->requestRedraw(); + } + } + })); + } } - return jsi::Value::undefined(); - }); - } - - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawCallback), - JSI_EXPORT_FUNC(RNSkJsiViewApi, invalidateSkiaView), - JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot), - JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawMode), - JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView)) + + // Return unsubscribe method that unsubscribes to all values + // that we subscribed to. + return jsi::Function::createFromHostFunction(runtime, + jsi::PropNameID::forUtf8(runtime, "unsubscribe"), + 0, + JSI_HOST_FUNCTION_LAMBDA { + // decrease dependency count on the Skia View + for(auto &unsub : unsubscribers) { + unsub(); + } + return jsi::Value::undefined(); + }); + } + + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setJsiProperty), + JSI_EXPORT_FUNC(RNSkJsiViewApi, callJsiMethod), + JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView), + JSI_EXPORT_FUNC(RNSkJsiViewApi, requestRedraw), + JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot)) /** * Constructor @@ -203,7 +230,7 @@ class RNSkJsiViewApi : public JsiHostObject { : JsiHostObject(), _platformContext(platformContext) {} /** - * Invalidates the api object + * Invalidates the Skia View Api object */ void invalidate() { unregisterAll(); @@ -214,11 +241,12 @@ class RNSkJsiViewApi : public JsiHostObject { */ void unregisterAll() { // Unregister all views - auto tempList = _callbackInfos; + auto tempList = _viewInfos; for (const auto& info : tempList) { - unregisterSkiaDrawView(info.first); + unregisterSkiaView(info.first); } - _callbackInfos.clear(); + std::lock_guard lock(_mutex); + _viewInfos.clear(); } /** @@ -226,51 +254,48 @@ class RNSkJsiViewApi : public JsiHostObject { * @param nativeId Id of view to register * @param view View to register */ - void registerSkiaDrawView(size_t nativeId, std::shared_ptr view) { - auto info = getEnsuredCallbackInfo(nativeId); + void registerSkiaView(size_t nativeId, std::shared_ptr view) { + auto info = getEnsuredViewInfo(nativeId); + std::lock_guard lock(_mutex); info->view = view; - if (info->drawCallback != nullptr) { - info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); - } + info->view->setNativeId(nativeId); + info->view->setJsiProperties(info->props); + info->props.clear(); } /** * Unregisters a Skia draw view * @param nativeId View id */ - void unregisterSkiaDrawView(size_t nativeId) { - if (_callbackInfos.count(nativeId) == 0) { + void unregisterSkiaView(size_t nativeId) { + if (_viewInfos.count(nativeId) == 0) { return; } - auto info = getEnsuredCallbackInfo(nativeId); - if (info->view != nullptr) { - info->view->setDrawCallback(nullptr); - } + auto info = getEnsuredViewInfo(nativeId); + + std::lock_guard lock(_mutex); info->view = nullptr; - info->drawCallback = nullptr; - _callbackInfos.erase(nativeId); + _viewInfos.erase(nativeId); } - + /** Sets a skia draw view for the given id. This function can be used to mark that an underlying SkiaView is not available (it could be removed due to ex. a transition). The view can be set to a nullptr - or a valid view, effectively toggling the view's availability. If - a valid view is set, the setDrawCallback method is called on the - view (if a valid callback exists). + or a valid view, effectively toggling the view's availability. */ - void setSkiaDrawView(size_t nativeId, std::shared_ptr view) { - if (_callbackInfos.find(nativeId) == _callbackInfos.end()) { + void setSkiaView(size_t nativeId, std::shared_ptr view) { + if (_viewInfos.find(nativeId) == _viewInfos.end()) { return; } - auto info = getEnsuredCallbackInfo(nativeId); - if (view != nullptr && info->drawCallback != nullptr) { + auto info = getEnsuredViewInfo(nativeId); + std::lock_guard lock(_mutex); + if (view != nullptr) { info->view = view; info->view->setNativeId(nativeId); - info->view->setDrawCallback(info->drawCallback); - } else if(view == nullptr && info->drawCallback != nullptr) { - info->view->setDrawCallback(nullptr); + info->view->setJsiProperties(info->props); + info->props.clear(); + } else if(view == nullptr) { info->view = view; } } @@ -281,28 +306,17 @@ class RNSkJsiViewApi : public JsiHostObject { * @param nativeId View id * @return The callback info object for the requested view */ - CallbackInfo *getEnsuredCallbackInfo(size_t nativeId) { - if (_callbackInfos.count(nativeId) == 0) { - CallbackInfo info; - _callbackInfos.emplace(nativeId, info); + RNSkViewInfo *getEnsuredViewInfo(size_t nativeId) { + if (_viewInfos.count(nativeId) == 0) { + RNSkViewInfo info; + std::lock_guard lock(_mutex); + _viewInfos.emplace(nativeId, info); } - return &_callbackInfos.at(nativeId); + return &_viewInfos.at(nativeId); } - - /** - Send a redraw request to the view - */ - void requestRedrawView(size_t nativeId) { - auto info = getEnsuredCallbackInfo(nativeId); - if(info->view != nullptr) { - info->view->requestRedraw(); - } - } - - // List of callbacks - std::unordered_map _callbackInfos; - - // Platform context + + std::unordered_map _viewInfos; std::shared_ptr _platformContext; + std::mutex _mutex; }; } // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp index b273e054389e3..e103885437ca2 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace RNSkia { @@ -45,19 +45,19 @@ void RNSkManager::invalidate() { _platformContext->invalidate(); } -void RNSkManager::registerSkiaDrawView(size_t nativeId, std::shared_ptr view) { +void RNSkManager::registerSkiaView(size_t nativeId, std::shared_ptr view) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->registerSkiaDrawView(nativeId, view); + _viewApi->registerSkiaView(nativeId, view); } -void RNSkManager::unregisterSkiaDrawView(size_t nativeId) { +void RNSkManager::unregisterSkiaView(size_t nativeId) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->unregisterSkiaDrawView(nativeId); + _viewApi->unregisterSkiaView(nativeId); } -void RNSkManager::setSkiaDrawView(size_t nativeId, std::shared_ptr view) { +void RNSkManager::setSkiaView(size_t nativeId, std::shared_ptr view) { if (!_isInvalidated && _viewApi != nullptr) - _viewApi->setSkiaDrawView(nativeId, view); + _viewApi->setSkiaView(nativeId, view); } void RNSkManager::installBindings() { diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h index 8e86eeb65f337..7b07a32f2476b 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkManager.h @@ -12,7 +12,7 @@ namespace facebook { } namespace RNSkia { -class RNSkDrawView; +class RNSkView; class RNSkJsiViewApi; using namespace facebook; @@ -37,24 +37,24 @@ class RNSkManager { void invalidate(); /** - * Registers a RNSkDrawView with the given native id + * Registers a RNSkView with the given native id * @param nativeId Native view id * @param view View to register */ - void registerSkiaDrawView(size_t nativeId, std::shared_ptr view); + void registerSkiaView(size_t nativeId, std::shared_ptr view); /** - * Unregisters the RNSkDrawView from the list of registered views + * Unregisters the RNSkView from the list of registered views * @param nativeId Native view Id */ - void unregisterSkiaDrawView(size_t nativeId); + void unregisterSkiaView(size_t nativeId); /** Sets the view pointed to by nativeId to the provided value. Used when we want to remove a view without unregistering it - this happens typically on iOS. */ - void setSkiaDrawView(size_t nativeId, std::shared_ptr view); + void setSkiaView(size_t nativeId, std::shared_ptr view); /** * @return The platform context @@ -66,7 +66,7 @@ class RNSkManager { private: /** * Installs the javascript methods for registering/unregistering draw - * callbacks for RNSkDrawViews. Called on installation of the parent native + * callbacks for RNSkViews. Called on installation of the parent native * module. */ void installBindings(); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h new file mode 100644 index 0000000000000..d71eb171d0214 --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include +#include + +#pragma clang diagnostic pop + +class SkPicture; +class SkRect; +class SkImage; + +namespace RNSkia { + +using namespace facebook; + +class RNSkPictureRenderer: + public RNSkRenderer, + public std::enable_shared_from_this { +public: + RNSkPictureRenderer(std::function requestRedraw, + std::shared_ptr context): + RNSkRenderer(requestRedraw), + _platformContext(context) {} + + bool tryRender(std::shared_ptr canvasProvider) override { + performDraw(canvasProvider); + return true; + } + + void renderImmediate(std::shared_ptr canvasProvider) override { + performDraw(canvasProvider); + } + + void setPicture(std::shared_ptr picture) { + if(picture == nullptr) { + _picture = nullptr; + return; + } + + _picture = std::dynamic_pointer_cast(picture); + _requestRedraw(); + } + +private: + void performDraw(std::shared_ptr canvasProvider) { + if(_picture == nullptr) { + return; + } + + canvasProvider->renderToCanvas([=](SkCanvas* canvas){ + // Make sure to scale correctly + auto pd = _platformContext->getPixelDensity(); + canvas->save(); + canvas->scale(pd, pd); + + canvas->drawPicture(_picture->getObject()); + + // Restore and flush canvas + canvas->restore(); + canvas->flush(); + }); + } + + std::shared_ptr _platformContext; + std::shared_ptr _picture; +}; + +class RNSkPictureView: public RNSkView { +public: + /** + * Constructor + */ + RNSkPictureView(std::shared_ptr context, + std::shared_ptr canvasProvider): + RNSkView(context, + canvasProvider, + std::make_shared(std::bind(&RNSkPictureView::requestRedraw, this), context)) {} + + void setJsiProperties(std::unordered_map &props) override { + for(auto& prop: props) { + if(prop.first == "picture") { + if(prop.second.isUndefinedOrNull()) { + // Clear picture + std::static_pointer_cast(getRenderer())->setPicture(nullptr); + return; + } else if (prop.second.getType() != JsiWrapperValueType::HostObject) { + // We expect a function for the picture custom property + throw std::runtime_error("Expected an object for the picture custom property."); + } + + // Save picture + std::static_pointer_cast(getRenderer())->setPicture(prop.second.getAsHostObject()); + + // Request redraw + requestRedraw(); + + } else { + RNSkView::setJsiProperties(props); + } + } + } +}; +} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h new file mode 100644 index 0000000000000..5a6c6b2613e6f --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h @@ -0,0 +1,287 @@ + +#pragma once + +#include + +#include + +#include + +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include +#include + +#pragma clang diagnostic pop + +namespace RNSkia { + +using namespace facebook; + +class RNSkCanvasProvider { +public: + RNSkCanvasProvider(std::function requestRedraw): _requestRedraw(requestRedraw) {} + + /** + Returns the scaled width of the view + */ + virtual float getScaledWidth() = 0; + + /** + Returns the scaled height of the view + */ + virtual float getScaledHeight() = 0; + + /** + Render to a canvas + */ + virtual void renderToCanvas(const std::function&) = 0; +protected: + std::function _requestRedraw; +}; + +class RNSkRenderer { +public: + RNSkRenderer(std::function requestRedraw): _requestRedraw(requestRedraw) {} + + /** + Tries to render the current set of drawing operations. If we're busy we'll return false so that the calling RNSkBaseDrawView + can request a new render next frame. The tryRender method is typically called on each frame if there are any redraw + requests. The method will be called from the main thread, so the implementor must make sure any thread requirements are + met before rendering. This method will also allow the rendering to be dispatched to another thread. + */ + virtual bool tryRender(std::shared_ptr canvasProvider) = 0; + + /** + Renders directly to the canvas in the canvas provider. This method is called from a Javascript call to render a + snapshot of the SkiaView to an image, and can therefore run outside the tryRender loop and directly in the + javascript thread. + */ + virtual void renderImmediate(std::shared_ptr canvasProvider) = 0; + + void setShowDebugOverlays(bool showDebugOverlays) { _showDebugOverlays = showDebugOverlays; } + bool getShowDebugOverlays() { return _showDebugOverlays; } + +protected: + std::function _requestRedraw; + bool _showDebugOverlays; +}; + +class RNSkImageCanvasProvider: public RNSkCanvasProvider { +public: + RNSkImageCanvasProvider(std::function requestRedraw, + float width, + float height): + RNSkCanvasProvider(requestRedraw), + _width(width), + _height(height) { + _surface = SkSurface::MakeRasterN32Premul(_width, _height); + } + + /** + Returns a snapshot of the current surface/canvas + */ + sk_sp makeSnapshot(std::shared_ptr bounds) { + if(bounds != nullptr) { + SkIRect b = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(), bounds->height()); + return _surface->makeImageSnapshot(b); + } else { + return _surface->makeImageSnapshot(); + } + } + + /** + Returns the scaled width of the view + */ + float getScaledWidth() override { return _width; }; + + /** + Returns the scaled height of the view + */ + float getScaledHeight() override { return _height; }; + + /** + Render to a canvas + */ + void renderToCanvas(const std::function& cb) override { + cb(_surface->getCanvas()); + }; + +private: + float _width; + float _height; + sk_sp _surface; +}; + +enum RNSkDrawingMode { Default, Continuous }; + +using RNSkTouchInfo = struct { + enum TouchType { Start, Active, End, Cancelled }; + double x; + double y; + double force; + TouchType type; + size_t id; + long timestamp; +}; + +class RNSkView: public std::enable_shared_from_this { +public: + /** + * Constructor + */ + RNSkView(std::shared_ptr context, + std::shared_ptr canvasProvider, + std::shared_ptr renderer): + _platformContext(context), + _canvasProvider(canvasProvider), + _renderer(renderer) {} + + /** + Destructor + */ + virtual ~RNSkView() { + endDrawingLoop(); + } + + /** + Sets custom properties. Custom properties are properties that are set directly from Javascript without having + to go through the async bridge. + */ + virtual void setJsiProperties(std::unordered_map &props) { + throw std::runtime_error("The base Skia View does not support any custom properties."); + }; + + /** + Calls a custom action. + */ + virtual jsi::Value callJsiMethod(jsi::Runtime& runtime, + const std::string& name, + const jsi::Value *arguments, + size_t count) { + throw std::runtime_error("The base Skia View does not support any commands. Command " + name + " not found."); + }; + + /** + * Repaints the Skia view using the underlying context and the drawcallback. + * This method schedules a draw request that will be run on the correct + * thread and js runtime. + */ + void requestRedraw() { + _redrawRequestCounter++; + } + + /** + Sets the native id of the view + */ + virtual void setNativeId(size_t nativeId) { + _nativeId = nativeId; + beginDrawingLoop(); + } + + /** + Returns the native id + */ + size_t getNativeId() { return _nativeId; } + + /** + Sets the drawing mode for the view + */ + void setDrawingMode(RNSkDrawingMode mode) { + _drawingMode = mode; + requestRedraw(); + } + + /** + * Set to true to show the debug overlays on render + */ + void setShowDebugOverlays(bool show) { + _renderer->setShowDebugOverlays(show); + requestRedraw(); + } + + /** + Update touch state with new touch points + */ + virtual void updateTouchState(std::vector&) { + requestRedraw(); + } + + /** + Renders the view into an SkImage instead of the screen. + */ + sk_sp makeImageSnapshot(std::shared_ptr bounds) { + auto provider = std::make_shared(std::bind(&RNSkView::requestRedraw, this), + _canvasProvider->getScaledWidth(), + _canvasProvider->getScaledHeight()); + + _renderer->renderImmediate(provider); + return provider->makeSnapshot(bounds); + } + +protected: + std::shared_ptr getPlatformContext() { return _platformContext; } + std::shared_ptr getCanvasProvider() { return _canvasProvider; } + std::shared_ptr getRenderer() { return _renderer; } + + /** + Ends an ongoing beginDrawCallback loop for this view. This method is made protected if + the drawing loop should be stopped before reaching the destructor (like we do for Android + views) + */ + void endDrawingLoop() { + if(_drawingLoopId != 0) { + _drawingLoopId = 0; + _platformContext->endDrawLoop(_nativeId); + } + } + +private: + /** + Starts beginDrawCallback loop if the drawing mode is continuous + */ + void beginDrawingLoop() { + if (_drawingLoopId != 0 || _nativeId == 0) { + return; + } + // Set to zero to avoid calling beginDrawLoop before we return + _drawingLoopId = _platformContext->beginDrawLoop(_nativeId, + [weakSelf = weak_from_this()](bool invalidated) { + auto self = weakSelf.lock(); + if(self) { + self->drawLoopCallback(invalidated); + } + }); + } + + /** + Draw loop callback + */ + void drawLoopCallback(bool invalidated) { + if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) { + _redrawRequestCounter = 0; + + if(!_renderer->tryRender(_canvasProvider)) { + // The renderer could not render cause it was busy, just schedule redrawing + // on the next frame. + requestRedraw(); + } + } + } + + std::shared_ptr _platformContext; + std::shared_ptr _canvasProvider; + std::shared_ptr _renderer; + + RNSkDrawingMode _drawingMode; + size_t _nativeId; + + size_t _drawingLoopId = 0; + std::atomic _redrawRequestCounter = { 1 }; +}; + +} // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h index 3dec3bf655443..b871b70bb286d 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkComputedValue.h @@ -33,20 +33,30 @@ class RNSkComputedValue : public RNSkReadonlyValue !arguments[0].asObject(runtime).isFunction(runtime)) { throw jsi::JSError(runtime, "Expected callback function as first parameter"); } - + if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) { throw jsi::JSError(runtime, "Expected array of dependencies as second parameter"); } - + // Get callback for calculating result _callback = std::make_shared(arguments[0].asObject(runtime).asFunction(runtime)); } - + + void invalidate() override { + RNSkReadonlyValue::invalidate(); + + // Unregister listeners + for(const auto &unsubscribe: _unsubscribers) { + unsubscribe(); + } + _unsubscribers.clear(); + } + void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) { // Save dependencies std::vector> dependencies; - + // Ensure that all dependencies are Values auto deps = arguments[1].asObject(runtime).asArray(runtime); const std::size_t size = deps.size(runtime); @@ -63,7 +73,7 @@ class RNSkComputedValue : public RNSkReadonlyValue } dependencies.push_back(value); } - + // register change handler on dependencies _unsubscribers.reserve(_unsubscribers.size() + size); for(const auto &dep: dependencies) { @@ -75,18 +85,11 @@ class RNSkComputedValue : public RNSkReadonlyValue } })); } - + // Set initial value dependencyUpdated(runtime); } - - virtual ~RNSkComputedValue() { - // Unregister listeners - for(const auto &unsubscribe: _unsubscribers) { - unsubscribe(); - } - } - + private: void dependencyUpdated(jsi::Runtime &runtime) { // Calculate new value diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h index 2211344d7a228..a779bbd1058c4 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkReadonlyValue.h @@ -29,27 +29,29 @@ class RNSkReadonlyValue : public JsiSkHostObject, : JsiSkHostObject(platformContext), _valueHolder(std::make_unique(*platformContext->getJsRuntime())) { } - - virtual ~RNSkReadonlyValue() { } + + virtual ~RNSkReadonlyValue() { + invalidate(); + } JSI_PROPERTY_GET(__typename__) { return jsi::String::createFromUtf8(runtime, "RNSkValue"); } - + JSI_PROPERTY_GET(current) { return getCurrent(runtime); } - + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__), JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current)) - + JSI_HOST_FUNCTION(addListener) { if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) { throw jsi::JSError(runtime, "Expected function as first parameter."); return jsi::Value::undefined(); } auto callback = std::make_shared(arguments[0].asObject(runtime).asFunction(runtime)); - + auto unsubscribe = addListener([weakSelf = weak_from_this(), callback = std::move(callback)](jsi::Runtime& runtime){ auto self = weakSelf.lock(); @@ -58,7 +60,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, callback->call(runtime, selfReadonlyValue->get_current(runtime)); } }); - + return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "unsubscribe"), 0, @@ -67,9 +69,17 @@ class RNSkReadonlyValue : public JsiSkHostObject, return jsi::Value::undefined(); }); } - - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener)) - + + + + JSI_HOST_FUNCTION(__invalidate) { + invalidate(); + return jsi::Value::undefined(); + } + + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener), + JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate)) + /** * Adds a callback that will be called whenever the value changes * @param cb Callback @@ -86,7 +96,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, } }; } - + /** Updates the underlying value and notifies all listeners about the change. Listeners are only notified if the value was actually changed for numeric, boolean and string @@ -101,13 +111,22 @@ class RNSkReadonlyValue : public JsiSkHostObject, notifyListeners(runtime); } } - + + /** + Override to implement invalidation logic for the value. In the base class this function + clears all subscribers. + */ + virtual void invalidate() { + std::lock_guard lock(_mutex); + _listeners.clear(); + } + jsi::Value getCurrent(jsi::Runtime &runtime) { return _valueHolder->getCurrent(runtime); } - + protected: - + /** Notifies listeners about changes @param runtime Current JS Runtime @@ -122,7 +141,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, listener.second(runtime); } } - + /** Removes a subscription listeners @param listenerId identifier of listener to remove @@ -134,7 +153,7 @@ class RNSkReadonlyValue : public JsiSkHostObject, private: std::unique_ptr _valueHolder; - + long _listenerId = 0; std::unordered_map> _listeners; std::mutex _mutex; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h index b168c33f6e7b3..141632a5ecc80 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/values/RNSkValue.h @@ -26,22 +26,22 @@ class RNSkValue : public RNSkReadonlyValue update(runtime, arguments[0]); } } - + ~RNSkValue() { unsubscribe(); } - + JSI_PROPERTY_SET(current) { // When someone else is setting the value we need to stop any ongoing // animations unsubscribe(); update(runtime, value); } - + JSI_PROPERTY_SET(animation) { // Cancel existing animation unsubscribe(); - + // Verify input if(value.isObject() && value.asObject(runtime).isHostObject(runtime)) { auto animation = value.asObject(runtime).getHostObject(runtime); @@ -55,23 +55,24 @@ class RNSkValue : public RNSkReadonlyValue throw jsi::JSError(runtime, "Animation expected."); } } - + JSI_PROPERTY_GET(animation) { if(_animation != nullptr) { return jsi::Object::createFromHostObject(runtime, _animation); } return jsi::Value::undefined(); } - + JSI_EXPORT_PROPERTY_SETTERS(JSI_EXPORT_PROP_SET(RNSkValue, current), JSI_EXPORT_PROP_SET(RNSkValue, animation)) - + JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__), JSI_EXPORT_PROP_GET(RNSkValue, current), JSI_EXPORT_PROP_GET(RNSkValue, animation)) - + JSI_EXPORT_FUNCTIONS( JSI_EXPORT_FUNC(RNSkValue, addListener), + JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate) ) private: @@ -90,26 +91,26 @@ class RNSkValue : public RNSkReadonlyValue _animation->startClock(); } } - + void animationDidUpdate(jsi::Runtime& runtime) { if(_animation != nullptr) { // Update ourselves from the current animation value update(runtime, _animation->get_current(runtime)); } } - + void unsubscribe() { if(_unsubscribe != nullptr) { (*_unsubscribe)(); _unsubscribe = nullptr; } - + if(_animation != nullptr) { _animation->stopClock(); _animation = nullptr; } } - + std::shared_ptr _animation; std::shared_ptr> _unsubscribe; }; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h index 92485ec75f5af..8bd1ee0daacec 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/utils/RNSkLog.h @@ -54,19 +54,19 @@ class RNSkLogger { #endif va_end(args); } - + static void logToJavascriptConsole(jsi::Runtime& runtime, const std::string& message) { auto console = RNSkLogger::getJavascriptConsole(runtime).asObject(runtime); auto log = console.getPropertyAsFunction(runtime, "log"); log.call(runtime, jsi::String::createFromUtf8(runtime, message)); } - + static void warnToJavascriptConsole(jsi::Runtime& runtime, const std::string& message) { auto console = RNSkLogger::getJavascriptConsole(runtime).asObject(runtime); auto warn = console.getPropertyAsFunction(runtime, "warn"); warn.call(runtime, jsi::String::createFromUtf8(runtime, message)); } - + private: static jsi::Value getJavascriptConsole(jsi::Runtime& runtime) { auto console = runtime.global().getProperty(runtime, "console"); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.h deleted file mode 100644 index 507bb62ecb6db..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#import "PlatformContext.h" -#import "RNSKDrawView.h" -#import -#import - -#import -#import -#import - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#import -#import -#import - -#pragma clang diagnostic pop - -class RNSkDrawViewImpl : public RNSkia::RNSkDrawView { -public: - RNSkDrawViewImpl(std::shared_ptr context); - ~RNSkDrawViewImpl(); - - CALayer* getLayer() { return _layer; } - - void setSize(int width, int height); - -protected: - float getScaledWidth() override { return _width * _context->getPixelDensity(); }; - float getScaledHeight() override { return _height * _context->getPixelDensity(); }; - -private: - void drawPicture(const sk_sp picture) override; - bool createSkiaSurface(); - - int _nativeId; - float _width = -1; - float _height = -1; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - CAMetalLayer *_layer; -#pragma clang diagnostic pop - - static id _commandQueue; - static id _device; - static sk_sp _skContext; - - std::shared_ptr _context; -}; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h new file mode 100644 index 0000000000000..841fbd2fe4f8c --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h @@ -0,0 +1,38 @@ +#pragma once + +#import "RNSkPlatformContext.h" +#import "RNSkView.h" + +#import +#import + +class RNSkMetalCanvasProvider: public RNSkia::RNSkCanvasProvider { +public: + RNSkMetalCanvasProvider(std::function requestRedraw, + std::shared_ptr context); + + ~RNSkMetalCanvasProvider(); + + float getScaledWidth() override; + float getScaledHeight() override; + + void renderToCanvas(const std::function& cb) override; + + void setSize(int width, int height); + + CALayer* getLayer(); + +private: + std::shared_ptr _context; + float _width = -1; + float _height = -1; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + CAMetalLayer *_layer; +#pragma clang diagnostic pop + + static id _commandQueue; + static id _device; + static sk_sp _skContext; + +}; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm similarity index 69% rename from ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.mm rename to ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm index b7a73af46d3bb..5ba9d03b8db81 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm @@ -1,4 +1,5 @@ -#import +#import +#import #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -7,23 +8,30 @@ #import #import -#pragma clang diagnostic pop +#import -#import -#import +#pragma clang diagnostic pop // These static class members are used by all Skia Views -id RNSkDrawViewImpl::_device = MTLCreateSystemDefaultDevice(); -id RNSkDrawViewImpl::_commandQueue = id(CFRetain((GrMTLHandle)[_device newCommandQueue])); +id RNSkMetalCanvasProvider::_device = nullptr; +id RNSkMetalCanvasProvider::_commandQueue = nullptr; +sk_sp RNSkMetalCanvasProvider::_skContext = nullptr; -sk_sp RNSkDrawViewImpl::_skContext = nullptr; +RNSkMetalCanvasProvider::RNSkMetalCanvasProvider(std::function requestRedraw, + std::shared_ptr context): +RNSkCanvasProvider(requestRedraw), + _context(context) { + if (!_device) { + _device = MTLCreateSystemDefaultDevice(); + } + if (!_commandQueue) { + _commandQueue = id(CFRetain((GrMTLHandle)[_device newCommandQueue])); + } -RNSkDrawViewImpl::RNSkDrawViewImpl(std::shared_ptr context): - _context(context), RNSkia::RNSkDrawView(context) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability-new" _layer = [CAMetalLayer layer]; -#pragma clang diagnostic pop + #pragma clang diagnostic pop _layer.framebufferOnly = NO; _layer.device = _device; @@ -32,7 +40,7 @@ _layer.pixelFormat = MTLPixelFormatBGRA8Unorm; } -RNSkDrawViewImpl::~RNSkDrawViewImpl() { +RNSkMetalCanvasProvider::~RNSkMetalCanvasProvider() { if([[NSThread currentThread] isMainThread]) { _layer = NULL; } else { @@ -50,17 +58,20 @@ } } -void RNSkDrawViewImpl::setSize(int width, int height) { - _width = width; - _height = height; - _layer.frame = CGRectMake(0, 0, width, height); - _layer.drawableSize = CGSizeMake(width * _context->getPixelDensity(), - height* _context->getPixelDensity()); - - requestRedraw(); -} +/** + Returns the scaled width of the view + */ +float RNSkMetalCanvasProvider::getScaledWidth() { return _width * _context->getPixelDensity(); }; -void RNSkDrawViewImpl::drawPicture(const sk_sp picture) { +/** + Returns the scaled height of the view + */ +float RNSkMetalCanvasProvider::getScaledHeight() { return _height * _context->getPixelDensity(); }; + +/** + Render to a canvas + */ +void RNSkMetalCanvasProvider::renderToCanvas(const std::function& cb) { if(_width == -1 && _height == -1) { return; } @@ -103,10 +114,22 @@ GrBackendRenderTarget backendRT(_layer.drawableSize.width, } skSurface->getCanvas()->clear(SK_AlphaTRANSPARENT); - skSurface->getCanvas()->drawPicture(picture); + cb(skSurface->getCanvas()); id commandBuffer([_commandQueue commandBuffer]); [commandBuffer presentDrawable:currentDrawable]; [commandBuffer commit]; } +}; + +void RNSkMetalCanvasProvider::setSize(int width, int height) { + _width = width; + _height = height; + _layer.frame = CGRectMake(0, 0, width, height); + _layer.drawableSize = CGSizeMake(width * _context->getPixelDensity(), + height* _context->getPixelDensity()); + + _requestRedraw(); } + +CALayer* RNSkMetalCanvasProvider::getLayer() { return _layer; } diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.h similarity index 89% rename from ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.h rename to ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.h index 355774dcf8766..9ebe300160ef5 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.h @@ -30,9 +30,9 @@ using namespace facebook; static void handleNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo); -class PlatformContext : public RNSkPlatformContext { +class RNSkiOSPlatformContext : public RNSkPlatformContext { public: - PlatformContext(jsi::Runtime *runtime, + RNSkiOSPlatformContext(jsi::Runtime *runtime, std::shared_ptr callInvoker) : RNSkPlatformContext(runtime, callInvoker, [[UIScreen mainScreen] scale]) { // We need to make sure we invalidate when modules are freed @@ -46,7 +46,7 @@ class PlatformContext : public RNSkPlatformContext { ); } - ~PlatformContext() { + ~RNSkiOSPlatformContext() { CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetLocalCenter(), this); } @@ -70,7 +70,7 @@ class PlatformContext : public RNSkPlatformContext { static void handleNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { - (static_cast(observer))->willInvalidateModules(); + (static_cast(observer))->willInvalidateModules(); } } // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm similarity index 80% rename from ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.mm rename to ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm index 5a2df55d3cc36..5ba5c9208cec5 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/PlatformContext.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm @@ -1,4 +1,4 @@ -#include "PlatformContext.h" +#include "RNSkiOSPlatformContext.h" #import #include @@ -8,7 +8,7 @@ namespace RNSkia { - void PlatformContext::performStreamOperation(const std::string &sourceUri, + void RNSkiOSPlatformContext::performStreamOperation(const std::string &sourceUri, const std::function)> &op) { RNSkMeasureTime("PlatformContext::performStreamOperation"); @@ -28,11 +28,11 @@ std::thread(loader).detach(); } -void PlatformContext::raiseError(const std::exception &err) { +void RNSkiOSPlatformContext::raiseError(const std::exception &err) { RCTFatal(RCTErrorWithMessage([NSString stringWithUTF8String:err.what()])); } -void PlatformContext::startDrawLoop() { +void RNSkiOSPlatformContext::startDrawLoop() { if(_displayLink == nullptr) { _displayLink = [[DisplayLink alloc] init]; [_displayLink start:^(double time) { @@ -41,7 +41,7 @@ } } -void PlatformContext::stopDrawLoop() { +void RNSkiOSPlatformContext::stopDrawLoop() { if(_displayLink != nullptr) { [_displayLink stop]; _displayLink = nullptr; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSView.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSView.h new file mode 100644 index 0000000000000..f407ecc217939 --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkiOSView.h @@ -0,0 +1,34 @@ +#pragma once + +#import + +#import "RNSkView.h" +#import "RNSkiOSPlatformContext.h" +#import "RNSkMetalCanvasProvider.h" + +class RNSkBaseiOSView { +public: + virtual CALayer* getLayer() = 0; + virtual void setSize(int width, int height) = 0; + virtual std::shared_ptr getDrawView() = 0; +}; + +template +class RNSkiOSView: public RNSkBaseiOSView, public T { +public: + RNSkiOSView(std::shared_ptr context): + T(context, std::make_shared(std::bind(&RNSkia::RNSkView::requestRedraw, this), context)) {} + + CALayer* getLayer() override { + return std::static_pointer_cast(this->getCanvasProvider())->getLayer(); + } + + void setSize(int width, int height) override { + std::static_pointer_cast(this->getCanvasProvider())->setSize(width, height); + } + + std::shared_ptr getDrawView() override { + return this->shared_from_this(); + } + +}; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.h deleted file mode 100644 index 734e0cd45add2..0000000000000 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#import -#import - -#import -#import - -#import - -class RNSkDrawViewImpl; - -@interface SkiaDrawView : UIView - -- (instancetype)initWithManager: (RNSkia::RNSkManager*)manager; - -- (std::shared_ptr) impl; - -- (void) setDrawingMode:(std::string) mode; -- (void) setDebugMode:(bool) debugMode; -- (void) setNativeId:(size_t) nativeId; - -@end diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawViewManager.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawViewManager.mm index 9ba9bd94ffd99..9d3944966a9fb 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawViewManager.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawViewManager.mm @@ -1,42 +1,50 @@ #include #include +#include +#include +#include + #include #include -#include -#include +#include + + @implementation SkiaDrawViewManager +RCT_EXPORT_MODULE(SkiaDrawView) + - (SkiaManager*) skiaManager { auto bridge = [RCTBridge currentBridge]; auto skiaModule = (RNSkiaModule*)[bridge moduleForName:@"RNSkia"]; return [skiaModule manager]; } -RCT_CUSTOM_VIEW_PROPERTY(nativeID, NSNumber, SkiaDrawView) { +RCT_CUSTOM_VIEW_PROPERTY(nativeID, NSNumber, SkiaUIView) { // Get parameter int nativeId = [[RCTConvert NSString:json] intValue]; - [(SkiaDrawView*)view setNativeId:nativeId]; + [(SkiaUIView*)view setNativeId:nativeId]; } -RCT_CUSTOM_VIEW_PROPERTY(mode, NSString, SkiaDrawView) { +RCT_CUSTOM_VIEW_PROPERTY(mode, NSString, SkiaUIView) { std::string mode = json != NULL ? [[RCTConvert NSString:json] UTF8String] : "default"; - [(SkiaDrawView*)view setDrawingMode: mode]; + [(SkiaUIView*)view setDrawingMode: mode]; } -RCT_CUSTOM_VIEW_PROPERTY(debug, BOOL, SkiaDrawView) { +RCT_CUSTOM_VIEW_PROPERTY(debug, BOOL, SkiaUIView) { bool debug = json != NULL ? [RCTConvert BOOL:json] : false; - [(SkiaDrawView*)view setDebugMode: debug]; + [(SkiaUIView*)view setDebugMode: debug]; } -RCT_EXPORT_MODULE(ReactNativeSkiaView) - - (UIView *)view { auto skManager = [[self skiaManager] skManager]; // Pass SkManager as a raw pointer to avoid circular dependenciesr - return [[SkiaDrawView alloc] initWithManager:skManager.get()]; + return [[SkiaUIView alloc] initWithManager: skManager.get() + factory: [](std::shared_ptr context) { + return std::make_shared>(context); + }]; } @end diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaManager.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaManager.mm index 5bfdc57b69dea..769c8e40f1a3c 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaManager.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaManager.mm @@ -7,11 +7,11 @@ #import -#import "PlatformContext.h" +#import "RNSkiOSPlatformContext.h" @implementation SkiaManager { std::shared_ptr _skManager; - std::shared_ptr _platformContext; + std::shared_ptr _platformContext; __weak RCTBridge* weakBridge; } @@ -37,7 +37,7 @@ - (instancetype) initWithBridge:(RCTBridge*)bridge { facebook::jsi::Runtime* jsRuntime = (facebook::jsi::Runtime*)cxxBridge.runtime; // Create platform context - _platformContext = std::make_shared(jsRuntime, callInvoker); + _platformContext = std::make_shared(jsRuntime, callInvoker); // Create the RNSkiaManager (cross platform) _skManager = std::make_shared(jsRuntime, callInvoker, _platformContext); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.h new file mode 100644 index 0000000000000..9d23bbeb753ee --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.h @@ -0,0 +1,8 @@ + +#pragma once + +#import + +@interface SkiaPictureViewManager : RCTViewManager + +@end diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.mm new file mode 100644 index 0000000000000..f194a889701ac --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaPictureViewManager.mm @@ -0,0 +1,51 @@ + +#include +#include + +#include +#include +#include + +#include +#include +#include + + + +@implementation SkiaPictureViewManager + +RCT_EXPORT_MODULE(SkiaPictureView) + +- (SkiaManager*) skiaManager { + auto bridge = [RCTBridge currentBridge]; + auto skiaModule = (RNSkiaModule*)[bridge moduleForName:@"RNSkia"]; + return [skiaModule manager]; +} + +RCT_CUSTOM_VIEW_PROPERTY(nativeID, NSNumber, SkiaUIView) { + // Get parameter + int nativeId = [[RCTConvert NSString:json] intValue]; + [(SkiaUIView*)view setNativeId:nativeId]; +} + +RCT_CUSTOM_VIEW_PROPERTY(mode, NSString, SkiaUIView) { + std::string mode = json != NULL ? [[RCTConvert NSString:json] UTF8String] : "default"; + [(SkiaUIView*)view setDrawingMode: mode]; +} + +RCT_CUSTOM_VIEW_PROPERTY(debug, BOOL, SkiaUIView) { + bool debug = json != NULL ? [RCTConvert BOOL:json] : false; + [(SkiaUIView*)view setDebugMode: debug]; +} + +- (UIView *)view +{ + auto skManager = [[self skiaManager] skManager]; + // Pass SkManager as a raw pointer to avoid circular dependenciesr + return [[SkiaUIView alloc] initWithManager: skManager.get() + factory: [](std::shared_ptr context) { + return std::make_shared>(context); + }]; +} + +@end diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.h new file mode 100644 index 0000000000000..4a17ee1a92896 --- /dev/null +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.h @@ -0,0 +1,26 @@ +#pragma once + +#import +#import + +#import +#import + +#import +#import + +class RNSkiOSJsView; + +@interface SkiaUIView : UIView + +- (instancetype)initWithManager: (RNSkia::RNSkManager*)manager + factory: (std::function( + std::shared_ptr)>)factory; + +- (std::shared_ptr) impl; + +- (void) setDrawingMode:(std::string) mode; +- (void) setDebugMode:(bool) debugMode; +- (void) setNativeId:(size_t) nativeId; + +@end diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm similarity index 64% rename from ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.mm rename to ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm index a66d93ad87818..7a7715c0885f1 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm @@ -1,24 +1,26 @@ #import -#import +#import #include #include -#import #import -@implementation SkiaDrawView { - std::shared_ptr _impl; +@implementation SkiaUIView { + std::shared_ptr _impl; RNSkia::RNSkManager* _manager; RNSkia::RNSkDrawingMode _drawingMode; + std::function(std::shared_ptr)> _factory; bool _debugMode; size_t _nativeId; } #pragma mark Initialization and destruction -- (instancetype) initWithManager: (RNSkia::RNSkManager*)manager; +- (instancetype) initWithManager: (RNSkia::RNSkManager*)manager + factory: (std::function( + std::shared_ptr)>)factory { self = [super init]; if (self) { @@ -26,6 +28,7 @@ - (instancetype) initWithManager: (RNSkia::RNSkManager*)manager; _nativeId = 0; _debugMode = false; _drawingMode = RNSkia::RNSkDrawingMode::Default; + _factory = factory; // Listen to notifications about module invalidation [[NSNotificationCenter defaultCenter] addObserver:self @@ -50,7 +53,7 @@ - (void) willMoveToSuperview:(UIView *)newWindow { [_impl->getLayer() removeFromSuperlayer]; if(_nativeId != 0 && _manager != nullptr) { - _manager->setSkiaDrawView(_nativeId, nullptr); + _manager->setSkiaView(_nativeId, nullptr); } _impl = nullptr; @@ -58,21 +61,28 @@ - (void) willMoveToSuperview:(UIView *)newWindow { } else { // Create implementation view when the parent view is set if(_impl == nullptr && _manager != nullptr) { - _impl = std::make_shared(_manager->getPlatformContext()); + _impl = _factory(_manager->getPlatformContext()); + if(_impl == nullptr) { + throw std::runtime_error("Expected Skia view implementation, got nullptr."); + } [self.layer addSublayer: _impl->getLayer()]; if(_nativeId != 0) { - _manager->setSkiaDrawView(_nativeId, _impl); + _manager->setSkiaView(_nativeId, _impl->getDrawView()); } - _impl->setDrawingMode(_drawingMode); - _impl->setShowDebugOverlays(_debugMode); + _impl->getDrawView()->setDrawingMode(_drawingMode); + _impl->getDrawView()->setShowDebugOverlays(_debugMode); } } } - (void) dealloc { if(_manager != nullptr && _nativeId != 0) { - _manager->unregisterSkiaDrawView(_nativeId); + _manager->unregisterSkiaView(_nativeId); } + + [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; + + assert(_impl == nullptr); } #pragma mark Layout @@ -90,14 +100,14 @@ -(void) setDrawingMode:(std::string) mode { _drawingMode = mode.compare("continuous") == 0 ? RNSkia::RNSkDrawingMode::Continuous : RNSkia::RNSkDrawingMode::Default; if(_impl != nullptr) { - _impl->setDrawingMode(_drawingMode); + _impl->getDrawView()->setDrawingMode(_drawingMode); } } -(void) setDebugMode:(bool) debugMode { _debugMode = debugMode; if(_impl != nullptr) { - _impl->setShowDebugOverlays(debugMode); + _impl->getDrawView()->setShowDebugOverlays(debugMode); } } @@ -105,13 +115,13 @@ - (void) setNativeId:(size_t) nativeId { _nativeId = nativeId; if(_impl != nullptr) { - _manager->registerSkiaDrawView(nativeId, _impl); + _manager->registerSkiaView(nativeId, _impl->getDrawView()); } } #pragma mark External API -- (std::shared_ptr) impl { +- (std::shared_ptr) impl { return _impl; } @@ -131,10 +141,10 @@ -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - (void) handleTouches:(NSSet*) touches withEvent:(UIEvent*) event { if (event.type == UIEventTypeTouches) { - std::vector nextTouches; + std::vector nextTouches; for (UITouch *touch in touches) { auto position = [touch preciseLocationInView:self]; - RNSkia::RNSkTouchPoint nextTouch; + RNSkia::RNSkTouchInfo nextTouch; nextTouch.x = position.x; nextTouch.y = position.y; nextTouch.force = [touch force]; @@ -142,26 +152,26 @@ - (void) handleTouches:(NSSet*) touches withEvent:(UIEvent*) event { auto phase = [touch phase]; switch(phase) { case UITouchPhaseBegan: - nextTouch.type = RNSkia::RNSkTouchType::Start; + nextTouch.type = RNSkia::RNSkTouchInfo::TouchType::Start; break; case UITouchPhaseMoved: - nextTouch.type = RNSkia::RNSkTouchType::Active; + nextTouch.type = RNSkia::RNSkTouchInfo::TouchType::Active; break; case UITouchPhaseEnded: - nextTouch.type = RNSkia::RNSkTouchType::End; + nextTouch.type = RNSkia::RNSkTouchInfo::TouchType::End; break; case UITouchPhaseCancelled: - nextTouch.type = RNSkia::RNSkTouchType::Cancelled; + nextTouch.type = RNSkia::RNSkTouchInfo::TouchType::Cancelled; break; default: - nextTouch.type = RNSkia::RNSkTouchType::Active; + nextTouch.type = RNSkia::RNSkTouchInfo::TouchType::Active; break; } nextTouches.push_back(nextTouch); } if(_impl != nullptr) { - _impl->updateTouchState(std::move(nextTouches)); + _impl->getDrawView()->updateTouchState(nextTouches); } } } diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json b/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json index 235b4a424723b..d5f32cf6e8e54 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json +++ b/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json @@ -1,6 +1,6 @@ { "name": "react-native-skia", - "version": "0.1.136", + "version": "0.1.153", "summary": "High-performance React Native Graphics using Skia", "description": "@shopify/react-native-skia", "homepage": "https://github.com/shopify/react-native-skia", @@ -13,7 +13,7 @@ }, "source": { "git": "https://github.com/shopify/react-native-skia/react-native-skia.git", - "tag": "0.1.136" + "tag": "0.1.153" }, "requires_arc": true, "pod_target_xcconfig": { diff --git a/packages/expo/bundledNativeModules.json b/packages/expo/bundledNativeModules.json index d4ad230809636..1f6a82bc38b29 100644 --- a/packages/expo/bundledNativeModules.json +++ b/packages/expo/bundledNativeModules.json @@ -104,7 +104,7 @@ "sentry-expo": "~5.0.0", "unimodules-app-loader": "~3.1.0", "unimodules-image-loader-interface": "~6.1.0", - "@shopify/react-native-skia": "0.1.137", + "@shopify/react-native-skia": "0.1.153", "@shopify/flash-list": "1.3.0", "@sentry/react-native": "^4.1.3" } From e43d4ccc60bee64702867318ae74368200f7800e Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:16:16 +0800 Subject: [PATCH 3/7] update Podfile.lock --- apps/bare-expo/ios/Podfile.lock | 4 ++-- ios/Podfile.lock | 24 ++++++++++----------- yarn.lock | 37 +++++++++++++-------------------- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/apps/bare-expo/ios/Podfile.lock b/apps/bare-expo/ios/Podfile.lock index 276a849973ea7..bd18454f2677d 100644 --- a/apps/bare-expo/ios/Podfile.lock +++ b/apps/bare-expo/ios/Podfile.lock @@ -622,7 +622,7 @@ PODS: - React-jsinspector (0.70.2) - React-logger (0.70.2): - glog - - react-native-netinfo (9.3.0): + - react-native-netinfo (9.3.3): - React-Core - react-native-safe-area-context (4.3.1): - RCT-Folly @@ -1350,7 +1350,7 @@ SPEC CHECKSUMS: React-jsiexecutor: 53bd208e5c27939c6e6365528393445a596a9a2b React-jsinspector: 26c42646ab0bb69e29e837e23754fe7121eeaf94 React-logger: 1bfd109a0ffa4c0989bbfac0c2d8c4abe4637faa - react-native-netinfo: 129bd99f607a2dc5bb096168f3e5c150fd1f1c95 + react-native-netinfo: b514dd6d9cd512b90e178c5b7158df1a1c568d47 react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de react-native-segmented-control: 06607462630512ff8eef652ec560e6235a30cc3e react-native-slider: 98b724cd3e44c3454a6d0724e796d4e9c52189ce diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 08a17cd21d7bd..9f04acf45a2f8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1915,32 +1915,32 @@ PODS: - ReactCommon/turbomodule/core - react-native-segmented-control (2.4.0): - React-Core - - react-native-skia (0.1.136): + - react-native-skia (0.1.153): - React - React-callinvoker - React-Core - - react-native-skia/Api (= 0.1.136) - - react-native-skia/Jsi (= 0.1.136) - - react-native-skia/RNSkia (= 0.1.136) - - react-native-skia/SkiaHeaders (= 0.1.136) - - react-native-skia/Utils (= 0.1.136) - - react-native-skia/Api (0.1.136): + - react-native-skia/Api (= 0.1.153) + - react-native-skia/Jsi (= 0.1.153) + - react-native-skia/RNSkia (= 0.1.153) + - react-native-skia/SkiaHeaders (= 0.1.153) + - react-native-skia/Utils (= 0.1.153) + - react-native-skia/Api (0.1.153): - React - React-callinvoker - React-Core - - react-native-skia/Jsi (0.1.136): + - react-native-skia/Jsi (0.1.153): - React - React-callinvoker - React-Core - - react-native-skia/RNSkia (0.1.136): + - react-native-skia/RNSkia (0.1.153): - React - React-callinvoker - React-Core - - react-native-skia/SkiaHeaders (0.1.136): + - react-native-skia/SkiaHeaders (0.1.153): - React - React-callinvoker - React-Core - - react-native-skia/Utils (0.1.136): + - react-native-skia/Utils (0.1.153): - React - React-callinvoker - React-Core @@ -3494,7 +3494,7 @@ SPEC CHECKSUMS: react-native-pager-view: 95d0418c3c74279840abec6926653d32447bafb6 react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de react-native-segmented-control: 06607462630512ff8eef652ec560e6235a30cc3e - react-native-skia: faacd6a970a757d67c4f4a44a31d347651abbb8e + react-native-skia: 78330615997e720dd07db28f4b8dfff22e9dd031 react-native-webview: d33e2db8925d090871ffeb232dfa50cb3a727581 React-perflogger: 6009895616a455781293950bbd63d53cfc7ffbc5 React-RCTActionSheet: 5e90aa5712af18bfc86c2c6d97d4dbe0e5451c1d diff --git a/yarn.lock b/yarn.lock index b3d33289d4a3e..2be9b25f0f5bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3309,10 +3309,10 @@ dependencies: invariant "^2.2.4" -"@react-native-community/netinfo@9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-9.3.0.tgz#9792c23341eab5c629566baee016146f4f3f6086" - integrity sha512-NNdMeIXXqmPCbXrWxVqRzZ1gEZ6L1ykotWnCZLVjQBUgjyGWdL5LiDM/bcIa5DLzqZY7Km08rMgB7BoHUuEmnQ== +"@react-native-community/netinfo@9.3.3": + version "9.3.3" + resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-9.3.3.tgz#ee6a36f7f084d84e90342743026717e7ddad6a90" + integrity sha512-/nlrGqItwRnqjis7yWhUq6lpxS8Sm1DMNsjNfABih9wGnh58Tu28z3Box/ifFnu0kD2Fdp0UZXe74QwoZDKA4A== "@react-native-community/slider@4.2.3": version "4.2.3" @@ -3539,13 +3539,13 @@ recyclerlistview "4.1.2" tslib "2.4.0" -"@shopify/react-native-skia@0.1.137": - version "0.1.137" - resolved "https://registry.yarnpkg.com/@shopify/react-native-skia/-/react-native-skia-0.1.137.tgz#c3f655cfc5ff1f58afd3b1efd26f7ec9bd28e262" - integrity sha512-eQn+kVxTaJTa8ptHLyXTrSQyPDGGX0wAWNOJS0GOg9zHM9+zkIkliriF0izXtGk8DgYGbUoVgz+JBQ41xHBihg== +"@shopify/react-native-skia@0.1.153": + version "0.1.153" + resolved "https://registry.yarnpkg.com/@shopify/react-native-skia/-/react-native-skia-0.1.153.tgz#59eb0e58c300d7e5dc74732bc60b3a14a721dc70" + integrity sha512-YrV4NDvJi7T2ha7F4MqNtYl+MZfUWtkGSodaylNBr6EJkG3HaG7pYQNqK6xYOSyPJZ104E2LBZF4dMoY3qaSfQ== dependencies: - canvaskit-wasm "^0.35.0" - react-reconciler "^0.26.2" + canvaskit-wasm "0.36.1" + react-reconciler "0.26.2" "@sideway/address@^4.1.3": version "4.1.4" @@ -5006,11 +5006,6 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@webgpu/types@^0.1.20": - version "0.1.21" - resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.1.21.tgz#b181202daec30d66ccd67264de23814cfd176d3a" - integrity sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow== - "@wojtekmaj/enzyme-adapter-react-17@^0.6.3": version "0.6.7" resolved "https://registry.yarnpkg.com/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.6.7.tgz#7784bd32f518b186218cebb26c98c852676f30b0" @@ -6627,12 +6622,10 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001400: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz#30f67d55a865da43e0aeec003f073ea8764d5d7c" integrity sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA== -canvaskit-wasm@^0.35.0: - version "0.35.0" - resolved "https://registry.yarnpkg.com/canvaskit-wasm/-/canvaskit-wasm-0.35.0.tgz#90afc625958367f4a27907fb8c03240045933a46" - integrity sha512-y/eTJ4xoIBkKzD37aQAvBL451LIp9YiB8Vs1e8J3Qwe7WcTHsAD00E5WocPzZo+0+XaSCkJ6cS/BxBDXTSnW1g== - dependencies: - "@webgpu/types" "^0.1.20" +canvaskit-wasm@0.36.1: + version "0.36.1" + resolved "https://registry.yarnpkg.com/canvaskit-wasm/-/canvaskit-wasm-0.36.1.tgz#341df38ce7894a925064beaf9eeacbf7699c6633" + integrity sha512-6IHlBBc9zDQBTHiGuz4Rf0j/P/ulW24q/yW+QY517e7jwQoM0nJ1+L3h4wUpfC4eQrcpVPQY8ZFbqMbUCzDxTw== capital-case@^1.0.4: version "1.0.4" @@ -17401,7 +17394,7 @@ react-query@^3.34.16: broadcast-channel "^3.4.1" match-sorter "^6.0.2" -react-reconciler@^0.26.2: +react-reconciler@0.26.2: version "0.26.2" resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.26.2.tgz#bbad0e2d1309423f76cf3c3309ac6c96e05e9d91" integrity sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q== From 96649f2fa645ba7aff15635bd27b3dfab3eab953 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:16:34 +0800 Subject: [PATCH 4/7] [NCL] Update skia example --- .../src/screens/Skia/SkiaScreen.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx b/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx index 4786a7fc5dbef..c2f09129efc7b 100644 --- a/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx +++ b/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx @@ -1,6 +1,6 @@ import type { SkiaValue } from '@shopify/react-native-skia'; import { - useDerivedValue, + useComputedValue, useLoop, BlurMask, vec, @@ -12,14 +12,11 @@ import { Easing, mix, } from '@shopify/react-native-skia'; -import React from 'react'; -import { Dimensions, StyleSheet } from 'react-native'; +import React, { useMemo } from 'react'; +import { StyleSheet, useWindowDimensions } from 'react-native'; -const { width, height } = Dimensions.get('window'); const c1 = '#61bea2'; const c2 = '#529ca0'; -const R = width / 4; -const center = vec(width / 2, height / 2 - 64); interface RingProps { index: number; @@ -27,27 +24,32 @@ interface RingProps { } const Ring = ({ index, progress }: RingProps) => { + const { width, height } = useWindowDimensions(); + const R = width / 4; + const center = useMemo(() => vec(width / 2, height / 2 - 64), [height, width]); const theta = (index * (2 * Math.PI)) / 6; - const transform = useDerivedValue(() => { + const transform = useComputedValue(() => { const { x, y } = polar2Canvas({ theta, radius: progress.current * R }, { x: 0, y: 0 }); const scale = mix(progress.current, 0.3, 1); return [{ translateX: x }, { translateY: y }, { scale }]; }, [progress]); return ( - - - + ); }; export default function SkiaScreen() { + const { width, height } = useWindowDimensions(); + const R = width / 4; + const center = useMemo(() => vec(width / 2, height / 2 - 64), [height, width]); + const progress = useLoop({ duration: 3000, easing: Easing.inOut(Easing.ease), }); - const transform = useDerivedValue( + const transform = useComputedValue( () => [{ rotate: mix(progress.current, -Math.PI, 0) }], [progress] ); From 69ada753cfd58332ec3d8c1233e4ea1c0d0887cc Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:22:45 +0800 Subject: [PATCH 5/7] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ca1f18f98625..870e935476ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Package-specific changes not released in any SDK will be added here just before - Updated `@react-native-community/netinfo` from `9.3.0` to `9.3.3`. ([#19421](https://github.com/expo/expo/pull/19421) by [@douglowder](https://github.com/douglowder)) - Updated `@react-native-picker/picker` from `2.4.2` to `2.4.6`. ([#19390](https://github.com/expo/expo/pull/19390) by [@aleqsio](https://github.com/aleqsio)) - Updated `react-native-screens` from `3.15.0` to `3.18.0`. ([#19383](https://github.com/expo/expo/pull/19383) by [@tsapeta](https://github.com/tsapeta)) +- Updated `@shopify/react-native-skia` from `0.1.136` to `0.1.153`. ([#19360](https://github.com/expo/expo/pull/19360) by [@kudo](https://github.com/kudo)) ### 🛠 Breaking changes From 5e48de7939ae430ab60e130ac901a38d50f38b77 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Mon, 3 Oct 2022 14:30:00 +0800 Subject: [PATCH 6/7] fix lint issue --- apps/native-component-list/src/screens/Skia/SkiaScreen.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx b/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx index c2f09129efc7b..a688ba7b161e6 100644 --- a/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx +++ b/apps/native-component-list/src/screens/Skia/SkiaScreen.tsx @@ -41,7 +41,6 @@ const Ring = ({ index, progress }: RingProps) => { export default function SkiaScreen() { const { width, height } = useWindowDimensions(); - const R = width / 4; const center = useMemo(() => vec(width / 2, height / 2 - 64), [height, width]); const progress = useLoop({ From 2a2d08dec49327ca0344d8487b0b30a292425874 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Wed, 5 Oct 2022 09:35:19 +0800 Subject: [PATCH 7/7] remove cmake version from versioned code --- .../sdk46/@shopify/react-native-skia/android/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/android/vendored/sdk46/@shopify/react-native-skia/android/build.gradle b/android/vendored/sdk46/@shopify/react-native-skia/android/build.gradle index 3285ca6bea9ba..1fb71513df797 100644 --- a/android/vendored/sdk46/@shopify/react-native-skia/android/build.gradle +++ b/android/vendored/sdk46/@shopify/react-native-skia/android/build.gradle @@ -138,7 +138,6 @@ android { externalNativeBuild { cmake { path file('CMakeLists.txt') - version '3.10.2' } }