diff options
Diffstat (limited to 'src/com/android/photos/shims/BitmapJobDrawable.java')
-rw-r--r-- | src/com/android/photos/shims/BitmapJobDrawable.java | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/com/android/photos/shims/BitmapJobDrawable.java b/src/com/android/photos/shims/BitmapJobDrawable.java new file mode 100644 index 000000000..32dbc8078 --- /dev/null +++ b/src/com/android/photos/shims/BitmapJobDrawable.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013 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.photos.shims; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; + +import com.android.gallery3d.data.MediaItem; +import com.android.gallery3d.ui.BitmapLoader; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.FutureListener; +import com.android.gallery3d.util.ThreadPool; +import com.android.photos.data.GalleryBitmapPool; + + +public class BitmapJobDrawable extends Drawable implements Runnable { + + private ThumbnailLoader mLoader; + private MediaItem mItem; + private Bitmap mBitmap; + private Paint mPaint = new Paint(); + private Matrix mDrawMatrix = new Matrix(); + private int mRotation = 0; + + public BitmapJobDrawable() { + } + + public void setMediaItem(MediaItem item) { + if (mItem == item) return; + + if (mLoader != null) { + mLoader.cancelLoad(); + } + mItem = item; + if (mBitmap != null) { + GalleryBitmapPool.getInstance().put(mBitmap); + mBitmap = null; + } + if (mItem != null) { + // TODO: Figure out why ThumbnailLoader doesn't like to be re-used + mLoader = new ThumbnailLoader(this); + mLoader.startLoad(); + mRotation = mItem.getRotation(); + } + invalidateSelf(); + } + + @Override + public void run() { + Bitmap bitmap = mLoader.getBitmap(); + if (bitmap != null) { + mBitmap = bitmap; + updateDrawMatrix(); + } + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + updateDrawMatrix(); + } + + @Override + public void draw(Canvas canvas) { + Rect bounds = getBounds(); + if (mBitmap != null) { + canvas.save(); + canvas.clipRect(bounds); + canvas.concat(mDrawMatrix); + canvas.rotate(mRotation, bounds.centerX(), bounds.centerY()); + canvas.drawBitmap(mBitmap, 0, 0, mPaint); + canvas.restore(); + } else { + mPaint.setColor(0xFFCCCCCC); + canvas.drawRect(bounds, mPaint); + } + } + + private void updateDrawMatrix() { + Rect bounds = getBounds(); + if (mBitmap == null || bounds.isEmpty()) { + mDrawMatrix.reset(); + return; + } + + float scale; + float dx = 0, dy = 0; + + int dwidth = mBitmap.getWidth(); + int dheight = mBitmap.getHeight(); + int vwidth = bounds.width(); + int vheight = bounds.height(); + + // Calculates a matrix similar to ScaleType.CENTER_CROP + if (dwidth * vheight > vwidth * dheight) { + scale = (float) vheight / (float) dheight; + dx = (vwidth - dwidth * scale) * 0.5f; + } else { + scale = (float) vwidth / (float) dwidth; + dy = (vheight - dheight * scale) * 0.5f; + } + + mDrawMatrix.setScale(scale, scale); + mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); + invalidateSelf(); + } + + @Override + public int getIntrinsicWidth() { + return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); + } + + @Override + public int getIntrinsicHeight() { + return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); + } + + @Override + public int getOpacity() { + Bitmap bm = mBitmap; + return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ? + PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; + } + + @Override + public void setAlpha(int alpha) { + int oldAlpha = mPaint.getAlpha(); + if (alpha != oldAlpha) { + mPaint.setAlpha(alpha); + invalidateSelf(); + } + } + + @Override + public void setColorFilter(ColorFilter cf) { + mPaint.setColorFilter(cf); + invalidateSelf(); + } + + private static class ThumbnailLoader extends BitmapLoader { + private static final ThreadPool sThreadPool = new ThreadPool(0, 2); + private BitmapJobDrawable mParent; + + public ThumbnailLoader(BitmapJobDrawable parent) { + mParent = parent; + } + + @Override + protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { + return sThreadPool.submit( + mParent.mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this); + } + + @Override + protected void onLoadComplete(Bitmap bitmap) { + mParent.scheduleSelf(mParent, 0); + } + } + +} |