From 9dde0c9f7fc9852b7cd552e3b6fe42beaf8a2cf5 Mon Sep 17 00:00:00 2001 From: DatLag Date: Sat, 15 Feb 2025 16:25:35 +0100 Subject: [PATCH 1/4] fix: native library loading Introduce a NativeLoader which takes care of loading native libraries. ReLinker is not needed on API Level > 23 and causes more trouble than it solves. Refs: #341 --- .../rive/runtime/kotlin/RiveInitializer.kt | 7 ++- .../rive/runtime/kotlin/core/NativeLoader.kt | 62 +++++++++++++++++++ .../java/app/rive/runtime/kotlin/core/Rive.kt | 12 ++-- .../runtime/kotlin/core/RiveInitialized.kt | 13 ++++ 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 kotlin/src/main/java/app/rive/runtime/kotlin/core/NativeLoader.kt create mode 100644 kotlin/src/main/java/app/rive/runtime/kotlin/core/RiveInitialized.kt diff --git a/kotlin/src/main/java/app/rive/runtime/kotlin/RiveInitializer.kt b/kotlin/src/main/java/app/rive/runtime/kotlin/RiveInitializer.kt index d118933a..daf4664e 100644 --- a/kotlin/src/main/java/app/rive/runtime/kotlin/RiveInitializer.kt +++ b/kotlin/src/main/java/app/rive/runtime/kotlin/RiveInitializer.kt @@ -3,6 +3,7 @@ package app.rive.runtime.kotlin import android.content.Context import androidx.startup.Initializer import app.rive.runtime.kotlin.core.Rive +import app.rive.runtime.kotlin.core.RiveInitialized /** * Initializes Rive; needs to be done at startup. @@ -37,9 +38,9 @@ import app.rive.runtime.kotlin.core.Rive * In fact, if you want to provide a custom renderer type you'll need to init Rive manually. */ -class RiveInitializer : Initializer { - override fun create(context: Context) { - return Rive.init(context) +class RiveInitializer : Initializer { + override fun create(context: Context): RiveInitialized { + return RiveInitialized(Rive.init(context)) } override fun dependencies(): List>> { diff --git a/kotlin/src/main/java/app/rive/runtime/kotlin/core/NativeLoader.kt b/kotlin/src/main/java/app/rive/runtime/kotlin/core/NativeLoader.kt new file mode 100644 index 00000000..6885760e --- /dev/null +++ b/kotlin/src/main/java/app/rive/runtime/kotlin/core/NativeLoader.kt @@ -0,0 +1,62 @@ +package app.rive.runtime.kotlin.core + +import android.content.Context +import android.os.Build +import com.getkeepsafe.relinker.ReLinker + +internal object NativeLoader { + + /** + * Loads specified library by name and covers edge cases. + * ReLinker is only needed for API Level < 23. + * + * @param context required for ReLinker + * @param name the name of the library to load + * @return `true` if successfully loaded + */ + fun loadLibrary(context: Context, name: String): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return loadLibrary(name) + } + + val relinkerLoaded = runCatching { + ReLinker.loadLibrary(context, name) + }.isSuccess + + // Ignore ReLinker result first, since it catches some exception and may not be loaded + // resulting in false-positives + // Loading twice won't work anyway so there is no problem + return loadLibrary(name) || relinkerLoaded + } + + /** + * Loads specified library by name and covers edge cases. + * May fail on some API Level < 23 devices. + * + * @param name the name of the library to load + * @return `true` if successfully loaded + */ + private fun loadLibrary(name: String): Boolean { + var loaded = true + + // normally it's just the name but some manufacturers mess with this + systemLoadLibrary(name) { + systemLoadLibrary("$name.so") { + systemLoadLibrary("lib$name") { + systemLoadLibrary("lib$name.so") { + loaded = false + } + } + } + } + return loaded + } + + private fun systemLoadLibrary(name: String, onError: () -> Unit = { }) { + if (runCatching { + System.loadLibrary(name) + }.isFailure) { + onError() + } + } +} \ No newline at end of file diff --git a/kotlin/src/main/java/app/rive/runtime/kotlin/core/Rive.kt b/kotlin/src/main/java/app/rive/runtime/kotlin/core/Rive.kt index bfed76e8..62123078 100644 --- a/kotlin/src/main/java/app/rive/runtime/kotlin/core/Rive.kt +++ b/kotlin/src/main/java/app/rive/runtime/kotlin/core/Rive.kt @@ -38,13 +38,15 @@ object Rive { * * @param defaultRenderer The default renderer to use when initializing [File] or * [RiveAnimationView]. Defaults to [RendererType.Skia]. + * @return `true` if initialized, `false` if some error occurred. */ - fun init(context: Context, defaultRenderer: RendererType = RendererType.Rive) { - // NOTE: loadLibrary also allows us to specify a version, something we might want to take - // advantage of - ReLinker.loadLibrary(context, RIVE_ANDROID) + fun init(context: Context, defaultRenderer: RendererType = RendererType.Rive): Boolean { + val loaded = NativeLoader.loadLibrary(context, RIVE_ANDROID) defaultRendererType = defaultRenderer - initializeCppEnvironment() + if (loaded) { + initializeCppEnvironment() + } + return loaded } /** diff --git a/kotlin/src/main/java/app/rive/runtime/kotlin/core/RiveInitialized.kt b/kotlin/src/main/java/app/rive/runtime/kotlin/core/RiveInitialized.kt new file mode 100644 index 00000000..bdbd8bc5 --- /dev/null +++ b/kotlin/src/main/java/app/rive/runtime/kotlin/core/RiveInitialized.kt @@ -0,0 +1,13 @@ +package app.rive.runtime.kotlin.core + +import app.rive.runtime.kotlin.RiveInitializer + +/** + * Represents the result of the [Rive] initialization. + * Only used for [RiveInitializer] to be compatible with other initializers. + * + * @property success Indicates whether the initialization was successful. + */ +data class RiveInitialized( + val success: Boolean +) From 72035539a66ac38670889eea84d52e786a9b91be Mon Sep 17 00:00:00 2001 From: blakdragan7 Date: Wed, 5 Mar 2025 04:37:10 +0000 Subject: [PATCH 2/4] Playstation RHI Support Diffs= f161bf4679 Tighter RHI integration, extra build options (#9149) --- .rive_head | 2 +- submodules/rive-runtime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.rive_head b/.rive_head index 65ac11c0..6a87ea9c 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -57d81702cb268580c8fbbb23084aa8a069982a0e +f161bf467917880176e3ded8ca0571879a76ff94 diff --git a/submodules/rive-runtime b/submodules/rive-runtime index 695dfdaf..a778f649 160000 --- a/submodules/rive-runtime +++ b/submodules/rive-runtime @@ -1 +1 @@ -Subproject commit 695dfdaffc3d63172a81567d698c4e59d1bae6b4 +Subproject commit a778f6497b2cd7f1e087c23a9db4f2a8fadfd3ed From 1424b6827110af013ec459f0e3c0c6cc0a49bbc6 Mon Sep 17 00:00:00 2001 From: luigi-rosso Date: Wed, 5 Mar 2025 05:04:25 +0000 Subject: [PATCH 3/4] Add RenderText to rive_native This lets the editor (and users of rive_native) draw text procedurally a little more easily directly through the runtime's RawText feature. This makes it easier to use all the high level features of our Text object in a procedural way, which is helpful for the editor to use on the Stage. Based on discussions with @alxgibsn where we found that there wasn't a good way to draw text with ellipses on the stage. You could (and we did) previously do this by using helpers like DisplayText which would do all the styling and glyph rendering in Dart. This will be more performant for cases where you don't need control of each individual glyph from Dart and just want to draw a blob of styled text. It will incur much less FFI overhead and should be used by the editor when possible for text handles/helpers (Rive Text should still go through the usual path as modifiers need per glyph control, Raw/RenderText does not work with modifiers). Diffs= de0026bd59 Add RenderText to rive_native (#9146) --- .rive_head | 2 +- submodules/rive-runtime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.rive_head b/.rive_head index 6a87ea9c..80d0685f 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -f161bf467917880176e3ded8ca0571879a76ff94 +de0026bd59569d4783370d6c95394536b4c79f3e diff --git a/submodules/rive-runtime b/submodules/rive-runtime index a778f649..a0383e95 160000 --- a/submodules/rive-runtime +++ b/submodules/rive-runtime @@ -1 +1 @@ -Subproject commit a778f6497b2cd7f1e087c23a9db4f2a8fadfd3ed +Subproject commit a0383e95f4b4dcbd4ea14ade130005294e294bbc From 62ef19630b90219ffd602f4e5db009b74182af55 Mon Sep 17 00:00:00 2001 From: bodymovin Date: Wed, 5 Mar 2025 05:58:29 +0000 Subject: [PATCH 4/4] fix dat converter formula crash the actual crash was caused by using size_t instead of int for the index. Since it would be set to -1 at the last loop, being a size_t would set it to max int and overflow causing a crash. But for safety I decided to change when converters are deleted, following how file assets are stored and only deleted when the file is deleted. Diffs= df6ccaa5ff fix dat converter formula crash (#9168) --- .rive_head | 2 +- submodules/rive-runtime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.rive_head b/.rive_head index 80d0685f..194f6df0 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -de0026bd59569d4783370d6c95394536b4c79f3e +df6ccaa5ff68ede57ae658e8b2a3af4aedeec1a8 diff --git a/submodules/rive-runtime b/submodules/rive-runtime index a0383e95..1d9f9f83 160000 --- a/submodules/rive-runtime +++ b/submodules/rive-runtime @@ -1 +1 @@ -Subproject commit a0383e95f4b4dcbd4ea14ade130005294e294bbc +Subproject commit 1d9f9f83124fec40403a13ca2310dba25f9d1aeb