Home | History | Annotate | Download | only in photomanager
      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.res.Resources;
     20 import android.graphics.Bitmap;
     21 import android.graphics.BitmapFactory;
     22 import android.graphics.Canvas;
     23 import android.graphics.Paint.Align;
     24 import android.graphics.Rect;
     25 import android.graphics.Typeface;
     26 import android.text.TextPaint;
     27 import android.text.TextUtils;
     28 
     29 import com.android.mail.R;
     30 import com.android.mail.bitmap.ColorPicker;
     31 import com.android.mail.ui.ImageCanvas.Dimensions;
     32 import com.android.mail.utils.BitmapUtil;
     33 import com.android.mail.utils.LogTag;
     34 import com.android.mail.utils.LogUtils;
     35 
     36 /**
     37  * LetterTileProvider is an implementation of the DefaultImageProvider. When no
     38  * matching contact photo is found, and there is a supplied displayName or email
     39  * address whose first letter corresponds to an English alphabet letter (or
     40  * number), this method creates a bitmap with the letter in the center of a
     41  * tile. If there is no English alphabet character (or digit), it creates a
     42  * bitmap with the default contact avatar.
     43  */
     44 public class LetterTileProvider {
     45     private static final String TAG = LogTag.getLogTag();
     46     private final Bitmap mDefaultBitmap;
     47     private final Bitmap[] mBitmapBackgroundCache;
     48     private final Bitmap[] mDefaultBitmapCache;
     49     private final Typeface mSansSerifLight;
     50     private final Rect mBounds;
     51     private final int mTileLetterFontSize;
     52     private final int mTileLetterFontSizeSmall;
     53     private final int mTileFontColor;
     54     private final TextPaint mPaint = new TextPaint();
     55     private final Canvas mCanvas = new Canvas();
     56     private final char[] mFirstChar = new char[1];
     57 
     58     private static final int POSSIBLE_BITMAP_SIZES = 3;
     59     private final ColorPicker mTileColorPicker;
     60 
     61     public LetterTileProvider(Resources res) {
     62         this(res, new ColorPicker.PaletteColorPicker(res));
     63     }
     64 
     65     public LetterTileProvider(Resources res, ColorPicker colorPicker) {
     66         mTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size_small);
     67         mTileLetterFontSizeSmall = res.getDimensionPixelSize(R.dimen.tile_letter_font_size_tiny);
     68         mTileFontColor = res.getColor(R.color.letter_tile_font_color);
     69         mSansSerifLight = Typeface.create("sans-serif-light", Typeface.NORMAL);
     70         mBounds = new Rect();
     71         mPaint.setTypeface(mSansSerifLight);
     72         mPaint.setColor(mTileFontColor);
     73         mPaint.setTextAlign(Align.CENTER);
     74         mPaint.setAntiAlias(true);
     75         mBitmapBackgroundCache = new Bitmap[POSSIBLE_BITMAP_SIZES];
     76 
     77         mDefaultBitmap = BitmapFactory.decodeResource(res, R.drawable.ic_anonymous_avatar_40dp);
     78         mDefaultBitmapCache = new Bitmap[POSSIBLE_BITMAP_SIZES];
     79 
     80         mTileColorPicker = colorPicker;
     81     }
     82 
     83     public Bitmap getLetterTile(final Dimensions dimensions, final String displayName,
     84             final String address) {
     85         final String display = !TextUtils.isEmpty(displayName) ? displayName : address;
     86         final char firstChar = display.charAt(0);
     87 
     88         // get an empty bitmap
     89         final Bitmap bitmap = getBitmap(dimensions, false /* getDefault */);
     90         if (bitmap == null) {
     91             LogUtils.w(TAG, "LetterTileProvider width(%d) or height(%d) is 0 for name %s and "
     92                     + "address %s.", dimensions.width, dimensions.height, displayName, address);
     93             return null;
     94         }
     95 
     96         final Canvas c = mCanvas;
     97         c.setBitmap(bitmap);
     98         c.drawColor(mTileColorPicker.pickColor(address));
     99 
    100         // If its a valid English alphabet letter,
    101         // draw the letter on top of the color
    102         if (isEnglishLetterOrDigit(firstChar)) {
    103             mFirstChar[0] = Character.toUpperCase(firstChar);
    104             mPaint.setTextSize(
    105                     dimensions.fontSize > 0 ? dimensions.fontSize : getFontSize(dimensions.scale));
    106             mPaint.getTextBounds(mFirstChar, 0, 1, mBounds);
    107             c.drawText(mFirstChar, 0, 1, 0 + dimensions.width / 2,
    108                     0 + dimensions.height / 2 + (mBounds.bottom - mBounds.top) / 2, mPaint);
    109         } else { // draw the generic icon on top
    110             c.drawBitmap(getBitmap(dimensions, true /* getDefault */), 0, 0, null);
    111         }
    112 
    113         return bitmap;
    114     }
    115 
    116     private static boolean isEnglishLetterOrDigit(char c) {
    117         return ('A' <= c && c <= 'Z')
    118                 || ('a' <= c && c <= 'z')
    119                 || ('0' <= c && c <= '9');
    120     }
    121 
    122     private Bitmap getBitmap(final Dimensions d, boolean getDefault) {
    123         if (d.width <= 0 || d.height <= 0) {
    124             LogUtils.w(TAG,
    125                     "LetterTileProvider width(%d) or height(%d) is 0.", d.width, d.height);
    126             return null;
    127         }
    128         final int pos;
    129         float scale = d.scale;
    130         if (scale == Dimensions.SCALE_ONE) {
    131             pos = 0;
    132         } else if (scale == Dimensions.SCALE_HALF) {
    133             pos = 1;
    134         } else {
    135             pos = 2;
    136         }
    137 
    138         final Bitmap[] cache = (getDefault) ? mDefaultBitmapCache : mBitmapBackgroundCache;
    139 
    140         Bitmap bitmap = cache[pos];
    141         // ensure bitmap is suitable for the desired w/h
    142         // (two-pane uses two different sets of dimensions depending on pane width)
    143         if (bitmap == null || bitmap.getWidth() != d.width || bitmap.getHeight() != d.height) {
    144             // create and place the bitmap
    145             if (getDefault) {
    146                 bitmap = BitmapUtil.centerCrop(mDefaultBitmap, d.width, d.height);
    147             } else {
    148                 bitmap = Bitmap.createBitmap(d.width, d.height, Bitmap.Config.ARGB_8888);
    149             }
    150             cache[pos] = bitmap;
    151         }
    152         return bitmap;
    153     }
    154 
    155     private int getFontSize(float scale)  {
    156         if (scale == Dimensions.SCALE_ONE) {
    157             return mTileLetterFontSize;
    158         } else {
    159             return mTileLetterFontSizeSmall;
    160         }
    161     }
    162 }
    163