BitmapJobDrawable.java revision 2ff8d80018c27abdd475a7610ab3d684c4b33acb
1d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckpackage com.android.photos.shims; 2d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 3d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.Bitmap; 4d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.Canvas; 5d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.ColorFilter; 6d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.Matrix; 7d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.Paint; 8d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.PixelFormat; 9d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.Rect; 10d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.graphics.drawable.Drawable; 11d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 12d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.data.MediaItem; 13d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.ui.BitmapLoader; 14d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.util.Future; 15d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.util.FutureListener; 16d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.gallery3d.util.ThreadPool; 172ff8d80018c27abdd475a7610ab3d684c4b33acbJohn Reckimport com.android.photos.data.GalleryBitmapPool; 18d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.photos.drawables.AutoThumbnailDrawable; 19d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 20d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 21d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckpublic class BitmapJobDrawable extends Drawable implements Runnable { 22d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 23d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private ThumbnailLoader mLoader; 24d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private MediaItem mItem; 25d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private Bitmap mBitmap; 26d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private Paint mPaint = new Paint(); 27d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private Matrix mDrawMatrix = new Matrix(); 28d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 29d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public BitmapJobDrawable() { 30d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 31d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 32d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void setMediaItem(MediaItem item) { 33d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (mLoader != null) { 34d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mLoader.cancelLoad(); 35d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 36d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mItem = item; 372ff8d80018c27abdd475a7610ab3d684c4b33acbJohn Reck if (mBitmap != null) { 382ff8d80018c27abdd475a7610ab3d684c4b33acbJohn Reck GalleryBitmapPool.getInstance().put(mBitmap); 392ff8d80018c27abdd475a7610ab3d684c4b33acbJohn Reck mBitmap = null; 402ff8d80018c27abdd475a7610ab3d684c4b33acbJohn Reck } 41d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck // TODO: Figure out why ThumbnailLoader doesn't like to be re-used 42d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mLoader = new ThumbnailLoader(this); 43d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mLoader.startLoad(); 44d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck invalidateSelf(); 45d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 46d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 47d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 48d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void run() { 49d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck Bitmap bitmap = mLoader.getBitmap(); 50d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (bitmap != null) { 51d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mBitmap = bitmap; 52d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck updateDrawMatrix(); 53d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 54d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 55d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 56d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 57d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected void onBoundsChange(Rect bounds) { 58d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck super.onBoundsChange(bounds); 59d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck updateDrawMatrix(); 60d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 61d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 62d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 63d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void draw(Canvas canvas) { 64d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck Rect bounds = getBounds(); 65d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (mBitmap != null) { 66d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.save(); 67d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.clipRect(bounds); 68d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.concat(mDrawMatrix); 69d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.drawBitmap(mBitmap, 0, 0, mPaint); 70d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.restore(); 71d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } else { 72d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mPaint.setColor(0xFFCCCCCC); 73d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck canvas.drawRect(bounds, mPaint); 74d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 75d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 76d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 77d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private void updateDrawMatrix() { 78d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck Rect bounds = getBounds(); 79d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (mBitmap == null || bounds.isEmpty()) { 80d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mDrawMatrix.reset(); 81d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return; 82d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 83d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 84d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck float scale; 85d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck float dx = 0, dy = 0; 86d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 87d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int dwidth = mBitmap.getWidth(); 88d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int dheight = mBitmap.getHeight(); 89d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int vwidth = bounds.width(); 90d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int vheight = bounds.height(); 91d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 92d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck // Calculates a matrix similar to ScaleType.CENTER_CROP 93d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (dwidth * vheight > vwidth * dheight) { 94d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck scale = (float) vheight / (float) dheight; 95d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck dx = (vwidth - dwidth * scale) * 0.5f; 96d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } else { 97d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck scale = (float) vwidth / (float) dwidth; 98d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck dy = (vheight - dheight * scale) * 0.5f; 99d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 100d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 101d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mDrawMatrix.setScale(scale, scale); 102d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); 103d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck invalidateSelf(); 104d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 105d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 106d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 107d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public int getIntrinsicWidth() { 108d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); 109d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 110d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 111d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 112d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public int getIntrinsicHeight() { 113d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); 114d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 115d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 116d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 117d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public int getOpacity() { 118d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck Bitmap bm = mBitmap; 119d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ? 120d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 121d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 122d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 123d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 124d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void setAlpha(int alpha) { 125d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck int oldAlpha = mPaint.getAlpha(); 126d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck if (alpha != oldAlpha) { 127d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mPaint.setAlpha(alpha); 128d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck invalidateSelf(); 129d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 130d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 131d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 132d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 133d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public void setColorFilter(ColorFilter cf) { 134d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mPaint.setColorFilter(cf); 135d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck invalidateSelf(); 136d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 137d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 138d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private static class ThumbnailLoader extends BitmapLoader { 139d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private static final ThreadPool sThreadPool = new ThreadPool(0, 2); 140d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck private BitmapJobDrawable mParent; 141d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 142d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck public ThumbnailLoader(BitmapJobDrawable parent) { 143d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mParent = parent; 144d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 145d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 146d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 147d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { 148d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck return sThreadPool.submit( 149d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mParent.mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this); 150d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 151d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 152d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck @Override 153d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck protected void onLoadComplete(Bitmap bitmap) { 154d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck mParent.scheduleSelf(mParent, 0); 155d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 156d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck } 157d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck 158d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck} 159