From 030f8dad6aefc42d0af39bc1b93f370937d3e2ab Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Thu, 11 Oct 2012 15:50:38 +0800 Subject: [PATCH] Fixes bugs in TiledTexture. 1. Upload tiles in SinglePhotoDataAdapter 2. Rebuild the upload queue after the screen nails being recycled bug: 6399444 Change-Id: I57e756f8d1d84742bf82dd34c83baf8df89ae4cc --- src/com/android/gallery3d/app/CropImage.java | 21 +- .../android/gallery3d/app/PhotoDataAdapter.java | 21 +- src/com/android/gallery3d/app/PhotoPage.java | 6 +- .../gallery3d/app/SinglePhotoDataAdapter.java | 11 ++ src/com/android/gallery3d/ui/BitmapScreenNail.java | 180 ++--------------- src/com/android/gallery3d/ui/PhotoView.java | 8 +- src/com/android/gallery3d/ui/TileImageView.java | 4 +- .../android/gallery3d/ui/TileImageViewAdapter.java | 32 +-- src/com/android/gallery3d/ui/TiledScreenNail.java | 216 +++++++++++++++++++++ src/com/android/gallery3d/util/GalleryUtils.java | 6 +- 10 files changed, 283 insertions(+), 222 deletions(-) create mode 100644 src/com/android/gallery3d/ui/TiledScreenNail.java diff --git a/src/com/android/gallery3d/app/CropImage.java b/src/com/android/gallery3d/app/CropImage.java index 2b7450441..89ca63d44 100644 --- a/src/com/android/gallery3d/app/CropImage.java +++ b/src/com/android/gallery3d/app/CropImage.java @@ -61,6 +61,7 @@ import com.android.gallery3d.exif.ExifOutputStream; import com.android.gallery3d.exif.ExifReader; import com.android.gallery3d.exif.ExifTag; import com.android.gallery3d.picasasource.PicasaSource; +import com.android.gallery3d.ui.BitmapScreenNail; import com.android.gallery3d.ui.BitmapTileProvider; import com.android.gallery3d.ui.CropView; import com.android.gallery3d.ui.GLRoot; @@ -151,6 +152,7 @@ public class CropImage extends AbstractGalleryActivity { private BitmapRegionDecoder mRegionDecoder; private Bitmap mBitmapInIntent; private boolean mUseRegionDecoder = false; + private BitmapScreenNail mBitmapScreenNail; private ProgressDialog mProgressDialog; private Future mLoadTask; @@ -813,8 +815,14 @@ public class CropImage extends AbstractGalleryActivity { BitmapUtils.UNCONSTRAINED, BACKUP_PIXEL_COUNT); mBitmap = regionDecoder.decodeRegion( new Rect(0, 0, width, height), options); - mCropView.setDataModel(new TileImageViewAdapter( - mBitmap, regionDecoder), mMediaItem.getFullImageRotation()); + + mBitmapScreenNail = new BitmapScreenNail(mBitmap); + + TileImageViewAdapter adapter = new TileImageViewAdapter(); + adapter.setScreenNail(mBitmapScreenNail, width, height); + adapter.setRegionDecoder(regionDecoder); + + mCropView.setDataModel(adapter, mMediaItem.getFullImageRotation()); if (mDoFaceDetection) { mCropView.detectFaces(mBitmap); } else { @@ -976,6 +984,15 @@ public class CropImage extends AbstractGalleryActivity { } } + @Override + protected void onDestroy() { + super.onDestroy(); + if (mBitmapScreenNail != null) { + mBitmapScreenNail.recycle(); + mBitmapScreenNail = null; + } + } + private void dismissProgressDialogIfShown() { if (mProgressDialog != null) { mProgressDialog.dismiss(); diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index 5ab022ac6..20f15be10 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -30,11 +30,11 @@ import com.android.gallery3d.data.MediaItem; import com.android.gallery3d.data.MediaObject; import com.android.gallery3d.data.MediaSet; import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.BitmapScreenNail; import com.android.gallery3d.ui.PhotoView; import com.android.gallery3d.ui.ScreenNail; import com.android.gallery3d.ui.SynchronizedHandler; import com.android.gallery3d.ui.TileImageViewAdapter; +import com.android.gallery3d.ui.TiledScreenNail; import com.android.gallery3d.ui.TiledTexture; import com.android.gallery3d.util.Future; import com.android.gallery3d.util.FutureListener; @@ -305,8 +305,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { entry.screenNailTask = null; // Combine the ScreenNails if we already have a BitmapScreenNail - if (entry.screenNail instanceof BitmapScreenNail) { - BitmapScreenNail original = (BitmapScreenNail) entry.screenNail; + if (entry.screenNail instanceof TiledScreenNail) { + TiledScreenNail original = (TiledScreenNail) entry.screenNail; screenNail = original.combine(screenNail); } @@ -404,7 +404,6 @@ public class PhotoDataAdapter implements PhotoPage.Model { updateImageCache(); updateImageRequests(); updateTileProvider(); - updateScreenNailUploadQueue(); if (mDataListener != null) { mDataListener.onPhotoChanged(index, mItemPath); @@ -424,8 +423,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { if (e == null) return; ScreenNail s = e.screenNail; - if (s instanceof BitmapScreenNail) { - TiledTexture t = ((BitmapScreenNail) s).getTexture(); + if (s instanceof TiledScreenNail) { + TiledTexture t = ((TiledScreenNail) s).getTexture(); if (t != null && !t.isReady()) mUploader.addTexture(t); } } @@ -717,7 +716,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { bitmap = BitmapUtils.rotateBitmap(bitmap, mItem.getRotation() - mItem.getFullImageRotation(), true); } - return bitmap == null ? null : new BitmapScreenNail(bitmap); + return bitmap == null ? null : new TiledScreenNail(bitmap); } } @@ -766,7 +765,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { private ScreenNail newPlaceholderScreenNail(MediaItem item) { int width = item.getWidth(); int height = item.getHeight(); - return new BitmapScreenNail(width, height); + return new TiledScreenNail(width, height); } // Returns the task if we started the task or the task is already started. @@ -828,8 +827,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { if (entry.requestedScreenNail != item.getDataVersion()) { // This ScreenNail is outdated, we want to update it if it's // still a placeholder. - if (entry.screenNail instanceof BitmapScreenNail) { - BitmapScreenNail s = (BitmapScreenNail) entry.screenNail; + if (entry.screenNail instanceof TiledScreenNail) { + TiledScreenNail s = (TiledScreenNail) entry.screenNail; s.updatePlaceholderSize( item.getWidth(), item.getHeight()); } @@ -847,6 +846,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { if (entry.screenNailTask != null) entry.screenNailTask.cancel(); if (entry.screenNail != null) entry.screenNail.recycle(); } + + updateScreenNailUploadQueue(); } private class FullImageListener diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index b11229f88..8d6bc60ac 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -61,7 +61,7 @@ import com.android.gallery3d.data.SnailItem; import com.android.gallery3d.data.SnailSource; import com.android.gallery3d.picasasource.PicasaSource; import com.android.gallery3d.ui.AnimationTime; -import com.android.gallery3d.ui.BitmapScreenNail; +import com.android.gallery3d.ui.TiledScreenNail; import com.android.gallery3d.ui.DetailsHelper; import com.android.gallery3d.ui.DetailsHelper.CloseListener; import com.android.gallery3d.ui.DetailsHelper.DetailsSource; @@ -269,7 +269,7 @@ public class PhotoPage extends ActivityState implements if (!mBackgroundFade.isActive()) { mFadeOutTexture = null; mOpenAnimationRect = null; - BitmapScreenNail.enableDrawPlaceholder(); + TiledScreenNail.enableDrawPlaceholder(); } else { float fadeAlpha = mBackgroundFade.get(); if (fadeAlpha < 1f) { @@ -1372,7 +1372,7 @@ public class PhotoPage extends ActivityState implements mFadeOutTexture = transitions.get(PreparePageFadeoutTexture.KEY_FADE_TEXTURE); if (mFadeOutTexture != null) { mBackgroundFade.start(); - BitmapScreenNail.disableDrawPlaceholder(); + TiledScreenNail.disableDrawPlaceholder(); mOpenAnimationRect = albumPageTransition == MSG_ALBUMPAGE_NONE ? (Rect) mData.getParcelable(KEY_OPEN_ANIMATION_RECT) : diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java index 2f6f16f3a..00f2fe78f 100644 --- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java @@ -27,6 +27,7 @@ import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.common.Utils; import com.android.gallery3d.data.MediaItem; import com.android.gallery3d.data.Path; +import com.android.gallery3d.ui.BitmapScreenNail; import com.android.gallery3d.ui.PhotoView; import com.android.gallery3d.ui.ScreenNail; import com.android.gallery3d.ui.SynchronizedHandler; @@ -50,6 +51,7 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter private PhotoView mPhotoView; private ThreadPool mThreadPool; private int mLoadingState = LOADING_INIT; + private BitmapScreenNail mBitmapScreenNail; public SinglePhotoDataAdapter( AbstractGalleryActivity activity, PhotoView view, MediaItem item) { @@ -113,6 +115,11 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter return false; } + private void setScreenNail(Bitmap bitmap, int width, int height) { + mBitmapScreenNail = new BitmapScreenNail(bitmap); + setScreenNail(mBitmapScreenNail, width, height); + } + private void onDecodeLargeComplete(ImageBundle bundle) { try { setScreenNail(bundle.backupImage, @@ -162,6 +169,10 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter if (task.get() == null) { mTask = null; } + if (mBitmapScreenNail != null) { + mBitmapScreenNail.recycle(); + mBitmapScreenNail = null; + } } @Override diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java index 9b629160c..741eefbe3 100644 --- a/src/com/android/gallery3d/ui/BitmapScreenNail.java +++ b/src/com/android/gallery3d/ui/BitmapScreenNail.java @@ -19,198 +19,40 @@ package com.android.gallery3d.ui; import android.graphics.Bitmap; import android.graphics.RectF; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.BitmapPool; -import com.android.gallery3d.data.MediaItem; - -// This is a ScreenNail wraps a Bitmap. There are some extra functions: -// -// - If we need to draw before the bitmap is available, we draw a rectange of -// placeholder color (gray). -// -// - When the the bitmap is available, and we have drawn the placeholder color -// before, we will do a fade-in animation. public class BitmapScreenNail implements ScreenNail { - @SuppressWarnings("unused") - private static final String TAG = "BitmapScreenNail"; - - // The duration of the fading animation in milliseconds - private static final int DURATION = 180; - - private static int sMaxSide = 640; - - // These are special values for mAnimationStartTime - private static final long ANIMATION_NOT_NEEDED = -1; - private static final long ANIMATION_NEEDED = -2; - private static final long ANIMATION_DONE = -3; - - private int mWidth; - private int mHeight; - private long mAnimationStartTime = ANIMATION_NOT_NEEDED; - - private Bitmap mBitmap; - private TiledTexture mTexture; + private final BitmapTexture mBitmapTexture; public BitmapScreenNail(Bitmap bitmap) { - mWidth = bitmap.getWidth(); - mHeight = bitmap.getHeight(); - mBitmap = bitmap; - mTexture = new TiledTexture(bitmap); - } - - public BitmapScreenNail(int width, int height) { - setSize(width, height); - } - - // This gets overridden by bitmap_screennail_placeholder - // in GalleryUtils.initialize - private static int mPlaceholderColor = 0xFF222222; - private static boolean mDrawPlaceholder = true; - - public static void setPlaceholderColor(int color) { - mPlaceholderColor = color; - } - - private void setSize(int width, int height) { - if (width == 0 || height == 0) { - width = sMaxSide; - height = sMaxSide * 3 / 4; - } - float scale = Math.min(1, (float) sMaxSide / Math.max(width, height)); - mWidth = Math.round(scale * width); - mHeight = Math.round(scale * height); - } - - private static void recycleBitmap(BitmapPool pool, Bitmap bitmap) { - if (pool == null || bitmap == null) return; - pool.recycle(bitmap); - } - - // Combines the two ScreenNails. - // Returns the used one and recycle the unused one. - public ScreenNail combine(ScreenNail other) { - if (other == null) { - return this; - } - - if (!(other instanceof BitmapScreenNail)) { - recycle(); - return other; - } - - // Now both are BitmapScreenNail. Move over the information about width, - // height, and Bitmap, then recycle the other. - BitmapScreenNail newer = (BitmapScreenNail) other; - mWidth = newer.mWidth; - mHeight = newer.mHeight; - if (newer.mTexture != null) { - recycleBitmap(MediaItem.getThumbPool(), mBitmap); - if (mTexture != null) mTexture.recycle(); - mBitmap = newer.mBitmap; - mTexture = newer.mTexture; - newer.mBitmap = null; - newer.mTexture = null; - } - newer.recycle(); - return this; - } - - public void updatePlaceholderSize(int width, int height) { - if (mBitmap != null) return; - if (width == 0 || height == 0) return; - setSize(width, height); + mBitmapTexture = new BitmapTexture(bitmap); } @Override public int getWidth() { - return mWidth; + return mBitmapTexture.getWidth(); } @Override public int getHeight() { - return mHeight; + return mBitmapTexture.getHeight(); } @Override - public void noDraw() { + public void draw(GLCanvas canvas, int x, int y, int width, int height) { + mBitmapTexture.draw(canvas, x, y, width, height); } @Override - public void recycle() { - if (mTexture != null) { - mTexture.recycle(); - mTexture = null; - } - recycleBitmap(MediaItem.getThumbPool(), mBitmap); - mBitmap = null; - } - - public static void disableDrawPlaceholder() { - mDrawPlaceholder = false; - } - - public static void enableDrawPlaceholder() { - mDrawPlaceholder = true; + public void noDraw() { + // do nothing } @Override - public void draw(GLCanvas canvas, int x, int y, int width, int height) { - if (mTexture == null || !mTexture.isReady()) { - if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { - mAnimationStartTime = ANIMATION_NEEDED; - } - if(mDrawPlaceholder) { - canvas.fillRect(x, y, width, height, mPlaceholderColor); - } - return; - } - - if (mAnimationStartTime == ANIMATION_NEEDED) { - mAnimationStartTime = AnimationTime.get(); - } - - if (isAnimating()) { - mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, - width, height); - } else { - mTexture.draw(canvas, x, y, width, height); - } + public void recycle() { + mBitmapTexture.recycle(); } @Override public void draw(GLCanvas canvas, RectF source, RectF dest) { - if (mTexture == null || !mTexture.isReady()) { - canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), - mPlaceholderColor); - return; - } - - mTexture.draw(canvas, source, dest); - } - - public boolean isAnimating() { - if (mAnimationStartTime < 0) return false; - if (AnimationTime.get() - mAnimationStartTime >= DURATION) { - mAnimationStartTime = ANIMATION_DONE; - return false; - } - return true; - } - - private float getRatio() { - float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; - return Utils.clamp(1.0f - r, 0.0f, 1.0f); - } - - public boolean isShowingPlaceholder() { - return (mBitmap == null) || isAnimating(); - } - - public TiledTexture getTexture() { - return mTexture; - } - - public static void setMaxSide(int size) { - sMaxSide = size; + canvas.drawTexture(mBitmapTexture, source, dest); } } diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index c6bf535db..edd7c72e3 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -850,8 +850,8 @@ public class PhotoView extends GLView { } private boolean isScreenNailAnimating() { - return (mScreenNail instanceof BitmapScreenNail) - && ((BitmapScreenNail) mScreenNail).isAnimating(); + return (mScreenNail instanceof TiledScreenNail) + && ((TiledScreenNail) mScreenNail).isAnimating(); } @Override @@ -1792,8 +1792,8 @@ public class PhotoView extends GLView { MediaItem item = mModel.getMediaItem(i); if (item == null) continue; ScreenNail sc = mModel.getScreenNail(i); - if (!(sc instanceof BitmapScreenNail) - || ((BitmapScreenNail) sc).isShowingPlaceholder()) continue; + if (!(sc instanceof TiledScreenNail) + || ((TiledScreenNail) sc).isShowingPlaceholder()) continue; // Now, sc is BitmapScreenNail and is not showing placeholder Rect rect = new Rect(getPhotoRect(i)); diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java index 18a7af849..8f26981fe 100644 --- a/src/com/android/gallery3d/ui/TileImageView.java +++ b/src/com/android/gallery3d/ui/TileImageView.java @@ -462,8 +462,8 @@ public class TileImageView extends GLView { } private boolean isScreenNailAnimating() { - return (mScreenNail instanceof BitmapScreenNail) - && ((BitmapScreenNail) mScreenNail).isAnimating(); + return (mScreenNail instanceof TiledScreenNail) + && ((TiledScreenNail) mScreenNail).isAnimating(); } private void uploadBackgroundTiles(GLCanvas canvas) { diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java index 08d337921..45e2ce218 100644 --- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java +++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java @@ -40,51 +40,25 @@ public class TileImageViewAdapter implements TileImageView.Model { public TileImageViewAdapter() { } - public TileImageViewAdapter( - Bitmap bitmap, BitmapRegionDecoder regionDecoder) { - Utils.checkNotNull(bitmap); - updateScreenNail(new BitmapScreenNail(bitmap), true); - mRegionDecoder = regionDecoder; - mImageWidth = regionDecoder.getWidth(); - mImageHeight = regionDecoder.getHeight(); - mLevelCount = calculateLevelCount(); - } - public synchronized void clear() { - updateScreenNail(null, false); + mScreenNail = null; mImageWidth = 0; mImageHeight = 0; mLevelCount = 0; mRegionDecoder = null; } - public synchronized void setScreenNail(Bitmap bitmap, int width, int height) { - Utils.checkNotNull(bitmap); - updateScreenNail(new BitmapScreenNail(bitmap), true); - mImageWidth = width; - mImageHeight = height; - mRegionDecoder = null; - mLevelCount = 0; - } - + // Caller is responsible to recycle the ScreenNail public synchronized void setScreenNail( ScreenNail screenNail, int width, int height) { Utils.checkNotNull(screenNail); - updateScreenNail(screenNail, false); + mScreenNail = screenNail; mImageWidth = width; mImageHeight = height; mRegionDecoder = null; mLevelCount = 0; } - private void updateScreenNail(ScreenNail screenNail, boolean own) { - if (mScreenNail != null && mOwnScreenNail) { - mScreenNail.recycle(); - } - mScreenNail = screenNail; - mOwnScreenNail = own; - } - public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) { mRegionDecoder = Utils.checkNotNull(decoder); mImageWidth = decoder.getWidth(); diff --git a/src/com/android/gallery3d/ui/TiledScreenNail.java b/src/com/android/gallery3d/ui/TiledScreenNail.java new file mode 100644 index 000000000..d2b34e3bf --- /dev/null +++ b/src/com/android/gallery3d/ui/TiledScreenNail.java @@ -0,0 +1,216 @@ +/* + * 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.gallery3d.ui; + +import android.graphics.Bitmap; +import android.graphics.RectF; + +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.data.BitmapPool; +import com.android.gallery3d.data.MediaItem; + +// This is a ScreenNail wraps a Bitmap. There are some extra functions: +// +// - If we need to draw before the bitmap is available, we draw a rectange of +// placeholder color (gray). +// +// - When the the bitmap is available, and we have drawn the placeholder color +// before, we will do a fade-in animation. +public class TiledScreenNail implements ScreenNail { + @SuppressWarnings("unused") + private static final String TAG = "TiledScreenNail"; + + // The duration of the fading animation in milliseconds + private static final int DURATION = 180; + + private static int sMaxSide = 640; + + // These are special values for mAnimationStartTime + private static final long ANIMATION_NOT_NEEDED = -1; + private static final long ANIMATION_NEEDED = -2; + private static final long ANIMATION_DONE = -3; + + private int mWidth; + private int mHeight; + private long mAnimationStartTime = ANIMATION_NOT_NEEDED; + + private Bitmap mBitmap; + private TiledTexture mTexture; + + public TiledScreenNail(Bitmap bitmap) { + mWidth = bitmap.getWidth(); + mHeight = bitmap.getHeight(); + mBitmap = bitmap; + mTexture = new TiledTexture(bitmap); + } + + public TiledScreenNail(int width, int height) { + setSize(width, height); + } + + // This gets overridden by bitmap_screennail_placeholder + // in GalleryUtils.initialize + private static int mPlaceholderColor = 0xFF222222; + private static boolean mDrawPlaceholder = true; + + public static void setPlaceholderColor(int color) { + mPlaceholderColor = color; + } + + private void setSize(int width, int height) { + if (width == 0 || height == 0) { + width = sMaxSide; + height = sMaxSide * 3 / 4; + } + float scale = Math.min(1, (float) sMaxSide / Math.max(width, height)); + mWidth = Math.round(scale * width); + mHeight = Math.round(scale * height); + } + + private static void recycleBitmap(BitmapPool pool, Bitmap bitmap) { + if (pool == null || bitmap == null) return; + pool.recycle(bitmap); + } + + // Combines the two ScreenNails. + // Returns the used one and recycle the unused one. + public ScreenNail combine(ScreenNail other) { + if (other == null) { + return this; + } + + if (!(other instanceof TiledScreenNail)) { + recycle(); + return other; + } + + // Now both are TiledScreenNail. Move over the information about width, + // height, and Bitmap, then recycle the other. + TiledScreenNail newer = (TiledScreenNail) other; + mWidth = newer.mWidth; + mHeight = newer.mHeight; + if (newer.mTexture != null) { + recycleBitmap(MediaItem.getThumbPool(), mBitmap); + if (mTexture != null) mTexture.recycle(); + mBitmap = newer.mBitmap; + mTexture = newer.mTexture; + newer.mBitmap = null; + newer.mTexture = null; + } + newer.recycle(); + return this; + } + + public void updatePlaceholderSize(int width, int height) { + if (mBitmap != null) return; + if (width == 0 || height == 0) return; + setSize(width, height); + } + + @Override + public int getWidth() { + return mWidth; + } + + @Override + public int getHeight() { + return mHeight; + } + + @Override + public void noDraw() { + } + + @Override + public void recycle() { + if (mTexture != null) { + mTexture.recycle(); + mTexture = null; + } + recycleBitmap(MediaItem.getThumbPool(), mBitmap); + mBitmap = null; + } + + public static void disableDrawPlaceholder() { + mDrawPlaceholder = false; + } + + public static void enableDrawPlaceholder() { + mDrawPlaceholder = true; + } + + @Override + public void draw(GLCanvas canvas, int x, int y, int width, int height) { + if (mTexture == null || !mTexture.isReady()) { + if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { + mAnimationStartTime = ANIMATION_NEEDED; + } + if(mDrawPlaceholder) { + canvas.fillRect(x, y, width, height, mPlaceholderColor); + } + return; + } + + if (mAnimationStartTime == ANIMATION_NEEDED) { + mAnimationStartTime = AnimationTime.get(); + } + + if (isAnimating()) { + mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, + width, height); + } else { + mTexture.draw(canvas, x, y, width, height); + } + } + + @Override + public void draw(GLCanvas canvas, RectF source, RectF dest) { + if (mTexture == null || !mTexture.isReady()) { + canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), + mPlaceholderColor); + return; + } + + mTexture.draw(canvas, source, dest); + } + + public boolean isAnimating() { + if (mAnimationStartTime < 0) return false; + if (AnimationTime.get() - mAnimationStartTime >= DURATION) { + mAnimationStartTime = ANIMATION_DONE; + return false; + } + return true; + } + + private float getRatio() { + float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; + return Utils.clamp(1.0f - r, 0.0f, 1.0f); + } + + public boolean isShowingPlaceholder() { + return (mBitmap == null) || isAnimating(); + } + + public TiledTexture getTexture() { + return mTexture; + } + + public static void setMaxSide(int size) { + sMaxSide = size; + } +} diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java index 195552116..62f22355e 100644 --- a/src/com/android/gallery3d/util/GalleryUtils.java +++ b/src/com/android/gallery3d/util/GalleryUtils.java @@ -42,7 +42,7 @@ import com.android.gallery3d.app.PackagesMonitor; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.ui.BitmapScreenNail; +import com.android.gallery3d.ui.TiledScreenNail; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; @@ -81,7 +81,7 @@ public class GalleryUtils { wm.getDefaultDisplay().getMetrics(metrics); sPixelDensity = metrics.density; Resources r = context.getResources(); - BitmapScreenNail.setPlaceholderColor(r.getColor( + TiledScreenNail.setPlaceholderColor(r.getColor( R.color.bitmap_screennail_placeholder)); initializeThumbnailSizes(metrics, r); } @@ -91,7 +91,7 @@ public class GalleryUtils { // Never need to completely fill the screen maxDimensionPixels = maxDimensionPixels / 2; MediaItem.setThumbnailSizes(maxDimensionPixels, 200); - BitmapScreenNail.setMaxSide(maxDimensionPixels); + TiledScreenNail.setMaxSide(maxDimensionPixels); } public static boolean isHighResolution(Context context) { -- 2.11.0