|
|
|
@ -9,7 +9,6 @@ import android.graphics.Paint;
|
|
|
|
|
import android.graphics.PixelFormat;
|
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
import android.graphics.drawable.Drawable.Callback;
|
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
|
import android.os.Build.VERSION;
|
|
|
|
|
import android.os.Build.VERSION_CODES;
|
|
|
|
@ -17,6 +16,7 @@ import android.text.Spannable;
|
|
|
|
|
import android.text.SpannableStringBuilder;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.util.SparseArray;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
|
|
import org.thoughtcrime.securesms.R;
|
|
|
|
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
|
|
|
@ -44,17 +44,14 @@ public class EmojiProvider {
|
|
|
|
|
// |==== misc ====||======== emoticons ========||========= flags ==========|
|
|
|
|
|
private static final Pattern EMOJI_RANGE = Pattern.compile("[\\u20a0-\\u32ff\\ud83c\\udc00-\\ud83d\\udeff\\udbb9\\udce5-\\udbb9\\udcee]");
|
|
|
|
|
|
|
|
|
|
public static final double EMOJI_FULL = 1.00;
|
|
|
|
|
public static final double EMOJI_SMALL = 0.90;
|
|
|
|
|
public static final int EMOJI_RAW_HEIGHT = 64;
|
|
|
|
|
public static final int EMOJI_RAW_WIDTH = 64;
|
|
|
|
|
public static final int EMOJI_VERT_PAD = 0;
|
|
|
|
|
public static final int EMOJI_PER_ROW = 32;
|
|
|
|
|
|
|
|
|
|
private final Context context;
|
|
|
|
|
private final double drawWidth;
|
|
|
|
|
private final double drawHeight;
|
|
|
|
|
private final double verticalPad;
|
|
|
|
|
private final float decodeScale;
|
|
|
|
|
private final float verticalPad;
|
|
|
|
|
|
|
|
|
|
public static EmojiProvider getInstance(Context context) {
|
|
|
|
|
if (instance == null) {
|
|
|
|
@ -69,11 +66,8 @@ public class EmojiProvider {
|
|
|
|
|
|
|
|
|
|
private EmojiProvider(Context context) {
|
|
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
|
this.drawHeight = Math.min(context.getResources().getDimension(R.dimen.emoji_drawer_size), EMOJI_RAW_HEIGHT);
|
|
|
|
|
double drawScale = drawHeight / EMOJI_RAW_HEIGHT;
|
|
|
|
|
this.drawWidth = EMOJI_RAW_WIDTH * drawScale;
|
|
|
|
|
this.verticalPad = EMOJI_VERT_PAD * drawScale;
|
|
|
|
|
Log.w(TAG, "draw size: " + drawWidth + "x" + drawHeight);
|
|
|
|
|
this.decodeScale = Math.min(1f, context.getResources().getDimension(R.dimen.emoji_drawer_size) / EMOJI_RAW_HEIGHT);
|
|
|
|
|
this.verticalPad = EMOJI_VERT_PAD * this.decodeScale;
|
|
|
|
|
for (EmojiPageModel page : EmojiPages.PAGES) {
|
|
|
|
|
if (page.hasSpriteMap()) {
|
|
|
|
|
final EmojiPageBitmap pageBitmap = new EmojiPageBitmap(page);
|
|
|
|
@ -84,15 +78,15 @@ public class EmojiProvider {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Spannable emojify(CharSequence text, Callback callback) {
|
|
|
|
|
public Spannable emojify(CharSequence text, TextView tv) {
|
|
|
|
|
Matcher matches = EMOJI_RANGE.matcher(text);
|
|
|
|
|
SpannableStringBuilder builder = new SpannableStringBuilder(text);
|
|
|
|
|
|
|
|
|
|
while (matches.find()) {
|
|
|
|
|
int codePoint = matches.group().codePointAt(0);
|
|
|
|
|
Drawable drawable = getEmojiDrawable(codePoint, EMOJI_SMALL);
|
|
|
|
|
Drawable drawable = getEmojiDrawable(codePoint);
|
|
|
|
|
if (drawable != null) {
|
|
|
|
|
builder.setSpan(new InvalidatingDrawableSpan(drawable, callback), matches.start(), matches.end(),
|
|
|
|
|
builder.setSpan(new EmojiSpan(drawable, tv), matches.start(), matches.end(),
|
|
|
|
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -100,17 +94,16 @@ public class EmojiProvider {
|
|
|
|
|
return builder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Drawable getEmojiDrawable(int emojiCode, double size) {
|
|
|
|
|
return getEmojiDrawable(offsets.get(emojiCode), size);
|
|
|
|
|
public Drawable getEmojiDrawable(int emojiCode) {
|
|
|
|
|
return getEmojiDrawable(offsets.get(emojiCode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Drawable getEmojiDrawable(DrawInfo drawInfo, double size) {
|
|
|
|
|
private Drawable getEmojiDrawable(DrawInfo drawInfo) {
|
|
|
|
|
if (drawInfo == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final EmojiDrawable drawable = new EmojiDrawable(drawInfo, drawWidth, drawHeight);
|
|
|
|
|
drawable.setBounds(0, 0, (int)(drawWidth * size), (int)(drawHeight * size));
|
|
|
|
|
final EmojiDrawable drawable = new EmojiDrawable(drawInfo, decodeScale);
|
|
|
|
|
drawInfo.page.get().addListener(new FutureTaskListener<Bitmap>() {
|
|
|
|
|
@Override public void onSuccess(final Bitmap result) {
|
|
|
|
|
Util.runOnMain(new Runnable() {
|
|
|
|
@ -129,22 +122,22 @@ public class EmojiProvider {
|
|
|
|
|
|
|
|
|
|
public class EmojiDrawable extends Drawable {
|
|
|
|
|
private final DrawInfo info;
|
|
|
|
|
private final double width;
|
|
|
|
|
private final double height;
|
|
|
|
|
private Bitmap bmp;
|
|
|
|
|
private float intrinsicWidth;
|
|
|
|
|
private float intrinsicHeight;
|
|
|
|
|
|
|
|
|
|
@Override public int getIntrinsicWidth() {
|
|
|
|
|
return (int)width;
|
|
|
|
|
return (int)intrinsicWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override public int getIntrinsicHeight() {
|
|
|
|
|
return (int)height;
|
|
|
|
|
return (int)intrinsicHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public EmojiDrawable(DrawInfo info, double width, double height) {
|
|
|
|
|
public EmojiDrawable(DrawInfo info, float decodeScale) {
|
|
|
|
|
this.info = info;
|
|
|
|
|
this.width = width;
|
|
|
|
|
this.height = height;
|
|
|
|
|
this.intrinsicWidth = EMOJI_RAW_WIDTH * decodeScale;
|
|
|
|
|
this.intrinsicHeight = EMOJI_RAW_HEIGHT * decodeScale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -157,10 +150,10 @@ public class EmojiProvider {
|
|
|
|
|
final int row_index = info.index % EMOJI_PER_ROW;
|
|
|
|
|
|
|
|
|
|
canvas.drawBitmap(bmp,
|
|
|
|
|
new Rect((int)(row_index * width),
|
|
|
|
|
(int)(row * height + row * verticalPad),
|
|
|
|
|
(int)((row_index + 1) * width),
|
|
|
|
|
(int)((row + 1) * height + row * verticalPad)),
|
|
|
|
|
new Rect((int)(row_index * intrinsicWidth),
|
|
|
|
|
(int)(row * intrinsicHeight + row * verticalPad),
|
|
|
|
|
(int)((row_index + 1) * intrinsicWidth),
|
|
|
|
|
(int)((row + 1) * intrinsicHeight + row * verticalPad)),
|
|
|
|
|
getBounds(),
|
|
|
|
|
paint);
|
|
|
|
|
}
|
|
|
|
@ -253,7 +246,7 @@ public class EmojiProvider {
|
|
|
|
|
try {
|
|
|
|
|
final InputStream measureStream = context.getAssets().open(model.getSprite());
|
|
|
|
|
final InputStream bitmapStream = context.getAssets().open(model.getSprite());
|
|
|
|
|
final Bitmap bitmap = BitmapUtil.createScaledBitmap(measureStream, bitmapStream, (float) drawHeight / (float) EMOJI_RAW_HEIGHT);
|
|
|
|
|
final Bitmap bitmap = BitmapUtil.createScaledBitmap(measureStream, bitmapStream, decodeScale);
|
|
|
|
|
bitmapReference = new SoftReference<>(bitmap);
|
|
|
|
|
Log.w(TAG, "onPageLoaded(" + model.getSprite() + ")");
|
|
|
|
|
return bitmap;
|
|
|
|
|