mirror of
https://github.com/oxen-io/session-android.git
synced 2025-05-03 06:10:48 +00:00
Split the 'people' emoji spritesheet into multiple chunks.
The aim of this is to help performance by breaking up the single massive spritesheet into smaller ones. This will limit the amount of data that needs to be kept in memory to render emoji. (Hopefully) Fixes #8357
This commit is contained in:
parent
e7c00a3066
commit
28081abe1c
Binary file not shown.
Before Width: | Height: | Size: 5.1 MiB |
BIN
assets/emoji/People_0.png
Normal file
BIN
assets/emoji/People_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
BIN
assets/emoji/People_1.png
Normal file
BIN
assets/emoji/People_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
BIN
assets/emoji/People_2.png
Normal file
BIN
assets/emoji/People_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/emoji/People_3.png
Normal file
BIN
assets/emoji/People_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 692 KiB |
BIN
assets/emoji/Skin Tones.png
Normal file
BIN
assets/emoji/Skin Tones.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1019 B |
@ -0,0 +1,59 @@
|
|||||||
|
package org.thoughtcrime.securesms.components.emoji;
|
||||||
|
|
||||||
|
import android.support.annotation.AttrRes;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CompositeEmojiPageModel implements EmojiPageModel {
|
||||||
|
@AttrRes private final int iconAttr;
|
||||||
|
@NonNull private final EmojiPageModel[] models;
|
||||||
|
|
||||||
|
public CompositeEmojiPageModel(@AttrRes int iconAttr, @NonNull EmojiPageModel... models) {
|
||||||
|
this.iconAttr = iconAttr;
|
||||||
|
this.models = models;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconAttr() {
|
||||||
|
return iconAttr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull List<String> getEmoji() {
|
||||||
|
List<String> emojis = new LinkedList<>();
|
||||||
|
for (EmojiPageModel model : models) {
|
||||||
|
emojis.addAll(model.getEmoji());
|
||||||
|
}
|
||||||
|
return emojis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull List<Emoji> getDisplayEmoji() {
|
||||||
|
List<Emoji> emojis = new LinkedList<>();
|
||||||
|
for (EmojiPageModel model : models) {
|
||||||
|
emojis.addAll(model.getDisplayEmoji());
|
||||||
|
}
|
||||||
|
return emojis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSpriteMap() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getSprite() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDynamic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -128,7 +128,7 @@ public class EmojiDrawer extends LinearLayout implements InputView, EmojiSelecti
|
|||||||
this.models = new LinkedList<>();
|
this.models = new LinkedList<>();
|
||||||
this.recentModel = new RecentEmojiPageModel(getContext());
|
this.recentModel = new RecentEmojiPageModel(getContext());
|
||||||
this.models.add(recentModel);
|
this.models.add(recentModel);
|
||||||
this.models.addAll(EmojiPages.PAGES);
|
this.models.addAll(EmojiPages.DISPLAY_PAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EmojiPagerAdapter extends PagerAdapter
|
public static class EmojiPagerAdapter extends PagerAdapter
|
||||||
|
File diff suppressed because one or more lines are too long
@ -61,7 +61,7 @@ class EmojiProvider {
|
|||||||
this.decodeScale = Math.min(1f, context.getResources().getDimension(R.dimen.emoji_drawer_size) / EMOJI_RAW_HEIGHT);
|
this.decodeScale = Math.min(1f, context.getResources().getDimension(R.dimen.emoji_drawer_size) / EMOJI_RAW_HEIGHT);
|
||||||
this.verticalPad = EMOJI_VERT_PAD * this.decodeScale;
|
this.verticalPad = EMOJI_VERT_PAD * this.decodeScale;
|
||||||
|
|
||||||
for (EmojiPageModel page : EmojiPages.PAGES) {
|
for (EmojiPageModel page : EmojiPages.DATA_PAGES) {
|
||||||
if (page.hasSpriteMap()) {
|
if (page.hasSpriteMap()) {
|
||||||
EmojiPageBitmap pageBitmap = new EmojiPageBitmap(context, page, decodeScale);
|
EmojiPageBitmap pageBitmap = new EmojiPageBitmap(context, page, decodeScale);
|
||||||
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.components.emoji.parsing;
|
package org.thoughtcrime.securesms.components.emoji.parsing;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
@ -11,16 +14,18 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel;
|
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||||
|
import org.thoughtcrime.securesms.util.Stopwatch;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class EmojiPageBitmap {
|
public class EmojiPageBitmap {
|
||||||
|
|
||||||
private static final String TAG = EmojiPageBitmap.class.getName();
|
private static final String TAG = EmojiPageBitmap.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final EmojiPageModel model;
|
private final EmojiPageModel model;
|
||||||
@ -35,6 +40,7 @@ public class EmojiPageBitmap {
|
|||||||
this.decodeScale = decodeScale;
|
this.decodeScale = decodeScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
public ListenableFutureTask<Bitmap> get() {
|
public ListenableFutureTask<Bitmap> get() {
|
||||||
Util.assertMainThread();
|
Util.assertMainThread();
|
||||||
|
|
||||||
@ -70,27 +76,31 @@ public class EmojiPageBitmap {
|
|||||||
private Bitmap loadPage() throws IOException {
|
private Bitmap loadPage() throws IOException {
|
||||||
if (bitmapReference != null && bitmapReference.get() != null) return bitmapReference.get();
|
if (bitmapReference != null && bitmapReference.get() != null) return bitmapReference.get();
|
||||||
|
|
||||||
try {
|
|
||||||
Bitmap originalBitmap = GlideApp.with(context.getApplicationContext())
|
|
||||||
.asBitmap()
|
|
||||||
.load("file:///android_asset/" + model.getSprite())
|
|
||||||
.skipMemoryCache(true)
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
||||||
.submit()
|
|
||||||
.get();
|
|
||||||
|
|
||||||
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, (int)(originalBitmap.getWidth() * decodeScale), (int)(originalBitmap.getHeight() * decodeScale), false);
|
float scale = decodeScale;
|
||||||
|
AssetManager assetManager = context.getAssets();
|
||||||
|
InputStream assetStream = assetManager.open(model.getSprite());
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
|
||||||
bitmapReference = new SoftReference<>(scaledBitmap);
|
if (Util.isLowMemory(context)) {
|
||||||
Log.i(TAG, "onPageLoaded(" + model.getSprite() + ")");
|
Log.i(TAG, "Low memory detected. Changing sample size.");
|
||||||
return scaledBitmap;
|
options.inSampleSize = 2;
|
||||||
} catch (InterruptedException e) {
|
scale = decodeScale * 2;
|
||||||
Log.w(TAG, e);
|
|
||||||
throw new IOException(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stopwatch stopwatch = new Stopwatch(model.getSprite());
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeStream(assetStream, null, options);
|
||||||
|
stopwatch.split("decode");
|
||||||
|
|
||||||
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int)(bitmap.getWidth() * scale), (int)(bitmap.getHeight() * scale), true);
|
||||||
|
stopwatch.split("scale");
|
||||||
|
stopwatch.stop(TAG);
|
||||||
|
|
||||||
|
bitmapReference = new SoftReference<>(scaledBitmap);
|
||||||
|
Log.i(TAG, "onPageLoaded(" + model.getSprite() + ") originalByteCount: " + bitmap.getByteCount()
|
||||||
|
+ " scaledByteCount: " + scaledBitmap.getByteCount()
|
||||||
|
+ " scaledSize: " + scaledBitmap.getWidth() + "x" + scaledBitmap.getHeight());
|
||||||
|
return scaledBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user