Extract code to draw fallback contact pictures to a separate class
This commit is contained in:
parent
c787845ebe
commit
e814b5dca0
3 changed files with 76 additions and 160 deletions
|
@ -8,13 +8,8 @@ import android.content.Context;
|
|||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.widget.ImageView;
|
||||
|
||||
|
@ -35,6 +30,7 @@ import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscode
|
|||
import com.bumptech.glide.request.FutureTarget;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.fsck.k9.contacts.ContactLetterBitmapCreator;
|
||||
import com.fsck.k9.contacts.ContactLetterExtractor;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
@ -47,35 +43,12 @@ public class ContactPictureLoader {
|
|||
*/
|
||||
private static final int PICTURE_SIZE = 40;
|
||||
|
||||
private static final ContactLetterExtractor CONTACT_LETTER_EXTRACTOR = new ContactLetterExtractor();
|
||||
|
||||
|
||||
private final Context context;
|
||||
private final ContactLetterBitmapCreator contactLetterBitmapCreator;
|
||||
private Contacts mContactsHelper;
|
||||
private int mPictureSizeInPx;
|
||||
|
||||
private int mDefaultBackgroundColor;
|
||||
|
||||
/**
|
||||
* @see <a href="http://developer.android.com/design/style/color.html">Color palette used</a>
|
||||
*/
|
||||
private final static int CONTACT_DUMMY_COLORS_ARGB[] = {
|
||||
0xff33B5E5,
|
||||
0xffAA66CC,
|
||||
0xff99CC00,
|
||||
0xffFFBB33,
|
||||
0xffFF4444,
|
||||
0xff0099CC,
|
||||
0xff9933CC,
|
||||
0xff669900,
|
||||
0xffFF8800,
|
||||
0xffCC0000
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
protected static String calcUnknownContactLetter(Address address) {
|
||||
return CONTACT_LETTER_EXTRACTOR.extractContactLetter(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -94,8 +67,8 @@ public class ContactPictureLoader {
|
|||
float scale = resources.getDisplayMetrics().density;
|
||||
mPictureSizeInPx = (int) (PICTURE_SIZE * scale);
|
||||
|
||||
mDefaultBackgroundColor = defaultBackgroundColor;
|
||||
|
||||
ContactLetterExtractor contactLetterExtractor = new ContactLetterExtractor();
|
||||
contactLetterBitmapCreator = new ContactLetterBitmapCreator(contactLetterExtractor, defaultBackgroundColor);
|
||||
}
|
||||
|
||||
public void loadContactPicture(final Address address, final ImageView imageView) {
|
||||
|
@ -188,39 +161,6 @@ public class ContactPictureLoader {
|
|||
return loadIgnoringErors(bitmapTarget);
|
||||
}
|
||||
|
||||
private int calcUnknownContactColor(Address address) {
|
||||
if (mDefaultBackgroundColor != 0) {
|
||||
return mDefaultBackgroundColor;
|
||||
}
|
||||
|
||||
int val = address.hashCode();
|
||||
int colorIndex = (val & Integer.MAX_VALUE) % CONTACT_DUMMY_COLORS_ARGB.length;
|
||||
return CONTACT_DUMMY_COLORS_ARGB[colorIndex];
|
||||
}
|
||||
|
||||
private Bitmap drawTextAndBgColorOnBitmap(Bitmap bitmap, FallbackGlideParams params) {
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
int rgb = calcUnknownContactColor(params.address);
|
||||
bitmap.eraseColor(rgb);
|
||||
|
||||
String letter = calcUnknownContactLetter(params.address);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Style.FILL);
|
||||
paint.setARGB(255, 255, 255, 255);
|
||||
paint.setTextSize(mPictureSizeInPx * 3 / 4); // just scale this down a bit
|
||||
Rect rect = new Rect();
|
||||
paint.getTextBounds(letter, 0, 1, rect);
|
||||
float width = paint.measureText(letter);
|
||||
canvas.drawText(letter,
|
||||
(mPictureSizeInPx / 2f) - (width / 2f),
|
||||
(mPictureSizeInPx / 2f) + (rect.height() / 2f), paint);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private class FallbackGlideBitmapDecoder implements ResourceDecoder<FallbackGlideParams, Bitmap> {
|
||||
private final Context context;
|
||||
|
||||
|
@ -235,7 +175,9 @@ public class ContactPictureLoader {
|
|||
if (bitmap == null) {
|
||||
bitmap = Bitmap.createBitmap(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
drawTextAndBgColorOnBitmap(bitmap, source);
|
||||
|
||||
Address address = source.address;
|
||||
contactLetterBitmapCreator.drawBitmap(bitmap, mPictureSizeInPx, address);
|
||||
return BitmapResource.obtain(bitmap, pool);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.fsck.k9.contacts
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import com.fsck.k9.mail.Address
|
||||
|
||||
/**
|
||||
* Draw a `Bitmap` containing the "contact letter" obtained by [ContactLetterExtractor].
|
||||
*
|
||||
* @param defaultBackgroundColor The ARGB value to be used as background color for the fallback picture. `0` to use a
|
||||
* dynamically calculated background color.
|
||||
*/
|
||||
class ContactLetterBitmapCreator(
|
||||
private val letterExtractor: ContactLetterExtractor,
|
||||
private val defaultBackgroundColor: Int
|
||||
) {
|
||||
fun drawBitmap(bitmap: Bitmap, pictureSizeInPx: Int, address: Address): Bitmap {
|
||||
val canvas = Canvas(bitmap)
|
||||
|
||||
val backgroundColor = calcUnknownContactColor(address)
|
||||
bitmap.eraseColor(backgroundColor)
|
||||
|
||||
val letter = letterExtractor.extractContactLetter(address)
|
||||
|
||||
val paint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
style = Paint.Style.FILL
|
||||
setARGB(255, 255, 255, 255)
|
||||
textSize = (pictureSizeInPx * 3 / 4).toFloat() // just scale this down a bit
|
||||
}
|
||||
|
||||
val rect = Rect()
|
||||
paint.getTextBounds(letter, 0, 1, rect)
|
||||
|
||||
val width = paint.measureText(letter)
|
||||
canvas.drawText(letter,
|
||||
pictureSizeInPx / 2f - width / 2f,
|
||||
pictureSizeInPx / 2f + rect.height() / 2f, paint)
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun calcUnknownContactColor(address: Address): Int {
|
||||
if (defaultBackgroundColor != 0) {
|
||||
return defaultBackgroundColor
|
||||
}
|
||||
|
||||
val hash = address.hashCode()
|
||||
val colorIndex = (hash and Integer.MAX_VALUE) % BACKGROUND_COLORS.size
|
||||
return BACKGROUND_COLORS[colorIndex]
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val BACKGROUND_COLORS = intArrayOf(
|
||||
0xff33B5E5L.toInt(),
|
||||
0xffAA66CCL.toInt(),
|
||||
0xff99CC00L.toInt(),
|
||||
0xffFFBB33L.toInt(),
|
||||
0xffFF4444L.toInt(),
|
||||
0xff0099CCL.toInt(),
|
||||
0xff9933CCL.toInt(),
|
||||
0xff669900L.toInt(),
|
||||
0xffFF8800L.toInt(),
|
||||
0xffCC0000L.toInt()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package com.fsck.k9.activity.misc;
|
||||
|
||||
|
||||
import com.fsck.k9.RobolectricTest;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
public class ContactPictureLoaderTest extends RobolectricTest {
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withNoNameUsesAddress() {
|
||||
Address address = new Address("<c@d.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("C", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withAsciiName() {
|
||||
Address address = new Address("abcd <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("A", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withLstroke() {
|
||||
Address address = new Address("Łatynka <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("Ł", result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withChinese() {
|
||||
Address address = new Address("千里之行﹐始于足下 <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("千", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withCombinedGlyphs() {
|
||||
Address address = new Address("\u0061\u0300 <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("\u0041\u0300", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_withSurrogatePair() {
|
||||
Address address = new Address("\uD800\uDFB5 <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("\uD800\uDFB5", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_ignoresSpace() {
|
||||
Address address = new Address(" abcd <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("A", result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_ignoresUsePunctuation() {
|
||||
Address address = new Address("-a <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("A", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calcUnknownContactLetter_ignoresMatchEmoji() {
|
||||
Address address = new Address("\uD83D\uDE00 <a@b.com>");
|
||||
|
||||
String result = ContactPictureLoader.calcUnknownContactLetter(address);
|
||||
|
||||
assertEquals("?", result);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue