1030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin/* 2030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * Copyright (C) 2012 The Android Open Source Project 3030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * 4030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * you may not use this file except in compliance with the License. 6030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * You may obtain a copy of the License at 7030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * 8030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * http://www.apache.org/licenses/LICENSE-2.0 9030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * 10030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * Unless required by applicable law or agreed to in writing, software 11030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * See the License for the specific language governing permissions and 14030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin * limitations under the License. 15030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin */ 16030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 17030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linpackage com.android.gallery3d.ui; 18030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 19030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linimport android.graphics.Bitmap; 20030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linimport android.graphics.RectF; 21030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 22030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linimport com.android.gallery3d.common.Utils; 23f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool; 24a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.GLCanvas; 25a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.TiledTexture; 26030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 27030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// This is a ScreenNail wraps a Bitmap. There are some extra functions: 28030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// 29030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// - If we need to draw before the bitmap is available, we draw a rectange of 30030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// placeholder color (gray). 31030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// 32030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// - When the the bitmap is available, and we have drawn the placeholder color 33030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin// before, we will do a fade-in animation. 34030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Linpublic class TiledScreenNail implements ScreenNail { 35030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @SuppressWarnings("unused") 36030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static final String TAG = "TiledScreenNail"; 37030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 38030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // The duration of the fading animation in milliseconds 39030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static final int DURATION = 180; 40030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 41030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static int sMaxSide = 640; 42030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 43030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // These are special values for mAnimationStartTime 44030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static final long ANIMATION_NOT_NEEDED = -1; 45030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static final long ANIMATION_NEEDED = -2; 46030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static final long ANIMATION_DONE = -3; 47030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 48030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private int mWidth; 49030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private int mHeight; 50030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private long mAnimationStartTime = ANIMATION_NOT_NEEDED; 51030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 52030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private Bitmap mBitmap; 53030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private TiledTexture mTexture; 54030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 55030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public TiledScreenNail(Bitmap bitmap) { 56030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mWidth = bitmap.getWidth(); 57030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mHeight = bitmap.getHeight(); 58030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mBitmap = bitmap; 59030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture = new TiledTexture(bitmap); 60030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 61030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 62030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public TiledScreenNail(int width, int height) { 63030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin setSize(width, height); 64030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 65030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 66030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // This gets overridden by bitmap_screennail_placeholder 67030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // in GalleryUtils.initialize 68030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static int mPlaceholderColor = 0xFF222222; 69030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private static boolean mDrawPlaceholder = true; 70030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 71030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public static void setPlaceholderColor(int color) { 72030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mPlaceholderColor = color; 73030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 74030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 75030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private void setSize(int width, int height) { 76030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (width == 0 || height == 0) { 77030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin width = sMaxSide; 78030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin height = sMaxSide * 3 / 4; 79030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 80030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin float scale = Math.min(1, (float) sMaxSide / Math.max(width, height)); 81030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mWidth = Math.round(scale * width); 82030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mHeight = Math.round(scale * height); 83030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 84030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 85030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // Combines the two ScreenNails. 86030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // Returns the used one and recycle the unused one. 87030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public ScreenNail combine(ScreenNail other) { 88030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (other == null) { 89030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return this; 90030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 91030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 92030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (!(other instanceof TiledScreenNail)) { 93030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin recycle(); 94030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return other; 95030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 96030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 97030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // Now both are TiledScreenNail. Move over the information about width, 98030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin // height, and Bitmap, then recycle the other. 99030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin TiledScreenNail newer = (TiledScreenNail) other; 100030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mWidth = newer.mWidth; 101030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mHeight = newer.mHeight; 102030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (newer.mTexture != null) { 103f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu if (mBitmap != null) GalleryBitmapPool.getInstance().put(mBitmap); 104030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mTexture != null) mTexture.recycle(); 105030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mBitmap = newer.mBitmap; 106030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture = newer.mTexture; 107030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin newer.mBitmap = null; 108030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin newer.mTexture = null; 109030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 110030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin newer.recycle(); 111030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return this; 112030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 113030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 114030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public void updatePlaceholderSize(int width, int height) { 115030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mBitmap != null) return; 116030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (width == 0 || height == 0) return; 117030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin setSize(width, height); 118030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 119030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 120030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 121030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public int getWidth() { 122030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return mWidth; 123030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 124030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 125030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 126030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public int getHeight() { 127030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return mHeight; 128030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 129030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 130030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 131030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public void noDraw() { 132030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 133030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 134030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 135030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public void recycle() { 136030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mTexture != null) { 137030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture.recycle(); 138030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture = null; 139030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 140f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu if (mBitmap != null) { 141f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(mBitmap); 142f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu mBitmap = null; 143f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu } 144030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 145030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 146030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public static void disableDrawPlaceholder() { 147030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mDrawPlaceholder = false; 148030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 149030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 150030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public static void enableDrawPlaceholder() { 151030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mDrawPlaceholder = true; 152030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 153030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 154030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 155030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public void draw(GLCanvas canvas, int x, int y, int width, int height) { 156030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mTexture == null || !mTexture.isReady()) { 157030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { 158030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mAnimationStartTime = ANIMATION_NEEDED; 159030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 160030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if(mDrawPlaceholder) { 161030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin canvas.fillRect(x, y, width, height, mPlaceholderColor); 162030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 163030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return; 164030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 165030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 166030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mAnimationStartTime == ANIMATION_NEEDED) { 167030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mAnimationStartTime = AnimationTime.get(); 168030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 169030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 170030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (isAnimating()) { 171030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, 172030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin width, height); 173030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } else { 174030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture.draw(canvas, x, y, width, height); 175030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 176030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 177030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 178030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin @Override 179030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public void draw(GLCanvas canvas, RectF source, RectF dest) { 180030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mTexture == null || !mTexture.isReady()) { 181030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), 182030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mPlaceholderColor); 183030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return; 184030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 185030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 186030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mTexture.draw(canvas, source, dest); 187030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 188030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 189030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public boolean isAnimating() { 190d71a718afe02282153d86b78f6a44c4783203d54Owen Lin // The TiledTexture may not be uploaded completely yet. 191d71a718afe02282153d86b78f6a44c4783203d54Owen Lin // In that case, we count it as animating state and we will draw 192d71a718afe02282153d86b78f6a44c4783203d54Owen Lin // the placeholder in TileImageView. 193d71a718afe02282153d86b78f6a44c4783203d54Owen Lin if (mTexture == null || !mTexture.isReady()) return true; 194030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (mAnimationStartTime < 0) return false; 195030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin if (AnimationTime.get() - mAnimationStartTime >= DURATION) { 196030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin mAnimationStartTime = ANIMATION_DONE; 197030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return false; 198030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 199030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return true; 200030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 201030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 202030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin private float getRatio() { 203030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; 204030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return Utils.clamp(1.0f - r, 0.0f, 1.0f); 205030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 206030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 207030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public boolean isShowingPlaceholder() { 208030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return (mBitmap == null) || isAnimating(); 209030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 210030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 211030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public TiledTexture getTexture() { 212030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin return mTexture; 213030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 214030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin 215030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin public static void setMaxSide(int size) { 216030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin sMaxSide = size; 217030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin } 218030f8dad6aefc42d0af39bc1b93f370937d3e2abOwen Lin} 219