1b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang/* 2b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * Copyright (C) 2012 The Android Open Source Project 3b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * 4b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 5b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * you may not use this file except in compliance with the License. 6b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * You may obtain a copy of the License at 7b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * 8b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 9b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * 10b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * Unless required by applicable law or agreed to in writing, software 11b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 12b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * See the License for the specific language governing permissions and 14b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang * limitations under the License. 15b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang */ 161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linpackage com.android.gallery3d.ui; 181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.content.Context; 201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.Bitmap; 211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.Bitmap.Config; 221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.BitmapFactory; 231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.Canvas; 24d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Linimport android.graphics.PorterDuff; 251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.Typeface; 261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.text.TextPaint; 271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.text.TextUtils; 281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.R; 3031cac30e46a293f6d0901e22c6ab0d083cae7021Owen Linimport com.android.gallery3d.data.DataSourceType; 31f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool; 321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.util.ThreadPool; 331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.util.ThreadPool.JobContext; 341a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linpublic class AlbumLabelMaker { 36c90a116a7fd65d41e8258dc7b9a14218649697e6Bobby Georgescu private static final int BORDER_SIZE = 0; 37cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 38c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin private final AlbumSetSlotRenderer.LabelSpec mSpec; 391a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final TextPaint mTitlePaint; 401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final TextPaint mCountPaint; 411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final Context mContext; 421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 43d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private int mLabelWidth; 44f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private int mBitmapWidth; 45f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private int mBitmapHeight; 46d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 471a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final LazyLoadedBitmap mLocalSetIcon; 481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final LazyLoadedBitmap mPicasaIcon; 491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final LazyLoadedBitmap mCameraIcon; 501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 51c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) { 521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mContext = context; 531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mSpec = spec; 54915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false); 55915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false); 561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder); 581a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa); 591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera); 601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 611a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 62cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin public static int getBorderSize() { 63cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin return BORDER_SIZE; 64cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin } 65cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private Bitmap getOverlayAlbumIcon(int sourceType) { 671a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin switch (sourceType) { 6831cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin case DataSourceType.TYPE_CAMERA: 691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return mCameraIcon.get(); 7031cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin case DataSourceType.TYPE_LOCAL: 711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return mLocalSetIcon.get(); 7231cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin case DataSourceType.TYPE_PICASA: 731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return mPicasaIcon.get(); 741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return null; 761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 781a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private static TextPaint getTextPaint(int textSize, int color, boolean isBold) { 791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin TextPaint paint = new TextPaint(); 801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin paint.setTextSize(textSize); 811a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin paint.setAntiAlias(true); 821a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin paint.setColor(color); 83c90a116a7fd65d41e8258dc7b9a14218649697e6Bobby Georgescu //paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY); 841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (isBold) { 851a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); 861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 871a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return paint; 881a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 891a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private class LazyLoadedBitmap { 911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private Bitmap mBitmap; 921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private int mResId; 931a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public LazyLoadedBitmap(int resId) { 951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mResId = resId; 961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public synchronized Bitmap get() { 991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (mBitmap == null) { 1001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin BitmapFactory.Options options = new BitmapFactory.Options(); 1011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 1021a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mBitmap = BitmapFactory.decodeResource( 1031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mContext.getResources(), mResId, options); 1041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return mBitmap; 1061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1071a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 109d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin public synchronized void setLabelWidth(int width) { 110d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin if (mLabelWidth == width) return; 111d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin mLabelWidth = width; 112cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin int borders = 2 * BORDER_SIZE; 113f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu mBitmapWidth = width + borders; 114f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu mBitmapHeight = mSpec.labelBackgroundHeight + borders; 115d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 116d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 1171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public ThreadPool.Job<Bitmap> requestLabel( 118d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin String title, String count, int sourceType) { 1198ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin return new AlbumLabelJob(title, count, sourceType); 1201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1228ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin static void drawText(Canvas canvas, 1231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin int x, int y, String text, int lengthLimit, TextPaint p) { 1241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin // The TextPaint cannot be used concurrently 1251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin synchronized (p) { 1261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin text = TextUtils.ellipsize( 1271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin text, p, lengthLimit, TextUtils.TruncateAt.END).toString(); 1281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p); 1291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private class AlbumLabelJob implements ThreadPool.Job<Bitmap> { 1331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final String mTitle; 1341a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final String mCount; 1351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private final int mSourceType; 1361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1378ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin public AlbumLabelJob(String title, String count, int sourceType) { 1381a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mTitle = title; 1391a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mCount = count; 1401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mSourceType = sourceType; 1411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1431a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin @Override 1441a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public Bitmap run(JobContext jc) { 145c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin AlbumSetSlotRenderer.LabelSpec s = mSpec; 1461a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1478ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin String title = mTitle; 1488ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin String count = mCount; 1491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin Bitmap icon = getOverlayAlbumIcon(mSourceType); 150d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 151cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin Bitmap bitmap; 152d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin int labelWidth; 153d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 154d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin synchronized (this) { 155d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin labelWidth = mLabelWidth; 156f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth, mBitmapHeight); 157d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 158cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 159d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin if (bitmap == null) { 160cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin int borders = 2 * BORDER_SIZE; 161cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin bitmap = Bitmap.createBitmap(labelWidth + borders, 162cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin s.labelBackgroundHeight + borders, Config.ARGB_8888); 163d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 1641a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 165cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin Canvas canvas = new Canvas(bitmap); 166cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin canvas.clipRect(BORDER_SIZE, BORDER_SIZE, 167cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin bitmap.getWidth() - BORDER_SIZE, 168cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin bitmap.getHeight() - BORDER_SIZE); 169915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC); 170cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 171cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin canvas.translate(BORDER_SIZE, BORDER_SIZE); 172cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 1731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin // draw title 1741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (jc.isCancelled()) return null; 175c90a116a7fd65d41e8258dc7b9a14218649697e6Bobby Georgescu int x = s.leftMargin + s.iconSize; 176e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu // TODO: is the offset relevant in new reskin? 177e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu // int y = s.titleOffset; 178e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu int y = (s.labelBackgroundHeight - s.titleFontSize) / 2; 179e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu drawText(canvas, x, y, title, labelWidth - s.leftMargin - x - 180e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu s.titleRightMargin, mTitlePaint); 1811a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 182e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu // draw count 1831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (jc.isCancelled()) return null; 184e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu x = labelWidth - s.titleRightMargin; 185e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu y = (s.labelBackgroundHeight - s.countFontSize) / 2; 1861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin drawText(canvas, x, y, count, 187e24cc7208a6d3760a87dfd4b80a7a6683fe146ebBobby Georgescu labelWidth - x , mCountPaint); 1881a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1891a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin // draw the icon 1901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (icon != null) { 1911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (jc.isCancelled()) return null; 1921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin float scale = (float) s.iconSize / icon.getWidth(); 193c90a116a7fd65d41e8258dc7b9a14218649697e6Bobby Georgescu canvas.translate(s.leftMargin, (s.labelBackgroundHeight - 194c90a116a7fd65d41e8258dc7b9a14218649697e6Bobby Georgescu Math.round(scale * icon.getHeight()))/2f); 1951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin canvas.scale(scale, scale); 1961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin canvas.drawBitmap(icon, 0, 0, null); 1971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 1981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 1991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return bitmap; 2001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 2011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 202d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 203b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang public void recycleLabel(Bitmap label) { 204f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(label); 205d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 2061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin} 207