Home | History | Annotate | Download | only in ui
      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