summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOwen Lin <owenlin@google.com>2012-10-11 15:50:38 +0800
committerOwen Lin <owenlin@google.com>2012-10-16 10:29:28 +0800
commitd3cd5c499ce58f3ad69d58acafd4f251a149fdbb (patch)
treee4477f8db5f3322ecafd343bb71a043053163c56
parenta942400efc37c5dd05b3c615092ae8d0f2ca7e2c (diff)
downloadandroid_packages_apps_Snap-d3cd5c499ce58f3ad69d58acafd4f251a149fdbb.tar.gz
android_packages_apps_Snap-d3cd5c499ce58f3ad69d58acafd4f251a149fdbb.tar.bz2
android_packages_apps_Snap-d3cd5c499ce58f3ad69d58acafd4f251a149fdbb.zip
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
-rw-r--r--src/com/android/gallery3d/app/CropImage.java21
-rw-r--r--src/com/android/gallery3d/app/PhotoDataAdapter.java21
-rw-r--r--src/com/android/gallery3d/app/PhotoPage.java6
-rw-r--r--src/com/android/gallery3d/app/SinglePhotoDataAdapter.java11
-rw-r--r--src/com/android/gallery3d/ui/BitmapScreenNail.java180
-rw-r--r--src/com/android/gallery3d/ui/PhotoView.java8
-rw-r--r--src/com/android/gallery3d/ui/TileImageView.java4
-rw-r--r--src/com/android/gallery3d/ui/TileImageViewAdapter.java32
-rw-r--r--src/com/android/gallery3d/ui/TiledScreenNail.java216
-rw-r--r--src/com/android/gallery3d/util/GalleryUtils.java6
10 files changed, 283 insertions, 222 deletions
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<BitmapRegionDecoder> 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) {