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