From aea901a02eaccd67ace5ec289bde46e1840939f7 Mon Sep 17 00:00:00 2001 From: Artem Umerov Date: Sat, 6 May 2023 23:16:06 +0300 Subject: [PATCH] 25 25 --- .../fenrir/activity/qr/CameraScanActivity.kt | 5 + .../ShortVideoPagerPresenter.kt | 7 + .../dev/ragnarok/fenrir/api/impl/VideoApi.kt | 6 + .../fenrir/fragment/PreferencesFragment.kt | 15 +- .../fave/faveposts/FavePostsPresenter.kt | 8 + .../newsfeedsearch/NewsFeedSearchPresenter.kt | 8 + .../search/wallsearch/WallSearchPresenter.kt | 8 + .../videopreview/VideoPreviewPresenter.kt | 8 + .../WallAudiosAttachmentsPresenter.kt | 8 + .../WallPostCommentAttachmentsPresenter.kt | 8 + .../WallPostQueryAttachmentsPresenter.kt | 8 + .../fragment/wallpost/WallPostPresenter.kt | 8 + .../photopager/PhotoPagerPresenter.kt | 47 +--- .../activity/qr/CameraScanActivity.kt | 5 + build.gradle | 8 +- .../jni/animation/libyuv/include/libyuv/row.h | 40 +++- .../animation/libyuv/include/libyuv/version.h | 2 +- .../jni/animation/libyuv/source/cpu_id.cc | 103 ++++----- .../libyuv/source/planar_functions.cc | 42 ++++ .../jni/animation/libyuv/source/row_rvv.cc | 208 +++++++++++++++--- .../thorvg/src/lib/sw_engine/tvgSwCommon.h | 4 +- .../thorvg/src/lib/sw_engine/tvgSwRaster.cpp | 45 +++- .../thorvg/src/lib/sw_engine/tvgSwRasterC.h | 24 ++ .../src/lib/sw_engine/tvgSwRenderer.cpp | 44 ++-- .../thorvg/src/lib/sw_engine/tvgSwRenderer.h | 6 +- .../src/main/jni/thorvg/src/lib/tvgCanvas.cpp | 12 +- .../src/main/jni/thorvg/src/lib/tvgCommon.h | 2 +- .../main/jni/thorvg/src/lib/tvgLoadModule.h | 6 +- .../main/jni/thorvg/src/lib/tvgPicture.cpp | 2 +- .../main/jni/thorvg/src/lib/tvgPictureImpl.h | 25 ++- .../src/main/jni/thorvg/src/lib/tvgRender.h | 29 ++- .../main/jni/thorvg/src/lib/tvgSwCanvas.cpp | 2 +- .../jni/thorvg/src/lib/tvgTaskScheduler.h | 63 ++---- .../thorvg/src/loaders/raw/tvgRawLoader.cpp | 31 +-- .../jni/thorvg/src/loaders/raw/tvgRawLoader.h | 2 +- .../thorvg/src/loaders/svg/tvgSvgLoader.cpp | 100 ++++++--- .../jni/thorvg/src/loaders/svg/tvgSvgLoader.h | 1 - .../src/loaders/svg/tvgSvgLoaderCommon.h | 18 +- .../src/loaders/svg/tvgSvgSceneBuilder.cpp | 63 +++--- .../src/loaders/svg/tvgSvgSceneBuilder.h | 2 +- material/build.gradle | 2 +- 41 files changed, 698 insertions(+), 337 deletions(-) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/qr/CameraScanActivity.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/qr/CameraScanActivity.kt index 7292ab63b..32fb7f3a3 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/qr/CameraScanActivity.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/qr/CameraScanActivity.kt @@ -473,6 +473,11 @@ class CameraScanActivity : NoMainActivity() { val height = generatedQRCode.height val pixels = IntArray(width * height) generatedQRCode.getPixels(pixels, 0, width, 0, 0, width, height) + for (i in pixels.indices) { + if (Color.alpha(pixels[i]) < 90) { + pixels[i] = Color.WHITE + } + } val source = RGBLuminanceSource(width, height, pixels) val binaryBitmap = BinaryBitmap(HybridBinarizer(source)) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/shortvideopager/ShortVideoPagerPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/shortvideopager/ShortVideoPagerPresenter.kt index 7ccfc1ea0..a88a9f563 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/shortvideopager/ShortVideoPagerPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/shortvideopager/ShortVideoPagerPresenter.kt @@ -15,6 +15,7 @@ import dev.ragnarok.fenrir.model.Commented import dev.ragnarok.fenrir.model.Video import dev.ragnarok.fenrir.model.VideoSize import dev.ragnarok.fenrir.nonNullNoEmpty +import dev.ragnarok.fenrir.settings.Settings import dev.ragnarok.fenrir.util.AppPerms.hasReadWriteStoragePermission import dev.ragnarok.fenrir.util.DownloadWorkUtils.doDownloadVideo import dev.ragnarok.fenrir.util.Pair @@ -266,6 +267,12 @@ class ShortVideoPagerPresenter( } fun fireLikeClick() { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } if (mShortVideos.isEmpty()) { return } diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/VideoApi.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/VideoApi.kt index e03416adb..7c8b35c7a 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/VideoApi.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/VideoApi.kt @@ -195,6 +195,12 @@ internal class VideoApi(accountId: Long, provider: IServiceProvider) : var finalName = name if (finalName?.startsWith("VID_", false) == true) { finalName = "Telegram $finalName" + } else if (finalName?.startsWith("VID-", false) == true && finalName.contains( + "-WA", + false + ) + ) { + finalName = "WhatsApp $finalName" } service.getVideoServer(isPrivate, group_id, finalName) .map(extractResponseWithErrorHandling()) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/PreferencesFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/PreferencesFragment.kt index 8f25b1827..2590e602b 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/PreferencesFragment.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/PreferencesFragment.kt @@ -1755,10 +1755,17 @@ class PreferencesFragment : AbsPreferencesFragment(), PreferencesAdapter.OnScree pref("account_cache_cleaner") { titleRes = R.string.account_cache_cleaner onClick { - DBHelper.removeDatabaseFor(requireActivity(), accountId) - cleanCache(requireActivity(), true) - Includes.stores.stickers().clearAccount(accountId).fromIOToMain() - .subscribe(RxUtils.dummy(), RxUtils.ignore()) + MaterialAlertDialogBuilder(requireActivity()).setIcon(R.drawable.ic_outline_delete) + .setTitle(R.string.select) + .setMessage(R.string.do_delete) + .setPositiveButton(R.string.button_yes) { _: DialogInterface?, _: Int -> + DBHelper.removeDatabaseFor(requireActivity(), accountId) + cleanCache(requireActivity(), true) + Includes.stores.stickers().clearAccount(accountId).fromIOToMain() + .subscribe(RxUtils.dummy(), RxUtils.ignore()) + } + .setNegativeButton(R.string.button_no, null) + .setCancelable(true).show() true } } diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/fave/faveposts/FavePostsPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/fave/faveposts/FavePostsPresenter.kt index 7b5a93e61..8a151978b 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/fave/faveposts/FavePostsPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/fave/faveposts/FavePostsPresenter.kt @@ -10,6 +10,8 @@ import dev.ragnarok.fenrir.domain.Repository.walls import dev.ragnarok.fenrir.fragment.base.PlaceSupportPresenter import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.model.Post +import dev.ragnarok.fenrir.settings.Settings +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.findInfoByPredicate import dev.ragnarok.fenrir.util.rxutils.RxUtils.ignore import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -140,6 +142,12 @@ class FavePostsPresenter(accountId: Long, savedInstanceState: Bundle?) : } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(wallInteractor.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { t -> onLikeError(t) }) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/newsfeedsearch/NewsFeedSearchPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/newsfeedsearch/NewsFeedSearchPresenter.kt index b333d28bc..035671ceb 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/newsfeedsearch/NewsFeedSearchPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/newsfeedsearch/NewsFeedSearchPresenter.kt @@ -14,9 +14,11 @@ import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.getParcelableCompat import dev.ragnarok.fenrir.model.Commented import dev.ragnarok.fenrir.model.Post +import dev.ragnarok.fenrir.settings.Settings import dev.ragnarok.fenrir.trimmedNonNullNoEmpty import dev.ragnarok.fenrir.util.Pair import dev.ragnarok.fenrir.util.Pair.Companion.create +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.rxutils.RxUtils.ignore import io.reactivex.rxjava3.core.Single @@ -83,6 +85,12 @@ class NewsFeedSearchPresenter( } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(walls.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { t -> diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/wallsearch/WallSearchPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/wallsearch/WallSearchPresenter.kt index 9dcd5d434..f7c2436e9 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/wallsearch/WallSearchPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/search/wallsearch/WallSearchPresenter.kt @@ -13,9 +13,11 @@ import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.getParcelableCompat import dev.ragnarok.fenrir.model.Post import dev.ragnarok.fenrir.requireNonNull +import dev.ragnarok.fenrir.settings.Settings import dev.ragnarok.fenrir.trimmedNonNullNoEmpty import dev.ragnarok.fenrir.util.Pair import dev.ragnarok.fenrir.util.Pair.Companion.create +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.rxutils.RxUtils.ignore import io.reactivex.rxjava3.core.Single @@ -100,6 +102,12 @@ class WallSearchPresenter( } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(walls.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { t -> diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewPresenter.kt index 63ca31b8f..9e92c70cb 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewPresenter.kt @@ -20,7 +20,9 @@ import dev.ragnarok.fenrir.getParcelableCompat import dev.ragnarok.fenrir.model.Commented import dev.ragnarok.fenrir.model.Owner import dev.ragnarok.fenrir.model.Video +import dev.ragnarok.fenrir.settings.Settings import dev.ragnarok.fenrir.util.Pair +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.getCauseIfRuntime import dev.ragnarok.fenrir.util.toast.CustomToast.Companion.createCustomToast @@ -298,6 +300,12 @@ class VideoPreviewPresenter( } fun fireLikeClick() { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } video?.let { val add = !it.isUserLikes appendDisposable(interactor.likeOrDislike(accountId, ownerId, videoId, accessKey, add) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallaudiosattachments/WallAudiosAttachmentsPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallaudiosattachments/WallAudiosAttachmentsPresenter.kt index 6b613f7d2..503802b9b 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallaudiosattachments/WallAudiosAttachmentsPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallaudiosattachments/WallAudiosAttachmentsPresenter.kt @@ -9,6 +9,8 @@ import dev.ragnarok.fenrir.fragment.base.PlaceSupportPresenter import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.model.Post import dev.ragnarok.fenrir.model.criteria.WallCriteria +import dev.ragnarok.fenrir.settings.Settings +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.getCauseIfRuntime import dev.ragnarok.fenrir.util.Utils.intValueIn import dev.ragnarok.fenrir.util.Utils.safeCountOf @@ -171,6 +173,12 @@ class WallAudiosAttachmentsPresenter( } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(fInteractor.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { t -> diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostcommentattachments/WallPostCommentAttachmentsPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostcommentattachments/WallPostCommentAttachmentsPresenter.kt index 68f14f521..d6bbb3b55 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostcommentattachments/WallPostCommentAttachmentsPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostcommentattachments/WallPostCommentAttachmentsPresenter.kt @@ -9,6 +9,8 @@ import dev.ragnarok.fenrir.fragment.base.PlaceSupportPresenter import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.model.Post import dev.ragnarok.fenrir.model.criteria.WallCriteria +import dev.ragnarok.fenrir.settings.Settings +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.getCauseIfRuntime import dev.ragnarok.fenrir.util.Utils.intValueIn import dev.ragnarok.fenrir.util.Utils.safeCountOf @@ -189,6 +191,12 @@ class WallPostCommentAttachmentsPresenter( } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(fInteractor.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostqueryattachments/WallPostQueryAttachmentsPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostqueryattachments/WallPostQueryAttachmentsPresenter.kt index 8dc936664..c152a4165 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostqueryattachments/WallPostQueryAttachmentsPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallattachments/wallpostqueryattachments/WallPostQueryAttachmentsPresenter.kt @@ -9,6 +9,8 @@ import dev.ragnarok.fenrir.fragment.base.PlaceSupportPresenter import dev.ragnarok.fenrir.fromIOToMain import dev.ragnarok.fenrir.model.* import dev.ragnarok.fenrir.model.criteria.WallCriteria +import dev.ragnarok.fenrir.settings.Settings +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.getCauseIfRuntime import dev.ragnarok.fenrir.util.Utils.intValueIn import dev.ragnarok.fenrir.util.Utils.safeCountOf @@ -350,6 +352,12 @@ class WallPostQueryAttachmentsPresenter( } fun fireLikeClick(post: Post) { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } appendDisposable(fInteractor.like(accountId, post.ownerId, post.vkid, !post.isUserLikes) .fromIOToMain() .subscribe(ignore()) { t -> diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallpost/WallPostPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallpost/WallPostPresenter.kt index a1d03e484..2bd794f1c 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallpost/WallPostPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wallpost/WallPostPresenter.kt @@ -26,6 +26,8 @@ import dev.ragnarok.fenrir.model.ParcelableOwnerWrapper import dev.ragnarok.fenrir.model.Post import dev.ragnarok.fenrir.nonNullNoEmpty import dev.ragnarok.fenrir.requireNonNull +import dev.ragnarok.fenrir.settings.Settings +import dev.ragnarok.fenrir.util.Utils import dev.ragnarok.fenrir.util.Utils.getCauseIfRuntime import dev.ragnarok.fenrir.util.rxutils.RxUtils.ignore @@ -255,6 +257,12 @@ class WallPostPresenter( } fun fireLikeClick() { + if (Settings.get().other().isDisable_likes || Utils.isHiddenAccount( + accountId + ) + ) { + return + } if (post != null) { appendDisposable(wallInteractor.like( accountId, diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/photopager/PhotoPagerPresenter.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/photopager/PhotoPagerPresenter.kt index 669baa10d..525d3bbed 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/photopager/PhotoPagerPresenter.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/photopager/PhotoPagerPresenter.kt @@ -7,7 +7,6 @@ import android.content.pm.ResolveInfo import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri -import android.os.Build import android.os.Bundle import androidx.browser.customtabs.CustomTabColorSchemeParams import androidx.browser.customtabs.CustomTabsIntent @@ -15,10 +14,10 @@ import androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTI import androidx.core.net.toFile import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.zxing.* -import com.google.zxing.common.HybridBinarizer import com.squareup.picasso3.BitmapTarget import com.squareup.picasso3.Picasso import dev.ragnarok.filegallery.R +import dev.ragnarok.filegallery.activity.qr.CameraScanActivity import dev.ragnarok.filegallery.fragment.base.RxSupportPresenter import dev.ragnarok.filegallery.model.Photo import dev.ragnarok.filegallery.model.Video @@ -32,8 +31,6 @@ import dev.ragnarok.filegallery.util.DownloadWorkUtils.doDownloadPhoto import dev.ragnarok.filegallery.util.Utils import java.io.File import java.util.Calendar -import java.util.EnumMap -import java.util.EnumSet open class PhotoPagerPresenter internal constructor( initialData: ArrayList, @@ -151,46 +148,6 @@ open class PhotoPagerPresenter internal constructor( return false } - internal fun decodeFromBitmap(gen: Bitmap?): String? { - if (gen == null) { - return "error" - } - var generatedQRCode: Bitmap? = gen - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && generatedQRCode?.config == Bitmap.Config.HARDWARE) { - generatedQRCode = generatedQRCode.copy(Bitmap.Config.ARGB_8888, true) - } - if (generatedQRCode == null) { - return "error" - } - val width: Int = generatedQRCode.width - val height: Int = generatedQRCode.height - val pixels = IntArray(width * height) - generatedQRCode.getPixels(pixels, 0, width, 0, 0, width, height) - val source = RGBLuminanceSource(width, height, pixels) - val binaryBitmap = BinaryBitmap(HybridBinarizer(source)) - val reader = MultiFormatReader() - val hints: MutableMap = EnumMap(DecodeHintType::class.java) - hints[DecodeHintType.POSSIBLE_FORMATS] = EnumSet.of( - BarcodeFormat.QR_CODE, - BarcodeFormat.EAN_13, - BarcodeFormat.EAN_8, - BarcodeFormat.RSS_14, - BarcodeFormat.CODE_39, - BarcodeFormat.CODE_93, - BarcodeFormat.CODE_128, - BarcodeFormat.ITF - ) - reader.setHints(hints) - val result: Result = try { - reader.decodeWithState(binaryBitmap) - } catch (e: Exception) { - return e.localizedMessage - } ?: run { - return "error" - } - return result.text - } - @Suppress("deprecation") private fun getCustomTabsPackages(context: Context): ArrayList { val pm = context.packageManager @@ -241,7 +198,7 @@ open class PhotoPagerPresenter internal constructor( PicassoInstance.with().load(current.photo_url) .into(object : BitmapTarget { override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { - val data = decodeFromBitmap(bitmap) + val data = CameraScanActivity.decodeFromBitmap(bitmap) MaterialAlertDialogBuilder(context) .setIcon(R.drawable.qr_code) .setMessage(data) diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/qr/CameraScanActivity.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/qr/CameraScanActivity.kt index bca547db6..8b804ba20 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/qr/CameraScanActivity.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/activity/qr/CameraScanActivity.kt @@ -473,6 +473,11 @@ class CameraScanActivity : NoMainActivity() { val height = generatedQRCode.height val pixels = IntArray(width * height) generatedQRCode.getPixels(pixels, 0, width, 0, 0, width, height) + for (i in pixels.indices) { + if (Color.alpha(pixels[i]) < 90) { + pixels[i] = Color.WHITE + } + } val source = RGBLuminanceSource(width, height, pixels) val binaryBitmap = BinaryBitmap(HybridBinarizer(source)) diff --git a/build.gradle b/build.gradle index 303dd39bb..e6ac29ba2 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ buildscript { ext.recyclerviewVersion = "1.3.0" ext.savedStateVersion = "1.2.1" ext.swiperefreshlayoutVersion = "1.2.0-alpha01" - ext.tracingVersion = "1.2.0-beta03" + ext.tracingVersion = "1.2.0-beta04" ext.transitionVersion = "1.4.1" ext.vectordrawableVersion = "1.2.0-beta01" ext.webkitVersion = "1.7.0-beta01" @@ -58,7 +58,7 @@ buildscript { //common libraries ext.kotlin_version = "1.8.21" - ext.kotlin_coroutines = "1.7.0-RC" + ext.kotlin_coroutines = "1.7.0" ext.kotlin_serializer = "1.5.0" ext.okhttpLibraryVersion = "5.0.0-alpha.11" ext.okioVersion = "3.3.0" @@ -66,7 +66,7 @@ buildscript { ext.guavaVersion = "31.1-android" ext.errorproneVersion = "2.15.0" ext.checkerCompatQualVersion = "2.5.5" - ext.checkerQualAndroidVersion = "3.33.0" + ext.checkerQualAndroidVersion = "3.34.0" ext.desugarLibraryVersion = "2.0.3" //APP_PROPS @@ -91,7 +91,7 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:8.0.0" + classpath "com.android.tools.build:gradle:8.0.1" classpath "com.google.gms:google-services:4.3.15" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" diff --git a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h index 176b37814..6e973bcfe 100644 --- a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h +++ b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h @@ -757,13 +757,19 @@ extern "C" { #define HAS_RAWTOYJROW_LASX #endif -#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) #define HAS_AB64TOARGBROW_RVV #define HAS_AR64TOARGBROW_RVV #define HAS_ARGBTOAB64ROW_RVV #define HAS_ARGBTOAR64ROW_RVV #define HAS_ARGBTORAWROW_RVV #define HAS_ARGBTORGB24ROW_RVV +#define HAS_MERGEARGBROW_RVV +#define HAS_MERGERGBROW_RVV +#define HAS_MERGEXRGBROW_RVV +#define HAS_SPLITARGBROW_RVV +#define HAS_SPLITRGBROW_RVV +#define HAS_SPLITXRGBROW_RVV #define HAS_RAWTOARGBROW_RVV #define HAS_RAWTORGB24ROW_RVV #define HAS_RAWTORGBAROW_RVV @@ -2282,6 +2288,11 @@ void SplitRGBRow_NEON(const uint8_t* src_rgb, uint8_t* dst_g, uint8_t* dst_b, int width); +void SplitRGBRow_RVV(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); void SplitRGBRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, @@ -2308,6 +2319,11 @@ void MergeRGBRow_NEON(const uint8_t* src_r, const uint8_t* src_b, uint8_t* dst_rgb, int width); +void MergeRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); void MergeRGBRow_Any_SSSE3(const uint8_t* y_buf, const uint8_t* u_buf, const uint8_t* v_buf, @@ -2342,6 +2358,12 @@ void MergeARGBRow_NEON(const uint8_t* src_r, const uint8_t* src_a, uint8_t* dst_argb, int width); +void MergeARGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + const uint8_t* src_a, + uint8_t* dst_argb, + int width); void MergeARGBRow_Any_SSE2(const uint8_t* y_buf, const uint8_t* u_buf, const uint8_t* v_buf, @@ -2390,6 +2412,12 @@ void SplitARGBRow_NEON(const uint8_t* src_rgba, uint8_t* dst_b, uint8_t* dst_a, int width); +void SplitARGBRow_RVV(const uint8_t* src_rgba, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + uint8_t* dst_a, + int width); void SplitARGBRow_Any_SSE2(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, @@ -2434,6 +2462,11 @@ void MergeXRGBRow_NEON(const uint8_t* src_r, const uint8_t* src_b, uint8_t* dst_argb, int width); +void MergeXRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_argb, + int width); void MergeXRGBRow_Any_SSE2(const uint8_t* y_buf, const uint8_t* u_buf, const uint8_t* v_buf, @@ -2474,6 +2507,11 @@ void SplitXRGBRow_NEON(const uint8_t* src_rgba, uint8_t* dst_g, uint8_t* dst_b, int width); +void SplitXRGBRow_RVV(const uint8_t* src_rgba, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); void SplitXRGBRow_Any_SSE2(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, diff --git a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/version.h b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/version.h index a7a656351..7f41b76cf 100644 --- a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/version.h +++ b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1866 +#define LIBYUV_VERSION 1867 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/libfenrir/src/main/jni/animation/libyuv/source/cpu_id.cc b/libfenrir/src/main/jni/animation/libyuv/source/cpu_id.cc index d5202c8d0..0c4a1581c 100644 --- a/libfenrir/src/main/jni/animation/libyuv/source/cpu_id.cc +++ b/libfenrir/src/main/jni/animation/libyuv/source/cpu_id.cc @@ -40,7 +40,6 @@ extern "C" { // cpu_info_ variable for SIMD instruction sets detected. LIBYUV_API int cpu_info_ = 0; -// TODO(fbarchard): Consider using int for cpuid so casting is not needed. // Low level cpuid for X86. #if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ defined(__x86_64__)) && \ @@ -143,7 +142,8 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { // This will occur for Chrome sandbox for Pepper or Render process. return kCpuHasNEON; } - while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) { + memset(cpuinfo_line, 0, sizeof(cpuinfo_line)); + while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) { if (memcmp(cpuinfo_line, "Features", 8) == 0) { char* p = strstr(cpuinfo_line, " neon"); if (p && (p[5] == ' ' || p[5] == '\n')) { @@ -162,38 +162,9 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { return 0; } -// TODO(fbarchard): Consider read_msa_ir(). -LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name) { - char cpuinfo_line[512]; - int flag = 0x0; - FILE* f = fopen(cpuinfo_name, "re"); - if (!f) { - // Assume nothing if /proc/cpuinfo is unavailable. - // This will occur for Chrome sandbox for Pepper or Render process. - return 0; - } - while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) { - if (memcmp(cpuinfo_line, "cpu model", 9) == 0) { - // Workaround early kernel without MSA in ASEs line. - if (strstr(cpuinfo_line, "Loongson-2K")) { - flag |= kCpuHasMSA; - } - } - if (memcmp(cpuinfo_line, "ASEs implemented", 16) == 0) { - if (strstr(cpuinfo_line, "msa")) { - flag |= kCpuHasMSA; - } - // ASEs is the last line, so we can break here. - break; - } - } - fclose(f); - return flag; -} - LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) { char cpuinfo_line[512]; - int flag = 0x0; + int flag = 0; FILE* f = fopen(cpuinfo_name, "re"); if (!f) { #if defined(__riscv_vector) @@ -204,43 +175,47 @@ LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) { return 0; #endif } - while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) { + memset(cpuinfo_line, 0, sizeof(cpuinfo_line)); + while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) { if (memcmp(cpuinfo_line, "isa", 3) == 0) { // ISA string must begin with rv64{i,e,g} for a 64-bit processor. char* isa = strstr(cpuinfo_line, "rv64"); if (isa) { - const int isa_len = strlen(isa); - // 5 ISA characters + 1 new-line character - if (isa_len < 6) { + size_t isa_len = strlen(isa); + char* extensions; + size_t extensions_len = 0; + size_t std_isa_len; + // Remove the new-line character at the end of string + if (isa[isa_len - 1] == '\n') { + isa[--isa_len] = '\0'; + } + // 5 ISA characters + if (isa_len < 5) { fclose(f); return 0; } // Skip {i,e,g} canonical checking. // Skip rvxxx isa += 5; - // Find the very first occurrence of 's', 'x' or 'z'. // To detect multi-letter standard, non-standard, and // supervisor-level extensions. - int otherExts_len = 0; - char* otherExts = strpbrk(isa, "zxs"); - if (otherExts) { - otherExts_len = strlen(otherExts); + extensions = strpbrk(isa, "zxs"); + if (extensions) { // Multi-letter extensions are seperated by a single underscore // as described in RISC-V User-Level ISA V2.2. - char* ext = strtok(otherExts, "_"); + char* ext = strtok(extensions, "_"); + extensions_len = strlen(extensions); while (ext) { // Search for the ZVFH (Vector FP16) extension. - // The ZVFH implied the (Scalar FP16)ZFH extension. - if (!strcmp(ext, "zvfh") || !strcmp(ext, "zvfh\n")) { + if (!strcmp(ext, "zvfh")) { flag |= kCpuHasRVVZVFH; } ext = strtok(NULL, "_"); } } - const int std_isa_len = isa_len - otherExts_len - 5 - 1; + std_isa_len = isa_len - extensions_len - 5; // Detect the v in the standard single-letter extensions. - // Skip optional Zve* and Zvl* extensions detection at otherExts. if (memchr(isa, 'v', std_isa_len)) { // The RVV implied the F extension. flag |= kCpuHasRVV; @@ -248,9 +223,11 @@ LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) { } } #if defined(__riscv_vector) + // Assume RVV if /proc/cpuinfo is from x86 host running QEMU. else if ((memcmp(cpuinfo_line, "vendor_id\t: GenuineIntel", 24) == 0) || (memcmp(cpuinfo_line, "vendor_id\t: AuthenticAMD", 24) == 0)) { - flag |= kCpuHasRVV; + fclose(f); + return kCpuHasRVV; } #endif } @@ -258,14 +235,42 @@ LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) { return flag; } -// TODO(fbarchard): Consider read_loongarch_ir(). +LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name) { + char cpuinfo_line[512]; + int flag = 0; + FILE* f = fopen(cpuinfo_name, "re"); + if (!f) { + // Assume nothing if /proc/cpuinfo is unavailable. + // This will occur for Chrome sandbox for Pepper or Render process. + return 0; + } + memset(cpuinfo_line, 0, sizeof(cpuinfo_line)); + while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) { + if (memcmp(cpuinfo_line, "cpu model", 9) == 0) { + // Workaround early kernel without MSA in ASEs line. + if (strstr(cpuinfo_line, "Loongson-2K")) { + flag |= kCpuHasMSA; + } + } + if (memcmp(cpuinfo_line, "ASEs implemented", 16) == 0) { + if (strstr(cpuinfo_line, "msa")) { + flag |= kCpuHasMSA; + } + // ASEs is the last line, so we can break here. + break; + } + } + fclose(f); + return flag; +} + #define LOONGARCH_CFG2 0x2 #define LOONGARCH_CFG2_LSX (1 << 6) #define LOONGARCH_CFG2_LASX (1 << 7) #if defined(__loongarch__) LIBYUV_API SAFEBUFFERS int LoongarchCpuCaps(void) { - int flag = 0x0; + int flag = 0; uint32_t cfg2 = 0; __asm__ volatile("cpucfg %0, %1 \n\t" : "+&r"(cfg2) : "r"(LOONGARCH_CFG2)); diff --git a/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc b/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc index b5a2e1a03..c6f9d5c75 100644 --- a/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc +++ b/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc @@ -1268,6 +1268,11 @@ void SplitRGBPlane(const uint8_t* src_rgb, } } #endif +#if defined(HAS_SPLITRGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + SplitRGBRow = SplitRGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { // Copy a row of RGB. @@ -1327,6 +1332,11 @@ void MergeRGBPlane(const uint8_t* src_r, } } #endif +#if defined(HAS_MERGERGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + MergeRGBRow = MergeRGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { // Merge a row of U and V into a row of RGB. @@ -1358,6 +1368,9 @@ static void SplitARGBPlaneAlpha(const uint8_t* src_argb, assert(height > 0); + if (width <= 0 || height == 0) { + return; + } if (src_stride_argb == width * 4 && dst_stride_r == width && dst_stride_g == width && dst_stride_b == width && dst_stride_a == width) { width *= height; @@ -1398,6 +1411,11 @@ static void SplitARGBPlaneAlpha(const uint8_t* src_argb, } } #endif +#if defined(HAS_SPLITARGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + SplitARGBRow = SplitARGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { SplitARGBRow(src_argb, dst_r, dst_g, dst_b, dst_a, width); @@ -1425,6 +1443,9 @@ static void SplitARGBPlaneOpaque(const uint8_t* src_argb, uint8_t* dst_b, int width) = SplitXRGBRow_C; assert(height > 0); + if (width <= 0 || height == 0) { + return; + } if (src_stride_argb == width * 4 && dst_stride_r == width && dst_stride_g == width && dst_stride_b == width) { width *= height; @@ -1464,6 +1485,11 @@ static void SplitARGBPlaneOpaque(const uint8_t* src_argb, } } #endif +#if defined(HAS_SPLITXRGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + SplitXRGBRow = SplitXRGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { SplitXRGBRow(src_argb, dst_r, dst_g, dst_b, width); @@ -1530,6 +1556,9 @@ static void MergeARGBPlaneAlpha(const uint8_t* src_r, assert(height > 0); + if (width <= 0 || height == 0) { + return; + } if (src_stride_r == width && src_stride_g == width && src_stride_b == width && src_stride_a == width && dst_stride_argb == width * 4) { width *= height; @@ -1561,6 +1590,11 @@ static void MergeARGBPlaneAlpha(const uint8_t* src_r, } } #endif +#if defined(HAS_MERGEARGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + MergeARGBRow = MergeARGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { MergeARGBRow(src_r, src_g, src_b, src_a, dst_argb, width); @@ -1590,6 +1624,9 @@ static void MergeARGBPlaneOpaque(const uint8_t* src_r, assert(height > 0); + if (width <= 0 || height == 0) { + return; + } if (src_stride_r == width && src_stride_g == width && src_stride_b == width && dst_stride_argb == width * 4) { width *= height; @@ -1620,6 +1657,11 @@ static void MergeARGBPlaneOpaque(const uint8_t* src_r, } } #endif +#if defined(HAS_MERGEXRGBROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + MergeXRGBRow = MergeXRGBRow_RVV; + } +#endif for (y = 0; y < height; ++y) { MergeXRGBRow(src_r, src_g, src_b, dst_argb, width); diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc index bd21d44e6..956ed9f95 100644 --- a/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc +++ b/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc @@ -19,7 +19,7 @@ #include "libyuv/row.h" -#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) #include #ifdef __cplusplus @@ -99,85 +99,223 @@ void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { } void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); - width -= vl; - src_raw += (3 * vl); - dst_argb += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); - width -= vl; - src_raw += (3 * vl); - dst_rgba += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_rgba += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_raw, vl); __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_r, v_g, v_b, vl); - width -= vl; - src_raw += (3 * vl); - dst_rgb24 += (3 * vl); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_rgb24 += vl * 3; + } while (w > 0); } void ARGBToRAWRow_RVV(const uint8_t* src_argb, uint8_t* dst_raw, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r, v_a; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); __riscv_vsseg3e8_v_u8m2(dst_raw, v_r, v_g, v_b, vl); - width -= vl; - src_argb += (4 * vl); - dst_raw += (3 * vl); - } while (width > 0); + w -= vl; + src_argb += vl * 4; + dst_raw += vl * 3; + } while (w > 0); } void ARGBToRGB24Row_RVV(const uint8_t* src_argb, uint8_t* dst_rgb24, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r, v_a; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); - width -= vl; - src_argb += (4 * vl); - dst_rgb24 += (3 * vl); - } while (width > 0); + w -= vl; + src_argb += vl * 4; + dst_rgb24 += vl * 3; + } while (w > 0); } void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_argb, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_rgb24, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); - width -= vl; - src_rgb24 += (3 * vl); - dst_argb += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_rgb24 += vl * 3; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); +} + +void SplitRGBRow_RVV(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_rgb, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_rgb += vl * 3; + } while (w > 0); +} + +void MergeRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_r = __riscv_vle8_v_u8m2(src_r, vl); + vuint8m2_t v_g = __riscv_vle8_v_u8m2(src_g, vl); + vuint8m2_t v_b = __riscv_vle8_v_u8m2(src_b, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb, v_r, v_g, v_b, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + dst_rgb += vl * 3; + } while (w > 0); +} + +void SplitARGBRow_RVV(const uint8_t* src_argb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + uint8_t* dst_a, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vse8_v_u8m2(dst_a, v_a, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_a += vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_argb += vl * 4; + } while (w > 0); +} + +void MergeARGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + const uint8_t* src_a, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_r = __riscv_vle8_v_u8m2(src_r, vl); + vuint8m2_t v_g = __riscv_vle8_v_u8m2(src_g, vl); + vuint8m2_t v_b = __riscv_vle8_v_u8m2(src_b, vl); + vuint8m2_t v_a = __riscv_vle8_v_u8m2(src_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + src_a += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void SplitXRGBRow_RVV(const uint8_t* src_argb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_argb += vl * 4; + } while (w > 0); +} + +void MergeXRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + vuint8m2_t v_r, v_g, v_b; + v_r = __riscv_vle8_v_u8m2(src_r, vl); + v_g = __riscv_vle8_v_u8m2(src_g, vl); + v_b = __riscv_vle8_v_u8m2(src_b, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } #ifdef __cplusplus @@ -185,4 +323,4 @@ void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, } // namespace libyuv #endif -#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwCommon.h b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwCommon.h index 3e26990a5..04b56ffdf 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwCommon.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwCommon.h @@ -358,6 +358,8 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); bool rasterClear(SwSurface* surface); void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); -void rasterUnpremultiply(SwSurface* surface); +void rasterUnpremultiply(Surface* surface); +void rasterPremultiply(Surface* surface); +bool rasterConvertCS(Surface* surface, ColorSpace to); #endif /* _TVG_SW_COMMON_H_ */ diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRaster.cpp b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRaster.cpp index c49a05953..41416dfff 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRaster.cpp +++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRaster.cpp @@ -1452,10 +1452,10 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) bool rasterCompositor(SwSurface* surface) { - if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) { + if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) { surface->blender.join = _abgrJoin; surface->blender.lumaValue = _abgrLumaValue; - } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { + } else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) { surface->blender.join = _argbJoin; surface->blender.lumaValue = _argbLumaValue; } else { @@ -1481,8 +1481,10 @@ bool rasterClear(SwSurface* surface) } -void rasterUnpremultiply(SwSurface* surface) +void rasterUnpremultiply(Surface* surface) { + TVGLOG("SW_ENGINE", "Unpremultiply [Size: %d x %d]", surface->w, surface->h); + //OPTIMIZE_ME: +SIMD for (uint32_t y = 0; y < surface->h; y++) { auto buffer = surface->buffer + surface->stride * y; @@ -1503,6 +1505,25 @@ void rasterUnpremultiply(SwSurface* surface) } } } + surface->premultiplied = false; +} + + +void rasterPremultiply(Surface* surface) +{ + TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); + + //OPTIMIZE_ME: +SIMD + auto buffer = surface->buffer; + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w; ++x, ++dst) { + auto c = *dst; + auto a = (c >> 24); + *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); + } + } + surface->premultiplied = true; } @@ -1572,4 +1593,22 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con //TODO: case: _rasterAlphaImageMesh() if (mesh && mesh->triangleCnt > 0) return _transformedRGBAImageMesh(surface, image, mesh, transform, &bbox, opacity); else return _rasterRGBAImage(surface, image, transform, bbox, opacity); +} + + +bool rasterConvertCS(Surface* surface, ColorSpace to) +{ + //TOOD: Support SIMD accelerations + auto from = surface->cs; + + if ((from == ColorSpace::ABGR8888 && to == ColorSpace::ARGB8888) || (from == ColorSpace::ABGR8888S && to == ColorSpace::ARGB8888S)) { + surface->cs = to; + return cRasterABGRtoARGB(surface); + } + if ((from == ColorSpace::ARGB8888 && to == ColorSpace::ABGR8888) || (from == ColorSpace::ARGB8888S && to == ColorSpace::ABGR8888S)) { + surface->cs = to; + return cRasterARGBtoABGR(surface); + } + + return false; } \ No newline at end of file diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterC.h b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterC.h index 18118aaed..fb19b1ee9 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterC.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterC.h @@ -61,3 +61,27 @@ static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& regi } return true; } + + +static bool inline cRasterABGRtoARGB(Surface* surface) +{ + TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB [Size: %d x %d]", surface->w, surface->h); + + auto buffer = surface->buffer; + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w; ++x, ++dst) { + auto c = *dst; + //flip Blue, Red channels + *dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16); + } + } + return true; +} + + +static bool inline cRasterARGBtoABGR(Surface* surface) +{ + //exactly same with ABGRtoARGB + return cRasterABGRtoARGB(surface); +} \ No newline at end of file diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp index d69b21561..bc35ebb8f 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp @@ -167,6 +167,9 @@ struct SwShapeTask : SwTask } } + //Clear current task memorypool here if the clippers would use the same memory pool + shapeDelOutline(&shape, mpool, tid); + //Clip Path for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { auto clipper = static_cast(*clip); @@ -177,11 +180,10 @@ struct SwShapeTask : SwTask //Clip stroke rle if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; } - goto end; + return; err: shapeReset(&shape); - end: shapeDelOutline(&shape, mpool, tid); } @@ -258,6 +260,7 @@ struct SwSceneTask : SwTask struct SwImageTask : SwTask { SwImage image; + Surface* source; //Image source const RenderMesh* mesh = nullptr; //Should be valid ptr in action bool clip(SwRleData* target) override @@ -276,6 +279,17 @@ struct SwImageTask : SwTask { auto clipRegion = bbox; + //Convert colorspace if it's not aligned. + if (source->owner) { + if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); + if (!source->premultiplied) rasterPremultiply(source); + } + + image.data = source->buffer; + image.w = source->w; + image.h = source->h; + image.stride = source->stride; + //Invisible shape turned to visible by alpha. if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) { imageReset(&image); @@ -287,17 +301,19 @@ struct SwImageTask : SwTask if (mesh->triangleCnt == 0 && clips.count > 0) { if (!imageGenRle(&image, bbox, false)) goto end; if (image.rle) { + //Clear current task memorypool here if the clippers would use the same memory pool + imageDelOutline(&image, mpool, tid); for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { auto clipper = static_cast(*clip); //Guarantee composition targets get ready. clipper->done(tid); if (!clipper->clip(image.rle)) goto err; } + return; } } } goto end; - err: rleReset(image.rle); end: @@ -407,7 +423,7 @@ bool SwRenderer::viewport(const RenderRegion& vp) } -bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace) +bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs) { if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false; @@ -417,7 +433,9 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t surface->stride = stride; surface->w = w; surface->h = h; - surface->cs = colorSpace; + surface->cs = cs; + surface->premultiplied = true; + surface->owner = true; vport.x = vport.y = 0; vport.w = surface->w; @@ -447,7 +465,7 @@ void SwRenderer::clearCompositors() bool SwRenderer::postRender() { //Unmultiply alpha if needed - if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { + if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) { rasterUnpremultiply(surface); } @@ -709,16 +727,13 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, } -RenderData SwRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) { //prepare task auto task = static_cast(data); if (!task) task = new SwImageTask; if (flags & RenderUpdateFlag::Image) { - task->image.data = image->buffer; - task->image.w = image->w; - task->image.h = image->h; - task->image.stride = image->stride; + task->source = surface; task->mesh = mesh; } return prepareCommon(task, transform, opacity, clips, flags); @@ -755,13 +770,6 @@ SwRenderer::SwRenderer():mpool(globalMpool) } -uint32_t SwRenderer::colorSpace() -{ - if (surface) return surface->cs; - return tvg::SwCanvas::ARGB8888; -} - - bool SwRenderer::init(uint32_t threads) { if ((initEngineCnt++) > 0) return true; diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.h b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.h index 6eff37823..e8847598f 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRenderer.h @@ -38,7 +38,7 @@ class SwRenderer : public RenderMethod public: RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; - RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; bool renderImage(RenderData data) override; @@ -50,7 +50,7 @@ class SwRenderer : public RenderMethod bool clear() override; bool sync() override; - bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace); + bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs); bool mempool(bool shared); Compositor* target(const RenderRegion& region) override; @@ -58,8 +58,6 @@ class SwRenderer : public RenderMethod bool endComposite(Compositor* cmp) override; void clearCompositors(); - uint32_t colorSpace() override; - static SwRenderer* gen(); static bool init(uint32_t threads); static int32_t init(); diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgCanvas.cpp b/libfenrir/src/main/jni/thorvg/src/lib/tvgCanvas.cpp index 843073502..95c66b94d 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgCanvas.cpp +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgCanvas.cpp @@ -58,13 +58,21 @@ Result Canvas::clear(bool free) noexcept Result Canvas::draw() noexcept { - return pImpl->draw(); + TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this); + auto ret = pImpl->draw(); + TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this); + + return ret; } Result Canvas::update(Paint* paint) noexcept { - return pImpl->update(paint, false); + TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this); + auto ret = pImpl->update(paint, false); + TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this); + + return ret; } diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgCommon.h b/libfenrir/src/main/jni/thorvg/src/lib/tvgCommon.h index d7bd58410..1731647c0 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgCommon.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgCommon.h @@ -72,7 +72,7 @@ enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown }; constexpr auto GreyColor = "\033[90m"; //grey constexpr auto ResetColors = "\033[0m"; //default #define TVGERR(tag, fmt, ...) fprintf(stderr, "%s[E]%s %s" tag "%s (%s %d): %s" fmt "\n", ErrorBgColor, ResetColors, ErrorColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__) - #define TVGLOG(tag, fmt, ...) fprintf(stderr, "%s[L]%s %s" tag "%s (%s %d): %s" fmt "\n", LogBgColor, ResetColors, LogColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__) + #define TVGLOG(tag, fmt, ...) fprintf(stdout, "%s[L]%s %s" tag "%s (%s %d): %s" fmt "\n", LogBgColor, ResetColors, LogColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__) #else #define TVGERR(...) #define TVGLOG(...) diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgLoadModule.h b/libfenrir/src/main/jni/thorvg/src/lib/tvgLoadModule.h index 4637c90d8..ee7c0c119 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgLoadModule.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgLoadModule.h @@ -36,8 +36,8 @@ class LoadModule float vy = 0; float vw = 0; float vh = 0; - float w = 0, h = 0; //default image size - uint32_t colorSpace = SwCanvas::ARGB8888; + float w = 0, h = 0; //default image size + ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open() virtual ~LoadModule() {} @@ -50,7 +50,7 @@ class LoadModule virtual bool read() = 0; virtual bool close() = 0; - virtual unique_ptr bitmap(uint32_t colorSpace) { return nullptr; } + virtual unique_ptr bitmap() { return nullptr; } virtual unique_ptr paint() { return nullptr; } }; diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgPicture.cpp b/libfenrir/src/main/jni/thorvg/src/lib/tvgPicture.cpp index 98ffe9017..897f7849c 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgPicture.cpp +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgPicture.cpp @@ -107,7 +107,7 @@ Result Picture::size(float* w, float* h) const noexcept const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept { //Try it, If not loaded yet. - pImpl->reload(); + pImpl->load(); if (pImpl->loader) { if (w) *w = static_cast(pImpl->loader->w); diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgPictureImpl.h b/libfenrir/src/main/jni/thorvg/src/lib/tvgPictureImpl.h index 92bb0baf3..b4d28e707 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgPictureImpl.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgPictureImpl.h @@ -66,14 +66,13 @@ struct Picture::Impl Surface* surface = nullptr; //bitmap picture uses RenderData rd = nullptr; //engine data float w = 0, h = 0; - uint32_t rendererColorSpace = 0; RenderMesh rm; //mesh data bool resizing = false; ~Impl() { if (paint) delete(paint); - free(surface); + delete(surface); } bool dispose(RenderMethod& renderer) @@ -86,7 +85,7 @@ struct Picture::Impl return ret; } - uint32_t reload() + uint32_t load() { if (loader) { if (!paint) { @@ -104,10 +103,11 @@ struct Picture::Impl if (paint) return RenderUpdateFlag::None; } } - free(surface); - if ((surface = loader->bitmap(rendererColorSpace).release())) { - loader->close(); - return RenderUpdateFlag::Image; + if (!surface) { + if ((surface = loader->bitmap().release())) { + loader->close(); + return RenderUpdateFlag::Image; + } } } return RenderUpdateFlag::None; @@ -129,8 +129,7 @@ struct Picture::Impl RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag, bool clipper) { - rendererColorSpace = renderer.colorSpace(); - auto flag = reload(); + auto flag = load(); if (surface) { auto transform = resizeTransform(pTransform); @@ -267,7 +266,7 @@ struct Picture::Impl Paint* duplicate() { - reload(); + load(); auto ret = Picture::gen(); @@ -276,8 +275,10 @@ struct Picture::Impl dup->loader = loader; if (surface) { - dup->surface = static_cast(malloc(sizeof(Surface))); + dup->surface = new Surface; *dup->surface = *surface; + //TODO: A dupilcation is not a proxy... it needs copy of the pixel data? + dup->surface->owner = false; } dup->w = w; dup->h = h; @@ -294,7 +295,7 @@ struct Picture::Impl Iterator* iterator() { - reload(); + load(); return new PictureIterator(paint); } }; diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgRender.h b/libfenrir/src/main/jni/thorvg/src/lib/tvgRender.h index b113e091a..8f9e7ce02 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgRender.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgRender.h @@ -29,18 +29,31 @@ namespace tvg { +using RenderData = void*; + enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; +struct Surface; + +enum ColorSpace +{ + ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. + ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. + ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. + ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. + Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace. +}; + struct Surface { - //TODO: Union for multiple types uint32_t* buffer; - uint32_t stride; - uint32_t w, h; - uint32_t cs; -}; + uint32_t stride; + uint32_t w, h; + ColorSpace cs; -using RenderData = void*; + bool premultiplied; //Alpha-premultiplied + bool owner; //Only owner could modify the buffer +}; struct Compositor { @@ -199,7 +212,7 @@ class RenderMethod virtual ~RenderMethod() {} virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) = 0; virtual RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; - virtual RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; + virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; virtual bool preRender() = 0; virtual bool renderShape(RenderData data) = 0; virtual bool renderImage(RenderData data) = 0; @@ -215,8 +228,6 @@ class RenderMethod virtual Compositor* target(const RenderRegion& region) = 0; virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0; virtual bool endComposite(Compositor* cmp) = 0; - - virtual uint32_t colorSpace() = 0; }; } diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgSwCanvas.cpp b/libfenrir/src/main/jni/thorvg/src/lib/tvgSwCanvas.cpp index 325fb3392..626bd51a2 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgSwCanvas.cpp +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgSwCanvas.cpp @@ -85,7 +85,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t auto renderer = static_cast(Canvas::pImpl->renderer); if (!renderer) return Result::MemoryCorruption; - if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments; + if (!renderer->target(buffer, stride, w, h, static_cast(cs))) return Result::InvalidArguments; //Paints must be updated again with this new target. Canvas::pImpl->needRefresh(); diff --git a/libfenrir/src/main/jni/thorvg/src/lib/tvgTaskScheduler.h b/libfenrir/src/main/jni/thorvg/src/lib/tvgTaskScheduler.h index cad887513..a3954c6dd 100644 --- a/libfenrir/src/main/jni/thorvg/src/lib/tvgTaskScheduler.h +++ b/libfenrir/src/main/jni/thorvg/src/lib/tvgTaskScheduler.h @@ -43,77 +43,40 @@ struct TaskScheduler struct Task { private: - mutex finishedMtx; - mutex preparedMtx; + mutex mtx; condition_variable cv; - bool finished = true; //if run() finished - bool prepared = false; //the task is requested + bool ready = true; + bool pending = false; public: - virtual ~Task() - { - if (!prepared) return; - - //Guarantee the task is finished by TaskScheduler. - unique_lock lock(preparedMtx); - - while (prepared) { - cv.wait(lock); - } - } + virtual ~Task() = default; void done(unsigned tid = 0) { - if (finished) return; - - lock_guard lock(finishedMtx); + if (!pending) return; - if (finished) return; - - //the job hasn't been launched yet. - - //set finished so that operator() quickly returns. - finished = true; - - run(tid); + unique_lock lock(mtx); + while (!ready) cv.wait(lock); + pending = false; } protected: virtual void run(unsigned tid) = 0; private: - void finish() - { - lock_guard lock(preparedMtx); - prepared = false; - cv.notify_one(); - } - void operator()(unsigned tid) { - if (finished) { - finish(); - return; - } - - lock_guard lock(finishedMtx); - - if (finished) { - finish(); - return; - } - run(tid); - finished = true; - - finish(); + lock_guard lock(mtx); + ready = true; + cv.notify_one(); } void prepare() { - finished = false; - prepared = true; + ready = false; + pending = true; } friend struct TaskSchedulerImpl; diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.cpp b/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.cpp index 749b70917..d81de06c7 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.cpp +++ b/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.cpp @@ -29,22 +29,6 @@ /* Internal Class Implementation */ /************************************************************************/ -static inline uint32_t CHANGE_COLORSPACE(uint32_t c) -{ - return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16); -} - - -static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h) -{ - auto buffer = data; - for (uint32_t y = 0; y < h; ++y, buffer += w) { - auto src = buffer; - for (uint32_t x = 0; x < w; ++x, ++src) { - *src = CHANGE_COLORSPACE(*src); - } - } -} /************************************************************************/ /* External Class Implementation */ @@ -74,6 +58,8 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) } else content = const_cast(data); + cs = ColorSpace::ARGB8888; + return true; } @@ -90,20 +76,19 @@ bool RawLoader::close() } -unique_ptr RawLoader::bitmap(uint32_t colorSpace) +unique_ptr RawLoader::bitmap() { if (!content) return nullptr; - if (this->colorSpace != colorSpace) { - this->colorSpace = colorSpace; - _changeColorSpace(content, static_cast(w), static_cast(h)); - } - auto surface = static_cast(malloc(sizeof(Surface))); + //TODO: It's better to keep this surface instance in the loader side + auto surface = new Surface; surface->buffer = content; surface->stride = static_cast(w); surface->w = static_cast(w); surface->h = static_cast(h); - surface->cs = colorSpace; + surface->cs = cs; + surface->premultiplied = true; + surface->owner = true; return unique_ptr(surface); } diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.h b/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.h index a5e3d5936..69f9bdc47 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.h +++ b/libfenrir/src/main/jni/thorvg/src/loaders/raw/tvgRawLoader.h @@ -36,7 +36,7 @@ class RawLoader : public LoadModule bool read() override; bool close() override; - unique_ptr bitmap(uint32_t colorSpace) override; + unique_ptr bitmap() override; }; diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 0eee115a3..3b1dc9e97 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -864,10 +864,18 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) if (!strcmp(key, "width")) { doc->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); - doc->viewFlag = (doc->viewFlag | SvgViewFlag::Width); + if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::WidthInPercent); + } else { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::Width); + } } else if (!strcmp(key, "height")) { doc->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical); - doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height); + if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::HeightInPercent); + } else { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height); + } } else if (!strcmp(key, "viewBox")) { if (_parseNumber(&value, &doc->vx)) { if (_parseNumber(&value, &doc->vy)) { @@ -3472,7 +3480,8 @@ SvgLoader::~SvgLoader() void SvgLoader::run(unsigned tid) { //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering - if (renderingDisabled) { + if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) { + TVGLOG("SVG", "The width and/or height set to 0 - rendering disabled."); root = Scene::gen(); return; } @@ -3495,7 +3504,7 @@ void SvgLoader::run(unsigned tid) if (loaderData.gradients.count > 0) _updateGradient(&loaderData, loaderData.doc, &loaderData.gradients); if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients); } - root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath, viewFlag); + root = svgSceneBuild(loaderData, {vx, vy, vw, vh}, w, h, align, meetOrSlice, svgPath, viewFlag); } @@ -3516,35 +3525,70 @@ bool SvgLoader::header() viewFlag = loaderData.doc->node.doc.viewFlag; align = loaderData.doc->node.doc.align; meetOrSlice = loaderData.doc->node.doc.meetOrSlice; - w = 1.0f; - h = 1.0f; - //Return the brief resource info such as viewbox: - if (viewFlag & SvgViewFlag::Width) { - w = loaderData.doc->node.doc.w; - } - if (viewFlag & SvgViewFlag::Height) { - h = loaderData.doc->node.doc.h; - } - //Override size if (viewFlag & SvgViewFlag::Viewbox) { vx = loaderData.doc->node.doc.vx; vy = loaderData.doc->node.doc.vy; vw = loaderData.doc->node.doc.vw; vh = loaderData.doc->node.doc.vh; - if (!(viewFlag & SvgViewFlag::Width)) w = vw; - if (!(viewFlag & SvgViewFlag::Height)) h = vh; + if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w; + else { + w = loaderData.doc->node.doc.vw; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w *= loaderData.doc->node.doc.w; + viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Width); + } + if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h; + else { + h = loaderData.doc->node.doc.vh; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h *= loaderData.doc->node.doc.h; + viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Height); + } + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. } else { - vw = w; - vh = h; + //Before loading, set default viewbox & size if they are empty + vx = vy = 0.0f; + if (viewFlag & SvgViewFlag::Width) { + vw = w = loaderData.doc->node.doc.w; + } else { + vw = 1.0f; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w = loaderData.doc->node.doc.w; + } else w = 1.0f; + } + + if (viewFlag & SvgViewFlag::Height) { + vh = h = loaderData.doc->node.doc.h; + } else { + vh = 1.0f; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h = loaderData.doc->node.doc.h; + } else h = 1.0f; + } + + run(0); + + //Override viewbox & size again after svg loading. + vx = loaderData.doc->node.doc.vx; + vy = loaderData.doc->node.doc.vy; + vw = loaderData.doc->node.doc.vw; + vh = loaderData.doc->node.doc.vh; + w = loaderData.doc->node.doc.w; + h = loaderData.doc->node.doc.h; } - } else { - TVGLOG("SVG", "No SVG File. There is no "); - return false; + + return true; } - return true; + TVGLOG("SVG", "No SVG File. There is no "); + return false; } @@ -3604,19 +3648,11 @@ bool SvgLoader::read() { if (!content || size == 0) return false; - if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) { - TVGLOG("SVG", "The width and/or height set to 0 - rendering disabled."); - renderingDisabled = true; - } + //the loading has been already completed in header() + if (root) return true; TaskScheduler::request(this); - //In case no viewbox and width/height data is provided the completion of loading - //has to be forced, in order to establish this data based on the whole picture bounding box. - if (!(viewFlag & SvgViewFlag::Viewbox) && (!(viewFlag & SvgViewFlag::Width) || !(viewFlag & SvgViewFlag::Height))) { - this->done(); - } - return true; } diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.h b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.h index 43882b7fb..5c74184ec 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.h +++ b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoader.h @@ -54,7 +54,6 @@ class SvgLoader : public LoadModule, public Task SvgViewFlag viewFlag = SvgViewFlag::None; AspectRatioAlign align = AspectRatioAlign::XMidYMid; AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet; - bool renderingDisabled = false; bool header(); void clear(); diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h index e66000f60..dec9fadeb 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h @@ -219,7 +219,9 @@ enum class SvgViewFlag None = 0x0, Width = 0x01, //viewPort width Height = 0x02, //viewPort height - Viewbox = 0x04 //viewBox x,y,w,h - used only if all 4 are correctly set + Viewbox = 0x04, //viewBox x,y,w,h - used only if all 4 are correctly set + WidthInPercent = 0x08, + HeightInPercent = 0x10 }; constexpr bool operator &(SvgViewFlag a, SvgViewFlag b) @@ -232,6 +234,11 @@ constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b) return SvgViewFlag(int(a) | int(b)); } +constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b) +{ + return SvgViewFlag(int(a) ^ int(b)); +} + enum class AspectRatioAlign { None, @@ -254,8 +261,8 @@ enum class AspectRatioMeetOrSlice struct SvgDocNode { - float w; - float h; + float w; //unit: point or in percentage see: SvgViewFlag + float h; //unit: point or in percentage see: SvgViewFlag float vx; float vy; float vw; @@ -546,6 +553,11 @@ struct SvgLoaderData bool style = false; }; +struct Box +{ + float x, y, w, h; +}; + /* * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017 * diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp index 2a33e382e..c5e5df893 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -61,11 +61,6 @@ /* Internal Class Implementation */ /************************************************************************/ -struct Box -{ - float x, y, w, h; -}; - static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath); static unique_ptr _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr); @@ -763,46 +758,45 @@ static unique_ptr _sceneBuildHelper(const SvgNode* node, const Box& vBox, } -static void _applySvgViewFlag(const Scene* scene, float& vx, float& vy, float& vw, float& vh, float& w, float& h, SvgViewFlag viewFlag) +static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, float& h, SvgViewFlag viewFlag) { - bool noViewbox = !(viewFlag & SvgViewFlag::Viewbox); - bool noWidth = !(viewFlag & SvgViewFlag::Width); - bool noHeight = !(viewFlag & SvgViewFlag::Height); - - if (noViewbox) { - float x, y; - scene->bounds(&x, &y, &vw, &vh, false); - if (noWidth && noHeight) { - vx = x; - vy = y; - } else { - vw = noWidth ? vw : w; - vh = noHeight ? vh : h; - } + bool validWidth = (viewFlag & SvgViewFlag::Width); + bool validHeight = (viewFlag & SvgViewFlag::Height); + + float x, y; + scene->bounds(&x, &y, &vBox.w, &vBox.h, false); + if (!validWidth && !validHeight) { + vBox.x = x; + vBox.y = y; + } else { + if (validWidth) vBox.w = w; + if (validHeight) vBox.h = h; } - w = noWidth ? vw : w; - h = noHeight ? vh : h; + + //the size would have 1x1 or percentage values. + if (!validWidth) w *= vBox.w; + if (!validHeight) h *= vBox.h; } /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -unique_ptr svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw, float& vh, float& w, float& h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) +unique_ptr svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) { //TODO: aspect ratio is valid only if viewBox was set - if (!node || (node->type != SvgNodeType::Doc)) return nullptr; + if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr; - Box vBox = {vx, vy, vw, vh}; - auto docNode = _sceneBuildHelper(node, vBox, svgPath, false, 0); - _applySvgViewFlag(docNode.get(), vx, vy, vw, vh, w, h, viewFlag); + auto docNode = _sceneBuildHelper(loaderData.doc, vBox, svgPath, false, 0); - if (!mathEqual(w, vw) || !mathEqual(h, vh)) { - Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, {vx, vy, vw, vh}); + if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag); + + if (!mathEqual(w, vBox.w) || !mathEqual(h, vBox.h)) { + Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox); docNode->transform(m); - } else if (!mathZero(vx) || !mathZero(vy)) { - docNode->translate(-vx, -vy); + } else if (!mathZero(vBox.x) || !mathZero(vBox.y)) { + docNode->translate(-vBox.x, -vBox.y); } auto viewBoxClip = Shape::gen(); @@ -816,5 +810,12 @@ unique_ptr svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw, auto root = Scene::gen(); root->push(move(compositeLayer)); + loaderData.doc->node.doc.vx = vBox.x; + loaderData.doc->node.doc.vy = vBox.y; + loaderData.doc->node.doc.vw = vBox.w; + loaderData.doc->node.doc.vh = vBox.h; + loaderData.doc->node.doc.w = w; + loaderData.doc->node.doc.h = h; + return root; } diff --git a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h index 0de8c9a7d..f6a60f850 100644 --- a/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h +++ b/libfenrir/src/main/jni/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h @@ -25,6 +25,6 @@ #include "tvgCommon.h" -unique_ptr svgSceneBuild(SvgNode* node, float& vx, float& vy, float& vw, float& vh, float& w, float& h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); +unique_ptr svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); #endif //_TVG_SVG_SCENE_BUILDER_H_ diff --git a/material/build.gradle b/material/build.gradle index 5711913cd..16dec5bfb 100644 --- a/material/build.gradle +++ b/material/build.gradle @@ -3,7 +3,7 @@ plugins { id("kotlin-android") } -//1.9.0-rc01 +//1.9.0 def srcDirs = [ 'com/google/android/material/animation',