/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.fastergallery.ui;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.TextUtils;
import com.android.fastergallery.app.FilterUtils;
import com.android.fastergallery.data.DataSourceType;
import com.android.fastergallery.util.ThreadPool;
import com.android.fastergallery.util.ThreadPool.JobContext;
import com.android.fasterphotos.data.GalleryBitmapPool;
import com.android.fastergallery.R;
public class AlbumTypeLabelMaker {
private static final int BORDER_SIZE = 0;
private final AlbumSetTypeSlotRenderer.LabelSpec mSpec;
private final TextPaint mTitlePaint;
private final TextPaint mCountPaint;
private final Context mContext;
private int mLabelWidth;
private int mBitmapWidth;
private int mBitmapHeight;
private final LazyLoadedBitmap mLocalSetIcon;
private final LazyLoadedBitmap mPicasaIcon;
private final LazyLoadedBitmap mCameraIcon;
public AlbumTypeLabelMaker(Context context, AlbumSetTypeSlotRenderer.LabelSpec spec) {
mContext = context;
mSpec = spec;
mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false);
mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false);
mLocalSetIcon = new LazyLoadedBitmap(
R.drawable.frame_overlay_gallery_folder);
mPicasaIcon = new LazyLoadedBitmap(
R.drawable.frame_overlay_gallery_picasa);
mCameraIcon = new LazyLoadedBitmap(
R.drawable.frame_overlay_gallery_camera);
}
public static int getBorderSize() {
return BORDER_SIZE;
}
private Bitmap getOverlayAlbumIcon(int sourceType) {
switch (sourceType) {
case DataSourceType.TYPE_CAMERA:
return mCameraIcon.get();
case DataSourceType.TYPE_LOCAL:
return mLocalSetIcon.get();
case DataSourceType.TYPE_PICASA:
return mPicasaIcon.get();
}
return null;
}
private static TextPaint getTextPaint(int textSize, int color,
boolean isBold) {
TextPaint paint = new TextPaint();
paint.setTextSize(textSize);
paint.setAntiAlias(true);
paint.setColor(color);
// paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY);
if (isBold) {
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
return paint;
}
private class LazyLoadedBitmap {
private Bitmap mBitmap;
private int mResId;
public LazyLoadedBitmap(int resId) {
mResId = resId;
}
public synchronized Bitmap get() {
if (mBitmap == null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
mBitmap = BitmapFactory.decodeResource(mContext.getResources(),
mResId, options);
}
return mBitmap;
}
}
public synchronized void setLabelWidth(int width, int height) {
if (mLabelWidth == width)
return;
if (AlbumSetTypeManager.get().getCurrentType()
== FilterUtils.CLUSTER_BY_LIST) {
width = width - height;
mLabelWidth = width;
int borders = 2 * BORDER_SIZE;
mBitmapWidth = width + borders;
mBitmapHeight = mSpec.labelBackgroundHeight*2 + borders;
} else {
mLabelWidth = width;
int borders = 2 * BORDER_SIZE;
mBitmapWidth = width + borders;
mBitmapHeight = mSpec.labelBackgroundHeight + borders;
}
}
public ThreadPool.Job<Bitmap> requestLabel(String title, String path,
String count, int sourceType, int type) {
return new AlbumLabelJob(title, path, count, sourceType, type);
}
public ThreadPool.Job<Bitmap> requestLabel(String title, String path,
String count, String filePath, String fileDate, int sourceType, int type) {
return new AlbumLabelJob(title, path, count, filePath, fileDate, sourceType, type);
}
static void drawText(Canvas canvas, int x, int y, String text,
int lengthLimit, TextPaint p) {
// The TextPaint cannot be used concurrently
synchronized (p) {
text = TextUtils.ellipsize(text, p, lengthLimit,
TextUtils.TruncateAt.END).toString();
canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p);
}
}
private class AlbumLabelJob implements ThreadPool.Job<Bitmap> {
private final String mFilePath;
private final String mFileDate;
private final String mTitle;
private final String mCount;
private final int mSourceType;
private final int mViewType;
public AlbumLabelJob(String title, String path, String count,
int sourceType, int type) {
this(title, path, count, "", "", sourceType, type);
}
public AlbumLabelJob(String title, String path, String count, String filePath, String fileDate,
int sourceType, int type) {
mFilePath = (null == filePath) ? "" : filePath;
mFileDate = (null == fileDate) ? "" : fileDate;
mTitle = title;
mCount = count;
mSourceType = sourceType;
mViewType = type;
}
@Override
public Bitmap run(JobContext jc) {
AlbumSetTypeSlotRenderer.LabelSpec s = mSpec;
String filePath = mFilePath;
String fileDate = mFileDate;
String title = mTitle;
String count = mCount;
Bitmap icon = getOverlayAlbumIcon(mSourceType);
Bitmap bitmap;
int labelWidth;
synchronized (this) {
labelWidth = mLabelWidth;
bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth,
mBitmapHeight);
}
if (bitmap == null) {
int borders = 2 * BORDER_SIZE;
int height = s.labelBackgroundHeight + borders;
if (mViewType == FilterUtils.CLUSTER_BY_LIST) {
height = mBitmapHeight;
}
bitmap = Bitmap.createBitmap(labelWidth + borders,
height, Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
canvas.clipRect(BORDER_SIZE, BORDER_SIZE, bitmap.getWidth()
- BORDER_SIZE, bitmap.getHeight() - BORDER_SIZE);
canvas.translate(BORDER_SIZE, BORDER_SIZE);
switch(mViewType) {
case FilterUtils.CLUSTER_BY_LIST:
renderByList(jc, s, canvas, title, count, filePath, fileDate, labelWidth);
break;
case FilterUtils.CLUSTER_BY_TIME:
renderByTime(jc, s, canvas, title, count, labelWidth);
break;
default:
renderByOther(jc, s, canvas, title, count, labelWidth, icon);
break;
}
return bitmap;
}
}
/**
* render list view
* @param jc
* @param s
* @param canvas
* @param title
* @param count
* @param filePath
* @param fileDate
* @param labelWidth
*/
private void renderByList(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String title, String count, String filePath, String fileDate, int labelWidth) {
//清除上次画布内容
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
//draw title
drawTitle(jc, s, canvas, title, labelWidth, 0);
//draw count
drawCount(jc, s, canvas, count, labelWidth);
//draw filePath
drawFilePath(jc, s, canvas, filePath, labelWidth);
//draw fileDate
drawFileDate(jc, s, canvas, fileDate, labelWidth);
}
/**
* render time view
* @param jc
* @param s
* @param canvas
* @param title
* @param count
* @param labelWidth
*/
private void renderByTime(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String title, String count, int labelWidth) {
//draw background
canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
// draw title
drawTitle(jc, s, canvas, title, labelWidth, s.iconSize);
// draw count
drawCount(jc, s, canvas, count, labelWidth);
}
/**
* render other view (exclude time or list view)
* @param jc
* @param s
* @param canvas
* @param title
* @param count
* @param labelWidth
* @param icon
*/
private void renderByOther(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String title, String count, int labelWidth, Bitmap icon) {
//draw background
canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
// draw title
drawTitle(jc, s, canvas, title, labelWidth, s.iconSize);
// draw count
drawCount(jc, s, canvas, count, labelWidth);
// draw the icon
drawIcon(jc, s, canvas, icon);
}
/**
* draw title
* @param jc
* @param s
* @param canvas
* @param title
* @param labelWidth
* @param iconSize
*/
private void drawTitle(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String title, int labelWidth, int iconSize) {
if (jc.isCancelled()) {
return ;
}
int x = s.leftMargin + iconSize;
int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
drawText(canvas, x, y, title, labelWidth - s.leftMargin - x
- s.titleRightMargin, mTitlePaint);
}
/**
* draw count
* @param jc
* @param s
* @param canvas
* @param count
* @param labelWidth
*/
private void drawCount(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String count, int labelWidth) {
if (jc.isCancelled()) {
return ;
}
int x = labelWidth - s.titleRightMargin;
int y = (s.labelBackgroundHeight - s.countFontSize) / 2;
drawText(canvas, x, y, count, labelWidth - x, mCountPaint);
}
/**
* draw icon
* @param jc
* @param s
* @param canvas
* @param icon
*/
private void drawIcon(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, Bitmap icon) {
if (jc.isCancelled()) {
return ;
}
float scale = (float) s.iconSize / icon.getWidth();
canvas.translate(s.leftMargin, (s.labelBackgroundHeight - Math.round(scale * icon.getHeight())) / 2f);
canvas.scale(scale, scale);
canvas.drawBitmap(icon, 0, 0, null);
}
/**
* draw filePath
* @param jc
* @param s
* @param canvas
* @param filePath
* @param labelWidth
*/
private void drawFilePath(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String filePath, int labelWidth) {
if (jc.isCancelled()) {
return ;
}
int offset = (s.labelBackgroundHeight - s.titleFontSize) / 2;
int lineHeight = (mBitmapHeight - offset - 2 * (offset + s.titleFontSize))/2;
int x = s.leftMargin;
int y = offset + s.titleFontSize + lineHeight;
drawText(canvas, x, y, filePath, labelWidth - x, mTitlePaint);
}
/**
* draw fileDate
* @param jc
* @param s
* @param canvas
* @param fileDate
* @param labelWidth
*/
private void drawFileDate(JobContext jc, AlbumSetTypeSlotRenderer.LabelSpec s, Canvas canvas, String fileDate, int labelWidth) {
if (jc.isCancelled()) {
return ;
}
int offset = (s.labelBackgroundHeight - s.titleFontSize) / 2;
int lineHeight = (mBitmapHeight - offset - 2 * (offset + s.titleFontSize))/2;
int x = s.leftMargin;
int y = offset + 2*(s.titleFontSize + lineHeight);
drawText(canvas, x, y, fileDate, labelWidth - x, mTitlePaint);
}
public void recycleLabel(Bitmap label) {
GalleryBitmapPool.getInstance().put(label);
}
}