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