1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.mail.photomanager; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.content.res.TypedArray; 22 import android.graphics.Bitmap; 23 import android.graphics.BitmapFactory; 24 import android.graphics.Canvas; 25 import android.graphics.Paint.Align; 26 import android.graphics.Rect; 27 import android.graphics.Typeface; 28 import android.text.TextPaint; 29 import android.text.TextUtils; 30 31 import com.android.mail.R; 32 import com.android.mail.ui.ImageCanvas.Dimensions; 33 import com.android.mail.utils.BitmapUtil; 34 import com.android.mail.utils.LogTag; 35 import com.android.mail.utils.LogUtils; 36 37 /** 38 * LetterTileProvider is an implementation of the DefaultImageProvider. When no 39 * matching contact photo is found, and there is a supplied displayName or email 40 * address whose first letter corresponds to an English alphabet letter (or 41 * number), this method creates a bitmap with the letter in the center of a 42 * tile. If there is no English alphabet character (or digit), it creates a 43 * bitmap with the default contact avatar. 44 */ 45 @Deprecated 46 public class LetterTileProvider { 47 private static final String TAG = LogTag.getLogTag(); 48 private final Bitmap mDefaultBitmap; 49 private final Bitmap[] mBitmapBackgroundCache; 50 private final Bitmap[] mDefaultBitmapCache; 51 private final Typeface mSansSerifLight; 52 private final Rect mBounds; 53 private final int mTileLetterFontSize; 54 private final int mTileLetterFontSizeSmall; 55 private final int mTileFontColor; 56 private final TextPaint mPaint = new TextPaint(); 57 private final TypedArray mColors; 58 private final int mColorCount; 59 private final int mDefaultColor; 60 private final Canvas mCanvas = new Canvas(); 61 private final Dimensions mDims = new Dimensions(); 62 private final char[] mFirstChar = new char[1]; 63 64 private static final int POSSIBLE_BITMAP_SIZES = 3; 65 66 public LetterTileProvider(Context context) { 67 final Resources res = context.getResources(); 68 mTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size); 69 mTileLetterFontSizeSmall = res 70 .getDimensionPixelSize(R.dimen.tile_letter_font_size_small); 71 mTileFontColor = res.getColor(R.color.letter_tile_font_color); 72 mSansSerifLight = Typeface.create("sans-serif-light", Typeface.NORMAL); 73 mBounds = new Rect(); 74 mPaint.setTypeface(mSansSerifLight); 75 mPaint.setColor(mTileFontColor); 76 mPaint.setTextAlign(Align.CENTER); 77 mPaint.setAntiAlias(true); 78 mBitmapBackgroundCache = new Bitmap[POSSIBLE_BITMAP_SIZES]; 79 80 mDefaultBitmap = BitmapFactory.decodeResource(res, R.drawable.ic_generic_man); 81 mDefaultBitmapCache = new Bitmap[POSSIBLE_BITMAP_SIZES]; 82 83 mColors = res.obtainTypedArray(R.array.letter_tile_colors); 84 mColorCount = mColors.length(); 85 mDefaultColor = res.getColor(R.color.letter_tile_default_color); 86 } 87 88 public Bitmap getLetterTile(final Dimensions dimensions, final String displayName, 89 final String address) { 90 final String display = !TextUtils.isEmpty(displayName) ? displayName : address; 91 final char firstChar = display.charAt(0); 92 93 // get an empty bitmap 94 final Bitmap bitmap = getBitmap(dimensions, false /* getDefault */); 95 if (bitmap == null) { 96 LogUtils.w(TAG, "LetterTileProvider width(%d) or height(%d) is 0 for name %s and " 97 + "address %s.", dimensions.width, dimensions.height, displayName, address); 98 return null; 99 } 100 101 final Canvas c = mCanvas; 102 c.setBitmap(bitmap); 103 c.drawColor(pickColor(address)); 104 105 // If its a valid English alphabet letter, 106 // draw the letter on top of the color 107 if (isEnglishLetterOrDigit(firstChar)) { 108 mFirstChar[0] = Character.toUpperCase(firstChar); 109 mPaint.setTextSize(getFontSize(dimensions.scale)); 110 mPaint.getTextBounds(mFirstChar, 0, 1, mBounds); 111 c.drawText(mFirstChar, 0, 1, 0 + dimensions.width / 2, 112 0 + dimensions.height / 2 + (mBounds.bottom - mBounds.top) / 2, mPaint); 113 } else { // draw the generic icon on top 114 c.drawBitmap(getBitmap(dimensions, true /* getDefault */), 0, 0, null); 115 } 116 117 return bitmap; 118 } 119 120 private static boolean isEnglishLetterOrDigit(char c) { 121 return ('A' <= c && c <= 'Z') 122 || ('a' <= c && c <= 'z') 123 || ('0' <= c && c <= '9'); 124 } 125 126 private Bitmap getBitmap(final Dimensions d, boolean getDefault) { 127 if (d.width <= 0 || d.height <= 0) { 128 LogUtils.w(TAG, 129 "LetterTileProvider width(%d) or height(%d) is 0.", d.width, d.height); 130 return null; 131 } 132 final int pos; 133 float scale = d.scale; 134 if (scale == Dimensions.SCALE_ONE) { 135 pos = 0; 136 } else if (scale == Dimensions.SCALE_HALF) { 137 pos = 1; 138 } else { 139 pos = 2; 140 } 141 142 final Bitmap[] cache = (getDefault) ? mDefaultBitmapCache : mBitmapBackgroundCache; 143 144 Bitmap bitmap = cache[pos]; 145 // ensure bitmap is suitable for the desired w/h 146 // (two-pane uses two different sets of dimensions depending on pane width) 147 if (bitmap == null || bitmap.getWidth() != d.width || bitmap.getHeight() != d.height) { 148 // create and place the bitmap 149 if (getDefault) { 150 bitmap = BitmapUtil.centerCrop(mDefaultBitmap, d.width, d.height); 151 } else { 152 bitmap = Bitmap.createBitmap(d.width, d.height, Bitmap.Config.ARGB_8888); 153 } 154 cache[pos] = bitmap; 155 } 156 return bitmap; 157 } 158 159 private int getFontSize(float scale) { 160 if (scale == Dimensions.SCALE_ONE) { 161 return mTileLetterFontSize; 162 } else { 163 return mTileLetterFontSizeSmall; 164 } 165 } 166 167 private int pickColor(String emailAddress) { 168 // String.hashCode() implementation is not supposed to change across java versions, so 169 // this should guarantee the same email address always maps to the same color. 170 int color = Math.abs(emailAddress.hashCode()) % mColorCount; 171 return mColors.getColor(color, mDefaultColor); 172 } 173 } 174