> :
LinearLayoutManager(requireActivity(), LinearLayoutManager.HORIZONTAL, false)
mStoryAdapter = HorizontalStoryAdapter(mutableListOf())
mStoryAdapter?.setListener(object : HorizontalStoryAdapter.Listener {
- override fun onOptionClick(item: Story, pos: Int) {
+ override fun onStoryClick(item: Story, pos: Int) {
openHistoryVideo(
Settings.get().accounts().current, ArrayList(
presenter?.stories ?: emptyList()
), pos
)
}
+
+ override fun onStoryLongClick(item: Story, pos: Int): Boolean {
+ PlaceFactory.getLikesCopiesPlace(
+ Settings.get().accounts().current,
+ "stories_view",
+ item.ownerId,
+ item.id,
+ null
+ ).tryOpenWith(requireActivity())
+ return true
+ }
})
headerStoryRecyclerView.adapter = mStoryAdapter
mWallAdapter = WallAdapter(requireActivity(), mutableListOf(), this, this)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/IAttachmentsPlacesView.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/IAttachmentsPlacesView.kt
index df21a0539..819aadef7 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/IAttachmentsPlacesView.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/IAttachmentsPlacesView.kt
@@ -45,8 +45,8 @@ interface IAttachmentsPlacesView {
fun openPoll(accountId: Long, apiPoll: Poll)
fun openSearch(accountId: Long, @SearchContentType type: Int, criteria: BaseSearchCriteria?)
fun openComments(accountId: Long, commented: Commented, focusToCommentId: Int?)
- fun goToLikes(accountId: Long, type: String?, ownerId: Long, id: Int)
- fun goToReposts(accountId: Long, type: String?, ownerId: Long, id: Int)
+ fun goToLikes(accountId: Long, type: String, ownerId: Long, id: Int)
+ fun goToReposts(accountId: Long, type: String, ownerId: Long, id: Int)
fun repostPost(accountId: Long, post: Post)
fun openStory(accountId: Long, story: Story)
fun openAudioPlaylist(accountId: Long, playlist: AudioPlaylist)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportMvpFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportMvpFragment.kt
index 11c885e27..ff0287afa 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportMvpFragment.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportMvpFragment.kt
@@ -324,7 +324,7 @@ abstract class PlaceSupportMvpFragment, V> : BaseMv
.tryOpenWith(requireActivity())
}
- override fun goToLikes(accountId: Long, type: String?, ownerId: Long, id: Int) {
+ override fun goToLikes(accountId: Long, type: String, ownerId: Long, id: Int) {
PlaceFactory.getLikesCopiesPlace(
accountId,
type,
@@ -335,7 +335,7 @@ abstract class PlaceSupportMvpFragment
, V> : BaseMv
.tryOpenWith(requireActivity())
}
- override fun goToReposts(accountId: Long, type: String?, ownerId: Long, id: Int) {
+ override fun goToReposts(accountId: Long, type: String, ownerId: Long, id: Int) {
PlaceFactory.getLikesCopiesPlace(
accountId,
type,
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportPresenter.kt
index bc16d233b..f1b8d5687 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportPresenter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/PlaceSupportPresenter.kt
@@ -155,7 +155,7 @@ abstract class PlaceSupportPresenter(accountId: Long, savedInstanceState: Bun
}
}
- fun fireCopiesLikesClick(type: String?, ownerId: Long, itemId: Int, filter: String?) {
+ fun fireCopiesLikesClick(type: String, ownerId: Long, itemId: Int, filter: String?) {
if (ILikesInteractor.FILTER_LIKES == filter) {
view?.goToLikes(accountId, type, ownerId, itemId)
} else if (ILikesInteractor.FILTER_COPIES == filter) {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/horizontal/HorizontalStoryAdapter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/horizontal/HorizontalStoryAdapter.kt
index d1e28d918..57732b383 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/horizontal/HorizontalStoryAdapter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/base/horizontal/HorizontalStoryAdapter.kt
@@ -61,7 +61,13 @@ class HorizontalStoryAdapter(data: MutableList) :
Constants.PICASSO_TAG
)
}
- viewHolder.itemView.setOnClickListener { listener?.onOptionClick(item, position) }
+ viewHolder.itemView.setOnClickListener { listener?.onStoryClick(item, position) }
+ viewHolder.itemView.setOnLongClickListener {
+ listener?.onStoryLongClick(
+ item,
+ position
+ ) == true
+ }
}
override fun viewHolder(view: View, type: Int): Holder {
@@ -77,7 +83,8 @@ class HorizontalStoryAdapter(data: MutableList) :
}
interface Listener {
- fun onOptionClick(item: Story, pos: Int)
+ fun onStoryClick(item: Story, pos: Int)
+ fun onStoryLongClick(item: Story, pos: Int): Boolean
}
class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedFragment.kt
index 49c99f7fb..376fee010 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedFragment.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedFragment.kt
@@ -298,7 +298,7 @@ class FeedFragment : PlaceSupportMvpFragment(), IFeedV
return true
}
- override fun goToLikes(accountId: Long, type: String?, ownerId: Long, id: Int) {
+ override fun goToLikes(accountId: Long, type: String, ownerId: Long, id: Int) {
getLikesCopiesPlace(
accountId,
type,
@@ -308,7 +308,7 @@ class FeedFragment : PlaceSupportMvpFragment(), IFeedV
).tryOpenWith(requireActivity())
}
- override fun goToReposts(accountId: Long, type: String?, ownerId: Long, id: Int) {
+ override fun goToReposts(accountId: Long, type: String, ownerId: Long, id: Int) {
getLikesCopiesPlace(
accountId,
type,
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedPresenter.kt
index f32b853e4..690e259c2 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedPresenter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/FeedPresenter.kt
@@ -398,7 +398,7 @@ class FeedPresenter(accountId: Long, savedInstanceState: Bundle?) :
fun fireNewsShareLongClick(news: News) {
view?.goToReposts(
accountId,
- news.type,
+ news.type.orEmpty(),
news.sourceId,
news.postId
)
@@ -407,7 +407,7 @@ class FeedPresenter(accountId: Long, savedInstanceState: Bundle?) :
fun fireNewsLikeLongClick(news: News) {
view?.goToLikes(
accountId,
- news.type,
+ news.type.orEmpty(),
news.sourceId,
news.postId
)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/IFeedView.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/IFeedView.kt
index 07bf59a85..3475c3abf 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/IFeedView.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feed/IFeedView.kt
@@ -18,8 +18,8 @@ interface IFeedView : IAttachmentsPlacesView, IMvpView, IErrorView {
fun showRefreshing(refreshing: Boolean)
fun scrollFeedSourcesToPosition(position: Int)
fun scrollTo(pos: Int)
- override fun goToLikes(accountId: Long, type: String?, ownerId: Long, id: Int)
- override fun goToReposts(accountId: Long, type: String?, ownerId: Long, id: Int)
+ override fun goToLikes(accountId: Long, type: String, ownerId: Long, id: Int)
+ override fun goToReposts(accountId: Long, type: String, ownerId: Long, id: Int)
fun goToPostComments(accountId: Long, postId: Int, ownerId: Long)
fun showSuccessToast()
fun askToReload()
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedbackvkofficial/FeedbackVKOfficialAdapter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
index 0611c7fb7..0e711020a 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
@@ -63,7 +63,11 @@ class FeedbackVKOfficialAdapter(
if (IconRes == null && Page.iconURL == null) {
if (isSmall) {
holder.small.visibility = View.VISIBLE
- holder.small.setImageResource(R.drawable.client_round)
+ holder.small.setImageResource(
+ if (Settings.get()
+ .other().isRunes_show
+ ) R.drawable.client_round else R.drawable.client_round_vk
+ )
Utils.setColorFilter(
holder.small, CurrentTheme.getColorPrimary(
context
@@ -71,7 +75,11 @@ class FeedbackVKOfficialAdapter(
)
} else {
holder.small.visibility = View.INVISIBLE
- holder.avatar.setImageResource(R.drawable.client_round)
+ holder.avatar.setImageResource(
+ if (Settings.get()
+ .other().isRunes_show
+ ) R.drawable.client_round else R.drawable.client_round_vk
+ )
Utils.setColorFilter(
holder.avatar, CurrentTheme.getColorPrimary(
context
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/likes/LikesFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/likes/LikesFragment.kt
index cd48c2026..c88a694bb 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/likes/LikesFragment.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/likes/LikesFragment.kt
@@ -14,7 +14,11 @@ class LikesFragment : AbsOwnersListFragment(accountId, savedInstanceState) {
private val likesInteractor: ILikesInteractor = InteractorFactory.createLikesInteractor()
@@ -29,22 +29,39 @@ class LikesListPresenter(
loadingNow = true
//this.loadingOffset = offset;
resolveRefreshingView()
- netDisposable.add(likesInteractor.getLikes(
- accountId,
- type,
- ownerId,
- itemId,
- filter,
- 50,
- offset
- )
- .fromIOToMain()
- .subscribe({ owners ->
- onDataReceived(
- offset,
- owners
- )
- }) { t -> onDataGetError(t) })
+ if (type == "stories_view") {
+ netDisposable.add(likesInteractor.getStoriesViewers(
+ accountId,
+ ownerId,
+ itemId,
+ 50,
+ offset
+ )
+ .fromIOToMain()
+ .subscribe({ owners ->
+ onDataReceived(
+ offset,
+ owners
+ )
+ }) { t -> onDataGetError(t) })
+ } else {
+ netDisposable.add(likesInteractor.getLikes(
+ accountId,
+ type,
+ ownerId,
+ itemId,
+ filter,
+ 50,
+ offset
+ )
+ .fromIOToMain()
+ .subscribe({ owners ->
+ onDataReceived(
+ offset,
+ owners
+ )
+ }) { t -> onDataGetError(t) })
+ }
}
private fun onDataGetError(t: Throwable) {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewFragment.kt
index 901e3c424..7f253229f 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewFragment.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/videopreview/VideoPreviewFragment.kt
@@ -458,8 +458,8 @@ class VideoPreviewFragment : BaseMvpFragment()) {
if (video.externalLink?.contains("youtube") == true) {
when {
- AppPrefs.isVancedYoutubeInstalled(requireActivity()) -> {
- playWithYoutubeVanced(video)
+ AppPrefs.isReVancedYoutubeInstalled(requireActivity()) -> {
+ playWithYoutubeReVanced(video)
}
AppPrefs.isNewPipeInstalled(requireActivity()) -> {
@@ -660,7 +660,7 @@ class VideoPreviewFragment : BaseMvpFragment playWithYoutube(video)
- Menu.YOUTUBE_VANCED -> playWithYoutubeVanced(video)
+ Menu.YOUTUBE_VANCED -> playWithYoutubeReVanced(video)
Menu.COUB -> playWithCoub(video)
Menu.PLAY_ANOTHER_SOFT -> video.externalLink?.let { playWithExternalSoftware(it) }
Menu.PLAY_BROWSER -> video.player?.let { playWithExternalSoftware(it) }
@@ -812,14 +812,14 @@ class VideoPreviewFragment : BaseMvpFragment? = null
+
fun isCoubInstalled(context: Context): Boolean {
return isPackageIntalled(context, "com.coub.android")
}
@@ -17,8 +19,21 @@ object AppPrefs {
return isPackageIntalled(context, "com.google.android.youtube")
}
- fun isVancedYoutubeInstalled(context: Context): Boolean {
- return isPackageIntalled(context, "app.revanced.android.youtube")
+ fun isReVancedYoutubeInstalled(context: Context): Boolean {
+ if (isPackageIntalled(context, "app.revanced.android.youtube")) {
+ revanced = Pair(
+ "app.revanced.android.youtube",
+ "com.google.android.apps.youtube.app.application.Shell\$UrlActivity"
+ )
+ return true
+ } else if (isPackageIntalled(context, "app.rvx.android.youtube")) {
+ revanced = Pair(
+ "app.rvx.android.youtube",
+ "com.google.android.apps.youtube.app.application.Shell\$UrlActivity"
+ )
+ return true
+ }
+ return false
}
@Suppress("deprecation")
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/ISettings.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/ISettings.kt
index 5c0ff18e3..6cd6570c4 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/ISettings.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/ISettings.kt
@@ -223,6 +223,7 @@ interface ISettings {
val isSnow_mode: Boolean
val photoRoundMode: Int
val fontSize: Int
+ val fontOnlyForChats: Boolean
val isLoad_history_notif: Boolean
val isDont_write: Boolean
val isOver_ten_attach: Boolean
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/MainSettings.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/MainSettings.kt
index 27ff25200..d609dfb20 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/MainSettings.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/MainSettings.kt
@@ -145,11 +145,10 @@ internal class MainSettings(context: Context) : IMainSettings {
0
}
override val fontSize: Int
- get() = try {
- defaultPreferences.getString("font_size", "0")?.trim { it <= ' ' }?.toInt() ?: 0
- } catch (e: Exception) {
- 0
- }
+ get() = defaultPreferences.getInt("font_size_int", 0)
+
+ override val fontOnlyForChats: Boolean
+ get() = defaultPreferences.getBoolean("font_only_for_chats", false)
override fun setPrefDisplayImageSize(@PhotoSize size: Int) {
defaultPreferences
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/SecuritySettings.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/SecuritySettings.kt
index e029c5864..e13187317 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/SecuritySettings.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/SecuritySettings.kt
@@ -208,7 +208,7 @@ class SecuritySettings internal constructor(context: Context) : ISecuritySetting
private const val KEY_HIDDEN_PEERS = "hidden_peers"
private const val pinHistoryDepth = 3
- internal fun extractPinEnterHistrory(preferences: SharedPreferences): ArrayList {
+ internal fun extractPinEnterHistory(preferences: SharedPreferences): ArrayList {
val set = preferences.getStringSet(KEY_PIN_ENTER_HISTORY, null)
val result = ArrayList(safeCountOf(set))
if (set != null) {
@@ -235,9 +235,9 @@ class SecuritySettings internal constructor(context: Context) : ISecuritySetting
init {
mPinHash = mPrefs.getString(KEY_PIN_HASH, null)
- mPinEnterHistory = extractPinEnterHistrory(mPrefs)
+ mPinEnterHistory = extractPinEnterHistory(mPrefs)
mKeyEncryptionPolicyAccepted = mPrefs.getBoolean(KEY_ENCRYPTION_POLICY_ACCEPTED, false)
hiddenPeers = Collections.synchronizedSet(HashSet(1))
reloadHiddenDialogSettings()
}
-}
\ No newline at end of file
+}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/backup/SettingsBackup.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/backup/SettingsBackup.kt
index ab89197ae..c894a6cbe 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/backup/SettingsBackup.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/settings/backup/SettingsBackup.kt
@@ -40,7 +40,8 @@ class SettingsBackup {
var player_cover_transform: String? = null
var pref_display_photo_size: Int? = null
var photo_rounded_view: String? = null
- var font_size: String? = null
+ var font_size_int: Int? = null
+ var font_only_for_chats: Boolean? = null
var is_open_url_internal: String? = null
var webview_night_mode: Boolean? = null
var load_history_notif: Boolean? = null
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/Utils.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/Utils.kt
index 86211bfe4..3671e60c3 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/Utils.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/Utils.kt
@@ -915,17 +915,11 @@ object Utils {
}
fun setTint(view: ImageView?, @ColorInt color: Int) {
- if (view == null) {
- return
- }
- view.imageTintList = ColorStateList.valueOf(color)
+ view?.imageTintList = ColorStateList.valueOf(color)
}
fun setBackgroundTint(view: View?, @ColorInt color: Int) {
- if (view == null) {
- return
- }
- view.backgroundTintList = ColorStateList.valueOf(color)
+ view?.backgroundTintList = ColorStateList.valueOf(color)
}
@Suppress("DEPRECATION")
@@ -1440,7 +1434,7 @@ object Utils {
}
}
- fun updateActivityContext(base: Context): Context {
+ fun updateActivityContext(base: Context, isChatActivity: Boolean = false): Context {
if (getSystemLocale(base.resources.configuration) != null && getSystemLocale(base.resources.configuration)?.language.nonNullNoEmpty()) {
Constants.DEVICE_COUNTRY_CODE =
getSystemLocale(base.resources.configuration)?.language?.lowercase(Locale.getDefault())
@@ -1453,7 +1447,7 @@ object Utils {
val locale = getLocaleSettings(lang)
updateDateLang(locale)
updateDateLang()
- return if (size == 0) {
+ return if (size == 0 || Settings.get().main().fontOnlyForChats && !isChatActivity) {
if (lang == Lang.DEFAULT) {
base
} else {
@@ -1465,7 +1459,7 @@ object Utils {
} else {
val res = base.resources
val config = Configuration(res.configuration)
- config.fontScale = res.configuration.fontScale + 0.15f * size
+ config.fontScale = res.configuration.fontScale + 0.05f * size
if (lang != Lang.DEFAULT) {
setSystemLocaleLegacy(config, getLocaleSettings(lang))
}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/JsonElementSerializers.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/JsonElementSerializers.kt
index 2c9333d87..08e3ba12c 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/JsonElementSerializers.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/JsonElementSerializers.kt
@@ -15,7 +15,7 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonElement].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonElement].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
* Currently, this hierarchy has no guarantees on descriptor content.
*
@@ -26,7 +26,6 @@ import kotlinx.serialization.encoding.Encoder
* assertEquals(JsonObject(mapOf("key" to JsonLiteral(1.0))), literal)
* ```
*/
-@Serializer(forClass = JsonElement::class)
@PublishedApi
internal object JsonElementSerializer : KSerializer {
@OptIn(InternalSerializationApi::class)
@@ -59,10 +58,9 @@ internal object JsonElementSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonPrimitive].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonPrimitive].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonPrimitive::class)
@PublishedApi
internal object JsonPrimitiveSerializer : KSerializer {
@OptIn(InternalSerializationApi::class)
@@ -93,10 +91,9 @@ internal object JsonPrimitiveSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonNull].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonNull].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonNull::class)
@PublishedApi
internal object JsonNullSerializer : KSerializer {
// technically, JsonNull is an object, but it does not call beginStructure/endStructure at all
@@ -166,10 +163,9 @@ private object JsonLiteralSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonObject].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonObject].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonObject::class)
@PublishedApi
internal object JsonObjectSerializer : KSerializer {
@@ -197,10 +193,9 @@ internal object JsonObjectSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonArray].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonArray].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonArray::class)
@PublishedApi
internal object JsonArraySerializer : KSerializer {
@@ -223,11 +218,11 @@ internal object JsonArraySerializer : KSerializer {
}
}
-internal fun verify(encoder: Encoder) {
+private fun verify(encoder: Encoder) {
encoder.asJsonEncoder()
}
-internal fun verify(decoder: Decoder) {
+private fun verify(decoder: Decoder) {
decoder.asJsonDecoder()
}
@@ -249,7 +244,7 @@ internal fun Encoder.asJsonEncoder() = this as? JsonEncoder
* Used to resolve cyclic dependencies between recursive serializable structures.
*/
@OptIn(ExperimentalSerializationApi::class)
-internal fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object : SerialDescriptor {
+private fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object : SerialDescriptor {
private val original: SerialDescriptor by lazy(deferred)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/JsonNamesMap.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/JsonNamesMap.kt
index 3648be28f..d041e091f 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/JsonNamesMap.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/JsonNamesMap.kt
@@ -108,12 +108,16 @@ internal fun SerialDescriptor.getJsonNameIndexOrThrow(
@OptIn(ExperimentalSerializationApi::class)
internal inline fun Json.tryCoerceValue(
elementDescriptor: SerialDescriptor,
- peekNull: () -> Boolean,
+ peekNull: (consume: Boolean) -> Boolean,
peekString: () -> String?,
onEnumCoercing: () -> Unit = {}
): Boolean {
- if (!elementDescriptor.isNullable && peekNull()) return true
+ if (!elementDescriptor.isNullable && peekNull(true)) return true
if (elementDescriptor.kind == SerialKind.ENUM) {
+ if (elementDescriptor.isNullable && peekNull(false)) {
+ return false
+ }
+
val enumValue = peekString()
?: return false // if value is not a string, decodeEnum() will throw correct exception
val enumIndex = elementDescriptor.getJsonNameIndex(this, enumValue)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/StreamingJsonDecoder.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/StreamingJsonDecoder.kt
index 6b2029264..38b3967d2 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/StreamingJsonDecoder.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/StreamingJsonDecoder.kt
@@ -17,6 +17,7 @@ import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.AbstractDecoder
+import kotlinx.serialization.encoding.ChunkedDecoder
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE
import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME
@@ -34,7 +35,7 @@ internal open class StreamingJsonDecoder(
@JvmField internal val lexer: AbstractJsonLexer,
descriptor: SerialDescriptor,
private var discriminatorHolder: DiscriminatorHolder?
-) : JsonDecoder, AbstractDecoder() {
+) : JsonDecoder, ChunkedDecoder, AbstractDecoder() {
// A mutable reference to the discriminator that have to be skipped when in optimistic phase
// of polymorphic serialization, see `decodeSerializableValue`
@@ -93,7 +94,6 @@ internal open class StreamingJsonDecoder(
}
discriminatorHolder = DiscriminatorHolder(discriminator)
-
@Suppress("UNCHECKED_CAST")
return actualSerializer.deserialize(this) as T
@@ -149,7 +149,7 @@ internal open class StreamingJsonDecoder(
}
override fun decodeNotNullMark(): Boolean {
- return !(elementMarker?.isUnmarkedNull ?: false) && lexer.tryConsumeNotNull()
+ return !(elementMarker?.isUnmarkedNull ?: false) && !lexer.tryConsumeNull()
}
override fun decodeNull(): Nothing? {
@@ -225,7 +225,7 @@ internal open class StreamingJsonDecoder(
private fun coerceInputValue(descriptor: SerialDescriptor, index: Int): Boolean =
json.tryCoerceValue(
descriptor.getElementDescriptor(index),
- { !lexer.tryConsumeNotNull() },
+ { lexer.tryConsumeNull(it) },
{ lexer.peekString(configuration.isLenient) },
{ lexer.consumeString() /* skip unknown enum string*/ }
)
@@ -362,6 +362,10 @@ internal open class StreamingJsonDecoder(
}
}
+ override fun decodeStringChunked(consumeChunk: (chunk: String) -> Unit) {
+ lexer.consumeStringChunked(configuration.isLenient, consumeChunk)
+ }
+
override fun decodeInline(descriptor: SerialDescriptor): Decoder =
if (descriptor.isUnsignedNumber) JsonDecoderForUnsignedTypes(lexer, json)
else super.decodeInline(descriptor)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
index 8fedd4514..e349d97e7 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
@@ -251,25 +251,28 @@ internal abstract class AbstractJsonLexer {
/**
* Tries to consume `null` token from input.
- * Returns `true` if the next 4 chars in input are not `null`,
- * `false` otherwise and consumes it.
+ * Returns `false` if the next 4 chars in input are not `null`,
+ * `true` otherwise and consumes it if [doConsume] is `true`.
*/
- fun tryConsumeNotNull(): Boolean {
+ fun tryConsumeNull(doConsume: Boolean = true): Boolean {
var current = skipWhitespaces()
current = prefetchOrEof(current)
// Cannot consume null due to EOF, maybe something else
val len = source.length - current
- if (len < 4 || current == -1) return true
+ if (len < 4 || current == -1) return false
for (i in 0..3) {
- if (NULL[i] != source[current + i]) return true
+ if (NULL[i] != source[current + i]) return false
}
/*
* If we're in lenient mode, this might be the string with 'null' prefix,
* distinguish it from 'null'
*/
- if (len > 4 && charToTokenClass(source[current + 4]) == TC_OTHER) return true
- currentPosition = current + 4
- return false
+ if (len > 4 && charToTokenClass(source[current + 4]) == TC_OTHER) return false
+
+ if (doConsume) {
+ currentPosition = current + 4
+ }
+ return true
}
open fun skipWhitespaces(): Int {
@@ -314,6 +317,66 @@ internal abstract class AbstractJsonLexer {
*/
abstract fun consumeKeyString(): String
+ private fun insideString(isLenient: Boolean, char: Char): Boolean = if (isLenient) {
+ charToTokenClass(char) == TC_OTHER
+ } else {
+ char != STRING
+ }
+
+ open fun consumeStringChunked(
+ isLenient: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) { // open to allow simpler implementations (i.e. StringJsonLexer)
+ val nextToken = peekNextToken()
+ if (isLenient && nextToken != TC_OTHER) return // noting to consume
+
+ if (!isLenient) {
+ consumeNextToken(STRING)
+ }
+ var currentPosition = this.currentPosition
+ var lastPosition = currentPosition
+ var char = source[currentPosition] // Avoid two range checks visible in the profiler
+ var usedAppend = false
+ while (insideString(isLenient, char)) {
+ if (!isLenient && char == STRING_ESC) { // handle escaping only in non-lenient mode
+ usedAppend = true
+ currentPosition = prefetchOrEof(appendEscape(lastPosition, currentPosition))
+ lastPosition = currentPosition
+ } else {
+ currentPosition++
+ }
+ if (currentPosition >= source.length) {
+ // end of chunk
+ writeRange(lastPosition, currentPosition, usedAppend, consumeChunk)
+ usedAppend = false
+ currentPosition = prefetchOrEof(currentPosition)
+ if (currentPosition == -1)
+ fail("EOF", currentPosition)
+ lastPosition = currentPosition
+ }
+ char = source[currentPosition]
+ }
+ writeRange(lastPosition, currentPosition, usedAppend, consumeChunk)
+ this.currentPosition = currentPosition
+ if (!isLenient) {
+ consumeNextToken(STRING)
+ }
+ }
+
+ private fun writeRange(
+ fromIndex: Int,
+ toIndex: Int,
+ currentChunkHasEscape: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) {
+ if (currentChunkHasEscape) {
+ consumeChunk(decodedString(fromIndex, toIndex))
+ } else {
+ consumeChunk(substring(fromIndex, toIndex))
+ }
+ }
+
+
fun consumeString(): String {
if (peekedString != null) {
return takePeeked()
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/StringJsonLexer.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/StringJsonLexer.kt
index 97559e8bb..7af16e29d 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/StringJsonLexer.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/json/internal/lexer/StringJsonLexer.kt
@@ -103,6 +103,14 @@ internal class StringJsonLexer(override val source: String) : AbstractJsonLexer(
return source.substring(current, closingQuote)
}
+ override fun consumeStringChunked(
+ isLenient: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) {
+ (if (isLenient) consumeStringLenient() else consumeString()).chunked(BATCH_SIZE)
+ .forEach(consumeChunk)
+ }
+
override fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? {
val positionSnapshot = currentPosition
try {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/MsgPackTreeReader.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/MsgPackTreeReader.kt
index 891709378..89f8a6a5e 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/MsgPackTreeReader.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/MsgPackTreeReader.kt
@@ -32,7 +32,7 @@ internal class MsgPackTreeReader(
.joinToNumber()
type == MsgPackType.Array.ARRAY32 -> {
- if (basicMsgPackDecoder.configuration.preventOverflows) {
+ if (basicMsgPackDecoder.getConfiguration().preventOverflows) {
val number = basicMsgPackDecoder.dataBuffer.takeNext(4).joinToNumber()
if (number !in Int.MIN_VALUE..Int.MAX_VALUE) {
throw MsgPackSerializationException.overflowError(basicMsgPackDecoder.dataBuffer)
@@ -64,7 +64,7 @@ internal class MsgPackTreeReader(
.joinToNumber()
type == MsgPackType.Map.MAP32 -> {
- if (basicMsgPackDecoder.configuration.preventOverflows) {
+ if (basicMsgPackDecoder.getConfiguration().preventOverflows) {
val number = basicMsgPackDecoder.dataBuffer.takeNext(4).joinToNumber()
if (number !in Int.MIN_VALUE..Int.MAX_VALUE) {
throw MsgPackSerializationException.overflowError(basicMsgPackDecoder.dataBuffer)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/internal/MsgPackDecoder.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/internal/MsgPackDecoder.kt
index 35bc5ffac..389a4281e 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/internal/MsgPackDecoder.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/util/serializeble/msgpack/internal/MsgPackDecoder.kt
@@ -22,26 +22,27 @@ interface MsgPackTypeDecoder {
}
internal class BasicMsgPackDecoder(
- val configuration: MsgPackConfiguration,
+ private val configuration: MsgPackConfiguration,
override val serializersModule: SerializersModule,
val dataBuffer: MsgPackDataInputBuffer,
private val msgUnpacker: MsgUnpacker = BasicMsgUnpacker(dataBuffer),
val inlineDecoders: Map Decoder> = mapOf()
) : AbstractDecoder(), MsgPackTypeDecoder {
fun decodeMsgPackElement(): JsonElement = MsgPackTreeReader(this).read()
+ fun getConfiguration(): MsgPackConfiguration {
+ return configuration
+ }
- val depthStack: ArrayDeque = ArrayDeque()
-
- override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
+ internal fun decodeElementIndexInternal(descriptor: SerialDescriptor): Int {
if (descriptor.kind in arrayOf(StructureKind.CLASS, StructureKind.OBJECT)) {
val next = dataBuffer.peekSafely()
if (next != null && MsgPackType.String.isString(next)) {
val fieldName = kotlin.runCatching { decodeString() }.getOrNull()
?: return CompositeDecoder.UNKNOWN_NAME
val index = descriptor.getElementIndex(fieldName)
- return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys && depthStack.isEmpty()) {
+ return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
MsgPackNullableDynamicSerializer.deserialize(this)
- decodeElementIndex(descriptor)
+ index
} else {
index
}
@@ -52,6 +53,14 @@ internal class BasicMsgPackDecoder(
return 0
}
+ override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
+ val result = decodeElementIndexInternal(descriptor)
+ if (result == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
+ return decodeElementIndex(descriptor)
+ }
+ return result
+ }
+
override fun decodeSequentially(): Boolean = true
override fun decodeNotNullMark(): Boolean {
@@ -222,19 +231,12 @@ internal class BasicMsgPackDecoder(
return ExtensionTypeDecoder(this)
}
- depthStack.addFirst(Unit)
- // Handle extension types as arrays
val size = decodeCollectionSize(descriptor)
- return ClassMsgPackDecoder(this, size)
+ return ClassMsgPackDecoder(this, configuration, size)
}
return this
}
- override fun endStructure(descriptor: SerialDescriptor) {
- super.endStructure(descriptor)
- depthStack.removeFirstOrNull()
- }
-
override fun peekNextType(): Byte {
return dataBuffer.peek()
}
@@ -249,42 +251,19 @@ internal class MsgPackDecoder(
internal class ClassMsgPackDecoder(
private val basicMsgPackDecoder: BasicMsgPackDecoder,
+ private val configuration: MsgPackConfiguration,
private val size: Int
) : Decoder by basicMsgPackDecoder, CompositeDecoder by basicMsgPackDecoder,
MsgPackTypeDecoder by basicMsgPackDecoder {
override val serializersModule: SerializersModule = basicMsgPackDecoder.serializersModule
- private fun decodeElemIndex(descriptor: SerialDescriptor, size: Int): Int {
- if (descriptor.kind in arrayOf(StructureKind.CLASS, StructureKind.OBJECT)) {
- val next = basicMsgPackDecoder.dataBuffer.peekSafely()
- if (next != null && MsgPackType.String.isString(next)) {
- val fieldName = kotlin.runCatching { decodeString() }.getOrNull()
- ?: return CompositeDecoder.UNKNOWN_NAME
- val index = descriptor.getElementIndex(fieldName)
- return if (index == CompositeDecoder.UNKNOWN_NAME && basicMsgPackDecoder.configuration.ignoreUnknownKeys && basicMsgPackDecoder.depthStack.isEmpty()) {
- MsgPackNullableDynamicSerializer.deserialize(this)
- decodedElements++
- if (decodedElements >= size) CompositeDecoder.DECODE_DONE else decodeElemIndex(
- descriptor,
- size
- )
- } else {
- index
- }
- } else {
- return CompositeDecoder.DECODE_DONE
- }
- }
- return 0
- }
private var decodedElements = 0
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
if (decodedElements >= size) return CompositeDecoder.DECODE_DONE
- val result = decodeElemIndex(descriptor, size)
+ val result = basicMsgPackDecoder.decodeElementIndexInternal(descriptor)
if (result != CompositeDecoder.DECODE_DONE) decodedElements++
- return if (result == CompositeDecoder.UNKNOWN_NAME) {
- MsgPackNullableDynamicSerializer.deserialize(this)
+ return if (result == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
decodeElementIndex(descriptor)
} else {
result
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/view/emoji/EmojiconTextView.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/view/emoji/EmojiconTextView.kt
index d9f1ab942..d61c29cca 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/view/emoji/EmojiconTextView.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/view/emoji/EmojiconTextView.kt
@@ -162,8 +162,8 @@ class EmojiconTextView @JvmOverloads constructor(context: Context, attrs: Attrib
override fun onClick(widget: View) {
if (URL_YOUTUBE_PATTERN.matcher(url).find()) {
val menus = ModalBottomSheetDialogFragment.Builder()
- val hasVanced = AppPrefs.isVancedYoutubeInstalled(context)
- if (hasVanced) {
+ val hasReVanced = AppPrefs.isReVancedYoutubeInstalled(context)
+ if (hasReVanced) {
menus.add(
OptionRequest(
1,
@@ -181,7 +181,7 @@ class EmojiconTextView @JvmOverloads constructor(context: Context, attrs: Attrib
true
)
)
- if (!hasVanced && AppPrefs.isYoutubeInstalled(context)) {
+ if (!hasReVanced && AppPrefs.isYoutubeInstalled(context)) {
menus.add(
OptionRequest(
3,
@@ -216,8 +216,8 @@ class EmojiconTextView @JvmOverloads constructor(context: Context, attrs: Attrib
intent.data = Uri.parse(url)
intent.action = Intent.ACTION_VIEW
intent.component = ComponentName(
- "app.revanced.android.youtube",
- "com.google.android.apps.youtube.app.application.Shell\$UrlActivity"
+ AppPrefs.revanced?.first.orEmpty(),
+ AppPrefs.revanced?.second.orEmpty()
)
context.startActivity(intent)
}
diff --git a/app_fenrir/src/main/res/drawable/client_round.xml b/app_fenrir/src/main/res/drawable/client_round.xml
deleted file mode 100644
index 871aeb0cd..000000000
--- a/app_fenrir/src/main/res/drawable/client_round.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
diff --git a/app_fenrir/src/main/res/drawable/client_round_vk.xml b/app_fenrir/src/main/res/drawable/client_round_vk.xml
new file mode 100644
index 000000000..bcdab35eb
--- /dev/null
+++ b/app_fenrir/src/main/res/drawable/client_round_vk.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/app_fenrir/src/main/res/layout/content_post.xml b/app_fenrir/src/main/res/layout/content_post.xml
index 812d8ca59..5db141ad1 100644
--- a/app_fenrir/src/main/res/layout/content_post.xml
+++ b/app_fenrir/src/main/res/layout/content_post.xml
@@ -62,7 +62,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:drawablePadding="4dp"
- android:text="@string/visible_only_dons"
+ android:text="@string/available_only_dons"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:visibility="gone"
app:drawableStartCompat="@drawable/donate"
diff --git a/app_fenrir/src/main/res/layout/fragment_post.xml b/app_fenrir/src/main/res/layout/fragment_post.xml
index b4de79f81..0cecfc3f5 100644
--- a/app_fenrir/src/main/res/layout/fragment_post.xml
+++ b/app_fenrir/src/main/res/layout/fragment_post.xml
@@ -107,7 +107,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:drawablePadding="4dp"
- android:text="@string/visible_only_dons"
+ android:text="@string/available_only_dons"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:visibility="gone"
app:drawableStartCompat="@drawable/donate"
diff --git a/app_fenrir/src/main/res/layout/item_feed.xml b/app_fenrir/src/main/res/layout/item_feed.xml
index 3cb58d4e8..c886c443b 100644
--- a/app_fenrir/src/main/res/layout/item_feed.xml
+++ b/app_fenrir/src/main/res/layout/item_feed.xml
@@ -122,7 +122,7 @@
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:drawablePadding="4dp"
- android:text="@string/visible_only_dons"
+ android:text="@string/available_only_dons"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:visibility="gone"
app:drawableStartCompat="@drawable/donate"
diff --git a/app_fenrir/src/main/res/values-be/strings.xml b/app_fenrir/src/main/res/values-be/strings.xml
index 1af36f2d8..e52f4fe50 100644
--- a/app_fenrir/src/main/res/values-be/strings.xml
+++ b/app_fenrir/src/main/res/values-be/strings.xml
@@ -47,14 +47,6 @@
- Не скругляць
-
- - Па змаўчанні
- - Маленькі
- - Сярэдні
- - Вялікі
- - Вялізны
-
-
- Адключыць
- Абнаўляць
@@ -1203,7 +1195,7 @@
Бітрэйт: %1$d kbs, Памер: %2$s
Перавышаны час чакання запыту
Няма падключэння да сеткі
- SMS-код
+ Код из SMS
Проксі
Налады
Пароль
@@ -1717,5 +1709,7 @@
Фатаграфіі на сцяне
Заблакаваць падпісчыка? Рэжым захавацца на сесію
Токен абмену
- Відаць толькі донам!
+ Даступна толькі донам!
+ Шрыфт толькі чатам
+ Прагляды
\ No newline at end of file
diff --git a/app_fenrir/src/main/res/values-ru/strings.xml b/app_fenrir/src/main/res/values-ru/strings.xml
index a0e69104c..bc1f3c96b 100644
--- a/app_fenrir/src/main/res/values-ru/strings.xml
+++ b/app_fenrir/src/main/res/values-ru/strings.xml
@@ -47,14 +47,6 @@
- Не скруглять
-
- - По умолчанию
- - Маленький
- - Средний
- - Большой
- - Огромный
-
-
- Отключить
- Обновлять
@@ -384,7 +376,7 @@
Недопустимый идентификатор альбома
Недопустимый сервер
Неверный хэш
- Неверный timestamp
+ Неверная отметка времени
Невозможно добавить в друзья самого себя
Невозможно добавить в друзья пользователя, который занес Вас в свой черный список
Невозможно добавить в друзья пользователя, который занесен в Ваш черный список
@@ -1205,7 +1197,7 @@
Битрейт: %1$d kbs, Размер: %2$s
Превышено время ожидание запроса
Нет подключения к сети
- SMS-код
+ Код из SMS
Прокси
Настройки
Пароль
@@ -1719,5 +1711,7 @@
Фотографии на стене
Заблокировать подписчика? Режим сохраниться на сессию
Токен обмена
- Видно только донам!
+ Доступно только донам!
+ Шрифт только чатам
+ Просмотры
\ No newline at end of file
diff --git a/app_fenrir/src/main/res/values/strings.xml b/app_fenrir/src/main/res/values/strings.xml
index 65e60202a..d66cdec2d 100644
--- a/app_fenrir/src/main/res/values/strings.xml
+++ b/app_fenrir/src/main/res/values/strings.xml
@@ -144,22 +144,6 @@
- 2
-
- - Default
- - Small
- - Average
- - Large
- - Huge
-
-
-
- - 0
- - -1
- - 1
- - 2
- - 3
-
-
- Disable
- Update
@@ -1438,7 +1422,7 @@
Bitrate: %1$d kbs, Size: %2$s
Request timed out
No network connection
- SMS-code
+ Code from SMS
Captcha
Proxy
Settings
@@ -1964,5 +1948,7 @@
Photos on Wall
Block a subscriber? Mode save per session
Exchange Token
- Visible only to dons!
+ Only available to dons!
+ Font only for chats
+ Views
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
index dc4f66349..267176dd1 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
@@ -371,17 +371,24 @@ class PreferencesFragment : AbsPreferencesFragment(), PreferencesAdapter.OnScree
}
}
- singleChoice(
- "font_size",
- selItems(R.array.array_font_size_names, R.array.array_font_size_items),
- parentFragmentManager
- ) {
- initialSelection = "0"
+ seekBar("font_size_int") {
+ min = -3
+ max = 9
+ default = 0
+ step = 1
+ showTickMarks = true
titleRes = R.string.font_size
- onSelectionChange {
- requireActivity().recreate()
+ onSeek {
+ sleepDataDisposable.dispose()
+ sleepDataDisposable = Single.just(Any())
+ .delay(1, TimeUnit.SECONDS)
+ .fromIOToMain()
+ .subscribe({
+ requireActivity().recreate()
+ }, { RxUtils.dummy() })
}
}
+
switch("use_internal_downloader") {
defaultValue = true
summaryRes = R.string.use_internal_downloader_summary
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/MainSettings.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/MainSettings.kt
index 167b128f0..8d88d26a8 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/MainSettings.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/MainSettings.kt
@@ -21,11 +21,7 @@ internal class MainSettings(context: Context) : IMainSettings {
private val localServerPublisher: PublishSubject = PublishSubject.create()
override fun getFontSize(): Int {
- return try {
- getPreferences(app).getString("font_size", "0")!!.trim().toInt()
- } catch (e: Exception) {
- 0
- }
+ return getPreferences(app).getInt("font_size_int", 0)
}
override val isValidate_tls: Boolean
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/SecuritySettings.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/SecuritySettings.kt
index b7127c4f1..f391b4610 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/SecuritySettings.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/SecuritySettings.kt
@@ -97,7 +97,7 @@ class SecuritySettings internal constructor(context: Context) : ISecuritySetting
const val KEY_USE_PIN_FOR_ENTRANCE = "use_pin_for_entrance"
private const val pinHistoryDepth = 3
- internal fun extractPinEnterHistrory(preferences: SharedPreferences): ArrayList {
+ internal fun extractPinEnterHistory(preferences: SharedPreferences): ArrayList {
val set = preferences.getStringSet(KEY_PIN_ENTER_HISTORY, null)
val result = ArrayList(safeCountOf(set))
if (set != null) {
@@ -120,6 +120,6 @@ class SecuritySettings internal constructor(context: Context) : ISecuritySetting
init {
mPinHash = mPrefs.getString(KEY_PIN_HASH, null)
- mPinEnterHistory = extractPinEnterHistrory(mPrefs)
+ mPinEnterHistory = extractPinEnterHistory(mPrefs)
}
-}
\ No newline at end of file
+}
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/backup/SettingsBackup.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/backup/SettingsBackup.kt
index 7008ea21b..0844493c9 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/backup/SettingsBackup.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/settings/backup/SettingsBackup.kt
@@ -23,7 +23,7 @@ class SettingsBackup {
var theme_overlay: String? = null
var language_ui: String? = null
var delete_disabled: Boolean? = null
- var font_size: String? = null
+ var font_size_int: Int? = null
var local_media_server: String? = null
var use_internal_downloader: Boolean? = null
var video_controller_to_decor: Boolean? = null
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/Utils.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/Utils.kt
index 441938294..d72d6a1fa 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/Utils.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/Utils.kt
@@ -183,10 +183,7 @@ object Utils {
}
fun setBackgroundTint(view: View?, @ColorInt color: Int) {
- if (view == null) {
- return
- }
- view.backgroundTintList = ColorStateList.valueOf(color)
+ view?.backgroundTintList = ColorStateList.valueOf(color)
}
fun setColorFilter(view: ImageView?, @ColorInt color: Int) {
@@ -412,7 +409,7 @@ object Utils {
} else {
val res = base.resources
val config = Configuration(res.configuration)
- config.fontScale = res.configuration.fontScale + 0.15f * size
+ config.fontScale = res.configuration.fontScale + 0.05f * size
if (lang != Lang.DEFAULT) {
setSystemLocaleLegacy(config, getLocaleSettings(lang))
}
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/JsonElementSerializers.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/JsonElementSerializers.kt
index a0eccb989..f7d73880b 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/JsonElementSerializers.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/JsonElementSerializers.kt
@@ -15,7 +15,7 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonElement].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonElement].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
* Currently, this hierarchy has no guarantees on descriptor content.
*
@@ -26,7 +26,6 @@ import kotlinx.serialization.encoding.Encoder
* assertEquals(JsonObject(mapOf("key" to JsonLiteral(1.0))), literal)
* ```
*/
-@Serializer(forClass = JsonElement::class)
@PublishedApi
internal object JsonElementSerializer : KSerializer {
@OptIn(InternalSerializationApi::class)
@@ -59,10 +58,9 @@ internal object JsonElementSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonPrimitive].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonPrimitive].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonPrimitive::class)
@PublishedApi
internal object JsonPrimitiveSerializer : KSerializer {
@OptIn(InternalSerializationApi::class)
@@ -93,10 +91,9 @@ internal object JsonPrimitiveSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonNull].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonNull].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonNull::class)
@PublishedApi
internal object JsonNullSerializer : KSerializer {
// technically, JsonNull is an object, but it does not call beginStructure/endStructure at all
@@ -166,10 +163,9 @@ private object JsonLiteralSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonObject].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonObject].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonObject::class)
@PublishedApi
internal object JsonObjectSerializer : KSerializer {
@@ -198,10 +194,9 @@ internal object JsonObjectSerializer : KSerializer {
}
/**
- * External [Serializer] object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonArray].
+ * Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [JsonArray].
* It can only be used by with [Json] format an its input ([JsonDecoder] and [JsonEncoder]).
*/
-@Serializer(forClass = JsonArray::class)
@PublishedApi
internal object JsonArraySerializer : KSerializer {
@@ -225,11 +220,11 @@ internal object JsonArraySerializer : KSerializer {
}
}
-internal fun verify(encoder: Encoder) {
+private fun verify(encoder: Encoder) {
encoder.asJsonEncoder()
}
-internal fun verify(decoder: Decoder) {
+private fun verify(decoder: Decoder) {
decoder.asJsonDecoder()
}
@@ -251,7 +246,7 @@ internal fun Encoder.asJsonEncoder() = this as? JsonEncoder
* Used to resolve cyclic dependencies between recursive serializable structures.
*/
@OptIn(ExperimentalSerializationApi::class)
-internal fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object : SerialDescriptor {
+private fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object : SerialDescriptor {
private val original: SerialDescriptor by lazy(deferred)
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/JsonNamesMap.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/JsonNamesMap.kt
index 6f20dbb94..40d568dc4 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/JsonNamesMap.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/JsonNamesMap.kt
@@ -108,12 +108,16 @@ internal fun SerialDescriptor.getJsonNameIndexOrThrow(
@OptIn(ExperimentalSerializationApi::class)
internal inline fun Json.tryCoerceValue(
elementDescriptor: SerialDescriptor,
- peekNull: () -> Boolean,
+ peekNull: (consume: Boolean) -> Boolean,
peekString: () -> String?,
onEnumCoercing: () -> Unit = {}
): Boolean {
- if (!elementDescriptor.isNullable && peekNull()) return true
+ if (!elementDescriptor.isNullable && peekNull(true)) return true
if (elementDescriptor.kind == SerialKind.ENUM) {
+ if (elementDescriptor.isNullable && peekNull(false)) {
+ return false
+ }
+
val enumValue = peekString()
?: return false // if value is not a string, decodeEnum() will throw correct exception
val enumIndex = elementDescriptor.getJsonNameIndex(this, enumValue)
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/StreamingJsonDecoder.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/StreamingJsonDecoder.kt
index a92069ed5..569467452 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/StreamingJsonDecoder.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/StreamingJsonDecoder.kt
@@ -17,6 +17,7 @@ import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.AbstractDecoder
+import kotlinx.serialization.encoding.ChunkedDecoder
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE
import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME
@@ -34,7 +35,7 @@ internal open class StreamingJsonDecoder(
@JvmField internal val lexer: AbstractJsonLexer,
descriptor: SerialDescriptor,
private var discriminatorHolder: DiscriminatorHolder?
-) : JsonDecoder, AbstractDecoder() {
+) : JsonDecoder, ChunkedDecoder, AbstractDecoder() {
// A mutable reference to the discriminator that have to be skipped when in optimistic phase
// of polymorphic serialization, see `decodeSerializableValue`
@@ -93,7 +94,6 @@ internal open class StreamingJsonDecoder(
}
discriminatorHolder = DiscriminatorHolder(discriminator)
-
@Suppress("UNCHECKED_CAST")
return actualSerializer.deserialize(this) as T
@@ -149,7 +149,7 @@ internal open class StreamingJsonDecoder(
}
override fun decodeNotNullMark(): Boolean {
- return !(elementMarker?.isUnmarkedNull ?: false) && lexer.tryConsumeNotNull()
+ return !(elementMarker?.isUnmarkedNull ?: false) && !lexer.tryConsumeNull()
}
override fun decodeNull(): Nothing? {
@@ -225,7 +225,7 @@ internal open class StreamingJsonDecoder(
private fun coerceInputValue(descriptor: SerialDescriptor, index: Int): Boolean =
json.tryCoerceValue(
descriptor.getElementDescriptor(index),
- { !lexer.tryConsumeNotNull() },
+ { lexer.tryConsumeNull(it) },
{ lexer.peekString(configuration.isLenient) },
{ lexer.consumeString() /* skip unknown enum string*/ }
)
@@ -362,6 +362,10 @@ internal open class StreamingJsonDecoder(
}
}
+ override fun decodeStringChunked(consumeChunk: (chunk: String) -> Unit) {
+ lexer.consumeStringChunked(configuration.isLenient, consumeChunk)
+ }
+
override fun decodeInline(descriptor: SerialDescriptor): Decoder =
if (descriptor.isUnsignedNumber) JsonDecoderForUnsignedTypes(lexer, json)
else super.decodeInline(descriptor)
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
index 893045edf..3c6712573 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/AbstractJsonLexer.kt
@@ -251,25 +251,28 @@ internal abstract class AbstractJsonLexer {
/**
* Tries to consume `null` token from input.
- * Returns `true` if the next 4 chars in input are not `null`,
- * `false` otherwise and consumes it.
+ * Returns `false` if the next 4 chars in input are not `null`,
+ * `true` otherwise and consumes it if [doConsume] is `true`.
*/
- fun tryConsumeNotNull(): Boolean {
+ fun tryConsumeNull(doConsume: Boolean = true): Boolean {
var current = skipWhitespaces()
current = prefetchOrEof(current)
// Cannot consume null due to EOF, maybe something else
val len = source.length - current
- if (len < 4 || current == -1) return true
+ if (len < 4 || current == -1) return false
for (i in 0..3) {
- if (NULL[i] != source[current + i]) return true
+ if (NULL[i] != source[current + i]) return false
}
/*
* If we're in lenient mode, this might be the string with 'null' prefix,
* distinguish it from 'null'
*/
- if (len > 4 && charToTokenClass(source[current + 4]) == TC_OTHER) return true
- currentPosition = current + 4
- return false
+ if (len > 4 && charToTokenClass(source[current + 4]) == TC_OTHER) return false
+
+ if (doConsume) {
+ currentPosition = current + 4
+ }
+ return true
}
open fun skipWhitespaces(): Int {
@@ -314,6 +317,66 @@ internal abstract class AbstractJsonLexer {
*/
abstract fun consumeKeyString(): String
+ private fun insideString(isLenient: Boolean, char: Char): Boolean = if (isLenient) {
+ charToTokenClass(char) == TC_OTHER
+ } else {
+ char != STRING
+ }
+
+ open fun consumeStringChunked(
+ isLenient: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) { // open to allow simpler implementations (i.e. StringJsonLexer)
+ val nextToken = peekNextToken()
+ if (isLenient && nextToken != TC_OTHER) return // noting to consume
+
+ if (!isLenient) {
+ consumeNextToken(STRING)
+ }
+ var currentPosition = this.currentPosition
+ var lastPosition = currentPosition
+ var char = source[currentPosition] // Avoid two range checks visible in the profiler
+ var usedAppend = false
+ while (insideString(isLenient, char)) {
+ if (!isLenient && char == STRING_ESC) { // handle escaping only in non-lenient mode
+ usedAppend = true
+ currentPosition = prefetchOrEof(appendEscape(lastPosition, currentPosition))
+ lastPosition = currentPosition
+ } else {
+ currentPosition++
+ }
+ if (currentPosition >= source.length) {
+ // end of chunk
+ writeRange(lastPosition, currentPosition, usedAppend, consumeChunk)
+ usedAppend = false
+ currentPosition = prefetchOrEof(currentPosition)
+ if (currentPosition == -1)
+ fail("EOF", currentPosition)
+ lastPosition = currentPosition
+ }
+ char = source[currentPosition]
+ }
+ writeRange(lastPosition, currentPosition, usedAppend, consumeChunk)
+ this.currentPosition = currentPosition
+ if (!isLenient) {
+ consumeNextToken(STRING)
+ }
+ }
+
+ private fun writeRange(
+ fromIndex: Int,
+ toIndex: Int,
+ currentChunkHasEscape: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) {
+ if (currentChunkHasEscape) {
+ consumeChunk(decodedString(fromIndex, toIndex))
+ } else {
+ consumeChunk(substring(fromIndex, toIndex))
+ }
+ }
+
+
fun consumeString(): String {
if (peekedString != null) {
return takePeeked()
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/StringJsonLexer.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/StringJsonLexer.kt
index afc48c98e..a22f51724 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/StringJsonLexer.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/json/internal/lexer/StringJsonLexer.kt
@@ -103,6 +103,14 @@ internal class StringJsonLexer(override val source: String) : AbstractJsonLexer(
return source.substring(current, closingQuote)
}
+ override fun consumeStringChunked(
+ isLenient: Boolean,
+ consumeChunk: (stringChunk: String) -> Unit
+ ) {
+ (if (isLenient) consumeStringLenient() else consumeString()).chunked(BATCH_SIZE)
+ .forEach(consumeChunk)
+ }
+
override fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? {
val positionSnapshot = currentPosition
try {
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/MsgPackTreeReader.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/MsgPackTreeReader.kt
index aee4c76d6..d37c7a9fa 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/MsgPackTreeReader.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/MsgPackTreeReader.kt
@@ -32,7 +32,7 @@ internal class MsgPackTreeReader(
.joinToNumber()
type == MsgPackType.Array.ARRAY32 -> {
- if (basicMsgPackDecoder.configuration.preventOverflows) {
+ if (basicMsgPackDecoder.getConfiguration().preventOverflows) {
val number = basicMsgPackDecoder.dataBuffer.takeNext(4).joinToNumber()
if (number !in Int.MIN_VALUE..Int.MAX_VALUE) {
throw MsgPackSerializationException.overflowError(basicMsgPackDecoder.dataBuffer)
@@ -64,7 +64,7 @@ internal class MsgPackTreeReader(
.joinToNumber()
type == MsgPackType.Map.MAP32 -> {
- if (basicMsgPackDecoder.configuration.preventOverflows) {
+ if (basicMsgPackDecoder.getConfiguration().preventOverflows) {
val number = basicMsgPackDecoder.dataBuffer.takeNext(4).joinToNumber()
if (number !in Int.MIN_VALUE..Int.MAX_VALUE) {
throw MsgPackSerializationException.overflowError(basicMsgPackDecoder.dataBuffer)
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/internal/MsgPackDecoder.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/internal/MsgPackDecoder.kt
index bcea224bd..f6b318b90 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/internal/MsgPackDecoder.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/util/serializeble/msgpack/internal/MsgPackDecoder.kt
@@ -22,26 +22,27 @@ interface MsgPackTypeDecoder {
}
internal class BasicMsgPackDecoder(
- val configuration: MsgPackConfiguration,
+ private val configuration: MsgPackConfiguration,
override val serializersModule: SerializersModule,
val dataBuffer: MsgPackDataInputBuffer,
private val msgUnpacker: MsgUnpacker = BasicMsgUnpacker(dataBuffer),
val inlineDecoders: Map Decoder> = mapOf()
) : AbstractDecoder(), MsgPackTypeDecoder {
fun decodeMsgPackElement(): JsonElement = MsgPackTreeReader(this).read()
+ fun getConfiguration(): MsgPackConfiguration {
+ return configuration
+ }
- val depthStack: ArrayDeque = ArrayDeque()
-
- override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
+ internal fun decodeElementIndexInternal(descriptor: SerialDescriptor): Int {
if (descriptor.kind in arrayOf(StructureKind.CLASS, StructureKind.OBJECT)) {
val next = dataBuffer.peekSafely()
if (next != null && MsgPackType.String.isString(next)) {
val fieldName = kotlin.runCatching { decodeString() }.getOrNull()
?: return CompositeDecoder.UNKNOWN_NAME
val index = descriptor.getElementIndex(fieldName)
- return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys && depthStack.isEmpty()) {
+ return if (index == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
MsgPackNullableDynamicSerializer.deserialize(this)
- decodeElementIndex(descriptor)
+ index
} else {
index
}
@@ -52,6 +53,14 @@ internal class BasicMsgPackDecoder(
return 0
}
+ override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
+ val result = decodeElementIndexInternal(descriptor)
+ if (result == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
+ return decodeElementIndex(descriptor)
+ }
+ return result
+ }
+
override fun decodeSequentially(): Boolean = true
override fun decodeNotNullMark(): Boolean {
@@ -222,19 +231,12 @@ internal class BasicMsgPackDecoder(
return ExtensionTypeDecoder(this)
}
- depthStack.addFirst(Unit)
- // Handle extension types as arrays
val size = decodeCollectionSize(descriptor)
- return ClassMsgPackDecoder(this, size)
+ return ClassMsgPackDecoder(this, configuration, size)
}
return this
}
- override fun endStructure(descriptor: SerialDescriptor) {
- super.endStructure(descriptor)
- depthStack.removeFirstOrNull()
- }
-
override fun peekNextType(): Byte {
return dataBuffer.peek()
}
@@ -249,42 +251,19 @@ internal class MsgPackDecoder(
internal class ClassMsgPackDecoder(
private val basicMsgPackDecoder: BasicMsgPackDecoder,
+ private val configuration: MsgPackConfiguration,
private val size: Int
) : Decoder by basicMsgPackDecoder, CompositeDecoder by basicMsgPackDecoder,
MsgPackTypeDecoder by basicMsgPackDecoder {
override val serializersModule: SerializersModule = basicMsgPackDecoder.serializersModule
- private fun decodeElemIndex(descriptor: SerialDescriptor, size: Int): Int {
- if (descriptor.kind in arrayOf(StructureKind.CLASS, StructureKind.OBJECT)) {
- val next = basicMsgPackDecoder.dataBuffer.peekSafely()
- if (next != null && MsgPackType.String.isString(next)) {
- val fieldName = kotlin.runCatching { decodeString() }.getOrNull()
- ?: return CompositeDecoder.UNKNOWN_NAME
- val index = descriptor.getElementIndex(fieldName)
- return if (index == CompositeDecoder.UNKNOWN_NAME && basicMsgPackDecoder.configuration.ignoreUnknownKeys && basicMsgPackDecoder.depthStack.isEmpty()) {
- MsgPackNullableDynamicSerializer.deserialize(this)
- decodedElements++
- if (decodedElements >= size) CompositeDecoder.DECODE_DONE else decodeElemIndex(
- descriptor,
- size
- )
- } else {
- index
- }
- } else {
- return CompositeDecoder.DECODE_DONE
- }
- }
- return 0
- }
private var decodedElements = 0
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
if (decodedElements >= size) return CompositeDecoder.DECODE_DONE
- val result = decodeElemIndex(descriptor, size)
+ val result = basicMsgPackDecoder.decodeElementIndexInternal(descriptor)
if (result != CompositeDecoder.DECODE_DONE) decodedElements++
- return if (result == CompositeDecoder.UNKNOWN_NAME) {
- MsgPackNullableDynamicSerializer.deserialize(this)
+ return if (result == CompositeDecoder.UNKNOWN_NAME && configuration.ignoreUnknownKeys) {
decodeElementIndex(descriptor)
} else {
result
diff --git a/app_filegallery/src/main/res/values-be/strings.xml b/app_filegallery/src/main/res/values-be/strings.xml
index 5450477b1..d45251cf8 100644
--- a/app_filegallery/src/main/res/values-be/strings.xml
+++ b/app_filegallery/src/main/res/values-be/strings.xml
@@ -32,14 +32,6 @@
- Material 1
-
- - Па змаўчанні
- - Маленькі
- - Сярэдні
- - Вялікі
- - Вялізны
-
-
- 1 хвіл.
- 2 хвіл.
diff --git a/app_filegallery/src/main/res/values-ru/strings.xml b/app_filegallery/src/main/res/values-ru/strings.xml
index fa0056737..44f5f054d 100644
--- a/app_filegallery/src/main/res/values-ru/strings.xml
+++ b/app_filegallery/src/main/res/values-ru/strings.xml
@@ -32,14 +32,6 @@
- Material 1
-
- - По умолчанию
- - Маленький
- - Средний
- - Большой
- - Огромный
-
-
- 1 мин.
- 2 мин.
diff --git a/app_filegallery/src/main/res/values/strings.xml b/app_filegallery/src/main/res/values/strings.xml
index b4140e1d8..1e9815e81 100644
--- a/app_filegallery/src/main/res/values/strings.xml
+++ b/app_filegallery/src/main/res/values/strings.xml
@@ -52,22 +52,6 @@
- 2
-
- - Default
- - Small
- - Average
- - Large
- - Huge
-
-
-
- - 0
- - -1
- - 1
- - 2
- - 3
-
-
- 1 min.
- 2 min.
diff --git a/build.gradle b/build.gradle
index 86a9e0f56..57a096143 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,7 +3,7 @@ buildscript {
ext.is_developer_build = true
ext.appCompileSDK = 33
- ext.appBuildTools = "33.0.1"
+ ext.appBuildTools = "33.0.2"
ext.appNdk = "25.2.9519653"
ext.appMinSDK = is_developer_build ? 29 : 21
ext.appTargetSDK = 31
@@ -13,24 +13,25 @@ buildscript {
ext.appFileGalleryVersionName = "1.999"
//androidx libraries
- ext.activityVersion = "1.7.0-beta01"
- ext.annotationVersion = "1.6.0-rc01"
+ ext.activityVersion = "1.7.0-beta02"
+ ext.annotationVersion = "1.6.0"
ext.appcompatVersion = "1.6.1"
ext.biometricVersion = "1.2.0-alpha05"
ext.browserVersion = "1.5.0"
ext.cameraVersion = "1.2.1"
ext.cardviewVersion = "1.0.0"
ext.collectionVersion = "1.3.0-alpha02"
- ext.constraintlayoutVersion = "2.1.4"
+ ext.concurentVersion = "1.2.0-alpha01"
+ ext.constraintlayoutVersion = "2.2.0-alpha07"
ext.coordinatorlayoutVersion = "1.2.0"
- ext.coreVersion = "1.9.0"
+ ext.coreVersion = "1.10.0-beta01"
ext.customviewVersion = "1.2.0-alpha02"
ext.customviewPoolingcontainerVersion = "1.0.0"
ext.dynamicanimationVersion = "1.1.0-alpha03"
ext.drawerlayoutVersion = "1.2.0-beta01"
ext.exifinterfaceVersion = "1.3.6"
- ext.fragmentVersion = "1.6.0-alpha05"
- ext.lifecycleVersion = "2.6.0-beta01"
+ ext.fragmentVersion = "1.6.0-alpha06"
+ ext.lifecycleVersion = "2.6.0-rc01"
ext.loaderVersion = "1.1.0"
ext.mediaVersion = "1.7.0-alpha01"
ext.recyclerviewVersion = "1.3.0-rc01"
@@ -50,21 +51,21 @@ buildscript {
ext.firebaseCommonVersion = "20.3.0"
ext.firebaseInstallationsInteropVersion = "17.1.0"
ext.firebaseComponentsVersion = "17.1.0"
- ext.firebaseAnnotationsVersion = "16.1.0"
+ ext.firebaseAnnotationsVersion = "16.2.0"
ext.playServicesTasksVersion = "18.0.2"
ext.autoValueVersion = "1.10.1"
//common libraries
ext.kotlin_version = "1.8.10"
ext.kotlin_coroutines = "1.6.4"
- ext.kotlin_serializer = "1.5.0-RC"
+ ext.kotlin_serializer = "1.5.0"
ext.okhttpLibraryVersion = "5.0.0-alpha.11"
ext.okioVersion = "3.3.0"
ext.rxJavaVersion = "3.1.6"
ext.guavaVersion = "31.1-android"
- ext.exoLibraryVersion = "2.18.2"
+ ext.exoLibraryVersion = "2.18.3"
ext.errorproneVersion = "2.15.0"
- ext.desugarLibraryVersion = "2.0.0"
+ ext.desugarLibraryVersion = "2.0.2"
//APP_PROPS
ext.targetAbi = is_developer_build ? ["arm64-v8a", "x86_64"] : ["arm64-v8a", "armeabi-v7a", "x86_64"]
@@ -81,13 +82,14 @@ buildscript {
ext.vk_app_finger_print = "48761EEF50EE53AFC4CC9C5F10E6BDE7F8F5B82F"
ext.kate_app_package = "com.perm.kate_new_6"
ext.kate_app_finger_print = "966882BA564C2619D55D0A9AFD4327A38C327456"
+ //keytool -printcert -jarfile *.apk
repositories {
google()
mavenCentral()
}
dependencies {
- classpath "com.android.tools.build:gradle:8.0.0-beta02"
+ classpath "com.android.tools.build:gradle:8.0.0-beta03"
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/camera2/build.gradle b/camera2/build.gradle
index 02b6bd82b..4110b009f 100644
--- a/camera2/build.gradle
+++ b/camera2/build.gradle
@@ -28,7 +28,7 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-android-extensions-runtime:$kotlin_version")
compileOnly("org.jetbrains.kotlin:kotlin-annotations-jvm:$kotlin_version")
compileOnly("org.checkerframework:checker-compat-qual:2.5.5")
- compileOnly("org.checkerframework:checker-qual-android:3.27.0")
+ compileOnly("org.checkerframework:checker-qual-android:3.31.0")
compileOnly("com.google.auto.value:auto-value-annotations:$autoValueVersion")
implementation("androidx.annotation:annotation:$annotationVersion")
implementation("androidx.appcompat:appcompat:$appcompatVersion")
@@ -40,6 +40,6 @@ dependencies {
implementation("com.google.errorprone:error_prone_annotations:${errorproneVersion}")
implementation("androidx.exifinterface:exifinterface:$exifinterfaceVersion")
implementation("com.google.guava:guava:$guavaVersion")
- implementation("androidx.concurrent:concurrent-futures:1.1.0")
+ implementation("androidx.concurrent:concurrent-futures:$concurentVersion")
annotationProcessor("com.google.auto.value:auto-value:$autoValueVersion")
}
diff --git a/firebase-installations/build.gradle b/firebase-installations/build.gradle
index d56d093e7..0eb99a6a5 100644
--- a/firebase-installations/build.gradle
+++ b/firebase-installations/build.gradle
@@ -41,7 +41,7 @@ android {
defaultConfig {
minSdk = appMinSDK
targetSdk = appTargetSDK
- buildConfigField("String", "VERSION_NAME", asStringVar("17.0.2"))
+ buildConfigField("String", "VERSION_NAME_INSTALLATION", asStringVar("17.0.2"))
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java
index 1f0b7b4fe..b8e157d10 100644
--- a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java
+++ b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java
@@ -59,6 +59,6 @@ public List> getComponents() {
c.get(Qualified.qualified(Blocking.class, Executor.class)))))
.build(),
HeartBeatConsumerComponent.create(),
- LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME));
+ LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME_INSTALLATION));
}
}
diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java b/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
index 819ba498c..d5c9f7895 100644
--- a/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
+++ b/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
@@ -16,7 +16,7 @@
import static android.content.ContentValues.TAG;
import static com.google.android.gms.common.internal.Preconditions.checkArgument;
-import static com.google.firebase.installations.BuildConfig.VERSION_NAME;
+import static com.google.firebase.installations.BuildConfig.VERSION_NAME_INSTALLATION;
import android.net.TrafficStats;
import android.text.TextUtils;
@@ -155,7 +155,7 @@ private static JSONObject buildCreateFirebaseInstallationRequestBody(
firebaseInstallationData.put("fid", fid);
firebaseInstallationData.put("appId", appId);
firebaseInstallationData.put("authVersion", FIREBASE_INSTALLATION_AUTH_VERSION);
- firebaseInstallationData.put("sdkVersion", SDK_VERSION_PREFIX + VERSION_NAME);
+ firebaseInstallationData.put("sdkVersion", SDK_VERSION_PREFIX + VERSION_NAME_INSTALLATION);
return firebaseInstallationData;
} catch (JSONException e) {
throw new IllegalStateException(e);
@@ -173,7 +173,7 @@ private static JSONObject buildCreateFirebaseInstallationRequestBody(
private static JSONObject buildGenerateAuthTokenRequestBody() {
try {
JSONObject sdkVersionData = new JSONObject();
- sdkVersionData.put("sdkVersion", SDK_VERSION_PREFIX + VERSION_NAME);
+ sdkVersionData.put("sdkVersion", SDK_VERSION_PREFIX + VERSION_NAME_INSTALLATION);
JSONObject firebaseInstallationData = new JSONObject();
firebaseInstallationData.put("installation", sdkVersionData);
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 5e1f8d81b..5f6d01f8a 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Wed Aug 17 12:17:04 MSK 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/libfenrir/ffmpeg.sh b/libfenrir/ffmpeg.sh
index 73cfa2712..933d1214a 100644
--- a/libfenrir/ffmpeg.sh
+++ b/libfenrir/ffmpeg.sh
@@ -1,9 +1,9 @@
#!/bin/bash
SCRIPT_DIR=${PWD}
cd ~/
-git clone git://source.ffmpeg.org/ffmpeg
+git clone https://git.videolan.org/git/ffmpeg.git
cd ffmpeg
-git checkout release/5.1
+git checkout release/6.0
rm -r -f ".git"
ENABLED_DECODERS=(gif mpeg4 h264 hevc mp3 aac ac3 eac3 flac vorbis alac)
diff --git a/libfenrir/src/main/java/com/github/luben/zstd/BaseZstdBufferDecompressingStreamNoFinalizer.java b/libfenrir/src/main/java/com/github/luben/zstd/BaseZstdBufferDecompressingStreamNoFinalizer.java
index 5e0a1e16d..b45081579 100644
--- a/libfenrir/src/main/java/com/github/luben/zstd/BaseZstdBufferDecompressingStreamNoFinalizer.java
+++ b/libfenrir/src/main/java/com/github/luben/zstd/BaseZstdBufferDecompressingStreamNoFinalizer.java
@@ -26,7 +26,7 @@ public abstract class BaseZstdBufferDecompressingStreamNoFinalizer implements Cl
protected ByteBuffer refill(ByteBuffer toRefill) {
return toRefill;
}
-
+
public boolean hasRemaining() {
return !streamEnd && (source.hasRemaining() || !finishedFrame);
}
diff --git a/libfenrir/src/main/java/com/github/luben/zstd/EndDirective.java b/libfenrir/src/main/java/com/github/luben/zstd/EndDirective.java
index 4fbb1c9b6..84f6d6eb6 100644
--- a/libfenrir/src/main/java/com/github/luben/zstd/EndDirective.java
+++ b/libfenrir/src/main/java/com/github/luben/zstd/EndDirective.java
@@ -10,7 +10,7 @@ public enum EndDirective {
END(2);
private final int value;
- EndDirective(int value) {
+ private EndDirective(int value) {
this.value = value;
}
diff --git a/libfenrir/src/main/java/com/github/luben/zstd/ZstdCompressCtx.java b/libfenrir/src/main/java/com/github/luben/zstd/ZstdCompressCtx.java
index 7efec84a8..4477b4893 100644
--- a/libfenrir/src/main/java/com/github/luben/zstd/ZstdCompressCtx.java
+++ b/libfenrir/src/main/java/com/github/luben/zstd/ZstdCompressCtx.java
@@ -61,7 +61,7 @@ public ZstdCompressCtx setMagicless(boolean magiclessFlag) {
releaseSharedLock();
return this;
}
-
+
/**
* Enable or disable compression checksums
* @param checksumFlag A 32-bits checksum of content is written at end of frame, default: false
@@ -199,7 +199,7 @@ public ZstdFrameProgression getFrameProgression() {
return getFrameProgression0();
}
private native ZstdFrameProgression getFrameProgression0();
-
+
/**
* Clear all state and parameters from the compression context. This leaves the object in a
* state identical to a newly created compression context.
diff --git a/libfenrir/src/main/java/com/github/luben/zstd/ZstdDecompressCtx.java b/libfenrir/src/main/java/com/github/luben/zstd/ZstdDecompressCtx.java
index 47e5bae43..5f1ac5894 100644
--- a/libfenrir/src/main/java/com/github/luben/zstd/ZstdDecompressCtx.java
+++ b/libfenrir/src/main/java/com/github/luben/zstd/ZstdDecompressCtx.java
@@ -44,7 +44,7 @@ public ZstdDecompressCtx setMagicless(boolean magiclessFlag) {
releaseSharedLock();
return this;
}
-
+
/**
* Load decompression dictionary
*
diff --git a/libfenrir/src/main/java/com/github/luben/zstd/ZstdFrameProgression.java b/libfenrir/src/main/java/com/github/luben/zstd/ZstdFrameProgression.java
index b8011858a..cb1577452 100644
--- a/libfenrir/src/main/java/com/github/luben/zstd/ZstdFrameProgression.java
+++ b/libfenrir/src/main/java/com/github/luben/zstd/ZstdFrameProgression.java
@@ -67,5 +67,5 @@ public int getCurrentJobID() {
public int getNbActiveWorkers() {
return nbActiveWorkers;
}
-
+
}
diff --git a/libfenrir/src/main/jni/animation/animation_jni.cpp b/libfenrir/src/main/jni/animation/animation_jni.cpp
index 093aeb3df..d92a9515a 100644
--- a/libfenrir/src/main/jni/animation/animation_jni.cpp
+++ b/libfenrir/src/main/jni/animation/animation_jni.cpp
@@ -33,7 +33,8 @@ static inline void print_ffmpeg_error(int error) {
}
*/
-struct VideoInfo {
+class VideoInfo {
+public:
~VideoInfo() {
if (video_dec_ctx) {
avcodec_close(video_dec_ctx);
@@ -651,4 +652,4 @@ Java_dev_ragnarok_fenrir_module_animation_AnimatedFileDrawable_getVideoFrame(JNI
}
}
return 0;
-}
+}
\ No newline at end of file
diff --git a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/rotate_row.h b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/rotate_row.h
index b773f886e..64d0b59f7 100644
--- a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/rotate_row.h
+++ b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/rotate_row.h
@@ -232,6 +232,27 @@ void TransposeWx1_16_C(const uint16_t* src,
uint16_t* dst,
int dst_stride,
int width);
+
+// Transpose 32 bit values (ARGB)
+void Transpose4x4_32_NEON(const uint8_t* src,
+ int src_stride,
+ uint8_t* dst,
+ int dst_stride,
+ int width);
+
+void Transpose4x4_32_C(const uint8_t* src,
+ int src_stride,
+ uint8_t* dst,
+ int dst_stride,
+ int width);
+
+// Transpose 32 bit values (ARGB)
+void Transpose8x8_32_NEON(const uint8_t* src,
+ int src_stride,
+ uint8_t* dst,
+ int dst_stride,
+ int width);
+
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
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 8d998727f..ff6ffe47c 100644
--- a/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h
+++ b/libfenrir/src/main/jni/animation/libyuv/include/libyuv/row.h
@@ -403,8 +403,9 @@ extern "C" {
// TODO(fbarchard): Port to GCC and Visual C
// TODO(fbarchard): re-enable HAS_ARGBTORGB24ROW_AVX512VBMI. Issue libyuv:789
#if !defined(LIBYUV_DISABLE_X86) && \
- (defined(__x86_64__) || defined(__i386__)) && (defined(CLANG_HAS_AVX512))
+ (defined(__x86_64__) || defined(__i386__)) && defined(CLANG_HAS_AVX512)
#define HAS_ARGBTORGB24ROW_AVX512VBMI
+#define HAS_MERGEUVROW_AVX512BW
#endif
// The following are available for AVX512 clang x64 platforms:
@@ -2184,6 +2185,10 @@ void MergeUVRow_AVX2(const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_uv,
int width);
+void MergeUVRow_AVX512BW(const uint8_t* src_u,
+ const uint8_t* src_v,
+ uint8_t* dst_uv,
+ int width);
void MergeUVRow_NEON(const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_uv,
@@ -2204,6 +2209,10 @@ void MergeUVRow_Any_AVX2(const uint8_t* y_buf,
const uint8_t* uv_buf,
uint8_t* dst_ptr,
int width);
+void MergeUVRow_Any_AVX512BW(const uint8_t* y_buf,
+ const uint8_t* uv_buf,
+ uint8_t* dst_ptr,
+ int width);
void MergeUVRow_Any_NEON(const uint8_t* y_buf,
const uint8_t* uv_buf,
uint8_t* dst_ptr,
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 adc49c4e4..42f816626 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 1857
+#define LIBYUV_VERSION 1861
#endif // INCLUDE_LIBYUV_VERSION_H_
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/convert.cc b/libfenrir/src/main/jni/animation/libyuv/source/convert.cc
index 15c70a659..37b7091b1 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/convert.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/convert.cc
@@ -919,11 +919,19 @@ int I422ToNV21(const uint8_t* src_y,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 32)) {
+ MergeUVRow = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow = MergeUVRow_Any_NEON;
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/convert_from_argb.cc b/libfenrir/src/main/jni/animation/libyuv/source/convert_from_argb.cc
index d548aec28..55516cbd8 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/convert_from_argb.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/convert_from_argb.cc
@@ -384,11 +384,19 @@ int ARGBToNV12(const uint8_t* src_argb,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_ = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow_ = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow_ = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 32)) {
+ MergeUVRow_ = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow_ = MergeUVRow_Any_NEON;
@@ -554,11 +562,19 @@ int ARGBToNV21(const uint8_t* src_argb,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_ = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow_ = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow_ = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 64)) {
+ MergeUVRow_ = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow_ = MergeUVRow_Any_NEON;
@@ -721,11 +737,19 @@ int ABGRToNV12(const uint8_t* src_abgr,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_ = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow_ = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow_ = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 64)) {
+ MergeUVRow_ = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow_ = MergeUVRow_Any_NEON;
@@ -889,11 +913,19 @@ int ABGRToNV21(const uint8_t* src_abgr,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_ = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow_ = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow_ = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 64)) {
+ MergeUVRow_ = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow_ = MergeUVRow_Any_NEON;
@@ -2916,11 +2948,19 @@ int RAWToJNV21(const uint8_t* src_raw,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_ = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(halfwidth, 32)) {
+ if (IS_ALIGNED(halfwidth, 16)) {
MergeUVRow_ = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow_ = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(halfwidth, 64)) {
+ MergeUVRow_ = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow_ = MergeUVRow_Any_NEON;
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 e08a44f6f..e3452f58e 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/planar_functions.cc
@@ -162,7 +162,7 @@ void Convert8To16Plane(const uint8_t* src_y,
int src_stride_y,
uint16_t* dst_y,
int dst_stride_y,
- int scale, // 16384 for 10 bits
+ int scale, // 1024 for 10 bits
int width,
int height) {
int y;
@@ -594,11 +594,19 @@ void MergeUVPlane(const uint8_t* src_u,
#if defined(HAS_MERGEUVROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow = MergeUVRow_Any_AVX2;
- if (IS_ALIGNED(width, 32)) {
+ if (IS_ALIGNED(width, 16)) {
MergeUVRow = MergeUVRow_AVX2;
}
}
#endif
+#if defined(HAS_MERGEUVROW_AVX512BW)
+ if (TestCpuFlag(kCpuHasAVX512BW)) {
+ MergeUVRow = MergeUVRow_Any_AVX512BW;
+ if (IS_ALIGNED(width, 32)) {
+ MergeUVRow = MergeUVRow_AVX512BW;
+ }
+ }
+#endif
#if defined(HAS_MERGEUVROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
MergeUVRow = MergeUVRow_Any_NEON;
@@ -728,7 +736,7 @@ void MergeUVPlane_16(const uint16_t* src_u,
#if defined(HAS_MERGEUVROW_16_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
MergeUVRow_16 = MergeUVRow_16_Any_AVX2;
- if (IS_ALIGNED(width, 16)) {
+ if (IS_ALIGNED(width, 8)) {
MergeUVRow_16 = MergeUVRow_16_AVX2;
}
}
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/rotate_common.cc b/libfenrir/src/main/jni/animation/libyuv/source/rotate_common.cc
index 2617c01b2..4b496d1b3 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/rotate_common.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/rotate_common.cc
@@ -166,6 +166,63 @@ void TransposeWxH_16_C(const uint16_t* src,
}
}
+// Transpose 32 bit values (ARGB)
+void Transpose4x4_32_C(const uint8_t* src,
+ int src_stride,
+ uint8_t* dst,
+ int dst_stride,
+ int width) {
+ const uint8_t* src1 = src + src_stride;
+ const uint8_t* src2 = src1 + src_stride;
+ const uint8_t* src3 = src2 + src_stride;
+ uint8_t* dst1 = dst + dst_stride;
+ uint8_t* dst2 = dst1 + dst_stride;
+ uint8_t* dst3 = dst2 + dst_stride;
+ int i;
+ for (i = 0; i < width; i += 4) {
+ uint32_t p00 = ((uint32_t*)(src))[0];
+ uint32_t p10 = ((uint32_t*)(src))[1];
+ uint32_t p20 = ((uint32_t*)(src))[2];
+ uint32_t p30 = ((uint32_t*)(src))[3];
+ uint32_t p01 = ((uint32_t*)(src1))[0];
+ uint32_t p11 = ((uint32_t*)(src1))[1];
+ uint32_t p21 = ((uint32_t*)(src1))[2];
+ uint32_t p31 = ((uint32_t*)(src1))[3];
+ uint32_t p02 = ((uint32_t*)(src2))[0];
+ uint32_t p12 = ((uint32_t*)(src2))[1];
+ uint32_t p22 = ((uint32_t*)(src2))[2];
+ uint32_t p32 = ((uint32_t*)(src2))[3];
+ uint32_t p03 = ((uint32_t*)(src3))[0];
+ uint32_t p13 = ((uint32_t*)(src3))[1];
+ uint32_t p23 = ((uint32_t*)(src3))[2];
+ uint32_t p33 = ((uint32_t*)(src3))[3];
+ ((uint32_t*)(dst))[0] = p00;
+ ((uint32_t*)(dst))[1] = p01;
+ ((uint32_t*)(dst))[2] = p02;
+ ((uint32_t*)(dst))[3] = p03;
+ ((uint32_t*)(dst1))[0] = p10;
+ ((uint32_t*)(dst1))[1] = p11;
+ ((uint32_t*)(dst1))[2] = p12;
+ ((uint32_t*)(dst1))[3] = p13;
+ ((uint32_t*)(dst2))[0] = p20;
+ ((uint32_t*)(dst2))[1] = p21;
+ ((uint32_t*)(dst2))[2] = p22;
+ ((uint32_t*)(dst2))[3] = p23;
+ ((uint32_t*)(dst3))[0] = p30;
+ ((uint32_t*)(dst3))[1] = p31;
+ ((uint32_t*)(dst3))[2] = p32;
+ ((uint32_t*)(dst3))[3] = p33;
+ src += src_stride * 4; // advance 4 rows
+ src1 += src_stride * 4;
+ src2 += src_stride * 4;
+ src3 += src_stride * 4;
+ dst += 4 * 4; // advance 4 columns
+ dst1 += 4 * 4;
+ dst2 += 4 * 4;
+ dst3 += 4 * 4;
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/rotate_neon64.cc b/libfenrir/src/main/jni/animation/libyuv/source/rotate_neon64.cc
index ea1cf82c2..95047fa7a 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/rotate_neon64.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/rotate_neon64.cc
@@ -435,6 +435,45 @@ void TransposeUVWx8_NEON(const uint8_t* src,
: "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16",
"v17", "v18", "v19", "v20", "v21", "v22", "v23", "v30", "v31");
}
+
+// Transpose 32 bit values (ARGB)
+void Transpose4x4_32_NEON(const uint8_t* src,
+ int src_stride,
+ uint8_t* dst,
+ int dst_stride,
+ int width) {
+ const uint8_t* src1 = src + src_stride;
+ const uint8_t* src2 = src1 + src_stride;
+ const uint8_t* src3 = src2 + src_stride;
+ uint8_t* dst1 = dst + dst_stride;
+ uint8_t* dst2 = dst1 + dst_stride;
+ uint8_t* dst3 = dst2 + dst_stride;
+ asm volatile(
+ // Main loop transpose 4x4. Read a column, write a row.
+ "1: \n"
+ "ld4 {v0.s, v1.s, v2.s, v3.s}[0], [%0], %9 \n"
+ "ld4 {v0.s, v1.s, v2.s, v3.s}[1], [%1], %9 \n"
+ "ld4 {v0.s, v1.s, v2.s, v3.s}[2], [%2], %9 \n"
+ "ld4 {v0.s, v1.s, v2.s, v3.s}[3], [%3], %9 \n"
+ "subs %w8, %w8, #4 \n" // w -= 4
+ "st1 {v0.4s}, [%4], 16 \n"
+ "st1 {v1.4s}, [%5], 16 \n"
+ "st1 {v2.4s}, [%6], 16 \n"
+ "st1 {v3.4s}, [%7], 16 \n"
+ "b.gt 1b \n"
+ : "+r"(src), // %0
+ "+r"(src1), // %1
+ "+r"(src2), // %2
+ "+r"(src3), // %3
+ "+r"(dst), // %4
+ "+r"(dst1), // %5
+ "+r"(dst2), // %6
+ "+r"(dst3), // %7
+ "+r"(width) // %8
+ : "r"((ptrdiff_t)(src_stride * 4)) // %9
+ : "memory", "cc", "v0", "v1", "v2", "v3");
+}
+
#endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
#ifdef __cplusplus
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_any.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_any.cc
index 012f0fb29..0168061ff 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_any.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_any.cc
@@ -569,7 +569,10 @@ ANY31PT(MergeXRGB16To8Row_Any_NEON,
ANY21(MergeUVRow_Any_SSE2, MergeUVRow_SSE2, 0, 1, 1, 2, 15)
#endif
#ifdef HAS_MERGEUVROW_AVX2
-ANY21(MergeUVRow_Any_AVX2, MergeUVRow_AVX2, 0, 1, 1, 2, 31)
+ANY21(MergeUVRow_Any_AVX2, MergeUVRow_AVX2, 0, 1, 1, 2, 15)
+#endif
+#ifdef HAS_MERGEUVROW_AVX512BW
+ANY21(MergeUVRow_Any_AVX512BW, MergeUVRow_AVX512BW, 0, 1, 1, 2, 31)
#endif
#ifdef HAS_MERGEUVROW_NEON
ANY21(MergeUVRow_Any_NEON, MergeUVRow_NEON, 0, 1, 1, 2, 15)
@@ -858,7 +861,7 @@ ANY21CT(P410ToAR30Row_Any_AVX2, P410ToAR30Row_AVX2, 0, 0, uint16_t, 2, 4, 15)
}
#ifdef HAS_MERGEUVROW_16_AVX2
-ANY21PT(MergeUVRow_16_Any_AVX2, MergeUVRow_16_AVX2, uint16_t, 2, 15)
+ANY21PT(MergeUVRow_16_Any_AVX2, MergeUVRow_16_AVX2, uint16_t, 2, 7)
#endif
#ifdef HAS_MERGEUVROW_16_NEON
ANY21PT(MergeUVRow_16_Any_NEON, MergeUVRow_16_NEON, uint16_t, 2, 7)
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_gcc.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_gcc.cc
index f36d0cf01..aa4c0d11e 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_gcc.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_gcc.cc
@@ -5142,36 +5142,59 @@ void DetileSplitUVRow_SSSE3(const uint8_t* src_uv,
}
#endif // HAS_DETILESPLITUVROW_SSSE3
+#ifdef HAS_MERGEUVROW_AVX512BW
+void MergeUVRow_AVX512BW(const uint8_t* src_u,
+ const uint8_t* src_v,
+ uint8_t* dst_uv,
+ int width) {
+ asm volatile("sub %0,%1 \n"
+
+ LABELALIGN
+ "1: \n"
+ "vpmovzxbw (%0),%%zmm0 \n"
+ "vpmovzxbw 0x00(%0,%1,1),%%zmm1 \n"
+ "lea 0x20(%0),%0 \n"
+ "vpsllw $0x8,%%zmm1,%%zmm1 \n"
+ "vporq %%zmm0,%%zmm1,%%zmm2 \n"
+ "vmovdqu64 %%zmm2,(%2) \n"
+ "lea 0x40(%2),%2 \n"
+ "sub $0x20,%3 \n"
+ "jg 1b \n"
+ "vzeroupper \n"
+ : "+r"(src_u), // %0
+ "+r"(src_v), // %1
+ "+r"(dst_uv), // %2
+ "+r"(width) // %3
+ :
+ : "memory", "cc", "xmm0", "xmm1", "xmm2");
+}
+#endif // HAS_MERGEUVROW_AVX512BW
+
#ifdef HAS_MERGEUVROW_AVX2
void MergeUVRow_AVX2(const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_uv,
int width) {
- asm volatile(
-
- "sub %0,%1 \n"
+ asm volatile("sub %0,%1 \n"
- LABELALIGN
+ LABELALIGN
"1: \n"
- "vmovdqu (%0),%%ymm0 \n"
- "vmovdqu 0x00(%0,%1,1),%%ymm1 \n"
- "lea 0x20(%0),%0 \n"
- "vpunpcklbw %%ymm1,%%ymm0,%%ymm2 \n"
- "vpunpckhbw %%ymm1,%%ymm0,%%ymm0 \n"
- "vextractf128 $0x0,%%ymm2,(%2) \n"
- "vextractf128 $0x0,%%ymm0,0x10(%2) \n"
- "vextractf128 $0x1,%%ymm2,0x20(%2) \n"
- "vextractf128 $0x1,%%ymm0,0x30(%2) \n"
- "lea 0x40(%2),%2 \n"
- "sub $0x20,%3 \n"
+ "vpmovzxbw (%0),%%ymm0 \n"
+ "vpmovzxbw 0x00(%0,%1,1),%%ymm1 \n"
+ "lea 0x10(%0),%0 \n"
+ "vpsllw $0x8,%%ymm1,%%ymm1 \n"
+ "vpor %%ymm0,%%ymm1,%%ymm2 \n"
+ "vmovdqu %%ymm2,(%2) \n"
+ "lea 0x20(%2),%2 \n"
+ "sub $0x10,%3 \n"
"jg 1b \n"
"vzeroupper \n"
- : "+r"(src_u), // %0
- "+r"(src_v), // %1
- "+r"(dst_uv), // %2
- "+r"(width) // %3
- :
- : "memory", "cc", "xmm0", "xmm1", "xmm2");
+ : "+r"(src_u), // %0
+ "+r"(src_v), // %1
+ "+r"(dst_uv), // %2
+ "+r"(width) // %3
+ :
+ : "memory", "cc", "xmm0", "xmm1", "xmm2");
}
#endif // HAS_MERGEUVROW_AVX2
@@ -5180,11 +5203,9 @@ void MergeUVRow_SSE2(const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_uv,
int width) {
- asm volatile(
+ asm volatile("sub %0,%1 \n"
- "sub %0,%1 \n"
-
- LABELALIGN
+ LABELALIGN
"1: \n"
"movdqu (%0),%%xmm0 \n"
"movdqu 0x00(%0,%1,1),%%xmm1 \n"
@@ -5197,12 +5218,12 @@ void MergeUVRow_SSE2(const uint8_t* src_u,
"lea 0x20(%2),%2 \n"
"sub $0x10,%3 \n"
"jg 1b \n"
- : "+r"(src_u), // %0
- "+r"(src_v), // %1
- "+r"(dst_uv), // %2
- "+r"(width) // %3
- :
- : "memory", "cc", "xmm0", "xmm1", "xmm2");
+ : "+r"(src_u), // %0
+ "+r"(src_v), // %1
+ "+r"(dst_uv), // %2
+ "+r"(width) // %3
+ :
+ : "memory", "cc", "xmm0", "xmm1", "xmm2");
}
#endif // HAS_MERGEUVROW_SSE2
@@ -5212,37 +5233,35 @@ void MergeUVRow_16_AVX2(const uint16_t* src_u,
uint16_t* dst_uv,
int depth,
int width) {
- depth = 16 - depth;
// clang-format off
asm volatile (
"vmovd %4,%%xmm3 \n"
+ "vmovd %5,%%xmm4 \n"
+
+
"sub %0,%1 \n"
+ // 8 pixels per loop.
- // 16 pixels per loop.
- LABELALIGN
+ LABELALIGN
"1: \n"
- "vmovdqu (%0),%%ymm0 \n"
- "vmovdqu (%0,%1,1),%%ymm1 \n"
- "add $0x20,%0 \n"
-
+ "vpmovzxwd (%0),%%ymm0 \n"
+ "vpmovzxwd 0x00(%0,%1,1),%%ymm1 \n"
+ "lea 0x10(%0),%0 \n"
"vpsllw %%xmm3,%%ymm0,%%ymm0 \n"
- "vpsllw %%xmm3,%%ymm1,%%ymm1 \n"
- "vpunpcklwd %%ymm1,%%ymm0,%%ymm2 \n" // mutates
- "vpunpckhwd %%ymm1,%%ymm0,%%ymm0 \n"
- "vextractf128 $0x0,%%ymm2,(%2) \n"
- "vextractf128 $0x0,%%ymm0,0x10(%2) \n"
- "vextractf128 $0x1,%%ymm2,0x20(%2) \n"
- "vextractf128 $0x1,%%ymm0,0x30(%2) \n"
- "add $0x40,%2 \n"
- "sub $0x10,%3 \n"
+ "vpslld %%xmm4,%%ymm1,%%ymm1 \n"
+ "vpor %%ymm0,%%ymm1,%%ymm2 \n"
+ "vmovdqu %%ymm2,(%2) \n"
+ "lea 0x20(%2),%2 \n"
+ "sub $0x8,%3 \n"
"jg 1b \n"
"vzeroupper \n"
- : "+r"(src_u), // %0
- "+r"(src_v), // %1
- "+r"(dst_uv), // %2
- "+r"(width) // %3
- : "r"(depth) // %4
- : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3");
+ : "+r"(src_u), // %0
+ "+r"(src_v), // %1
+ "+r"(dst_uv), // %2
+ "+r"(width) // %3
+ : "r"(16 - depth), // %4
+ "r"(32 - depth) // %5
+ : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4");
// clang-format on
}
#endif // HAS_MERGEUVROW_AVX2
@@ -5448,7 +5467,6 @@ void Convert16To8Row_AVX2(const uint16_t* src_y,
// 512 = 9 bits
// 1024 = 10 bits
// 4096 = 12 bits
-// TODO(fbarchard): reduce to SSE2
void Convert8To16Row_SSE2(const uint8_t* src_y,
uint16_t* dst_y,
int scale,
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_lasx.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_lasx.cc
index f824906d3..29ac9254d 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_lasx.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_lasx.cc
@@ -2036,8 +2036,8 @@ static void ARGBToYMatrixRow_LASX(const uint8_t* src_argb,
uint8_t* dst_y,
int width,
const struct RgbConstants* rgbconstants) {
- int32_t shuff[8] = {0, 4, 1, 5, 2, 6, 3, 7};
- asm volatile(
+ int32_t shuff[8] = {0, 4, 1, 5, 2, 6, 3, 7};
+ asm volatile(
"xvldrepl.b $xr0, %3, 0 \n\t" // load rgbconstants
"xvldrepl.b $xr1, %3, 1 \n\t" // load rgbconstants
"xvldrepl.b $xr2, %3, 2 \n\t" // load rgbconstants
@@ -2047,19 +2047,21 @@ static void ARGBToYMatrixRow_LASX(const uint8_t* src_argb,
"xvld $xr4, %0, 0 \n\t"
"xvld $xr5, %0, 32 \n\t"
"xvld $xr6, %0, 64 \n\t"
- "xvld $xr7, %0, 96 \n\t" // load 32 pixels of ARGB
+ "xvld $xr7, %0, 96 \n\t" // load 32 pixels of
+ // ARGB
"xvor.v $xr12, $xr3, $xr3 \n\t"
"xvor.v $xr13, $xr3, $xr3 \n\t"
- "addi.d %2, %2, -32 \n\t" // 32 processed per loop.
- "xvpickev.b $xr8, $xr5, $xr4 \n\t" //BR
+ "addi.d %2, %2, -32 \n\t" // 32 processed per
+ // loop.
+ "xvpickev.b $xr8, $xr5, $xr4 \n\t" // BR
"xvpickev.b $xr10, $xr7, $xr6 \n\t"
- "xvpickod.b $xr9, $xr5, $xr4 \n\t" //GA
+ "xvpickod.b $xr9, $xr5, $xr4 \n\t" // GA
"xvpickod.b $xr11, $xr7, $xr6 \n\t"
- "xvmaddwev.h.bu $xr12, $xr8, $xr0 \n\t" //B
+ "xvmaddwev.h.bu $xr12, $xr8, $xr0 \n\t" // B
"xvmaddwev.h.bu $xr13, $xr10, $xr0 \n\t"
- "xvmaddwev.h.bu $xr12, $xr9, $xr1 \n\t" //G
+ "xvmaddwev.h.bu $xr12, $xr9, $xr1 \n\t" // G
"xvmaddwev.h.bu $xr13, $xr11, $xr1 \n\t"
- "xvmaddwod.h.bu $xr12, $xr8, $xr2 \n\t" //R
+ "xvmaddwod.h.bu $xr12, $xr8, $xr2 \n\t" // R
"xvmaddwod.h.bu $xr13, $xr10, $xr2 \n\t"
"addi.d %0, %0, 128 \n\t"
"xvpickod.b $xr10, $xr13, $xr12 \n\t"
@@ -2067,13 +2069,11 @@ static void ARGBToYMatrixRow_LASX(const uint8_t* src_argb,
"xvst $xr11, %1, 0 \n\t"
"addi.d %1, %1, 32 \n\t"
"bnez %2, 1b \n\t"
- : "+&r"(src_argb), // %0
- "+&r"(dst_y), // %1
- "+&r"(width) // %2
- : "r"(rgbconstants),
- "r"(shuff)
- : "memory"
- );
+ : "+&r"(src_argb), // %0
+ "+&r"(dst_y), // %1
+ "+&r"(width) // %2
+ : "r"(rgbconstants), "r"(shuff)
+ : "memory");
}
void ARGBToYRow_LASX(const uint8_t* src_argb, uint8_t* dst_y, int width) {
@@ -2098,8 +2098,8 @@ static void RGBAToYMatrixRow_LASX(const uint8_t* src_rgba,
uint8_t* dst_y,
int width,
const struct RgbConstants* rgbconstants) {
- int32_t shuff[8] = {0, 4, 1, 5, 2, 6, 3, 7};
- asm volatile(
+ int32_t shuff[8] = {0, 4, 1, 5, 2, 6, 3, 7};
+ asm volatile(
"xvldrepl.b $xr0, %3, 0 \n\t" // load rgbconstants
"xvldrepl.b $xr1, %3, 1 \n\t" // load rgbconstants
"xvldrepl.b $xr2, %3, 2 \n\t" // load rgbconstants
@@ -2109,19 +2109,21 @@ static void RGBAToYMatrixRow_LASX(const uint8_t* src_rgba,
"xvld $xr4, %0, 0 \n\t"
"xvld $xr5, %0, 32 \n\t"
"xvld $xr6, %0, 64 \n\t"
- "xvld $xr7, %0, 96 \n\t" // load 32 pixels of RGBA
+ "xvld $xr7, %0, 96 \n\t" // load 32 pixels of
+ // RGBA
"xvor.v $xr12, $xr3, $xr3 \n\t"
"xvor.v $xr13, $xr3, $xr3 \n\t"
- "addi.d %2, %2, -32 \n\t" // 32 processed per loop.
- "xvpickev.b $xr8, $xr5, $xr4 \n\t" //AG
+ "addi.d %2, %2, -32 \n\t" // 32 processed per
+ // loop.
+ "xvpickev.b $xr8, $xr5, $xr4 \n\t" // AG
"xvpickev.b $xr10, $xr7, $xr6 \n\t"
- "xvpickod.b $xr9, $xr5, $xr4 \n\t" //BR
+ "xvpickod.b $xr9, $xr5, $xr4 \n\t" // BR
"xvpickod.b $xr11, $xr7, $xr6 \n\t"
- "xvmaddwev.h.bu $xr12, $xr9, $xr0 \n\t" //B
+ "xvmaddwev.h.bu $xr12, $xr9, $xr0 \n\t" // B
"xvmaddwev.h.bu $xr13, $xr11, $xr0 \n\t"
- "xvmaddwod.h.bu $xr12, $xr8, $xr1 \n\t" //G
+ "xvmaddwod.h.bu $xr12, $xr8, $xr1 \n\t" // G
"xvmaddwod.h.bu $xr13, $xr10, $xr1 \n\t"
- "xvmaddwod.h.bu $xr12, $xr9, $xr2 \n\t" //R
+ "xvmaddwod.h.bu $xr12, $xr9, $xr2 \n\t" // R
"xvmaddwod.h.bu $xr13, $xr11, $xr2 \n\t"
"addi.d %0, %0, 128 \n\t"
"xvpickod.b $xr10, $xr13, $xr12 \n\t"
@@ -2129,13 +2131,11 @@ static void RGBAToYMatrixRow_LASX(const uint8_t* src_rgba,
"xvst $xr11, %1, 0 \n\t"
"addi.d %1, %1, 32 \n\t"
"bnez %2, 1b \n\t"
- : "+&r"(src_rgba), // %0
- "+&r"(dst_y), // %1
- "+&r"(width) // %2
- : "r"(rgbconstants),
- "r"(shuff)
- : "memory"
- );
+ : "+&r"(src_rgba), // %0
+ "+&r"(dst_y), // %1
+ "+&r"(width) // %2
+ : "r"(rgbconstants), "r"(shuff)
+ : "memory");
}
void RGBAToYRow_LASX(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
@@ -2151,18 +2151,19 @@ void BGRAToYRow_LASX(const uint8_t* src_bgra, uint8_t* dst_y, int width) {
}
static void RGBToYMatrixRow_LASX(const uint8_t* src_rgba,
- uint8_t* dst_y,
- int width,
- const struct RgbConstants* rgbconstants) {
- int8_t shuff[128] = {0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
- 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
- 24, 26, 27, 29, 30, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15,
- 24, 26, 27, 29, 30, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15,
- 1, 0, 4, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0,
- 1, 0, 4, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0,
- 25, 0, 28, 0, 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0,
- 25, 0, 28, 0, 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0};
- asm volatile(
+ uint8_t* dst_y,
+ int width,
+ const struct RgbConstants* rgbconstants) {
+ int8_t shuff[128] = {
+ 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
+ 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
+ 24, 26, 27, 29, 30, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15,
+ 24, 26, 27, 29, 30, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15,
+ 1, 0, 4, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0,
+ 1, 0, 4, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0,
+ 25, 0, 28, 0, 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0,
+ 25, 0, 28, 0, 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0};
+ asm volatile(
"xvldrepl.b $xr0, %3, 0 \n\t" // load rgbconstants
"xvldrepl.b $xr1, %3, 1 \n\t" // load rgbconstants
"xvldrepl.b $xr2, %3, 2 \n\t" // load rgbconstants
@@ -2174,23 +2175,25 @@ static void RGBToYMatrixRow_LASX(const uint8_t* src_rgba,
"1: \n\t"
"xvld $xr8, %0, 0 \n\t"
"xvld $xr9, %0, 32 \n\t"
- "xvld $xr10, %0, 64 \n\t" // load 32 pixels of RGB
+ "xvld $xr10, %0, 64 \n\t" // load 32 pixels of
+ // RGB
"xvor.v $xr12, $xr3, $xr3 \n\t"
"xvor.v $xr13, $xr3, $xr3 \n\t"
"xvor.v $xr11, $xr9, $xr9 \n\t"
- "addi.d %2, %2, -32 \n\t" // 32 processed per loop.
- "xvpermi.q $xr9, $xr8, 0x30 \n\t" //src0
- "xvpermi.q $xr8, $xr10, 0x03 \n\t" //src1
- "xvpermi.q $xr10, $xr11, 0x30 \n\t" //src2
+ "addi.d %2, %2, -32 \n\t" // 32 processed per
+ // loop.
+ "xvpermi.q $xr9, $xr8, 0x30 \n\t" // src0
+ "xvpermi.q $xr8, $xr10, 0x03 \n\t" // src1
+ "xvpermi.q $xr10, $xr11, 0x30 \n\t" // src2
"xvshuf.b $xr14, $xr8, $xr9, $xr4 \n\t"
"xvshuf.b $xr15, $xr8, $xr10, $xr5 \n\t"
"xvshuf.b $xr16, $xr8, $xr9, $xr6 \n\t"
"xvshuf.b $xr17, $xr8, $xr10, $xr7 \n\t"
- "xvmaddwev.h.bu $xr12, $xr16, $xr1 \n\t" //G
+ "xvmaddwev.h.bu $xr12, $xr16, $xr1 \n\t" // G
"xvmaddwev.h.bu $xr13, $xr17, $xr1 \n\t"
- "xvmaddwev.h.bu $xr12, $xr14, $xr0 \n\t" //B
+ "xvmaddwev.h.bu $xr12, $xr14, $xr0 \n\t" // B
"xvmaddwev.h.bu $xr13, $xr15, $xr0 \n\t"
- "xvmaddwod.h.bu $xr12, $xr14, $xr2 \n\t" //R
+ "xvmaddwod.h.bu $xr12, $xr14, $xr2 \n\t" // R
"xvmaddwod.h.bu $xr13, $xr15, $xr2 \n\t"
"addi.d %0, %0, 96 \n\t"
"xvpickod.b $xr10, $xr13, $xr12 \n\t"
@@ -2202,8 +2205,7 @@ static void RGBToYMatrixRow_LASX(const uint8_t* src_rgba,
"+&r"(width) // %2
: "r"(rgbconstants), // %3
"r"(shuff) // %4
- : "memory"
- );
+ : "memory");
}
void RGB24ToYJRow_LASX(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) {
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_lsx.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_lsx.cc
index 0825b6335..9c1e16f22 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_lsx.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_lsx.cc
@@ -1679,7 +1679,7 @@ static void ARGBToYMatrixRow_LSX(const uint8_t* src_argb,
uint8_t* dst_y,
int width,
const struct RgbConstants* rgbconstants) {
- asm volatile(
+ asm volatile(
"vldrepl.b $vr0, %3, 0 \n\t" // load rgbconstants
"vldrepl.b $vr1, %3, 1 \n\t" // load rgbconstants
"vldrepl.b $vr2, %3, 2 \n\t" // load rgbconstants
@@ -1688,31 +1688,32 @@ static void ARGBToYMatrixRow_LSX(const uint8_t* src_argb,
"vld $vr4, %0, 0 \n\t"
"vld $vr5, %0, 16 \n\t"
"vld $vr6, %0, 32 \n\t"
- "vld $vr7, %0, 48 \n\t" // load 16 pixels of ARGB
+ "vld $vr7, %0, 48 \n\t" // load 16 pixels of
+ // ARGB
"vor.v $vr12, $vr3, $vr3 \n\t"
"vor.v $vr13, $vr3, $vr3 \n\t"
- "addi.d %2, %2, -16 \n\t" // 16 processed per loop.
- "vpickev.b $vr8, $vr5, $vr4 \n\t" //BR
+ "addi.d %2, %2, -16 \n\t" // 16 processed per
+ // loop.
+ "vpickev.b $vr8, $vr5, $vr4 \n\t" // BR
"vpickev.b $vr10, $vr7, $vr6 \n\t"
- "vpickod.b $vr9, $vr5, $vr4 \n\t" //GA
+ "vpickod.b $vr9, $vr5, $vr4 \n\t" // GA
"vpickod.b $vr11, $vr7, $vr6 \n\t"
- "vmaddwev.h.bu $vr12, $vr8, $vr0 \n\t" //B
+ "vmaddwev.h.bu $vr12, $vr8, $vr0 \n\t" // B
"vmaddwev.h.bu $vr13, $vr10, $vr0 \n\t"
- "vmaddwev.h.bu $vr12, $vr9, $vr1 \n\t" //G
+ "vmaddwev.h.bu $vr12, $vr9, $vr1 \n\t" // G
"vmaddwev.h.bu $vr13, $vr11, $vr1 \n\t"
- "vmaddwod.h.bu $vr12, $vr8, $vr2 \n\t" //R
+ "vmaddwod.h.bu $vr12, $vr8, $vr2 \n\t" // R
"vmaddwod.h.bu $vr13, $vr10, $vr2 \n\t"
"addi.d %0, %0, 64 \n\t"
"vpickod.b $vr10, $vr13, $vr12 \n\t"
"vst $vr10, %1, 0 \n\t"
"addi.d %1, %1, 16 \n\t"
"bnez %2, 1b \n\t"
- : "+&r"(src_argb), // %0
- "+&r"(dst_y), // %1
- "+&r"(width) // %2
+ : "+&r"(src_argb), // %0
+ "+&r"(dst_y), // %1
+ "+&r"(width) // %2
: "r"(rgbconstants)
- : "memory"
- );
+ : "memory");
}
void ARGBToYRow_LSX(const uint8_t* src_argb, uint8_t* dst_y, int width) {
@@ -1737,7 +1738,7 @@ static void RGBAToYMatrixRow_LSX(const uint8_t* src_rgba,
uint8_t* dst_y,
int width,
const struct RgbConstants* rgbconstants) {
- asm volatile(
+ asm volatile(
"vldrepl.b $vr0, %3, 0 \n\t" // load rgbconstants
"vldrepl.b $vr1, %3, 1 \n\t" // load rgbconstants
"vldrepl.b $vr2, %3, 2 \n\t" // load rgbconstants
@@ -1746,31 +1747,32 @@ static void RGBAToYMatrixRow_LSX(const uint8_t* src_rgba,
"vld $vr4, %0, 0 \n\t"
"vld $vr5, %0, 16 \n\t"
"vld $vr6, %0, 32 \n\t"
- "vld $vr7, %0, 48 \n\t" // load 16 pixels of RGBA
+ "vld $vr7, %0, 48 \n\t" // load 16 pixels of
+ // RGBA
"vor.v $vr12, $vr3, $vr3 \n\t"
"vor.v $vr13, $vr3, $vr3 \n\t"
- "addi.d %2, %2, -16 \n\t" // 16 processed per loop.
- "vpickev.b $vr8, $vr5, $vr4 \n\t" //AG
+ "addi.d %2, %2, -16 \n\t" // 16 processed per
+ // loop.
+ "vpickev.b $vr8, $vr5, $vr4 \n\t" // AG
"vpickev.b $vr10, $vr7, $vr6 \n\t"
- "vpickod.b $vr9, $vr5, $vr4 \n\t" //BR
+ "vpickod.b $vr9, $vr5, $vr4 \n\t" // BR
"vpickod.b $vr11, $vr7, $vr6 \n\t"
- "vmaddwev.h.bu $vr12, $vr9, $vr0 \n\t" //B
+ "vmaddwev.h.bu $vr12, $vr9, $vr0 \n\t" // B
"vmaddwev.h.bu $vr13, $vr11, $vr0 \n\t"
- "vmaddwod.h.bu $vr12, $vr8, $vr1 \n\t" //G
+ "vmaddwod.h.bu $vr12, $vr8, $vr1 \n\t" // G
"vmaddwod.h.bu $vr13, $vr10, $vr1 \n\t"
- "vmaddwod.h.bu $vr12, $vr9, $vr2 \n\t" //R
+ "vmaddwod.h.bu $vr12, $vr9, $vr2 \n\t" // R
"vmaddwod.h.bu $vr13, $vr11, $vr2 \n\t"
"addi.d %0, %0, 64 \n\t"
"vpickod.b $vr10, $vr13, $vr12 \n\t"
"vst $vr10, %1, 0 \n\t"
"addi.d %1, %1, 16 \n\t"
"bnez %2, 1b \n\t"
- : "+&r"(src_rgba), // %0
- "+&r"(dst_y), // %1
- "+&r"(width) // %2
+ : "+&r"(src_rgba), // %0
+ "+&r"(dst_y), // %1
+ "+&r"(width) // %2
: "r"(rgbconstants)
- : "memory"
- );
+ : "memory");
}
void RGBAToYRow_LSX(const uint8_t* src_rgba, uint8_t* dst_y, int width) {
@@ -1789,11 +1791,12 @@ static void RGBToYMatrixRow_LSX(const uint8_t* src_rgba,
uint8_t* dst_y,
int width,
const struct RgbConstants* rgbconstants) {
- int8_t shuff[64] = {0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
- 24, 26, 27, 29, 30, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15,
- 1, 0, 4, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0,
- 25, 0, 28, 0, 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0};
- asm volatile(
+ int8_t shuff[64] = {0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18,
+ 20, 21, 23, 24, 26, 27, 29, 30, 0, 1, 3, 4, 6,
+ 7, 9, 10, 12, 13, 15, 1, 0, 4, 0, 7, 0, 10,
+ 0, 13, 0, 16, 0, 19, 0, 22, 0, 25, 0, 28, 0,
+ 31, 0, 2, 0, 5, 0, 8, 0, 11, 0, 14, 0};
+ asm volatile(
"vldrepl.b $vr0, %3, 0 \n\t" // load rgbconstants
"vldrepl.b $vr1, %3, 1 \n\t" // load rgbconstants
"vldrepl.b $vr2, %3, 2 \n\t" // load rgbconstants
@@ -1805,19 +1808,21 @@ static void RGBToYMatrixRow_LSX(const uint8_t* src_rgba,
"1: \n\t"
"vld $vr8, %0, 0 \n\t"
"vld $vr9, %0, 16 \n\t"
- "vld $vr10, %0, 32 \n\t" // load 16 pixels of RGB
+ "vld $vr10, %0, 32 \n\t" // load 16 pixels of
+ // RGB
"vor.v $vr12, $vr3, $vr3 \n\t"
"vor.v $vr13, $vr3, $vr3 \n\t"
- "addi.d %2, %2, -16 \n\t" // 16 processed per loop.
+ "addi.d %2, %2, -16 \n\t" // 16 processed per
+ // loop.
"vshuf.b $vr14, $vr9, $vr8, $vr4 \n\t"
"vshuf.b $vr15, $vr9, $vr10, $vr5 \n\t"
"vshuf.b $vr16, $vr9, $vr8, $vr6 \n\t"
"vshuf.b $vr17, $vr9, $vr10, $vr7 \n\t"
- "vmaddwev.h.bu $vr12, $vr16, $vr1 \n\t" //G
+ "vmaddwev.h.bu $vr12, $vr16, $vr1 \n\t" // G
"vmaddwev.h.bu $vr13, $vr17, $vr1 \n\t"
- "vmaddwev.h.bu $vr12, $vr14, $vr0 \n\t" //B
+ "vmaddwev.h.bu $vr12, $vr14, $vr0 \n\t" // B
"vmaddwev.h.bu $vr13, $vr15, $vr0 \n\t"
- "vmaddwod.h.bu $vr12, $vr14, $vr2 \n\t" //R
+ "vmaddwod.h.bu $vr12, $vr14, $vr2 \n\t" // R
"vmaddwod.h.bu $vr13, $vr15, $vr2 \n\t"
"addi.d %0, %0, 48 \n\t"
"vpickod.b $vr10, $vr13, $vr12 \n\t"
@@ -1829,8 +1834,7 @@ static void RGBToYMatrixRow_LSX(const uint8_t* src_rgba,
"+&r"(width) // %2
: "r"(rgbconstants), // %3
"r"(shuff) // %4
- : "memory"
- );
+ : "memory");
}
void RGB24ToYJRow_LSX(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) {
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/scale.cc b/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
index 65a4685fc..830754ce6 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
@@ -1065,10 +1065,10 @@ void ScalePlaneBilinearDown(int src_width,
const int max_y = (src_height - 1) << 16;
int j;
- void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr,
+ void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr,
int dst_width, int x, int dx) =
(src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C;
- void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr,
+ void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_C;
ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
@@ -1188,10 +1188,10 @@ void ScalePlaneBilinearDown_16(int src_width,
const int max_y = (src_height - 1) << 16;
int j;
- void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr,
+ void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr,
int dst_width, int x, int dx) =
(src_width >= 32768) ? ScaleFilterCols64_16_C : ScaleFilterCols_16_C;
- void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr,
+ void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_16_C;
ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
@@ -1276,10 +1276,10 @@ void ScalePlaneBilinearUp(int src_width,
int dx = 0;
int dy = 0;
const int max_y = (src_height - 1) << 16;
- void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr,
+ void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_C;
- void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr,
+ void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr,
int dst_width, int x, int dx) =
filtering ? ScaleFilterCols_C : ScaleCols_C;
ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
@@ -1744,10 +1744,10 @@ void ScalePlaneBilinearUp_16(int src_width,
int dx = 0;
int dy = 0;
const int max_y = (src_height - 1) << 16;
- void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr,
+ void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_16_C;
- void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr,
+ void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr,
int dst_width, int x, int dx) =
filtering ? ScaleFilterCols_16_C : ScaleCols_16_C;
ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
@@ -1872,7 +1872,7 @@ static void ScalePlaneSimple(int src_width,
const uint8_t* src_ptr,
uint8_t* dst_ptr) {
int i;
- void (*ScaleCols)(uint8_t * dst_ptr, const uint8_t* src_ptr, int dst_width,
+ void (*ScaleCols)(uint8_t* dst_ptr, const uint8_t* src_ptr, int dst_width,
int x, int dx) = ScaleCols_C;
// Initial source x/y coordinate and step values as 16.16 fixed point.
int x = 0;
@@ -1909,7 +1909,7 @@ static void ScalePlaneSimple_16(int src_width,
const uint16_t* src_ptr,
uint16_t* dst_ptr) {
int i;
- void (*ScaleCols)(uint16_t * dst_ptr, const uint16_t* src_ptr, int dst_width,
+ void (*ScaleCols)(uint16_t* dst_ptr, const uint16_t* src_ptr, int dst_width,
int x, int dx) = ScaleCols_16_C;
// Initial source x/y coordinate and step values as 16.16 fixed point.
int x = 0;
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/scale_common.cc b/libfenrir/src/main/jni/animation/libyuv/source/scale_common.cc
index f18324034..da9ca713e 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/scale_common.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/scale_common.cc
@@ -1633,7 +1633,7 @@ void ScalePlaneVertical(int src_height,
enum FilterMode filtering) {
// TODO(fbarchard): Allow higher bpp.
int dst_width_bytes = dst_width * bpp;
- void (*InterpolateRow)(uint8_t * dst_argb, const uint8_t* src_argb,
+ void (*InterpolateRow)(uint8_t* dst_argb, const uint8_t* src_argb,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_C;
const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
@@ -1712,7 +1712,7 @@ void ScalePlaneVertical_16(int src_height,
enum FilterMode filtering) {
// TODO(fbarchard): Allow higher wpp.
int dst_width_words = dst_width * wpp;
- void (*InterpolateRow)(uint16_t * dst_argb, const uint16_t* src_argb,
+ void (*InterpolateRow)(uint16_t* dst_argb, const uint16_t* src_argb,
ptrdiff_t src_stride, int dst_width,
int source_y_fraction) = InterpolateRow_16_C;
const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
@@ -1791,7 +1791,7 @@ void ScalePlaneVertical_16To8(int src_height,
// TODO(fbarchard): Allow higher wpp.
int dst_width_words = dst_width * wpp;
// TODO(https://crbug.com/libyuv/931): Add NEON 32 bit and AVX2 versions.
- void (*InterpolateRow_16To8)(uint8_t * dst_argb, const uint16_t* src_argb,
+ void (*InterpolateRow_16To8)(uint8_t* dst_argb, const uint16_t* src_argb,
ptrdiff_t src_stride, int scale, int dst_width,
int source_y_fraction) = InterpolateRow_16To8_C;
const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
diff --git a/libfenrir/src/main/jni/compress/zstd/common/error_private.c b/libfenrir/src/main/jni/compress/zstd/common/error_private.c
index 0cff6b80b..075fc5ef4 100644
--- a/libfenrir/src/main/jni/compress/zstd/common/error_private.c
+++ b/libfenrir/src/main/jni/compress/zstd/common/error_private.c
@@ -54,7 +54,7 @@ const char* ERR_getErrorString(ERR_enum code)
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
- case PREFIX(externalMatchFinder_failed): return "External matchfinder returned an error code";
+ case PREFIX(sequenceProducer_failed): return "Block-level external sequence producer returned an error code";
case PREFIX(externalSequences_invalid): return "External sequences are not valid";
case PREFIX(maxCode):
default: return notErrorCode;
diff --git a/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress.c b/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress.c
index 5b89ca6d2..b55f684cd 100644
--- a/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress.c
+++ b/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress.c
@@ -615,7 +615,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
bounds.upperBound = (int)ZSTD_ps_disable;
return bounds;
- case ZSTD_c_enableMatchFinderFallback:
+ case ZSTD_c_enableSeqProducerFallback:
bounds.lowerBound = 0;
bounds.upperBound = 1;
return bounds;
@@ -695,7 +695,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
case ZSTD_c_useRowMatchFinder:
case ZSTD_c_deterministicRefPrefix:
case ZSTD_c_prefetchCDictTables:
- case ZSTD_c_enableMatchFinderFallback:
+ case ZSTD_c_enableSeqProducerFallback:
case ZSTD_c_maxBlockSize:
case ZSTD_c_searchForExternalRepcodes:
default:
@@ -754,7 +754,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
case ZSTD_c_useRowMatchFinder:
case ZSTD_c_deterministicRefPrefix:
case ZSTD_c_prefetchCDictTables:
- case ZSTD_c_enableMatchFinderFallback:
+ case ZSTD_c_enableSeqProducerFallback:
case ZSTD_c_maxBlockSize:
case ZSTD_c_searchForExternalRepcodes:
break;
@@ -989,8 +989,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
CCtxParams->prefetchCDictTables = (ZSTD_paramSwitch_e)value;
return CCtxParams->prefetchCDictTables;
- case ZSTD_c_enableMatchFinderFallback:
- BOUNDCHECK(ZSTD_c_enableMatchFinderFallback, value);
+ case ZSTD_c_enableSeqProducerFallback:
+ BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value);
CCtxParams->enableMatchFinderFallback = value;
return CCtxParams->enableMatchFinderFallback;
@@ -1140,7 +1140,7 @@ size_t ZSTD_CCtxParams_getParameter(
case ZSTD_c_prefetchCDictTables:
*value = (int)CCtxParams->prefetchCDictTables;
break;
- case ZSTD_c_enableMatchFinderFallback:
+ case ZSTD_c_enableSeqProducerFallback:
*value = CCtxParams->enableMatchFinderFallback;
break;
case ZSTD_c_maxBlockSize:
@@ -1610,8 +1610,8 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
/* Helper function for calculating memory requirements.
* Gives a tighter bound than ZSTD_sequenceBound() by taking minMatch into account. */
-static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useExternalMatchFinder) {
- U32 const divider = (minMatch==3 || useExternalMatchFinder) ? 3 : 4;
+static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequenceProducer) {
+ U32 const divider = (minMatch==3 || useSequenceProducer) ? 3 : 4;
return blockSize / divider;
}
@@ -1623,12 +1623,12 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
const size_t buffInSize,
const size_t buffOutSize,
const U64 pledgedSrcSize,
- int useExternalMatchFinder,
+ int useSequenceProducer,
size_t maxBlockSize)
{
size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);
size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize);
- size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useExternalMatchFinder);
+ size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer);
size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
+ ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef))
+ 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
@@ -1648,7 +1648,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
- size_t const externalSeqSpace = useExternalMatchFinder
+ size_t const externalSeqSpace = useSequenceProducer
? ZSTD_cwksp_aligned_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence))
: 0;
@@ -1679,7 +1679,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
* be needed. However, we still allocate two 0-sized buffers, which can
* take space under ASAN. */
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
- &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, params->useExternalMatchFinder, params->maxBlockSize);
+ &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
}
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
@@ -1740,7 +1740,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
- ZSTD_CONTENTSIZE_UNKNOWN, params->useExternalMatchFinder, params->maxBlockSize);
+ ZSTD_CONTENTSIZE_UNKNOWN, params->useSequenceProducer, params->maxBlockSize);
}
}
@@ -2024,7 +2024,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
{ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));
size_t const blockSize = MIN(params->maxBlockSize, windowSize);
- size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, params->useExternalMatchFinder);
+ size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, params->useSequenceProducer);
size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)
? ZSTD_compressBound(blockSize) + 1
: 0;
@@ -2041,7 +2041,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
size_t const neededSpace =
ZSTD_estimateCCtxSize_usingCCtxParams_internal(
¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,
- buffInSize, buffOutSize, pledgedSrcSize, params->useExternalMatchFinder, params->maxBlockSize);
+ buffInSize, buffOutSize, pledgedSrcSize, params->useSequenceProducer, params->maxBlockSize);
int resizeWorkspace;
FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
@@ -2155,7 +2155,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
}
/* reserve space for block-level external sequences */
- if (params->useExternalMatchFinder) {
+ if (params->useSequenceProducer) {
size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
zc->externalMatchCtx.seqBufferCapacity = maxNbExternalSeq;
zc->externalMatchCtx.seqBuffer =
@@ -3022,26 +3022,26 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
ssPtr->longLengthType = ZSTD_llt_none;
}
-/* ZSTD_postProcessExternalMatchFinderResult() :
+/* ZSTD_postProcessSequenceProducerResult() :
* Validates and post-processes sequences obtained through the external matchfinder API:
* - Checks whether nbExternalSeqs represents an error condition.
* - Appends a block delimiter to outSeqs if one is not already present.
* See zstd.h for context regarding block delimiters.
* Returns the number of sequences after post-processing, or an error code. */
-static size_t ZSTD_postProcessExternalMatchFinderResult(
+static size_t ZSTD_postProcessSequenceProducerResult(
ZSTD_Sequence* outSeqs, size_t nbExternalSeqs, size_t outSeqsCapacity, size_t srcSize
) {
RETURN_ERROR_IF(
nbExternalSeqs > outSeqsCapacity,
- externalMatchFinder_failed,
- "External matchfinder returned error code %lu",
+ sequenceProducer_failed,
+ "External sequence producer returned error code %lu",
(unsigned long)nbExternalSeqs
);
RETURN_ERROR_IF(
nbExternalSeqs == 0 && srcSize > 0,
- externalMatchFinder_failed,
- "External matchfinder produced zero sequences for a non-empty src buffer!"
+ sequenceProducer_failed,
+ "Got zero sequences from external sequence producer for a non-empty src buffer!"
);
if (srcSize == 0) {
@@ -3061,7 +3061,7 @@ static size_t ZSTD_postProcessExternalMatchFinderResult(
* produced an invalid parse, by definition of ZSTD_sequenceBound(). */
RETURN_ERROR_IF(
nbExternalSeqs == outSeqsCapacity,
- externalMatchFinder_failed,
+ sequenceProducer_failed,
"nbExternalSeqs == outSeqsCapacity but lastSeq is not a block delimiter!"
);
@@ -3139,9 +3139,9 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
/* External matchfinder + LDM is technically possible, just not implemented yet.
* We need to revisit soon and implement it. */
RETURN_ERROR_IF(
- zc->appliedParams.useExternalMatchFinder,
+ zc->appliedParams.useSequenceProducer,
parameter_combination_unsupported,
- "Long-distance matching with external matchfinder enabled is not currently supported."
+ "Long-distance matching with external sequence producer enabled is not currently supported."
);
/* Updates ldmSeqStore.pos */
@@ -3158,9 +3158,9 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
/* External matchfinder + LDM is technically possible, just not implemented yet.
* We need to revisit soon and implement it. */
RETURN_ERROR_IF(
- zc->appliedParams.useExternalMatchFinder,
+ zc->appliedParams.useSequenceProducer,
parameter_combination_unsupported,
- "Long-distance matching with external matchfinder enabled is not currently supported."
+ "Long-distance matching with external sequence producer enabled is not currently supported."
);
ldmSeqStore.seq = zc->ldmSequences;
@@ -3177,7 +3177,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
zc->appliedParams.useRowMatchFinder,
src, srcSize);
assert(ldmSeqStore.pos == ldmSeqStore.size);
- } else if (zc->appliedParams.useExternalMatchFinder) {
+ } else if (zc->appliedParams.useSequenceProducer) {
assert(
zc->externalMatchCtx.seqBufferCapacity >= ZSTD_sequenceBound(srcSize)
);
@@ -3195,7 +3195,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
windowSize
);
- size_t const nbPostProcessedSeqs = ZSTD_postProcessExternalMatchFinderResult(
+ size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult(
zc->externalMatchCtx.seqBuffer,
nbExternalSeqs,
zc->externalMatchCtx.seqBufferCapacity,
@@ -3217,7 +3217,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
"Failed to copy external sequences to seqStore!"
);
ms->ldmSeqStore = NULL;
- DEBUGLOG(5, "Copied %lu sequences from external matchfinder to internal seqStore.", (unsigned long)nbExternalSeqs);
+ DEBUGLOG(5, "Copied %lu sequences from external sequence producer to internal seqStore.", (unsigned long)nbExternalSeqs);
return ZSTDbss_compress;
}
@@ -3233,7 +3233,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
ms->ldmSeqStore = NULL;
DEBUGLOG(
5,
- "External matchfinder returned error code %lu. Falling back to internal matchfinder.",
+ "External sequence producer returned error code %lu. Falling back to internal parser.",
(unsigned long)nbExternalSeqs
);
lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
@@ -6033,9 +6033,9 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
#ifdef ZSTD_MULTITHREAD
/* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */
RETURN_ERROR_IF(
- params.useExternalMatchFinder == 1 && params.nbWorkers >= 1,
+ params.useSequenceProducer == 1 && params.nbWorkers >= 1,
parameter_combination_unsupported,
- "External matchfinder isn't supported with nbWorkers >= 1"
+ "External sequence producer isn't supported with nbWorkers >= 1"
);
if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
@@ -6251,7 +6251,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
*/
static size_t
ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch,
- size_t posInSrc, U32 windowLog, size_t dictSize, int useExternalMatchFinder)
+ size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer)
{
U32 const windowSize = 1u << windowLog;
/* posInSrc represents the amount of data the decoder would decode up to this point.
@@ -6260,7 +6260,7 @@ ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch,
* window size. After output surpasses windowSize, we're limited to windowSize offsets again.
*/
size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
- size_t const matchLenLowerBound = (minMatch == 3 || useExternalMatchFinder) ? 3 : 4;
+ size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4;
RETURN_ERROR_IF(offCode > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!");
/* Validate maxNbSeq is large enough for the given matchLength and minMatch */
RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch");
@@ -6325,7 +6325,7 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
if (cctx->appliedParams.validateSequences) {
seqPos->posInSrc += litLength + matchLength;
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
- cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useExternalMatchFinder),
+ cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
"Sequence validation failed");
}
RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,
@@ -6463,7 +6463,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
if (cctx->appliedParams.validateSequences) {
seqPos->posInSrc += litLength + matchLength;
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
- cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useExternalMatchFinder),
+ cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useSequenceProducer),
"Sequence validation failed");
}
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength);
@@ -6908,9 +6908,9 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
}
-void ZSTD_registerExternalMatchFinder(
+void ZSTD_registerSequenceProducer(
ZSTD_CCtx* zc, void* mState,
- ZSTD_externalMatchFinder_F* mFinder
+ ZSTD_sequenceProducer_F* mFinder
) {
if (mFinder != NULL) {
ZSTD_externalMatchCtx emctx;
@@ -6919,9 +6919,9 @@ void ZSTD_registerExternalMatchFinder(
emctx.seqBuffer = NULL;
emctx.seqBufferCapacity = 0;
zc->externalMatchCtx = emctx;
- zc->requestedParams.useExternalMatchFinder = 1;
+ zc->requestedParams.useSequenceProducer = 1;
} else {
ZSTD_memset(&zc->externalMatchCtx, 0, sizeof(zc->externalMatchCtx));
- zc->requestedParams.useExternalMatchFinder = 0;
+ zc->requestedParams.useSequenceProducer = 0;
}
}
diff --git a/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress_internal.h b/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress_internal.h
index dac7a0aa2..cbb85e527 100644
--- a/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress_internal.h
+++ b/libfenrir/src/main/jni/compress/zstd/compress/zstd_compress_internal.h
@@ -353,8 +353,8 @@ struct ZSTD_CCtx_params_s {
/* Indicates whether an external matchfinder has been referenced.
* Users can't set this externally.
- * It is set internally in ZSTD_registerExternalMatchFinder(). */
- int useExternalMatchFinder;
+ * It is set internally in ZSTD_registerSequenceProducer(). */
+ int useSequenceProducer;
/* Adjust the max block size*/
size_t maxBlockSize;
@@ -395,7 +395,7 @@ typedef struct {
/* Context for block-level external matchfinder API */
typedef struct {
void* mState;
- ZSTD_externalMatchFinder_F* mFinder;
+ ZSTD_sequenceProducer_F* mFinder;
ZSTD_Sequence* seqBuffer;
size_t seqBufferCapacity;
} ZSTD_externalMatchCtx;
diff --git a/libfenrir/src/main/jni/compress/zstd/zstd.h b/libfenrir/src/main/jni/compress/zstd/zstd.h
index 91a3679a1..95aac0737 100644
--- a/libfenrir/src/main/jni/compress/zstd/zstd.h
+++ b/libfenrir/src/main/jni/compress/zstd/zstd.h
@@ -478,7 +478,7 @@ typedef enum {
* ZSTD_c_useBlockSplitter
* ZSTD_c_useRowMatchFinder
* ZSTD_c_prefetchCDictTables
- * ZSTD_c_enableMatchFinderFallback
+ * ZSTD_c_enableSeqProducerFallback
* ZSTD_c_maxBlockSize
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly;
@@ -565,7 +565,7 @@ typedef enum {
* They will be used to compress next frame.
* Resetting session never fails.
* - The parameters : changes all parameters back to "default".
- * This also removes any reference to any dictionary or external matchfinder.
+ * This also removes any reference to any dictionary or external sequence producer.
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
* - Both : similar to resetting the session, followed by resetting parameters.
@@ -1627,8 +1627,8 @@ ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
* Note : only single-threaded compression is supported.
* ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
*
- * Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the external matchfinder API at this time.
- * Size estimates assume that no external matchfinder is registered.
+ * Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
+ * Size estimates assume that no external sequence producer is registered.
*/
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
@@ -1650,8 +1650,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);
* In this case, get total size by adding ZSTD_estimate?DictSize
* Note 2 : only single-threaded compression is supported.
* ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
- * Note 3 : ZSTD_estimateCStreamSize* functions are not compatible with the external matchfinder API at this time.
- * Size estimates assume that no external matchfinder is registered.
+ * Note 3 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.
+ * Size estimates assume that no external sequence producer is registered.
*/
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
@@ -2113,19 +2113,19 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
*/
#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16
-/* ZSTD_c_enableMatchFinderFallback
+/* ZSTD_c_enableSeqProducerFallback
* Allowed values are 0 (disable) and 1 (enable). The default setting is 0.
*
- * Controls whether zstd will fall back to an internal matchfinder if an
- * external matchfinder is registered and returns an error code. This fallback is
- * block-by-block: the internal matchfinder will only be called for blocks where
- * the external matchfinder returns an error code. Fallback compression will
+ * Controls whether zstd will fall back to an internal sequence producer if an
+ * external sequence producer is registered and returns an error code. This fallback
+ * is block-by-block: the internal sequence producer will only be called for blocks
+ * where the external sequence producer returns an error code. Fallback parsing will
* follow any other cParam settings, such as compression level, the same as in a
* normal (fully-internal) compression operation.
*
- * The user is strongly encouraged to read the full external matchfinder API
+ * The user is strongly encouraged to read the full Block-Level Sequence Producer API
* documentation (below) before setting this parameter. */
-#define ZSTD_c_enableMatchFinderFallback ZSTD_c_experimentalParam17
+#define ZSTD_c_enableSeqProducerFallback ZSTD_c_experimentalParam17
/* ZSTD_c_maxBlockSize
* Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).
@@ -2141,12 +2141,13 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
/* ZSTD_c_searchForExternalRepcodes
* This parameter affects how zstd parses external sequences, such as sequences
- * provided through the compressSequences() API or from an external matchfinder.
+ * provided through the compressSequences() API or from an external block-level
+ * sequence producer.
*
* If set to ZSTD_ps_enable, the library will check for repeated offsets in
* external sequences, even if those repcodes are not explicitly indicated in
* the "rep" field. Note that this is the only way to exploit repcode matches
- * while using compressSequences() or an external matchfinder, since zstd
+ * while using compressSequences() or an external sequence producer, since zstd
* currently ignores the "rep" field of external sequences.
*
* If set to ZSTD_ps_disable, the library will not exploit repeated offsets in
@@ -2805,43 +2806,52 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_
ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
-/* ********************** EXTERNAL MATCHFINDER API **********************
+/* ********************* BLOCK-LEVEL SEQUENCE PRODUCER API *********************
*
* *** OVERVIEW ***
- * This API allows users to replace the zstd internal block-level matchfinder
- * with an external matchfinder function. Potential applications of the API
- * include hardware-accelerated matchfinders and matchfinders specialized to
- * particular types of data.
- *
- * See contrib/externalMatchfinder for an example program employing the
- * external matchfinder API.
+ * The Block-Level Sequence Producer API allows users to provide their own custom
+ * sequence producer which libzstd invokes to process each block. The produced list
+ * of sequences (literals and matches) is then post-processed by libzstd to produce
+ * valid compressed blocks.
+ *
+ * This block-level offload API is a more granular complement of the existing
+ * frame-level offload API compressSequences() (introduced in v1.5.1). It offers
+ * an easier migration story for applications already integrated with libzstd: the
+ * user application continues to invoke the same compression functions
+ * ZSTD_compress2() or ZSTD_compressStream2() as usual, and transparently benefits
+ * from the specific advantages of the external sequence producer. For example,
+ * the sequence producer could be tuned to take advantage of known characteristics
+ * of the input, to offer better speed / ratio, or could leverage hardware
+ * acceleration not available within libzstd itself.
+ *
+ * See contrib/externalSequenceProducer for an example program employing the
+ * Block-Level Sequence Producer API.
*
* *** USAGE ***
* The user is responsible for implementing a function of type
- * ZSTD_externalMatchFinder_F. For each block, zstd will pass the following
+ * ZSTD_sequenceProducer_F. For each block, zstd will pass the following
* arguments to the user-provided function:
*
- * - externalMatchState: a pointer to a user-managed state for the external
- * matchfinder.
+ * - sequenceProducerState: a pointer to a user-managed state for the sequence
+ * producer.
*
- * - outSeqs, outSeqsCapacity: an output buffer for sequences produced by the
- * external matchfinder. outSeqsCapacity is guaranteed >=
- * ZSTD_sequenceBound(srcSize). The memory backing outSeqs is managed by
- * the CCtx.
+ * - outSeqs, outSeqsCapacity: an output buffer for the sequence producer.
+ * outSeqsCapacity is guaranteed >= ZSTD_sequenceBound(srcSize). The memory
+ * backing outSeqs is managed by the CCtx.
*
- * - src, srcSize: an input buffer which the external matchfinder must parse
- * into sequences. srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX.
+ * - src, srcSize: an input buffer for the sequence producer to parse.
+ * srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX.
*
- * - dict, dictSize: a history buffer, which may be empty, which the external
- * matchfinder may reference as it produces sequences for the src buffer.
- * Currently, zstd will always pass dictSize == 0 into external matchfinders,
- * but this will change in the future.
+ * - dict, dictSize: a history buffer, which may be empty, which the sequence
+ * producer may reference as it parses the src buffer. Currently, zstd will
+ * always pass dictSize == 0 into external sequence producers, but this will
+ * change in the future.
*
* - compressionLevel: a signed integer representing the zstd compression level
- * set by the user for the current operation. The external matchfinder may
- * choose to use this information to change its compression strategy and
- * speed/ratio tradeoff. Note: The compression level does not reflect zstd
- * parameters set through the advanced API.
+ * set by the user for the current operation. The sequence producer may choose
+ * to use this information to change its compression strategy and speed/ratio
+ * tradeoff. Note: the compression level does not reflect zstd parameters set
+ * through the advanced API.
*
* - windowSize: a size_t representing the maximum allowed offset for external
* sequences. Note that sequence offsets are sometimes allowed to exceed the
@@ -2851,7 +2861,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* bloc
* The user-provided function shall return a size_t representing the number of
* sequences written to outSeqs. This return value will be treated as an error
* code if it is greater than outSeqsCapacity. The return value must be non-zero
- * if srcSize is non-zero. The ZSTD_EXTERNAL_MATCHFINDER_ERROR macro is provided
+ * if srcSize is non-zero. The ZSTD_SEQUENCE_PRODUCER_ERROR macro is provided
* for convenience, but any value greater than outSeqsCapacity will be treated as
* an error code.
*
@@ -2859,68 +2869,71 @@ ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* bloc
* written to outSeqs must be a valid parse of the src buffer. Data corruption may
* occur if the parse is not valid. A parse is defined to be valid if the
* following conditions hold:
- * - The sum of matchLengths and literalLengths is equal to srcSize.
- * - All sequences in the parse have matchLength != 0, except for the final
- * sequence. matchLength is not constrained for the final sequence.
- * - All offsets respect the windowSize parameter as specified in
+ * - The sum of matchLengths and literalLengths must equal srcSize.
+ * - All sequences in the parse, except for the final sequence, must have
+ * matchLength >= ZSTD_MINMATCH_MIN. The final sequence must have
+ * matchLength >= ZSTD_MINMATCH_MIN or matchLength == 0.
+ * - All offsets must respect the windowSize parameter as specified in
* doc/zstd_compression_format.md.
+ * - If the final sequence has matchLength == 0, it must also have offset == 0.
*
* zstd will only validate these conditions (and fail compression if they do not
* hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence
* validation has a performance cost.
*
* If the user-provided function returns an error, zstd will either fall back
- * to an internal matchfinder or fail the compression operation. The user can
- * choose between the two behaviors by setting the
- * ZSTD_c_enableMatchFinderFallback cParam. Fallback compression will follow any
- * other cParam settings, such as compression level, the same as in a normal
- * compression operation.
- *
- * The user shall instruct zstd to use a particular ZSTD_externalMatchFinder_F
- * function by calling ZSTD_registerExternalMatchFinder(cctx, externalMatchState,
- * externalMatchFinder). This setting will persist until the next parameter reset
- * of the CCtx.
- *
- * The externalMatchState must be initialized by the user before calling
- * ZSTD_registerExternalMatchFinder. The user is responsible for destroying the
- * externalMatchState.
+ * to an internal sequence producer or fail the compression operation. The user can
+ * choose between the two behaviors by setting the ZSTD_c_enableSeqProducerFallback
+ * cParam. Fallback compression will follow any other cParam settings, such as
+ * compression level, the same as in a normal compression operation.
+ *
+ * The user shall instruct zstd to use a particular ZSTD_sequenceProducer_F
+ * function by calling
+ * ZSTD_registerSequenceProducer(cctx,
+ * sequenceProducerState,
+ * sequenceProducer)
+ * This setting will persist until the next parameter reset of the CCtx.
+ *
+ * The sequenceProducerState must be initialized by the user before calling
+ * ZSTD_registerSequenceProducer(). The user is responsible for destroying the
+ * sequenceProducerState.
*
* *** LIMITATIONS ***
- * External matchfinders are compatible with all zstd compression APIs which respect
- * advanced parameters. However, there are three limitations:
- *
- * First, the ZSTD_c_enableLongDistanceMatching cParam is not supported.
- * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with an
- * external matchfinder.
- * - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in
- * some cases (see its documentation for details). Users must explicitly set
- * ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an
- * external matchfinder is registered.
+ * This API is compatible with all zstd compression APIs which respect advanced parameters.
+ * However, there are three limitations:
+ *
+ * First, the ZSTD_c_enableLongDistanceMatching cParam is not currently supported.
+ * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with a block-level
+ * external sequence producer.
+ * - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in some
+ * cases (see its documentation for details). Users must explicitly set
+ * ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an external
+ * sequence producer is registered.
* - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default
* whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should
- * check the docs on ZSTD_c_enableLongDistanceMatching whenever the external
- * matchfinder API is used in conjunction with advanced settings (like windowLog).
+ * check the docs on ZSTD_c_enableLongDistanceMatching whenever the Block-Level Sequence
+ * Producer API is used in conjunction with advanced settings (like ZSTD_c_windowLog).
*
- * Second, history buffers are not supported. Concretely, zstd will always pass
- * dictSize == 0 to the external matchfinder (for now). This has two implications:
- * - Dictionaries are not supported. Compression will *not* fail if the user
+ * Second, history buffers are not currently supported. Concretely, zstd will always pass
+ * dictSize == 0 to the external sequence producer (for now). This has two implications:
+ * - Dictionaries are not currently supported. Compression will *not* fail if the user
* references a dictionary, but the dictionary won't have any effect.
- * - Stream history is not supported. All compression APIs, including streaming
- * APIs, work with the external matchfinder, but the external matchfinder won't
- * receive any history from the previous block. Each block is an independent chunk.
+ * - Stream history is not currently supported. All advanced compression APIs, including
+ * streaming APIs, work with external sequence producers, but each block is treated as
+ * an independent chunk without history from previous blocks.
*
- * Third, multi-threading within a single compression is not supported. In other words,
- * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external matchfinder is registered.
+ * Third, multi-threading within a single compression is not currently supported. In other words,
+ * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external sequence producer is registered.
* Multi-threading across compressions is fine: simply create one CCtx per thread.
*
* Long-term, we plan to overcome all three limitations. There is no technical blocker to
* overcoming them. It is purely a question of engineering effort.
*/
-#define ZSTD_EXTERNAL_MATCHFINDER_ERROR ((size_t)(-1))
+#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1))
-typedef size_t ZSTD_externalMatchFinder_F (
- void* externalMatchState,
+typedef size_t ZSTD_sequenceProducer_F (
+ void* sequenceProducerState,
ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,
const void* src, size_t srcSize,
const void* dict, size_t dictSize,
@@ -2928,32 +2941,30 @@ typedef size_t ZSTD_externalMatchFinder_F (
size_t windowSize
);
-/*! ZSTD_registerExternalMatchFinder() :
- * Instruct zstd to use an external matchfinder function.
+/*! ZSTD_registerSequenceProducer() :
+ * Instruct zstd to use a block-level external sequence producer function.
*
- * The externalMatchState must be initialized by the caller, and the caller is
+ * The sequenceProducerState must be initialized by the caller, and the caller is
* responsible for managing its lifetime. This parameter is sticky across
* compressions. It will remain set until the user explicitly resets compression
* parameters.
*
- * External matchfinder registration is considered to be an "advanced parameter",
- * part of the "advanced API". This means it will only have an effect on
- * compression APIs which respect advanced parameters, such as compress2() and
- * compressStream(). Older compression APIs such as compressCCtx(), which predate
- * the introduction of "advanced parameters", will ignore any external matchfinder
- * setting.
+ * Sequence producer registration is considered to be an "advanced parameter",
+ * part of the "advanced API". This means it will only have an effect on compression
+ * APIs which respect advanced parameters, such as compress2() and compressStream2().
+ * Older compression APIs such as compressCCtx(), which predate the introduction of
+ * "advanced parameters", will ignore any external sequence producer setting.
*
- * The external matchfinder can be "cleared" by registering a NULL external
- * matchfinder function pointer. This removes all limitations described above in
- * the "LIMITATIONS" section of the API docs.
+ * The sequence producer can be "cleared" by registering a NULL function pointer. This
+ * removes all limitations described above in the "LIMITATIONS" section of the API docs.
*
- * The user is strongly encouraged to read the full API documentation (above)
- * before calling this function. */
+ * The user is strongly encouraged to read the full API documentation (above) before
+ * calling this function. */
ZSTDLIB_STATIC_API void
-ZSTD_registerExternalMatchFinder(
+ZSTD_registerSequenceProducer(
ZSTD_CCtx* cctx,
- void* externalMatchState,
- ZSTD_externalMatchFinder_F* externalMatchFinder
+ void* sequenceProducerState,
+ ZSTD_sequenceProducer_F* sequenceProducer
);
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
diff --git a/libfenrir/src/main/jni/compress/zstd/zstd_errors.h b/libfenrir/src/main/jni/compress/zstd/zstd_errors.h
index 6a66bedcb..dc75eeeba 100644
--- a/libfenrir/src/main/jni/compress/zstd/zstd_errors.h
+++ b/libfenrir/src/main/jni/compress/zstd/zstd_errors.h
@@ -95,7 +95,7 @@ typedef enum {
ZSTD_error_seekableIO = 102,
ZSTD_error_dstBuffer_wrong = 104,
ZSTD_error_srcBuffer_wrong = 105,
- ZSTD_error_externalMatchFinder_failed = 106,
+ ZSTD_error_sequenceProducer_failed = 106,
ZSTD_error_externalSequences_invalid = 107,
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
} ZSTD_ErrorCode;
diff --git a/material/build.gradle b/material/build.gradle
index 2338ed989..0ee81b34b 100644
--- a/material/build.gradle
+++ b/material/build.gradle
@@ -3,7 +3,7 @@ plugins {
id("kotlin-android")
}
-//1.9.0-alpha01
+//1.9.0-alpha02
def srcDirs = [
'com/google/android/material/animation',
diff --git a/material/java/com/google/android/material/appbar/res-public/values/public.xml b/material/java/com/google/android/material/appbar/res-public/values/public.xml
index 1b357e185..b350134b0 100644
--- a/material/java/com/google/android/material/appbar/res-public/values/public.xml
+++ b/material/java/com/google/android/material/appbar/res-public/values/public.xml
@@ -23,6 +23,7 @@
+
diff --git a/material/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java b/material/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java
index 021db832a..236012d93 100644
--- a/material/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java
+++ b/material/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java
@@ -531,6 +531,7 @@ public boolean onLayoutChild(
peekHeightMin =
parent.getResources().getDimensionPixelSize(R.dimen.design_bottom_sheet_peek_height_min);
setWindowInsetsListener(child);
+ ViewCompat.setWindowInsetsAnimationCallback(child, new InsetsAnimationCallback(child));
viewRef = new WeakReference<>(child);
// Only set MaterialShapeDrawable as background if shapeTheming is enabled, otherwise will
// default to android:background declared in styles or layout.
diff --git a/material/java/com/google/android/material/bottomsheet/InsetsAnimationCallback.java b/material/java/com/google/android/material/bottomsheet/InsetsAnimationCallback.java
new file mode 100644
index 000000000..e9d717344
--- /dev/null
+++ b/material/java/com/google/android/material/bottomsheet/InsetsAnimationCallback.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.material.bottomsheet;
+
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.core.view.WindowInsetsAnimationCompat;
+import androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat;
+import androidx.core.view.WindowInsetsCompat;
+import com.google.android.material.animation.AnimationUtils;
+import java.util.List;
+
+class InsetsAnimationCallback extends WindowInsetsAnimationCompat.Callback {
+
+ private final View view;
+
+ private int startY;
+ private int startTranslationY;
+
+ private final int[] tmpLocation = new int[2];
+
+ public InsetsAnimationCallback(View view) {
+ super(DISPATCH_MODE_STOP);
+ this.view = view;
+ }
+
+ @Override
+ public void onPrepare(@NonNull WindowInsetsAnimationCompat windowInsetsAnimationCompat) {
+ view.getLocationOnScreen(tmpLocation);
+ startY = tmpLocation[1];
+ }
+
+ @NonNull
+ @Override
+ public BoundsCompat onStart(
+ @NonNull WindowInsetsAnimationCompat windowInsetsAnimationCompat,
+ @NonNull BoundsCompat boundsCompat) {
+ view.getLocationOnScreen(tmpLocation);
+ int endY = tmpLocation[1];
+ startTranslationY = startY - endY;
+
+ // Move the view back to its original position before the insets were applied.
+ view.setTranslationY(startTranslationY);
+
+ return boundsCompat;
+ }
+
+ @NonNull
+ @Override
+ public WindowInsetsCompat onProgress(
+ @NonNull WindowInsetsCompat insets,
+ @NonNull List animationList) {
+ for (WindowInsetsAnimationCompat animation : animationList) {
+ if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) {
+ // Move the view to match the animated position of the keyboard.
+ float translationY =
+ AnimationUtils.lerp(startTranslationY, 0, animation.getInterpolatedFraction());
+ view.setTranslationY(translationY);
+ break;
+ }
+ }
+ return insets;
+ }
+
+ @Override
+ public void onEnd(@NonNull WindowInsetsAnimationCompat windowInsetsAnimationCompat) {
+ view.setTranslationY(0f);
+ }
+}
diff --git a/material/java/com/google/android/material/bottomsheet/res/values/themes_base.xml b/material/java/com/google/android/material/bottomsheet/res/values/themes_base.xml
index 2f96d701c..2f9768814 100644
--- a/material/java/com/google/android/material/bottomsheet/res/values/themes_base.xml
+++ b/material/java/com/google/android/material/bottomsheet/res/values/themes_base.xml
@@ -17,6 +17,7 @@
+
+
+
diff --git a/material/java/com/google/android/material/chip/res/values/styles.xml b/material/java/com/google/android/material/chip/res/values/styles.xml
index de3d4faae..71fdec641 100644
--- a/material/java/com/google/android/material/chip/res/values/styles.xml
+++ b/material/java/com/google/android/material/chip/res/values/styles.xml
@@ -388,11 +388,11 @@
diff --git a/material/java/com/google/android/material/color/ColorResourcesOverride.java b/material/java/com/google/android/material/color/ColorResourcesOverride.java
index 8b36a989d..6aa7b7fdd 100644
--- a/material/java/com/google/android/material/color/ColorResourcesOverride.java
+++ b/material/java/com/google/android/material/color/ColorResourcesOverride.java
@@ -47,6 +47,18 @@ public interface ColorResourcesOverride {
boolean applyIfPossible(
@NonNull Context context, @NonNull Map colorResourceIdsToColorValues);
+ /**
+ * Wraps the given Context with the theme overlay where color resources are updated at runtime.
+ * If not possible, the original Context will be returned.
+ *
+ * @param context The target context.
+ * @param colorResourceIdsToColorValues The mapping from the color resources id to the updated
+ * color value.
+ */
+ @NonNull
+ Context wrapContextIfPossible(
+ @NonNull Context context, @NonNull Map colorResourceIdsToColorValues);
+
@Nullable
static ColorResourcesOverride getInstance() {
if (VERSION_CODES.R <= VERSION.SDK_INT && VERSION.SDK_INT <= VERSION_CODES.TIRAMISU) {
diff --git a/material/java/com/google/android/material/color/ResourcesLoaderColorResourcesOverride.java b/material/java/com/google/android/material/color/ResourcesLoaderColorResourcesOverride.java
index 58f2fee40..cae7deee0 100644
--- a/material/java/com/google/android/material/color/ResourcesLoaderColorResourcesOverride.java
+++ b/material/java/com/google/android/material/color/ResourcesLoaderColorResourcesOverride.java
@@ -19,7 +19,10 @@
import com.google.android.material.R;
import android.content.Context;
+import android.content.res.Configuration;
import android.os.Build.VERSION_CODES;
+import android.view.ContextThemeWrapper;
+import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import java.util.Map;
@@ -50,6 +53,30 @@ public boolean applyIfPossible(
return false;
}
+ /**
+ * Wraps the given Context with the theme overlay where color resources are updated at runtime.
+ * If not possible, the original Context will be returned.
+ *
+ * @param context The target context.
+ * @param colorResourceIdsToColorValues The mapping from the color resources id to the updated
+ * color value.
+ */
+ @Override
+ @NonNull
+ public Context wrapContextIfPossible(
+ Context context, Map colorResourceIdsToColorValues) {
+ ContextThemeWrapper themeWrapper =
+ new ContextThemeWrapper(context, R.style.ThemeOverlay_Material3_PersonalizedColors);
+ // Because ContextThemeWrapper does not provide a new set of resources, override config to
+ // retrieve the new set of resources and to keep the original context's resources intact.
+ themeWrapper.applyOverrideConfiguration(new Configuration());
+
+ return ResourcesLoaderUtils.addResourcesLoaderToContext(
+ themeWrapper, colorResourceIdsToColorValues)
+ ? themeWrapper
+ : context;
+ }
+
static ColorResourcesOverride getInstance() {
return ResourcesLoaderColorResourcesOverrideSingleton.INSTANCE;
}
diff --git a/material/java/com/google/android/material/color/ThemeUtils.java b/material/java/com/google/android/material/color/ThemeUtils.java
index f0073f4fb..10be154bf 100644
--- a/material/java/com/google/android/material/color/ThemeUtils.java
+++ b/material/java/com/google/android/material/color/ThemeUtils.java
@@ -16,6 +16,8 @@
package com.google.android.material.color;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources.Theme;
@@ -23,14 +25,22 @@
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
import androidx.annotation.StyleRes;
-/** Utility methods for theme. */
-final class ThemeUtils {
+// TODO(b/269781013): move this class to internal folder, which involves resolving cyclic dependency
+// between color and internal folders
+/**
+ * Utility methods for theme.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public final class ThemeUtils {
private ThemeUtils() {}
- static void applyThemeOverlay(@NonNull Context context, @StyleRes int theme) {
+ public static void applyThemeOverlay(@NonNull Context context, @StyleRes int theme) {
// Use applyStyle() instead of setTheme() due to Force Dark issue.
context.getTheme().applyStyle(theme, /* force= */ true);
diff --git a/material/java/com/google/android/material/datepicker/DateSelector.java b/material/java/com/google/android/material/datepicker/DateSelector.java
index 5f473b1fa..649211130 100644
--- a/material/java/com/google/android/material/datepicker/DateSelector.java
+++ b/material/java/com/google/android/material/datepicker/DateSelector.java
@@ -146,6 +146,12 @@ static void showKeyboardWithAutoHideBehavior(@NonNull EditText... editTexts) {
editText.setOnFocusChangeListener(listener);
}
- ViewUtils.requestFocusAndShowKeyboard(editTexts[0]);
+ // TODO(b/246354286): Investigate issue with keyboard not showing on Android 12+
+ View viewToFocus = editTexts[0];
+ viewToFocus.postDelayed(
+ () ->
+ ViewUtils.requestFocusAndShowKeyboard(
+ viewToFocus, /* useWindowInsetsController= */ false),
+ 100);
}
}
diff --git a/material/java/com/google/android/material/internal/ViewUtils.java b/material/java/com/google/android/material/internal/ViewUtils.java
index cc1152684..70bc3db65 100644
--- a/material/java/com/google/android/material/internal/ViewUtils.java
+++ b/material/java/com/google/android/material/internal/ViewUtils.java
@@ -80,6 +80,16 @@ public static void showKeyboard(@NonNull View view, boolean useWindowInsetsContr
getInputMethodManager(view).showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
+ public static void requestFocusAndShowKeyboard(@NonNull final View view) {
+ requestFocusAndShowKeyboard(view, /* useWindowInsetsController= */ true);
+ }
+
+ public static void requestFocusAndShowKeyboard(
+ @NonNull final View view, boolean useWindowInsetsController) {
+ view.requestFocus();
+ view.post(() -> showKeyboard(view, useWindowInsetsController));
+ }
+
public static void hideKeyboard(@NonNull View view) {
hideKeyboard(view, /* useWindowInsetsController= */ true);
}
@@ -161,20 +171,6 @@ public static float dpToPx(@NonNull Context context, @Dimension(unit = Dimension
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
}
- public static void requestFocusAndShowKeyboard(@NonNull final View view) {
- view.requestFocus();
- view.post(
- new Runnable() {
- @Override
- public void run() {
- InputMethodManager inputMethodManager =
- (InputMethodManager)
- view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
- }
- });
- }
-
/**
* Wrapper around {@link androidx.core.view.OnApplyWindowInsetsListener} which also passes the
* initial padding set on the view. Used with {@link #doOnApplyWindowInsets(View,
diff --git a/material/java/com/google/android/material/internal/WindowUtils.java b/material/java/com/google/android/material/internal/WindowUtils.java
new file mode 100644
index 000000000..fe49868c8
--- /dev/null
+++ b/material/java/com/google/android/material/internal/WindowUtils.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.material.internal;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A util class for window operations.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class WindowUtils {
+
+ private static final String TAG = WindowUtils.class.getSimpleName();
+
+ private WindowUtils() {}
+
+ @NonNull
+ public static Rect getCurrentWindowBounds(@NonNull Context context) {
+ WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ return Api30Impl.getCurrentWindowBounds(windowManager);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ return Api17Impl.getCurrentWindowBounds(windowManager);
+ } else {
+ return Api14Impl.getCurrentWindowBounds(windowManager);
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ private static class Api30Impl {
+
+ @NonNull
+ static Rect getCurrentWindowBounds(@NonNull WindowManager windowManager) {
+ return windowManager.getCurrentWindowMetrics().getBounds();
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
+ private static class Api17Impl {
+
+ @NonNull
+ static Rect getCurrentWindowBounds(@NonNull WindowManager windowManager) {
+ Display defaultDisplay = windowManager.getDefaultDisplay();
+
+ Point defaultDisplaySize = new Point();
+ defaultDisplay.getRealSize(defaultDisplaySize);
+
+ Rect bounds = new Rect();
+ bounds.right = defaultDisplaySize.x;
+ bounds.bottom = defaultDisplaySize.y;
+
+ return bounds;
+ }
+ }
+
+ private static class Api14Impl {
+
+ @NonNull
+ static Rect getCurrentWindowBounds(@NonNull WindowManager windowManager) {
+ Display defaultDisplay = windowManager.getDefaultDisplay();
+ Point defaultDisplaySize = getRealSizeForDisplay(defaultDisplay);
+
+ Rect bounds = new Rect();
+ if (defaultDisplaySize.x == 0 || defaultDisplaySize.y == 0) {
+ defaultDisplay.getRectSize(bounds);
+ } else {
+ bounds.right = defaultDisplaySize.x;
+ bounds.bottom = defaultDisplaySize.y;
+ }
+
+ return bounds;
+ }
+
+ private static Point getRealSizeForDisplay(Display display) {
+ Point size = new Point();
+ try {
+ Method getRealSizeMethod = Display.class.getDeclaredMethod("getRealSize", Point.class);
+ getRealSizeMethod.setAccessible(true);
+ getRealSizeMethod.invoke(display, size);
+ } catch (NoSuchMethodException e) {
+ Log.w(TAG, e);
+ } catch (IllegalAccessException e) {
+ Log.w(TAG, e);
+ } catch (InvocationTargetException e) {
+ Log.w(TAG, e);
+ }
+ return size;
+ }
+ }
+}
diff --git a/material/java/com/google/android/material/navigation/NavigationView.java b/material/java/com/google/android/material/navigation/NavigationView.java
index c200df38c..87f448983 100644
--- a/material/java/com/google/android/material/navigation/NavigationView.java
+++ b/material/java/com/google/android/material/navigation/NavigationView.java
@@ -27,6 +27,7 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -44,7 +45,6 @@
import androidx.appcompat.view.menu.MenuItemImpl;
import androidx.appcompat.widget.TintTypedArray;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.Menu;
@@ -73,6 +73,7 @@
import com.google.android.material.internal.NavigationMenuPresenter;
import com.google.android.material.internal.ScrimInsetsFrameLayout;
import com.google.android.material.internal.ThemeEnforcement;
+import com.google.android.material.internal.WindowUtils;
import com.google.android.material.resources.MaterialResources;
import com.google.android.material.ripple.RippleUtils;
import com.google.android.material.shape.MaterialShapeDrawable;
@@ -975,11 +976,10 @@ public void onGlobalLayout() {
Activity activity = ContextUtils.getActivity(getContext());
if (activity != null && VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- DisplayMetrics displayMetrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
+ Rect displayBounds = WindowUtils.getCurrentWindowBounds(activity);
boolean isBehindSystemNav =
- displayMetrics.heightPixels - getHeight() == tmpLocation[1];
+ displayBounds.height() - getHeight() == tmpLocation[1];
boolean hasNonZeroAlpha =
Color.alpha(activity.getWindow().getNavigationBarColor()) != 0;
setDrawBottomInsetForeground(
@@ -988,8 +988,8 @@ public void onGlobalLayout() {
// The navigation view could be right aligned or just hidden out of view in a drawer
// layout when the global layout listener is called.
boolean isOnRightSide =
- (displayMetrics.widthPixels == tmpLocation[0])
- || (displayMetrics.widthPixels - getWidth() == tmpLocation[0]);
+ (displayBounds.width() == tmpLocation[0])
+ || (displayBounds.width() - getWidth() == tmpLocation[0]);
setDrawRightInsetForeground(isOnRightSide);
}
diff --git a/material/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java b/material/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java
index b99693cf0..f35fab699 100644
--- a/material/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java
+++ b/material/java/com/google/android/material/progressindicator/LinearDrawingDelegate.java
@@ -20,6 +20,7 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import androidx.annotation.ColorInt;
@@ -34,6 +35,7 @@ final class LinearDrawingDelegate extends DrawingDelegate= extraBottomMarginGestureInset) {
// No need to add extra offset if view is already outside of bottom gesture area
+ appliedBottomMarginGestureInset = extraBottomMarginGestureInset;
return;
}
@@ -312,6 +313,8 @@ public void run() {
return;
}
+ appliedBottomMarginGestureInset = extraBottomMarginGestureInset;
+
// Move view outside of bottom gesture area
MarginLayoutParams marginParams = (MarginLayoutParams) layoutParams;
marginParams.bottomMargin += extraBottomMarginGestureInset - currentInsetBottom;
@@ -322,9 +325,11 @@ public void run() {
private int extraBottomMarginWindowInset;
private int extraLeftMarginWindowInset;
private int extraRightMarginWindowInset;
- private int extraBottomMarginGestureInset;
private int extraBottomMarginAnchorView;
+ private int extraBottomMarginGestureInset;
+ private int appliedBottomMarginGestureInset;
+
private boolean pendingShowingView;
private List> callbacks;
@@ -455,10 +460,16 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) {
private void updateMargins() {
LayoutParams layoutParams = view.getLayoutParams();
- if (!(layoutParams instanceof MarginLayoutParams) || view.originalMargins == null) {
+ if (!(layoutParams instanceof MarginLayoutParams)) {
Log.w(TAG, "Unable to update margins because layout params are not MarginLayoutParams");
return;
}
+
+ if (view.originalMargins == null) {
+ Log.w(TAG, "Unable to update margins because original view margins are not set");
+ return;
+ }
+
if (view.getParent() == null) {
// Parent will set layout params to view again. Wait for addView() is done to update layout
// params, in case we save the already updated margins as the original margins.
@@ -467,17 +478,32 @@ private void updateMargins() {
int extraBottomMargin =
getAnchorView() != null ? extraBottomMarginAnchorView : extraBottomMarginWindowInset;
- MarginLayoutParams marginParams = (MarginLayoutParams) layoutParams;
- marginParams.bottomMargin = view.originalMargins.bottom + extraBottomMargin;
- marginParams.leftMargin = view.originalMargins.left + extraLeftMarginWindowInset;
- marginParams.rightMargin = view.originalMargins.right + extraRightMarginWindowInset;
- marginParams.topMargin = view.originalMargins.top;
- view.requestLayout();
- if (VERSION.SDK_INT >= VERSION_CODES.Q && shouldUpdateGestureInset()) {
- // Ensure there is only one gesture inset runnable running at a time
- view.removeCallbacks(bottomMarginGestureInsetRunnable);
- view.post(bottomMarginGestureInsetRunnable);
+ MarginLayoutParams marginParams = (MarginLayoutParams) layoutParams;
+ int newBottomMargin = view.originalMargins.bottom + extraBottomMargin;
+ int newLeftMargin = view.originalMargins.left + extraLeftMarginWindowInset;
+ int newRightMargin = view.originalMargins.right + extraRightMarginWindowInset;
+ int newTopMargin = view.originalMargins.top;
+
+ boolean marginChanged =
+ marginParams.bottomMargin != newBottomMargin
+ || marginParams.leftMargin != newLeftMargin
+ || marginParams.rightMargin != newRightMargin
+ || marginParams.topMargin != newTopMargin;
+ if (marginChanged) {
+ marginParams.bottomMargin = newBottomMargin;
+ marginParams.leftMargin = newLeftMargin;
+ marginParams.rightMargin = newRightMargin;
+ marginParams.topMargin = newTopMargin;
+ view.requestLayout();
+ }
+
+ if (marginChanged || appliedBottomMarginGestureInset != extraBottomMarginGestureInset) {
+ if (VERSION.SDK_INT >= VERSION_CODES.Q && shouldUpdateGestureInset()) {
+ // Ensure there is only one gesture inset runnable running at a time
+ view.removeCallbacks(bottomMarginGestureInsetRunnable);
+ view.post(bottomMarginGestureInsetRunnable);
+ }
}
}
@@ -823,14 +849,6 @@ private int getViewAbsoluteBottom() {
return absoluteLocation[1] + view.getHeight();
}
- @RequiresApi(VERSION_CODES.JELLY_BEAN_MR1)
- private int getScreenHeight() {
- WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics displayMetrics = new DisplayMetrics();
- windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
- return displayMetrics.heightPixels;
- }
-
private void setUpBehavior(CoordinatorLayout.LayoutParams lp) {
// If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior
CoordinatorLayout.LayoutParams clp = lp;
@@ -878,11 +896,7 @@ public void onDragStateChanged(int state) {
}
private void recalculateAndUpdateMargins() {
- int newBottomMarginAnchorView = calculateBottomMarginForAnchorView();
- if (newBottomMarginAnchorView == extraBottomMarginAnchorView) {
- return;
- }
- extraBottomMarginAnchorView = newBottomMarginAnchorView;
+ extraBottomMarginAnchorView = calculateBottomMarginForAnchorView();
updateMargins();
}
diff --git a/material/java/com/google/android/material/tabs/TabLayout.java b/material/java/com/google/android/material/tabs/TabLayout.java
index 88e4b25d5..4c1508cb1 100644
--- a/material/java/com/google/android/material/tabs/TabLayout.java
+++ b/material/java/com/google/android/material/tabs/TabLayout.java
@@ -758,6 +758,20 @@ public void setScrollPosition(
float positionOffset,
boolean updateSelectedTabView,
boolean updateIndicatorPosition) {
+ setScrollPosition(
+ position,
+ positionOffset,
+ updateSelectedTabView,
+ updateIndicatorPosition,
+ /* alwaysScroll= */ true);
+ }
+
+ void setScrollPosition(
+ int position,
+ float positionOffset,
+ boolean updateSelectedTabView,
+ boolean updateIndicatorPosition,
+ boolean alwaysScroll) {
final int roundedPosition = Math.round(position + positionOffset);
if (roundedPosition < 0 || roundedPosition >= slidingTabIndicator.getChildCount()) {
return;
@@ -772,7 +786,36 @@ public void setScrollPosition(
if (scrollAnimator != null && scrollAnimator.isRunning()) {
scrollAnimator.cancel();
}
- scrollTo(position < 0 ? 0 : calculateScrollXForTab(position, positionOffset), 0);
+ int scrollXForPosition = calculateScrollXForTab(position, positionOffset);
+ int scrollX = getScrollX();
+ // If the position is smaller than the selected tab position, the position is getting larger
+ // to reach the selected tab position so scrollX is increasing.
+ // We only want to update the scroll position if the new scroll position is greater than
+ // the current scroll position.
+ // Conversely if the position is greater than the selected tab position, the position is
+ // getting smaller to reach the selected tab position so scrollX is decreasing.
+ // We only update the scroll position if the new scroll position is less than the current
+ // scroll position.
+ // Lastly if the position is equal to the selected position, we want to set the scroll
+ // position which also updates the selected tab view and the indicator.
+ boolean toMove =
+ (position < getSelectedTabPosition() && scrollXForPosition >= scrollX)
+ || (position > getSelectedTabPosition() && scrollXForPosition <= scrollX)
+ || (position == getSelectedTabPosition());
+ // If the layout direction is RTL, the scrollXForPosition and scrollX comparisons are
+ // reversed since scrollX values remain the same in RTL but tab positions go RTL.
+ if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) {
+ toMove =
+ (position < getSelectedTabPosition() && scrollXForPosition <= scrollX)
+ || (position > getSelectedTabPosition()
+ && scrollXForPosition >= scrollX)
+ || (position == getSelectedTabPosition());
+ }
+ // We want to scroll if alwaysScroll is true, the viewpager is being dragged, or if we should
+ // scroll by the rules above.
+ if (toMove || viewPagerScrollState == SCROLL_STATE_DRAGGING || alwaysScroll) {
+ scrollTo(position < 0 ? 0 : scrollXForPosition, 0);
+ }
// Update the 'selected state' view as we scroll, if enabled
if (updateSelectedTabView) {
@@ -3537,7 +3580,7 @@ public void onPageScrolled(
final boolean updateIndicator =
!(scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
tabLayout.setScrollPosition(
- position, positionOffset, updateSelectedTabView, updateIndicator);
+ position, positionOffset, updateSelectedTabView, updateIndicator, false);
}
}
diff --git a/material/java/com/google/android/material/tabs/TabLayoutMediator.java b/material/java/com/google/android/material/tabs/TabLayoutMediator.java
index 94e219ae0..38a9a08e2 100644
--- a/material/java/com/google/android/material/tabs/TabLayoutMediator.java
+++ b/material/java/com/google/android/material/tabs/TabLayoutMediator.java
@@ -230,7 +230,7 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
boolean updateIndicator =
!(scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
tabLayout.setScrollPosition(
- position, positionOffset, updateSelectedTabView, updateIndicator);
+ position, positionOffset, updateSelectedTabView, updateIndicator, false);
}
}
diff --git a/material/java/com/google/android/material/textfield/CutoutDrawable.java b/material/java/com/google/android/material/textfield/CutoutDrawable.java
index 15dda0f19..6d8130fc6 100644
--- a/material/java/com/google/android/material/textfield/CutoutDrawable.java
+++ b/material/java/com/google/android/material/textfield/CutoutDrawable.java
@@ -25,6 +25,7 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Region.Op;
+import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.View;
@@ -38,31 +39,44 @@
* outline mode.
*/
class CutoutDrawable extends MaterialShapeDrawable {
- @NonNull protected final RectF cutoutBounds;
+ @NonNull CutoutDrawableState drawableState;
static CutoutDrawable create(@Nullable ShapeAppearanceModel shapeAppearanceModel) {
+ return create(new CutoutDrawableState(
+ shapeAppearanceModel != null ? shapeAppearanceModel : new ShapeAppearanceModel(),
+ new RectF()));
+ }
+
+ private static CutoutDrawable create(@NonNull CutoutDrawableState drawableState) {
return VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2
- ? new ImplApi18(shapeAppearanceModel)
- : new ImplApi14(shapeAppearanceModel);
+ ? new ImplApi18(drawableState)
+ : new ImplApi14(drawableState);
+ }
+
+ private CutoutDrawable(@NonNull CutoutDrawableState drawableState) {
+ super(drawableState);
+ this.drawableState = drawableState;
}
- private CutoutDrawable(@Nullable ShapeAppearanceModel shapeAppearanceModel) {
- super(shapeAppearanceModel != null ? shapeAppearanceModel : new ShapeAppearanceModel());
- cutoutBounds = new RectF();
+ @NonNull
+ @Override
+ public Drawable mutate() {
+ drawableState = new CutoutDrawableState(drawableState);
+ return this;
}
boolean hasCutout() {
- return !cutoutBounds.isEmpty();
+ return !drawableState.cutoutBounds.isEmpty();
}
void setCutout(float left, float top, float right, float bottom) {
// Avoid expensive redraws by only calling invalidateSelf if one of the cutout's dimensions has
// changed.
- if (left != cutoutBounds.left
- || top != cutoutBounds.top
- || right != cutoutBounds.right
- || bottom != cutoutBounds.bottom) {
- cutoutBounds.set(left, top, right, bottom);
+ if (left != drawableState.cutoutBounds.left
+ || top != drawableState.cutoutBounds.top
+ || right != drawableState.cutoutBounds.right
+ || bottom != drawableState.cutoutBounds.bottom) {
+ drawableState.cutoutBounds.set(left, top, right, bottom);
invalidateSelf();
}
}
@@ -78,21 +92,21 @@ void removeCutout() {
@TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
private static class ImplApi18 extends CutoutDrawable {
- ImplApi18(@Nullable ShapeAppearanceModel shapeAppearanceModel) {
- super(shapeAppearanceModel);
+ ImplApi18(@NonNull CutoutDrawableState drawableState) {
+ super(drawableState);
}
@Override
protected void drawStrokeShape(@NonNull Canvas canvas) {
- if (cutoutBounds.isEmpty()) {
+ if (drawableState.cutoutBounds.isEmpty()) {
super.drawStrokeShape(canvas);
} else {
// Saves the canvas so we can restore the clip after drawing the stroke.
canvas.save();
if (VERSION.SDK_INT >= VERSION_CODES.O) {
- canvas.clipOutRect(cutoutBounds);
+ canvas.clipOutRect(drawableState.cutoutBounds);
} else {
- canvas.clipRect(cutoutBounds, Op.DIFFERENCE);
+ canvas.clipRect(drawableState.cutoutBounds, Op.DIFFERENCE);
}
super.drawStrokeShape(canvas);
canvas.restore();
@@ -106,8 +120,8 @@ private static class ImplApi14 extends CutoutDrawable {
private Paint cutoutPaint;
private int savedLayer;
- ImplApi14(@Nullable ShapeAppearanceModel shapeAppearanceModel) {
- super(shapeAppearanceModel);
+ ImplApi14(@NonNull CutoutDrawableState drawableState) {
+ super(drawableState);
}
@Override
@@ -120,7 +134,7 @@ public void draw(@NonNull Canvas canvas) {
@Override
protected void drawStrokeShape(@NonNull Canvas canvas) {
super.drawStrokeShape(canvas);
- canvas.drawRect(cutoutBounds, getCutoutPaint());
+ canvas.drawRect(drawableState.cutoutBounds, getCutoutPaint());
}
private Paint getCutoutPaint() {
@@ -168,4 +182,28 @@ private boolean useHardwareLayer(Callback callback) {
return callback instanceof View;
}
}
+
+ private static final class CutoutDrawableState extends MaterialShapeDrawableState {
+ @NonNull private final RectF cutoutBounds;
+
+ private CutoutDrawableState(
+ @NonNull ShapeAppearanceModel shapeAppearanceModel, @NonNull RectF cutoutBounds) {
+ super(shapeAppearanceModel, null);
+ this.cutoutBounds = cutoutBounds;
+ }
+
+ private CutoutDrawableState(@NonNull CutoutDrawableState state) {
+ super(state);
+ this.cutoutBounds = state.cutoutBounds;
+ }
+
+ @NonNull
+ @Override
+ public Drawable newDrawable() {
+ CutoutDrawable drawable = CutoutDrawable.create(this);
+ // Force the calculation of the path for the new drawable.
+ drawable.invalidateSelf();
+ return drawable;
+ }
+ }
}
diff --git a/material/java/com/google/android/material/textfield/EndCompoundLayout.java b/material/java/com/google/android/material/textfield/EndCompoundLayout.java
index fb119d70c..7465f87e3 100644
--- a/material/java/com/google/android/material/textfield/EndCompoundLayout.java
+++ b/material/java/com/google/android/material/textfield/EndCompoundLayout.java
@@ -737,6 +737,21 @@ void updateSuffixTextViewPadding() {
textInputLayout.editText.getPaddingBottom());
}
+ int getSuffixTextEndOffset() {
+ int endIconOffset;
+ if (isEndIconVisible() || isErrorIconVisible()) {
+ endIconOffset =
+ endIconView.getMeasuredWidth()
+ + MarginLayoutParamsCompat.getMarginStart(
+ (MarginLayoutParams) endIconView.getLayoutParams());
+ } else {
+ endIconOffset = 0;
+ }
+ return ViewCompat.getPaddingEnd(this)
+ + ViewCompat.getPaddingEnd(suffixTextView)
+ + endIconOffset;
+ }
+
@Nullable
CheckableImageButton getCurrentEndIconView() {
if (isErrorIconVisible()) {
diff --git a/material/java/com/google/android/material/textfield/StartCompoundLayout.java b/material/java/com/google/android/material/textfield/StartCompoundLayout.java
index ebf845551..61f0df192 100644
--- a/material/java/com/google/android/material/textfield/StartCompoundLayout.java
+++ b/material/java/com/google/android/material/textfield/StartCompoundLayout.java
@@ -328,6 +328,21 @@ void updatePrefixTextViewPadding() {
editText.getCompoundPaddingBottom());
}
+ int getPrefixTextStartOffset() {
+ int startIconOffset;
+ if (isStartIconVisible()) {
+ startIconOffset =
+ startIconView.getMeasuredWidth()
+ + MarginLayoutParamsCompat.getMarginEnd(
+ (MarginLayoutParams) startIconView.getLayoutParams());
+ } else {
+ startIconOffset = 0;
+ }
+ return ViewCompat.getPaddingStart(this)
+ + ViewCompat.getPaddingStart(prefixTextView)
+ + startIconOffset;
+ }
+
void onHintStateChanged(boolean hintExpanded) {
this.hintExpanded = hintExpanded;
updateVisibility();
diff --git a/material/java/com/google/android/material/textfield/TextInputLayout.java b/material/java/com/google/android/material/textfield/TextInputLayout.java
index f1032ad26..acda4ac93 100644
--- a/material/java/com/google/android/material/textfield/TextInputLayout.java
+++ b/material/java/com/google/android/material/textfield/TextInputLayout.java
@@ -2769,35 +2769,37 @@ private Rect calculateCollapsedTextBounds(@NonNull Rect rect) {
bounds.right = rect.right - editText.getPaddingRight();
return bounds;
case BOX_BACKGROUND_FILLED:
- bounds.left = getLabelLeftBoundAlightWithPrefix(rect.left, isRtl);
+ bounds.left = getLabelLeftBoundAlignedWithPrefixAndSuffix(rect.left, isRtl);
bounds.top = rect.top + boxCollapsedPaddingTopPx;
- bounds.right = getLabelRightBoundAlignedWithSuffix(rect.right, isRtl);
+ bounds.right = getLabelRightBoundAlignedWithPrefixAndSuffix(rect.right, isRtl);
return bounds;
case BOX_BACKGROUND_NONE:
default:
- bounds.left = getLabelLeftBoundAlightWithPrefix(rect.left, isRtl);
+ bounds.left = getLabelLeftBoundAlignedWithPrefixAndSuffix(rect.left, isRtl);
bounds.top = getPaddingTop();
- bounds.right = getLabelRightBoundAlignedWithSuffix(rect.right, isRtl);
+ bounds.right = getLabelRightBoundAlignedWithPrefixAndSuffix(rect.right, isRtl);
return bounds;
}
}
- private int getLabelLeftBoundAlightWithPrefix(int rectLeft, boolean isRtl) {
- int left = rectLeft + editText.getCompoundPaddingLeft();
- if (getPrefixText() != null && !isRtl) {
- // Label should be vertically aligned with prefix
- left = left - getPrefixTextView().getMeasuredWidth() + getPrefixTextView().getPaddingLeft();
+ private int getLabelLeftBoundAlignedWithPrefixAndSuffix(int rectLeft, boolean isRtl) {
+ if (!isRtl && getPrefixText() != null) {
+ return rectLeft + startLayout.getPrefixTextStartOffset();
}
- return left;
+ if (isRtl && getSuffixText() != null) {
+ return rectLeft + endLayout.getSuffixTextEndOffset();
+ }
+ return rectLeft + editText.getCompoundPaddingLeft();
}
- private int getLabelRightBoundAlignedWithSuffix(int rectRight, boolean isRtl) {
- int right = rectRight - editText.getCompoundPaddingRight();
- if (getPrefixText() != null && isRtl) {
- // Label should be vertically aligned with prefix if in RTL
- right += getPrefixTextView().getMeasuredWidth() - getPrefixTextView().getPaddingRight();
+ private int getLabelRightBoundAlignedWithPrefixAndSuffix(int rectRight, boolean isRtl) {
+ if (!isRtl && getSuffixText() != null) {
+ return rectRight - endLayout.getSuffixTextEndOffset();
+ }
+ if (isRtl && getPrefixText() != null) {
+ return rectRight - startLayout.getPrefixTextStartOffset();
}
- return right;
+ return rectRight - editText.getCompoundPaddingRight();
}
@NonNull
diff --git a/material/java/com/google/android/material/timepicker/ChipTextInputComboView.java b/material/java/com/google/android/material/timepicker/ChipTextInputComboView.java
index b3add4ae3..883cf3e4e 100644
--- a/material/java/com/google/android/material/timepicker/ChipTextInputComboView.java
+++ b/material/java/com/google/android/material/timepicker/ChipTextInputComboView.java
@@ -108,7 +108,7 @@ public void setChecked(boolean checked) {
// Instead, the text in chip should be hidden.
chip.setVisibility(checked ? GONE : VISIBLE);
if (isChecked()) {
- ViewUtils.requestFocusAndShowKeyboard(editText);
+ ViewUtils.requestFocusAndShowKeyboard(editText, /* useWindowInsetsController= */ false);
}
}
diff --git a/preference/src/main/kotlin/de/maxr1998/modernpreferences/helpers/PreferencesDsl.kt b/preference/src/main/kotlin/de/maxr1998/modernpreferences/helpers/PreferencesDsl.kt
index 6ecd133a8..d27ec1668 100644
--- a/preference/src/main/kotlin/de/maxr1998/modernpreferences/helpers/PreferencesDsl.kt
+++ b/preference/src/main/kotlin/de/maxr1998/modernpreferences/helpers/PreferencesDsl.kt
@@ -351,4 +351,18 @@ inline fun ColorPickPreference.onColorBeforeChange(crossinline callback: (Int) -
ColorPickPreference.OnColorBeforeChangeListener { _, selection ->
callback(selection)
}
+}
+
+inline fun SeekBarPreference.onSeek(crossinline callback: (Int) -> Unit) {
+ seekAfterListener =
+ SeekBarPreference.OnSeekAfterListener { _, selection ->
+ callback(selection)
+ }
+}
+
+inline fun SeekBarPreference.onSeekBefore(crossinline callback: (Int) -> Boolean) {
+ seekBeforeListener =
+ SeekBarPreference.OnSeekBeforeListener { _, selection ->
+ callback(selection)
+ }
}
\ No newline at end of file
diff --git a/preference/src/main/kotlin/de/maxr1998/modernpreferences/preferences/SeekBarPreference.kt b/preference/src/main/kotlin/de/maxr1998/modernpreferences/preferences/SeekBarPreference.kt
index a1586124d..76835aed5 100644
--- a/preference/src/main/kotlin/de/maxr1998/modernpreferences/preferences/SeekBarPreference.kt
+++ b/preference/src/main/kotlin/de/maxr1998/modernpreferences/preferences/SeekBarPreference.kt
@@ -47,14 +47,16 @@ class SeekBarPreference(key: String) : Preference(key) {
var value: Int
get() = valueInternal
set(v) {
- if (v != valueInternal && seekListener?.onSeek(this, null, v) != false) {
+ if (v != valueInternal && seekBeforeListener?.onSeekBefore(this, v) != false) {
valueInternal = v
commitInt(value)
requestRebind()
+ seekAfterListener?.onSeekAfter(this, v)
}
}
- var seekListener: OnSeekListener? = null
+ var seekBeforeListener: OnSeekBeforeListener? = null
+ var seekAfterListener: OnSeekAfterListener? = null
var formatter: (Int) -> String = Int::toString
fun copySeek(o: SeekBarPreference): SeekBarPreference {
@@ -63,7 +65,8 @@ class SeekBarPreference(key: String) : Preference(key) {
default = o.default
step = o.step
showTickMarks = o.showTickMarks
- seekListener = o.seekListener
+ seekBeforeListener = o.seekBeforeListener
+ seekAfterListener = o.seekAfterListener
formatter = o.formatter
return this
}
@@ -112,10 +115,11 @@ class SeekBarPreference(key: String) : Preference(key) {
if (done) {
// Commit the last selected value
commitInt(valueInternal)
+ seekAfterListener?.onSeekAfter(this@SeekBarPreference, v)
} else {
val next = calcValue(v)
// Check if listener allows the value change
- if (seekListener?.onSeek(this@SeekBarPreference, holder, next) != false) {
+ if (seekBeforeListener?.onSeekBefore(this@SeekBarPreference, next) != false) {
// Update internal value
valueInternal = next
} else {
@@ -136,20 +140,24 @@ class SeekBarPreference(key: String) : Preference(key) {
private fun calcRaw(value: Int) = (value - min) / step
private fun calcValue(raw: Int) = min + raw * step
- fun interface OnSeekListener {
+ fun interface OnSeekAfterListener {
+ fun onSeekAfter(
+ preference: SeekBarPreference,
+ value: Int
+ )
+ }
+
+ fun interface OnSeekBeforeListener {
/**
* Notified when the [value][SeekBarPreference.value] of the connected [SeekBarPreference] changes.
* This is called *before* the change gets persisted, which can be prevented by returning false.
- *
- * @param holder the [ViewHolder][PreferencesAdapter.ViewHolder] with the views of the Preference instance,
* or null if the change didn't occur as part of a click event
* @param value the new state
*
* @return true to commit the new slider value to [SharedPreferences][android.content.SharedPreferences]
*/
- fun onSeek(
+ fun onSeekBefore(
preference: SeekBarPreference,
- holder: PreferencesAdapter.ViewHolder?,
value: Int
): Boolean
}
diff --git a/preference/src/main/res/layout/map_preference_widget_seekbar.xml b/preference/src/main/res/layout/map_preference_widget_seekbar.xml
index 018aef399..f44bceca6 100644
--- a/preference/src/main/res/layout/map_preference_widget_seekbar.xml
+++ b/preference/src/main/res/layout/map_preference_widget_seekbar.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:textColor="?colorAccent"
- android:textSize="12sp"
+ android:textSize="15sp"
app:layout_constraintBottom_toTopOf="@android:id/progress"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@android:id/progress"