AlbumLabelMaker.java revision 8ef6c55bdad9a3e835ce56bdc98681434b4ac5b3
1// Copyright 2012 Google Inc. All Rights Reserved. 2 3package com.android.gallery3d.ui; 4 5import android.content.Context; 6import android.graphics.Bitmap; 7import android.graphics.Bitmap.Config; 8import android.graphics.BitmapFactory; 9import android.graphics.Canvas; 10import android.graphics.Color; 11import android.graphics.PorterDuff; 12import android.graphics.Typeface; 13import android.text.TextPaint; 14import android.text.TextUtils; 15 16import com.android.gallery3d.R; 17import com.android.gallery3d.data.DataSourceType; 18import com.android.gallery3d.util.ThreadPool; 19import com.android.gallery3d.util.ThreadPool.JobContext; 20 21public class AlbumLabelMaker { 22 private static final int FONT_COLOR_TITLE = Color.WHITE; 23 private static final int FONT_COLOR_COUNT = 0x80FFFFFF; // 50% white 24 25 // We keep a border around the album label to prevent aliasing 26 private static final int BORDER_SIZE = 1; 27 private static final int BACKGROUND_COLOR = 0x60000000; // 36% Dark 28 29 private final AlbumSetSlotRenderer.LabelSpec mSpec; 30 private final TextPaint mTitlePaint; 31 private final TextPaint mCountPaint; 32 private final Context mContext; 33 34 private int mLabelWidth; 35 private BitmapPool mBitmapPool; 36 37 private final LazyLoadedBitmap mLocalSetIcon; 38 private final LazyLoadedBitmap mPicasaIcon; 39 private final LazyLoadedBitmap mCameraIcon; 40 private final LazyLoadedBitmap mMtpIcon; 41 42 public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) { 43 mContext = context; 44 mSpec = spec; 45 mTitlePaint = getTextPaint(spec.titleFontSize, FONT_COLOR_TITLE, false); 46 mCountPaint = getTextPaint(spec.countFontSize, FONT_COLOR_COUNT, true); 47 48 mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder); 49 mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa); 50 mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera); 51 mMtpIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_ptp); 52 } 53 54 public static int getBorderSize() { 55 return BORDER_SIZE; 56 } 57 58 private Bitmap getOverlayAlbumIcon(int sourceType) { 59 switch (sourceType) { 60 case DataSourceType.TYPE_CAMERA: 61 return mCameraIcon.get(); 62 case DataSourceType.TYPE_LOCAL: 63 return mLocalSetIcon.get(); 64 case DataSourceType.TYPE_MTP: 65 return mMtpIcon.get(); 66 case DataSourceType.TYPE_PICASA: 67 return mPicasaIcon.get(); 68 } 69 return null; 70 } 71 72 private static TextPaint getTextPaint(int textSize, int color, boolean isBold) { 73 TextPaint paint = new TextPaint(); 74 paint.setTextSize(textSize); 75 paint.setAntiAlias(true); 76 paint.setColor(color); 77 paint.setShadowLayer(2f, 0f, 0f, Color.BLACK); 78 if (isBold) { 79 paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); 80 } 81 return paint; 82 } 83 84 private class LazyLoadedBitmap { 85 private Bitmap mBitmap; 86 private int mResId; 87 88 public LazyLoadedBitmap(int resId) { 89 mResId = resId; 90 } 91 92 public synchronized Bitmap get() { 93 if (mBitmap == null) { 94 BitmapFactory.Options options = new BitmapFactory.Options(); 95 options.inPreferredConfig = Bitmap.Config.ARGB_8888; 96 mBitmap = BitmapFactory.decodeResource( 97 mContext.getResources(), mResId, options); 98 } 99 return mBitmap; 100 } 101 } 102 103 public synchronized void setLabelWidth(int width) { 104 if (mLabelWidth == width) return; 105 mLabelWidth = width; 106 int borders = 2 * BORDER_SIZE; 107 mBitmapPool = new BitmapPool( 108 width + borders, mSpec.labelBackgroundHeight + borders); 109 } 110 111 public ThreadPool.Job<Bitmap> requestLabel( 112 String title, String count, int sourceType) { 113 return new AlbumLabelJob(title, count, sourceType); 114 } 115 116 static void drawText(Canvas canvas, 117 int x, int y, String text, int lengthLimit, TextPaint p) { 118 // The TextPaint cannot be used concurrently 119 synchronized (p) { 120 text = TextUtils.ellipsize( 121 text, p, lengthLimit, TextUtils.TruncateAt.END).toString(); 122 canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p); 123 } 124 } 125 126 private class AlbumLabelJob implements ThreadPool.Job<Bitmap> { 127 private final String mTitle; 128 private final String mCount; 129 private final int mSourceType; 130 131 public AlbumLabelJob(String title, String count, int sourceType) { 132 mTitle = title; 133 mCount = count; 134 mSourceType = sourceType; 135 } 136 137 @Override 138 public Bitmap run(JobContext jc) { 139 AlbumSetSlotRenderer.LabelSpec s = mSpec; 140 141 String title = mTitle; 142 String count = mCount; 143 Bitmap icon = getOverlayAlbumIcon(mSourceType); 144 145 Bitmap bitmap; 146 int labelWidth; 147 148 synchronized (this) { 149 labelWidth = mLabelWidth; 150 bitmap = mBitmapPool.getBitmap(); 151 } 152 153 if (bitmap == null) { 154 int borders = 2 * BORDER_SIZE; 155 bitmap = Bitmap.createBitmap(labelWidth + borders, 156 s.labelBackgroundHeight + borders, Config.ARGB_8888); 157 } 158 159 Canvas canvas = new Canvas(bitmap); 160 canvas.clipRect(BORDER_SIZE, BORDER_SIZE, 161 bitmap.getWidth() - BORDER_SIZE, 162 bitmap.getHeight() - BORDER_SIZE); 163 canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC); 164 165 canvas.translate(BORDER_SIZE, BORDER_SIZE); 166 167 // draw title 168 if (jc.isCancelled()) return null; 169 int x = s.leftMargin; 170 int y = s.titleOffset; 171 drawText(canvas, x, y, title, labelWidth - s.leftMargin, mTitlePaint); 172 173 // draw the count 174 if (jc.isCancelled()) return null; 175 if (icon != null) x = s.iconSize; 176 y += s.titleFontSize + s.countOffset; 177 drawText(canvas, x, y, count, 178 labelWidth - s.leftMargin - s.iconSize, mCountPaint); 179 180 // draw the icon 181 if (icon != null) { 182 if (jc.isCancelled()) return null; 183 float scale = (float) s.iconSize / icon.getWidth(); 184 canvas.translate(0, bitmap.getHeight() 185 - Math.round(scale * icon.getHeight())); 186 canvas.scale(scale, scale); 187 canvas.drawBitmap(icon, 0, 0, null); 188 } 189 190 return bitmap; 191 } 192 } 193 194 public void reycleLabel(Bitmap label) { 195 mBitmapPool.recycle(label); 196 } 197 198 public void clearRecycledLabels() { 199 mBitmapPool.clear(); 200 } 201} 202