diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/db/impl/StickersStorage.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/db/impl/StickersStorage.kt index 4f0891b66..09eb981e1 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/db/impl/StickersStorage.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/db/impl/StickersStorage.kt @@ -25,7 +25,6 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.SingleEmitter import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.serializer -import java.util.Collections internal class StickersStorage(base: AppStorages) : AbsStorage(base), IStickersStorage { override fun storeStickerSets(accountId: Long, sets: List): Completable { @@ -126,7 +125,7 @@ internal class StickersStorage(base: AppStorages) : AbsStorage(base), IStickersS } stickers.add(mapStickerSet(cursor)) } - Collections.sort(stickers, COMPARATOR_STICKER_SET) + stickers.sortWith(COMPARATOR_STICKER_SET) cursor.close() e.onSuccess(stickers) log("StickersStorage.get", start, "count: " + stickers.size) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/abswall/AbsWallPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/abswall/AbsWallPresenter.kt index 1b652ec4d..89b031a94 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/abswall/AbsWallPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/abswall/AbsWallPresenter.kt @@ -48,7 +48,6 @@ import java.io.FileOutputStream import java.io.IOException import java.io.OutputStream import java.lang.Boolean.compare -import java.util.* import kotlin.math.abs abstract class AbsWallPresenter internal constructor( @@ -547,7 +546,7 @@ abstract class AbsWallPresenter internal constructor( post.setPinned(it.isPinned) } if (pinStateChanged) { - Collections.sort(wall, COMPARATOR) + wall.sortWith(COMPARATOR) safeNotifyWallDataSetChanged() } else { view?.notifyWallItemChanged(index) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/filemanagerselect/FileManagerSelectPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/filemanagerselect/FileManagerSelectPresenter.kt index 2270cd726..2165df9c3 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/filemanagerselect/FileManagerSelectPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/filemanagerselect/FileManagerSelectPresenter.kt @@ -11,7 +11,7 @@ import dev.ragnarok.fenrir.util.Objects.safeEquals import io.reactivex.rxjava3.core.Single import java.io.File import java.io.FilenameFilter -import java.util.* +import java.util.Locale class FileManagerSelectPresenter( private var path: File, @@ -202,8 +202,8 @@ class FileManagerSelectPresenter( for (i in fileListTmp) { if (i.isDir) dirsList.add(i) else flsList.add(i) } - Collections.sort(dirsList, ItemModificationComparator()) - Collections.sort(flsList, ItemModificationComparator()) + dirsList.sortWith(ItemModificationComparator()) + flsList.sortWith(ItemModificationComparator()) fileListTmp.clear() fileListTmp.addAll(dirsList) fileListTmp.addAll(flsList) diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/messages/dialogs/DialogsPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/messages/dialogs/DialogsPresenter.kt index eacc09e0d..0a8da3162 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/messages/dialogs/DialogsPresenter.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/messages/dialogs/DialogsPresenter.kt @@ -41,7 +41,6 @@ import dev.ragnarok.fenrir.util.Utils.needReloadStickers import dev.ragnarok.fenrir.util.rxutils.RxUtils.dummy import dev.ragnarok.fenrir.util.rxutils.RxUtils.ignore import io.reactivex.rxjava3.disposables.CompositeDisposable -import java.util.* class DialogsPresenter( accountId: Long, @@ -339,7 +338,7 @@ class DialogsPresenter( dialog.setTitle(it) } if (index != -1) { - Collections.sort(dialogs, COMPARATOR) + dialogs.sortWith(COMPARATOR) safeNotifyDataSetChanged() } else { if (Peer.isGroup(peerId) || Peer.isUser(peerId)) { @@ -353,7 +352,7 @@ class DialogsPresenter( .fromIOToMain() .subscribe({ dialogs.add(dialog) - Collections.sort(dialogs, COMPARATOR) + dialogs.sortWith(COMPARATOR) safeNotifyDataSetChanged() }, ignore()) ) @@ -361,7 +360,7 @@ class DialogsPresenter( ) } else { dialogs.add(dialog) - Collections.sort(dialogs, COMPARATOR) + dialogs.sortWith(COMPARATOR) safeNotifyDataSetChanged() } } diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/internal/OwnerLinkSpanFactory.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/internal/OwnerLinkSpanFactory.kt index b4b6dbfe3..4b7b1f935 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/internal/OwnerLinkSpanFactory.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/internal/OwnerLinkSpanFactory.kt @@ -8,7 +8,6 @@ import dev.ragnarok.fenrir.nonNullNoEmpty import dev.ragnarok.fenrir.orZero import dev.ragnarok.fenrir.settings.Settings import dev.ragnarok.fenrir.util.Utils.safeCountOfMultiple -import java.util.Collections import java.util.regex.Pattern import kotlin.math.abs @@ -44,7 +43,7 @@ object OwnerLinkSpanFactory { if (othersLinks.nonNullNoEmpty()) { all.addAll(othersLinks) } - Collections.sort(all, LINK_COMPARATOR) + all.sortWith(LINK_COMPARATOR) return all } return null @@ -74,7 +73,7 @@ object OwnerLinkSpanFactory { if (othersLinks.nonNullNoEmpty()) { all.addAll(othersLinks) } - Collections.sort(all, LINK_COMPARATOR) + all.sortWith(LINK_COMPARATOR) val result = Spannable.Factory.getInstance().newSpannable(replace(input, all)) for (link in all) { //TODO Нужно ли удалять spannable перед установкой новых diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/picasso/PicassoFileManagerHandler.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/picasso/PicassoFileManagerHandler.kt index 305225c51..adb2cbeab 100644 --- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/picasso/PicassoFileManagerHandler.kt +++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/picasso/PicassoFileManagerHandler.kt @@ -22,7 +22,6 @@ import dev.ragnarok.fenrir.util.CoverSafeResize import dev.ragnarok.fenrir.util.Utils import okio.source import java.io.* -import java.util.* class PicassoFileManagerHandler(val context: Context) : RequestHandler() { companion object { @@ -267,9 +266,7 @@ class PicassoFileManagerHandler(val context: Context) : RequestHandler() { val fList = direct.listFiles(filter) val dst = if (fList != null && fList.isNotEmpty()) { - val tmp = fList.toList() - Collections.sort(tmp, ItemModificationComparator()) - tmp[0] + fList.sortedWith(ItemModificationComparator())[0] } else { null } diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/db/impl/SearchRequestHelperStorage.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/db/impl/SearchRequestHelperStorage.kt index 4db4ccad1..0632f49b2 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/db/impl/SearchRequestHelperStorage.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/db/impl/SearchRequestHelperStorage.kt @@ -355,6 +355,22 @@ class SearchRequestHelperStorage internal constructor(context: Context) : return File(path).length() } + private class ItemModificationComparator : Comparator { + override fun compare(lhs: TagDir, rhs: TagDir): Int { + return when { + lhs.type == FileType.folder && rhs.type != FileType.folder -> { + -1 + } + + lhs.type != FileType.folder && rhs.type == FileType.folder -> { + 1 + } + + else -> rhs.id.compareTo(lhs.id) + } + } + } + override fun getTagDirs(ownerId: Int): Single> { return Single.fromCallable { val where = TagDirsColumns.OWNER_ID + " = ?" @@ -382,6 +398,7 @@ class SearchRequestHelperStorage internal constructor(context: Context) : ) } } + data.sortWith(ItemModificationComparator()) data } } diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanager/FileManagerPresenter.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanager/FileManagerPresenter.kt index 2f66d6a73..45b8cc01a 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanager/FileManagerPresenter.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanager/FileManagerPresenter.kt @@ -23,7 +23,7 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Single import java.io.File import java.io.FilenameFilter -import java.util.* +import java.util.Locale class FileManagerPresenter( private var path: File, @@ -285,8 +285,8 @@ class FileManagerPresenter( for (i in fileListTmp) { if (i.type == FileType.folder) dirsList.add(i) else flsList.add(i) } - Collections.sort(dirsList, ItemModificationComparator()) - Collections.sort(flsList, ItemModificationComparator()) + dirsList.sortWith(ItemModificationComparator()) + flsList.sortWith(ItemModificationComparator()) fileListTmp.clear() fileListTmp.addAll(dirsList) fileListTmp.addAll(flsList) @@ -366,8 +366,8 @@ class FileManagerPresenter( for (i in fileListTmp) { if (i.type == FileType.folder) dirsList.add(i) else flsList.add(i) } - Collections.sort(dirsList, ItemModificationComparator()) - Collections.sort(flsList, ItemModificationComparator()) + dirsList.sortWith(ItemModificationComparator()) + flsList.sortWith(ItemModificationComparator()) fileListTmp.clear() fileListTmp.addAll(dirsList) fileListTmp.addAll(flsList) diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanagerselect/FileManagerSelectPresenter.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanagerselect/FileManagerSelectPresenter.kt index 0243a123d..de3c62bc7 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanagerselect/FileManagerSelectPresenter.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/filemanagerselect/FileManagerSelectPresenter.kt @@ -11,7 +11,7 @@ import dev.ragnarok.filegallery.util.Objects.safeEquals import io.reactivex.rxjava3.core.Single import java.io.File import java.io.FilenameFilter -import java.util.* +import java.util.Locale class FileManagerSelectPresenter( private var path: File, @@ -202,8 +202,8 @@ class FileManagerSelectPresenter( for (i in fileListTmp) { if (i.isDir) dirsList.add(i) else flsList.add(i) } - Collections.sort(dirsList, ItemModificationComparator()) - Collections.sort(flsList, ItemModificationComparator()) + dirsList.sortWith(ItemModificationComparator()) + flsList.sortWith(ItemModificationComparator()) fileListTmp.clear() fileListTmp.addAll(dirsList) fileListTmp.addAll(flsList) diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/picasso/PicassoFileManagerHandler.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/picasso/PicassoFileManagerHandler.kt index be2fb7477..6c6eee581 100644 --- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/picasso/PicassoFileManagerHandler.kt +++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/picasso/PicassoFileManagerHandler.kt @@ -23,7 +23,6 @@ import dev.ragnarok.filegallery.util.CoverSafeResize import dev.ragnarok.filegallery.util.Utils import okio.source import java.io.* -import java.util.* class PicassoFileManagerHandler(val context: Context) : RequestHandler() { companion object { @@ -257,9 +256,7 @@ class PicassoFileManagerHandler(val context: Context) : RequestHandler() { val fList = direct.listFiles(filter) val dst = if (fList != null && fList.isNotEmpty()) { - val tmp = fList.toList() - Collections.sort(tmp, ItemModificationComparator()) - tmp[0] + fList.sortedWith(ItemModificationComparator())[0] } else { null } diff --git a/build.gradle b/build.gradle index 57a096143..dd6f90e7d 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ buildscript { ext.autoValueVersion = "1.10.1" //common libraries - ext.kotlin_version = "1.8.10" + ext.kotlin_version = "1.8.20-Beta" ext.kotlin_coroutines = "1.6.4" ext.kotlin_serializer = "1.5.0" ext.okhttpLibraryVersion = "5.0.0-alpha.11" @@ -89,7 +89,7 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:8.0.0-beta03" + classpath "com.android.tools.build:gradle:8.0.0-beta04" 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/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5f6d01f8a..10e9fa27b 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.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME 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 64d0b59f7..d047b703e 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 @@ -42,6 +42,8 @@ extern "C" { // The following are available for GCC 32 or 64 bit: #if !defined(LIBYUV_DISABLE_X86) && (defined(__i386__) || defined(__x86_64__)) #define HAS_TRANSPOSEWX8_SSSE3 +#define HAS_TRANSPOSE4X4_32_SSE2 +#define HAS_TRANSPOSE4X4_32_AVX2 #endif // The following are available for 64 bit GCC: @@ -56,6 +58,11 @@ extern "C" { #define HAS_TRANSPOSEUVWX8_NEON #endif +#if !defined(LIBYUV_DISABLE_NEON) && \ + (defined(LIBYUV_NEON) || defined(__aarch64__)) +#define HAS_TRANSPOSE4X4_32_NEON +#endif + #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) #define HAS_TRANSPOSEWX16_MSA #define HAS_TRANSPOSEUVWX16_MSA @@ -240,19 +247,24 @@ void Transpose4x4_32_NEON(const uint8_t* src, int dst_stride, int width); -void Transpose4x4_32_C(const uint8_t* src, - int src_stride, - uint8_t* dst, - int dst_stride, - int width); +void Transpose4x4_32_SSE2(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, +void Transpose4x4_32_AVX2(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); + #ifdef __cplusplus } // extern "C" } // namespace libyuv 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 42f816626..cc1e66e71 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 1861 +#define LIBYUV_VERSION 1862 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/libfenrir/src/main/jni/animation/libyuv/source/rotate_gcc.cc b/libfenrir/src/main/jni/animation/libyuv/source/rotate_gcc.cc index 1a3f8cbbd..fd5eee05f 100644 --- a/libfenrir/src/main/jni/animation/libyuv/source/rotate_gcc.cc +++ b/libfenrir/src/main/jni/animation/libyuv/source/rotate_gcc.cc @@ -365,6 +365,136 @@ void TransposeUVWx8_SSE2(const uint8_t* src, "xmm7", "xmm8", "xmm9"); } #endif // defined(HAS_TRANSPOSEUVWX8_SSE2) + +#if defined(HAS_TRANSPOSE4X4_32_SSE2) +// 4 values, little endian view +// a b c d +// e f g h +// i j k l +// m n o p + +// transpose 2x2 +// a e b f from row 0, 1 +// i m j n from row 2, 3 +// c g d h from row 0, 1 +// k o l p from row 2, 3 + +// transpose 4x4 +// a e i m from row 0, 1 +// b f j n from row 0, 1 +// c g k o from row 2, 3 +// d h l p from row 2, 3 + +// Transpose 32 bit values (ARGB) +void Transpose4x4_32_SSE2(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width) { + asm volatile( + // Main loop transpose 4x4. Read a column, write a row. + "1: \n" + "movdqu (%0),%%xmm0 \n" // a b c d + "movdqu (%0,%3),%%xmm1 \n" // e f g h + "lea (%0,%3,2),%0 \n" // src += stride * 2 + "movdqu (%0),%%xmm2 \n" // i j k l + "movdqu (%0,%3),%%xmm3 \n" // m n o p + "lea (%0,%3,2),%0 \n" // src += stride * 2 + + // Transpose 2x2 + "movdqa %%xmm0,%%xmm4 \n" + "movdqa %%xmm2,%%xmm5 \n" + "movdqa %%xmm0,%%xmm6 \n" + "movdqa %%xmm2,%%xmm7 \n" + "punpckldq %%xmm1,%%xmm4 \n" // a e b f from row 0, 1 + "punpckldq %%xmm3,%%xmm5 \n" // i m j n from row 2, 3 + "punpckhdq %%xmm1,%%xmm6 \n" // c g d h from row 0, 1 + "punpckhdq %%xmm3,%%xmm7 \n" // k o l p from row 2, 3 + + // Transpose 4x4 + "movdqa %%xmm4,%%xmm0 \n" + "movdqa %%xmm4,%%xmm1 \n" + "movdqa %%xmm6,%%xmm2 \n" + "movdqa %%xmm6,%%xmm3 \n" + "punpcklqdq %%xmm5,%%xmm0 \n" // a e i m from row 0, 1 + "punpckhqdq %%xmm5,%%xmm1 \n" // b f j n from row 0, 1 + "punpcklqdq %%xmm7,%%xmm2 \n" // c g k o from row 2, 3 + "punpckhqdq %%xmm7,%%xmm3 \n" // d h l p from row 2, 3 + + "movdqu %%xmm0,(%1) \n" + "lea 16(%1,%4),%1 \n" // dst += stride + 16 + "movdqu %%xmm1,-16(%1) \n" + "movdqu %%xmm2,-16(%1,%4) \n" + "movdqu %%xmm3,-16(%1,%4,2) \n" + "sub %4,%1 \n" + "sub $0x4,%2 \n" + "jg 1b \n" + : "+r"(src), // %0 + "+r"(dst), // %1 + "+rm"(width) // %2 + : "r"((ptrdiff_t)(src_stride)), // %3 + "r"((ptrdiff_t)(dst_stride)) // %4 + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", + "xmm7"); +} +#endif // defined(HAS_TRANSPOSE4X4_32_SSE2) + +#if defined(HAS_TRANSPOSE4X4_32_AVX2) + +// Transpose 32 bit values (ARGB) +void Transpose4x4_32_AVX2(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width) { + asm volatile( + // Main loop transpose 2 blocks of 4x4. Read a column, write a row. + "1: \n" + "vmovdqu (%0),%%xmm0 \n" // a b c d + "vmovdqu (%0,%3),%%xmm1 \n" // e f g h + "lea (%0,%3,2),%0 \n" // src += stride * 2 + "vmovdqu (%0),%%xmm2 \n" // i j k l + "vmovdqu (%0,%3),%%xmm3 \n" // m n o p + "lea (%0,%3,2),%0 \n" // src += stride * 2 + + "vinserti128 $1,(%0),%%ymm0,%%ymm0 \n" // a b c d + "vinserti128 $1,(%0,%3),%%ymm1,%%ymm1 \n" // e f g h + "lea (%0,%3,2),%0 \n" // src += stride * 2 + "vinserti128 $1,(%0),%%ymm2,%%ymm2 \n" // i j k l + "vinserti128 $1,(%0,%3),%%ymm3,%%ymm3 \n" // m n o p + "lea (%0,%3,2),%0 \n" // src += stride * 2 + + // Transpose 2x2 + "vpunpckldq %%ymm1,%%ymm0,%%ymm4 \n" // a e b f from row 0, 1 + "vpunpckldq %%ymm3,%%ymm2,%%ymm5 \n" // i m j n from row 2, 3 + "vpunpckhdq %%ymm1,%%ymm0,%%ymm6 \n" // c g d h from row 0, 1 + "vpunpckhdq %%ymm3,%%ymm2,%%ymm7 \n" // k o l p from row 2, 3 + + // Transpose 4x4 + "vpunpcklqdq %%ymm5,%%ymm4,%%ymm0 \n" // a e i m from row 0, 1 + "vpunpckhqdq %%ymm5,%%ymm4,%%ymm1 \n" // b f j n from row 0, 1 + "vpunpcklqdq %%ymm7,%%ymm6,%%ymm2 \n" // c g k o from row 2, 3 + "vpunpckhqdq %%ymm7,%%ymm6,%%ymm3 \n" // d h l p from row 2, 3 + + "vmovdqu %%ymm0,(%1) \n" + "lea 32(%1,%4),%1 \n" // dst += stride + 32 + "vmovdqu %%ymm1,-32(%1) \n" + "vmovdqu %%ymm2,-32(%1,%4) \n" + "vmovdqu %%ymm3,-32(%1,%4,2) \n" + "sub %4,%1 \n" + "sub $0x8,%2 \n" + "jg 1b \n" + "vzeroupper \n" + : "+r"(src), // %0 + "+r"(dst), // %1 + "+rm"(width) // %2 + : "r"((ptrdiff_t)(src_stride)), // %3 + "r"((ptrdiff_t)(dst_stride)) // %4 + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", + "xmm7"); +} +#endif // defined(HAS_TRANSPOSE4X4_32_AVX2) + #endif // defined(__x86_64__) || defined(__i386__) #ifdef __cplusplus diff --git a/material/java/com/google/android/material/appbar/AppBarLayout.java b/material/java/com/google/android/material/appbar/AppBarLayout.java index bfe9c41fc..ca7a98939 100644 --- a/material/java/com/google/android/material/appbar/AppBarLayout.java +++ b/material/java/com/google/android/material/appbar/AppBarLayout.java @@ -2214,7 +2214,15 @@ private void updateAppBarLayoutDrawableState( if (forceJump || (changed && shouldJumpElevationState(parent, layout))) { // If the collapsed state changed, we may need to // jump to the current state if we have an overlapping view - layout.jumpDrawablesToCurrentState(); + if (layout.getBackground() != null) { + layout.getBackground().jumpToCurrentState(); + } + if (VERSION.SDK_INT >= VERSION_CODES.M && layout.getForeground() != null) { + layout.getForeground().jumpToCurrentState(); + } + if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && layout.getStateListAnimator() != null) { + layout.getStateListAnimator().jumpToCurrentState(); + } } } diff --git a/material/java/com/google/android/material/badge/BadgeDrawable.java b/material/java/com/google/android/material/badge/BadgeDrawable.java index 94f295f5a..0a484537d 100644 --- a/material/java/com/google/android/material/badge/BadgeDrawable.java +++ b/material/java/com/google/android/material/badge/BadgeDrawable.java @@ -51,6 +51,7 @@ import com.google.android.material.internal.ThemeEnforcement; import com.google.android.material.resources.TextAppearance; import com.google.android.material.shape.MaterialShapeDrawable; +import com.google.android.material.shape.ShapeAppearanceModel; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -176,6 +177,9 @@ public class BadgeDrawable extends Drawable implements TextDrawableDelegate { @Retention(RetentionPolicy.SOURCE) @interface OffsetAlignmentMode {} + /** A value to indicate that a badge radius has not been specified. */ + static final int BADGE_RADIUS_NOT_SPECIFIED = -1; + @NonNull private final WeakReference contextRef; @NonNull private final MaterialShapeDrawable shapeDrawable; @NonNull private final TextDrawableHelper textDrawableHelper; @@ -249,6 +253,7 @@ private void onVisibilityUpdated() { } private void restoreState() { + onBadgeShapeAppearanceUpdated(); onBadgeTextAppearanceUpdated(); onMaxCharacterCountUpdated(); @@ -272,14 +277,23 @@ private BadgeDrawable( this.contextRef = new WeakReference<>(context); ThemeEnforcement.checkMaterialTheme(context); badgeBounds = new Rect(); - shapeDrawable = new MaterialShapeDrawable(); textDrawableHelper = new TextDrawableHelper(/* delegate= */ this); textDrawableHelper.getTextPaint().setTextAlign(Paint.Align.CENTER); this.state = new BadgeState(context, badgeResId, defStyleAttr, defStyleRes, savedState); - + shapeDrawable = + new MaterialShapeDrawable( + ShapeAppearanceModel.builder( + context, + state.hasNumber() + ? state.getBadgeWithTextShapeAppearanceResId() + : state.getBadgeShapeAppearanceResId(), + state.hasNumber() + ? state.getBadgeWithTextShapeAppearanceOverlayResId() + : state.getBadgeShapeAppearanceOverlayResId()) + .build()); restoreState(); } @@ -531,6 +545,7 @@ public void clearNumber() { private void onNumberUpdated() { textDrawableHelper.setTextWidthDirty(true); + onBadgeShapeAppearanceUpdated(); updateCenterAndBounds(); invalidateSelf(); } @@ -884,6 +899,68 @@ private void onBadgeTextAppearanceUpdated() { invalidateSelf(); } + /** + * Sets this badge without text's shape appearance resource. + * + * @param id This badge's shape appearance res id when there is no text. + * @attr ref com.google.android.material.R.styleable#Badge_badgeShapeAppearance + */ + public void setBadgeWithoutTextShapeAppearance(@StyleRes int id) { + state.setBadgeShapeAppearanceResId(id); + onBadgeShapeAppearanceUpdated(); + } + + /** + * Sets this badge without text's shape appearance overlay resource. + * + * @param id This badge's shape appearance overlay res id when there is no text. + * @attr ref com.google.android.material.R.styleable#Badge_badgeShapeAppearanceOverlay + */ + public void setBadgeWithoutTextShapeAppearanceOverlay(@StyleRes int id) { + state.setBadgeShapeAppearanceOverlayResId(id); + onBadgeShapeAppearanceUpdated(); + } + + /** + * Sets this badge with text's shape appearance resource. + * + * @param id This badge's shape appearance res id when there is text. + * @attr ref com.google.android.material.R.styleable#Badge_badgeWithTextShapeAppearance + */ + public void setBadgeWithTextShapeAppearance(@StyleRes int id) { + state.setBadgeWithTextShapeAppearanceResId(id); + onBadgeShapeAppearanceUpdated(); + } + + /** + * Sets this badge with text's shape appearance overlay resource. + * + * @param id This badge's shape appearance overlay res id when there is text. + * @attr ref com.google.android.material.R.styleable#Badge_badgeWithTextShapeAppearanceOverlay + */ + public void setBadgeWithTextShapeAppearanceOverlay(@StyleRes int id) { + state.setBadgeWithTextShapeAppearanceOverlayResId(id); + onBadgeShapeAppearanceUpdated(); + } + + private void onBadgeShapeAppearanceUpdated() { + Context context = contextRef.get(); + if (context == null) { + return; + } + shapeDrawable.setShapeAppearanceModel( + ShapeAppearanceModel.builder( + context, + state.hasNumber() + ? state.getBadgeWithTextShapeAppearanceResId() + : state.getBadgeShapeAppearanceResId(), + state.hasNumber() + ? state.getBadgeWithTextShapeAppearanceOverlayResId() + : state.getBadgeShapeAppearanceOverlayResId()) + .build()); + invalidateSelf(); + } + private void updateCenterAndBounds() { Context context = contextRef.get(); View anchorView = anchorViewRef != null ? anchorViewRef.get() : null; @@ -909,7 +986,11 @@ private void updateCenterAndBounds() { updateBadgeBounds(badgeBounds, badgeCenterX, badgeCenterY, halfBadgeWidth, halfBadgeHeight); - shapeDrawable.setCornerSize(cornerRadius); + // If there is a badge radius specified, override the corner size set by the shape appearance + // with the badge radius. + if (cornerRadius != BADGE_RADIUS_NOT_SPECIFIED) { + shapeDrawable.setCornerSize(cornerRadius); + } if (!tmpRect.equals(badgeBounds)) { shapeDrawable.setBounds(badgeBounds); } @@ -937,15 +1018,22 @@ private int getTotalHorizontalOffsetForState() { } private void calculateCenterAndBounds(@NonNull Rect anchorRect, @NonNull View anchorView) { - if (getNumber() <= MAX_CIRCULAR_BADGE_NUMBER_COUNT) { - cornerRadius = !hasNumber() ? state.badgeRadius : state.badgeWithTextRadius; + cornerRadius = !hasNumber() ? state.badgeRadius : state.badgeWithTextRadius; + if (cornerRadius != BADGE_RADIUS_NOT_SPECIFIED) { halfBadgeHeight = cornerRadius; halfBadgeWidth = cornerRadius; } else { - cornerRadius = state.badgeWithTextRadius; - halfBadgeHeight = cornerRadius; + halfBadgeHeight = + Math.round(!hasNumber() ? state.badgeHeight / 2 : state.badgeWithTextHeight / 2); + halfBadgeWidth = + Math.round(!hasNumber() ? state.badgeWidth / 2 : state.badgeWithTextWidth / 2); + } + if (getNumber() > MAX_CIRCULAR_BADGE_NUMBER_COUNT) { String badgeText = getBadgeText(); - halfBadgeWidth = textDrawableHelper.getTextWidth(badgeText) / 2f + state.badgeWidePadding; + halfBadgeWidth = + Math.max( + halfBadgeWidth, + textDrawableHelper.getTextWidth(badgeText) / 2f + state.badgeWidePadding); } int totalVerticalOffset = getTotalVerticalOffsetForState(); diff --git a/material/java/com/google/android/material/badge/BadgeState.java b/material/java/com/google/android/material/badge/BadgeState.java index cdde5e8aa..69021554b 100644 --- a/material/java/com/google/android/material/badge/BadgeState.java +++ b/material/java/com/google/android/material/badge/BadgeState.java @@ -19,6 +19,7 @@ import com.google.android.material.R; import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; +import static com.google.android.material.badge.BadgeDrawable.BADGE_RADIUS_NOT_SPECIFIED; import static com.google.android.material.badge.BadgeDrawable.OFFSET_ALIGNMENT_MODE_LEGACY; import static com.google.android.material.badge.BadgeDrawable.TOP_END; @@ -71,6 +72,10 @@ public final class BadgeState { final float badgeRadius; final float badgeWithTextRadius; + final float badgeWidth; + final float badgeHeight; + final float badgeWithTextWidth; + final float badgeWithTextHeight; final float badgeWidePadding; final int horizontalInset; final int horizontalInsetWithText; @@ -95,8 +100,7 @@ public final class BadgeState { Resources res = context.getResources(); badgeRadius = - a.getDimensionPixelSize( - R.styleable.Badge_badgeRadius, res.getDimensionPixelSize(R.dimen.mtrl_badge_radius)); + a.getDimensionPixelSize(R.styleable.Badge_badgeRadius, BADGE_RADIUS_NOT_SPECIFIED); badgeWidePadding = a.getDimensionPixelSize( R.styleable.Badge_badgeWidePadding, @@ -112,9 +116,20 @@ public final class BadgeState { .getDimensionPixelSize(R.dimen.mtrl_badge_text_horizontal_edge_offset); badgeWithTextRadius = - a.getDimensionPixelSize( - R.styleable.Badge_badgeWithTextRadius, - res.getDimensionPixelSize(R.dimen.mtrl_badge_with_text_radius)); + a.getDimensionPixelSize(R.styleable.Badge_badgeWithTextRadius, BADGE_RADIUS_NOT_SPECIFIED); + badgeWidth = + a.getDimension(R.styleable.Badge_badgeWidth, res.getDimension(R.dimen.m3_badge_size)); + badgeWithTextWidth = + a.getDimension( + R.styleable.Badge_badgeWithTextWidth, + res.getDimension(R.dimen.m3_badge_with_text_size)); + badgeHeight = + a.getDimension(R.styleable.Badge_badgeHeight, res.getDimension(R.dimen.m3_badge_size)); + badgeWithTextHeight = + a.getDimension( + R.styleable.Badge_badgeWithTextHeight, + res.getDimension(R.dimen.m3_badge_with_text_size)); + offsetAlignmentMode = a.getInt(R.styleable.Badge_offsetAlignmentMode, OFFSET_ALIGNMENT_MODE_LEGACY); @@ -153,6 +168,30 @@ public final class BadgeState { currentState.number = State.BADGE_NUMBER_NONE; } + currentState.badgeShapeAppearanceResId = + storedState.badgeShapeAppearanceResId == null + ? a.getResourceId( + R.styleable.Badge_badgeShapeAppearance, + R.style.ShapeAppearance_M3_Sys_Shape_Corner_Full) + : storedState.badgeShapeAppearanceResId; + + currentState.badgeShapeAppearanceOverlayResId = + storedState.badgeShapeAppearanceOverlayResId == null + ? a.getResourceId(R.styleable.Badge_badgeShapeAppearanceOverlay, 0) + : storedState.badgeShapeAppearanceOverlayResId; + + currentState.badgeWithTextShapeAppearanceResId = + storedState.badgeWithTextShapeAppearanceResId == null + ? a.getResourceId( + R.styleable.Badge_badgeWithTextShapeAppearance, + R.style.ShapeAppearance_M3_Sys_Shape_Corner_Full) + : storedState.badgeWithTextShapeAppearanceResId; + + currentState.badgeWithTextShapeAppearanceOverlayResId = + storedState.badgeWithTextShapeAppearanceOverlayResId == null + ? a.getResourceId(R.styleable.Badge_badgeWithTextShapeAppearanceOverlay, 0) + : storedState.badgeWithTextShapeAppearanceOverlayResId; + currentState.backgroundColor = (storedState.backgroundColor == null || storedState.notSaveColor) ? readColorFromAttributes(context, a, R.styleable.Badge_backgroundColor) @@ -326,6 +365,42 @@ void setTextAppearanceResId(@StyleRes int textAppearanceResId) { currentState.badgeTextAppearanceResId = textAppearanceResId; } + int getBadgeShapeAppearanceResId() { + return currentState.badgeShapeAppearanceResId; + } + + void setBadgeShapeAppearanceResId(int shapeAppearanceResId) { + overridingState.badgeShapeAppearanceResId = shapeAppearanceResId; + currentState.badgeShapeAppearanceResId = shapeAppearanceResId; + } + + int getBadgeShapeAppearanceOverlayResId() { + return currentState.badgeShapeAppearanceOverlayResId; + } + + void setBadgeShapeAppearanceOverlayResId(int shapeAppearanceOverlayResId) { + overridingState.badgeShapeAppearanceOverlayResId = shapeAppearanceOverlayResId; + currentState.badgeShapeAppearanceOverlayResId = shapeAppearanceOverlayResId; + } + + int getBadgeWithTextShapeAppearanceResId() { + return currentState.badgeWithTextShapeAppearanceResId; + } + + void setBadgeWithTextShapeAppearanceResId(int shapeAppearanceResId) { + overridingState.badgeWithTextShapeAppearanceResId = shapeAppearanceResId; + currentState.badgeWithTextShapeAppearanceResId = shapeAppearanceResId; + } + + int getBadgeWithTextShapeAppearanceOverlayResId() { + return currentState.badgeWithTextShapeAppearanceOverlayResId; + } + + void setBadgeWithTextShapeAppearanceOverlayResId(int shapeAppearanceOverlayResId) { + overridingState.badgeWithTextShapeAppearanceOverlayResId = shapeAppearanceOverlayResId; + currentState.badgeWithTextShapeAppearanceOverlayResId = shapeAppearanceOverlayResId; + } + @BadgeGravity int getBadgeGravity() { return currentState.badgeGravity; @@ -465,6 +540,11 @@ public static final class State implements Parcelable { @ColorInt private Integer badgeTextColor; @StyleRes private Integer badgeTextAppearanceResId; + @StyleRes private Integer badgeShapeAppearanceResId; + @StyleRes private Integer badgeShapeAppearanceOverlayResId; + @StyleRes private Integer badgeWithTextShapeAppearanceResId; + @StyleRes private Integer badgeWithTextShapeAppearanceOverlayResId; + private int alpha = 255; private int number = NOT_SET; private int maxCharacterCount = NOT_SET; @@ -503,6 +583,10 @@ public State() {} backgroundColor = (Integer) in.readSerializable(); badgeTextColor = (Integer) in.readSerializable(); badgeTextAppearanceResId = (Integer) in.readSerializable(); + badgeShapeAppearanceResId = (Integer) in.readSerializable(); + badgeShapeAppearanceOverlayResId = (Integer) in.readSerializable(); + badgeWithTextShapeAppearanceResId = (Integer) in.readSerializable(); + badgeWithTextShapeAppearanceOverlayResId = (Integer) in.readSerializable(); alpha = in.readInt(); number = in.readInt(); maxCharacterCount = in.readInt(); @@ -546,6 +630,10 @@ public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeSerializable(backgroundColor); dest.writeSerializable(badgeTextColor); dest.writeSerializable(badgeTextAppearanceResId); + dest.writeSerializable(badgeShapeAppearanceResId); + dest.writeSerializable(badgeShapeAppearanceOverlayResId); + dest.writeSerializable(badgeWithTextShapeAppearanceResId); + dest.writeSerializable(badgeWithTextShapeAppearanceOverlayResId); dest.writeInt(alpha); dest.writeInt(number); dest.writeInt(maxCharacterCount); diff --git a/material/java/com/google/android/material/badge/res-public/values/public.xml b/material/java/com/google/android/material/badge/res-public/values/public.xml index 5f5a79aae..e157e8f25 100644 --- a/material/java/com/google/android/material/badge/res-public/values/public.xml +++ b/material/java/com/google/android/material/badge/res-public/values/public.xml @@ -25,6 +25,14 @@ + + + + + + + + diff --git a/material/java/com/google/android/material/badge/res/values-af/strings.xml b/material/java/com/google/android/material/badge/res/values-af/strings.xml index 2965530b1..01c10ffd3 100644 --- a/material/java/com/google/android/material/badge/res/values-af/strings.xml +++ b/material/java/com/google/android/material/badge/res/values-af/strings.xml @@ -1,6 +1,6 @@ + - + + + + + + + + + @@ -43,6 +53,16 @@ + + + + + + + + diff --git a/material/java/com/google/android/material/badge/res/values/dimens.xml b/material/java/com/google/android/material/badge/res/values/dimens.xml index 42be9f322..21c565ad6 100644 --- a/material/java/com/google/android/material/badge/res/values/dimens.xml +++ b/material/java/com/google/android/material/badge/res/values/dimens.xml @@ -16,8 +16,8 @@ --> - 4dp - 8dp + 8dp + 16dp 4dp @@ -32,8 +32,8 @@ 12dp - 3dp - 8dp + @dimen/m3_comp_badge_size + @dimen/m3_comp_badge_large_size 1.5dp 1.5dp diff --git a/material/java/com/google/android/material/badge/res/values/styles.xml b/material/java/com/google/android/material/badge/res/values/styles.xml index 0ca533cdc..0ccdfd48d 100644 --- a/material/java/com/google/android/material/badge/res/values/styles.xml +++ b/material/java/com/google/android/material/badge/res/values/styles.xml @@ -17,14 +17,18 @@ + diff --git a/material/java/com/google/android/material/badge/res/values/tokens.xml b/material/java/com/google/android/material/badge/res/values/tokens.xml index 1b3edba73..e3f4fd894 100644 --- a/material/java/com/google/android/material/badge/res/values/tokens.xml +++ b/material/java/com/google/android/material/badge/res/values/tokens.xml @@ -22,5 +22,12 @@ ?attr/colorError +