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