Add default cover for no info modes

The improves swiping: before, with no default cover, one just swiped a black
screen with no scrolling feedback, which was rather unintuitive.
This commit is contained in:
Christopher Eby 2011-10-14 16:05:45 -05:00
parent bb39b8677e
commit cd847f4a93
5 changed files with 96 additions and 45 deletions

BIN
orig/default_cover.svgz Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -136,15 +136,18 @@ public final class CoverBitmap {
*/
public static Bitmap createBitmap(Context context, int style, Song song, int width, int height, Bitmap bitmap)
{
if (song == null)
return null;
switch (style) {
case STYLE_OVERLAPPING_BOX:
return createOverlappingBitmap(context, song, width, height, bitmap);
case STYLE_INFO_BELOW:
return createSeparatedBitmap(context, song, width, height, bitmap);
case STYLE_NO_INFO:
return createScaledBitmap(context, song, width, height, bitmap);
return createScaledBitmap(song.getCover(context), width, height, bitmap);
case STYLE_NO_INFO_ZOOMED:
return createZoomedBitmap(context, song, width, height, bitmap);
return createZoomedBitmap(song.getCover(context), width, height, bitmap);
default:
throw new IllegalArgumentException("Invalid bitmap type given: " + style);
}
@ -152,7 +155,7 @@ public final class CoverBitmap {
private static Bitmap createOverlappingBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
{
if (song == null || width < 1 || height < 1)
if (width < 1 || height < 1)
return null;
if (TEXT_SIZE == -1)
@ -246,7 +249,7 @@ public final class CoverBitmap {
private static Bitmap createSeparatedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
{
if (song == null || width < 1 || height < 1)
if (width < 1 || height < 1)
return null;
if (TEXT_SIZE == -1)
@ -346,69 +349,76 @@ public final class CoverBitmap {
return bitmap;
}
private static Bitmap createZoomedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
/**
* Scales a bitmap to completely fill a rectangle of the given size. Aspect
* ratio is preserved, thus, parts of the image will be cut off if the
* aspect ratio of the rectangle does not match that of the source bitmap.
*
* @param source The source bitmap.
* @param width Width of the result
* @param height Height of the result
* @param reuse A bitmap to store the result in if possible
* @return The zoomed bitmap.
*/
public static Bitmap createZoomedBitmap(Bitmap source, int width, int height, Bitmap reuse)
{
if (song == null || width < 1 || height < 1)
if (source == null || width < 1 || height < 1)
return null;
Bitmap cover = song.getCover(context);
if (cover == null)
return null;
Bitmap bitmap = null;
if (bitmap != null && (bitmap.getHeight() != height || bitmap.getWidth() != width)) {
bitmap.recycle();
bitmap = null;
if (reuse != null) {
if (reuse.getHeight() == height && reuse.getWidth() == width)
bitmap = reuse;
else
reuse.recycle();
}
if (bitmap == null)
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
int coverWidth = cover.getWidth();
int coverHeight = cover.getHeight();
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
int size = Math.max(width, height);
float scale = coverWidth < coverHeight ? (float)size / coverWidth : (float)size / coverHeight;
float scale = sourceWidth < sourceHeight ? (float)size / sourceWidth : (float)size / sourceHeight;
int srcWidth = (int)(Math.min(width, coverWidth * scale) / scale);
int srcHeight = (int)(Math.min(height, coverHeight * scale) / scale);
int xOffset = (coverWidth - srcWidth) / 2;
int yOffset = (coverHeight - srcHeight) / 2;
Rect src = new Rect(xOffset, yOffset, coverWidth - xOffset, coverHeight - yOffset);
int srcWidth = (int)(Math.min(width, sourceWidth * scale) / scale);
int srcHeight = (int)(Math.min(height, sourceHeight * scale) / scale);
int xOffset = (sourceWidth - srcWidth) / 2;
int yOffset = (sourceHeight - srcHeight) / 2;
Rect src = new Rect(xOffset, yOffset, sourceWidth - xOffset, sourceHeight - yOffset);
Rect dest = new Rect(0, 0, width, height);
canvas.drawBitmap(cover, src, dest, null);
canvas.drawBitmap(source, src, dest, null);
return bitmap;
}
/**
* Scales a cover to fit in a rectangle of the given size. Aspect ratio is
* Scales a bitmap to fit in a rectangle of the given size. Aspect ratio is
* preserved. At least one dimension of the result will match the provided
* dimension exactly.
*
* @param context A context to use.
* @param song The song to display information for
* @param source The source bitmap.
* @param width Maximum width of image
* @param height Maximum height of image
* @param bitmap A bitmap that will simply be recycled.
* @return The scaled Bitmap, or null if a cover could not be found.
* @param reuse A bitmap that will simply be recycled. (This method does not
* support reuse.)
* @return The scaled bitmap.
*/
private static Bitmap createScaledBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
public static Bitmap createScaledBitmap(Bitmap source, int width, int height, Bitmap reuse)
{
if (song == null || width < 1 || height < 1)
if (source == null || width < 1 || height < 1)
return null;
if (bitmap != null)
bitmap.recycle();
if (reuse != null)
reuse.recycle();
Bitmap cover = song.getCover(context);
if (cover == null)
return null;
int coverWidth = cover.getWidth();
int coverHeight = cover.getHeight();
float scale = Math.min((float)width / coverWidth, (float)height / coverHeight);
coverWidth *= scale;
coverHeight *= scale;
return Bitmap.createScaledBitmap(cover, coverWidth, coverHeight, false);
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
float scale = Math.min((float)width / sourceWidth, (float)height / sourceHeight);
sourceWidth *= scale;
sourceHeight *= scale;
return Bitmap.createScaledBitmap(source, sourceWidth, sourceHeight, false);
}
}

View File

@ -24,6 +24,7 @@ package org.kreed.vanilla;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
@ -75,6 +76,10 @@ public final class CoverView extends View implements Handler.Callback {
* Cache of cover bitmaps generated for songs. The song ids are the keys.
*/
private final Cache<Bitmap> mBitmapCache = new Cache<Bitmap>(8);
/**
* Cover art to use when a song has no cover art in no info display styles.
*/
private Bitmap mDefaultCover;
private final Scroller mScroller;
private VelocityTracker mVelocityTracker;
@ -126,6 +131,32 @@ public final class CoverView extends View implements Handler.Callback {
scrollTo(getWidth(), 0);
}
/**
* Create the cover to show when a song has no cover art. Only used in the
* no info modes.
*
* @return The default cover, now also stored in mDefaultCover.
*/
private Bitmap generateDefaultCover()
{
int style = mCoverStyle;
Bitmap result = null;
if (style == CoverBitmap.STYLE_NO_INFO || style == CoverBitmap.STYLE_NO_INFO_ZOOMED) {
Bitmap def = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.default_cover);
int width = getWidth();
int height = getHeight();
if (style == CoverBitmap.STYLE_NO_INFO)
result = CoverBitmap.createScaledBitmap(def, width, height, null);
else
result = CoverBitmap.createZoomedBitmap(def, width, height, null);
}
mDefaultCover = result;
return result;
}
/**
* Recreate all the necessary cached bitmaps.
*/
@ -137,6 +168,7 @@ public final class CoverView extends View implements Handler.Callback {
((Bitmap)bitmaps[i]).recycle();
bitmaps[i] = null;
}
mDefaultCover = null;
for (int i = 3; --i != -1; )
setSong(i, mSongs[i]);
}
@ -317,12 +349,21 @@ public final class CoverView extends View implements Handler.Callback {
if (song == null || song.id == -1)
return;
Bitmap bitmap = CoverBitmap.createBitmap(getContext(), mCoverStyle, song, getWidth(), getHeight(), mBitmapCache.discardOldest());
if (bitmap != null) {
mBitmaps[i] = bitmap;
mBitmapCache.put(song.id, bitmap);
postInvalidate();
Bitmap reuse = mBitmapCache.discardOldest();
if (reuse == mDefaultCover)
reuse = null;
int style = mCoverStyle;
Bitmap bitmap = CoverBitmap.createBitmap(getContext(), style, song, getWidth(), getHeight(), reuse);
if (bitmap == null && (style == CoverBitmap.STYLE_NO_INFO || style == CoverBitmap.STYLE_NO_INFO_ZOOMED)) {
bitmap = mDefaultCover;
if (bitmap == null)
bitmap = generateDefaultCover();
}
mBitmaps[i] = bitmap;
mBitmapCache.put(song.id, bitmap);
postInvalidate();
}
/**