mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Improve system emoji rendering across the app with EmojiCompat2.
Resolves #13327
This commit is contained in:
committed by
Greyson Parrelli
parent
abd80c5204
commit
10922594b3
@@ -42,11 +42,10 @@ public class EmojiEditText extends AppCompatEditText {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
|
||||
boolean forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
|
||||
boolean jumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
|
||||
a.recycle();
|
||||
|
||||
if (!isInEditMode() && (forceCustom || !SignalStore.settings().isPreferSystemEmoji())) {
|
||||
if (!isInEditMode() && !SignalStore.settings().isPreferSystemEmoji()) {
|
||||
setFilters(appendEmojiFilter(this.getFilters(), jumboEmoji));
|
||||
setEmojiCompatEnabled(false);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiPageCache;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.emoji.JumboEmoji;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.DeviceProperties;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
|
||||
@@ -121,6 +122,10 @@ public class EmojiProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (SignalStore.settings().isPreferSystemEmoji()) {
|
||||
return new SystemEmojiDrawable(drawInfo.getEmoji());
|
||||
}
|
||||
|
||||
final int lowMemoryDecodeScale = DeviceProperties.isLowMemoryDevice(context) ? 2 : 1;
|
||||
final EmojiSource source = EmojiSource.getLatest();
|
||||
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
|
||||
@@ -202,6 +207,10 @@ public class EmojiProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (SignalStore.settings().isPreferSystemEmoji()) {
|
||||
return new SystemEmojiDrawable(drawInfo.getEmoji());
|
||||
}
|
||||
|
||||
final int lowMemoryDecodeScale = DeviceProperties.isLowMemoryDevice(context) ? 2 : 1;
|
||||
final EmojiSource source = EmojiSource.getLatest();
|
||||
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
|
||||
|
||||
@@ -57,7 +57,6 @@ public class EmojiTextView extends AppCompatTextView {
|
||||
private static final char ELLIPSIS = '…';
|
||||
private static final float JUMBOMOJI_SCALE = 0.8f;
|
||||
|
||||
private boolean forceCustom;
|
||||
private CharSequence previousText;
|
||||
private BufferType previousBufferType;
|
||||
private TransformationMethod previousTransformationMethod;
|
||||
@@ -93,7 +92,6 @@ public class EmojiTextView extends AppCompatTextView {
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
|
||||
scaleEmojis = a.getBoolean(R.styleable.EmojiTextView_scaleEmojis, false);
|
||||
maxLength = a.getInteger(R.styleable.EmojiTextView_emoji_maxLength, -1);
|
||||
forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
|
||||
renderMentions = a.getBoolean(R.styleable.EmojiTextView_emoji_renderMentions, true);
|
||||
measureLastLine = a.getBoolean(R.styleable.EmojiTextView_measureLastLine, false);
|
||||
forceJumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
|
||||
@@ -445,7 +443,7 @@ public class EmojiTextView extends AppCompatTextView {
|
||||
}
|
||||
|
||||
private boolean useSystemEmoji() {
|
||||
return isInEditMode() || (!forceCustom && SignalStore.settings().isPreferSystemEmoji());
|
||||
return isInEditMode() || SignalStore.settings().isPreferSystemEmoji();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.thoughtcrime.securesms.components.emoji
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.ColorFilter
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.PixelFormat
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.text.Layout
|
||||
import android.text.StaticLayout
|
||||
import android.text.TextPaint
|
||||
import androidx.core.graphics.toRectF
|
||||
import androidx.core.graphics.withMatrix
|
||||
import androidx.emoji2.text.EmojiCompat
|
||||
|
||||
/**
|
||||
* [Drawable] that renders an emoji via the system font for available glyphs and EmojiCompat for
|
||||
* missing glyphs.
|
||||
*/
|
||||
class SystemEmojiDrawable(emoji: CharSequence) : Drawable() {
|
||||
|
||||
private val emojiLayout: StaticLayout = getStaticLayout(getProcessedEmoji(emoji))
|
||||
private val transform: Matrix = Matrix()
|
||||
|
||||
override fun onBoundsChange(bounds: Rect) {
|
||||
super.onBoundsChange(bounds)
|
||||
transform.setRectToRect(emojiLayout.getBounds(), bounds.toRectF(), Matrix.ScaleToFit.CENTER)
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas) {
|
||||
canvas.withMatrix(transform) {
|
||||
emojiLayout.draw(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setAlpha(alpha: Int) {}
|
||||
|
||||
override fun setColorFilter(colorFilter: ColorFilter?) {}
|
||||
|
||||
@Deprecated(
|
||||
"Deprecated in Java",
|
||||
ReplaceWith("PixelFormat.TRANSLUCENT", "android.graphics.PixelFormat")
|
||||
)
|
||||
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
|
||||
|
||||
companion object {
|
||||
private val textPaint: TextPaint = TextPaint()
|
||||
|
||||
private fun getStaticLayout(emoji: CharSequence): StaticLayout =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
StaticLayout.Builder.obtain(emoji, 0, emoji.length, textPaint, Int.MAX_VALUE).build()
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
StaticLayout(emoji, textPaint, Int.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 0f, 0f, true)
|
||||
}
|
||||
|
||||
private fun getProcessedEmoji(emoji: CharSequence): CharSequence =
|
||||
try {
|
||||
EmojiCompat.get().process(emoji) ?: emoji
|
||||
} catch (e: IllegalStateException) {
|
||||
emoji
|
||||
}
|
||||
|
||||
private fun StaticLayout.getBounds(): RectF =
|
||||
RectF(getLineLeft(0), 0f, getLineRight(0), getLineDescent(0) - getLineAscent(0).toFloat())
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,4 @@ package org.thoughtcrime.securesms.components.emoji.parsing
|
||||
|
||||
import org.thoughtcrime.securesms.emoji.EmojiPage
|
||||
|
||||
data class EmojiDrawInfo(val page: EmojiPage, val index: Int, private val emoji: String, val rawEmoji: String?, val jumboSheet: String?)
|
||||
data class EmojiDrawInfo(val page: EmojiPage, val index: Int, val emoji: String, val rawEmoji: String?, val jumboSheet: String?)
|
||||
|
||||
Reference in New Issue
Block a user