BitmapScreenNail.java revision e29fc4a51b99f12f7fae13fae272858df2e1af36
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.ui; 18 19import android.graphics.Bitmap; 20import android.graphics.RectF; 21 22import com.android.gallery3d.common.Utils; 23import com.android.gallery3d.data.BitmapPool; 24import com.android.gallery3d.data.MediaItem; 25 26// This is a ScreenNail wraps a Bitmap. There are some extra functions: 27// 28// - If we need to draw before the bitmap is available, we draw a rectange of 29// placeholder color (gray). 30// 31// - When the the bitmap is available, and we have drawn the placeholder color 32// before, we will do a fade-in animation. 33public class BitmapScreenNail implements ScreenNail { 34 @SuppressWarnings("unused") 35 private static final String TAG = "BitmapScreenNail"; 36 37 // The duration of the fading animation in milliseconds 38 private static final int DURATION = 180; 39 40 private static final int MAX_SIDE = 640; 41 42 // These are special values for mAnimationStartTime 43 private static final long ANIMATION_NOT_NEEDED = -1; 44 private static final long ANIMATION_NEEDED = -2; 45 private static final long ANIMATION_DONE = -3; 46 47 private int mWidth; 48 private int mHeight; 49 private long mAnimationStartTime = ANIMATION_NOT_NEEDED; 50 51 private Bitmap mBitmap; 52 private TiledTexture mTexture; 53 54 public BitmapScreenNail(Bitmap bitmap) { 55 mWidth = bitmap.getWidth(); 56 mHeight = bitmap.getHeight(); 57 mBitmap = bitmap; 58 mTexture = new TiledTexture(bitmap); 59 } 60 61 public BitmapScreenNail(int width, int height) { 62 setSize(width, height); 63 } 64 65 // This gets overridden by bitmap_screennail_placeholder 66 // in GalleryUtils.initialize 67 private static int mPlaceholderColor = 0xFF222222; 68 private static boolean mDrawPlaceholder = true; 69 70 public static void setPlaceholderColor(int color) { 71 mPlaceholderColor = color; 72 } 73 74 private void setSize(int width, int height) { 75 if (width == 0 || height == 0) { 76 width = 640; 77 height = 480; 78 } 79 float scale = Math.min(1, (float) MAX_SIDE / Math.max(width, height)); 80 mWidth = Math.round(scale * width); 81 mHeight = Math.round(scale * height); 82 } 83 84 private static void recycleBitmap(BitmapPool pool, Bitmap bitmap) { 85 if (pool == null || bitmap == null) return; 86 pool.recycle(bitmap); 87 } 88 89 // Combines the two ScreenNails. 90 // Returns the used one and recycle the unused one. 91 public ScreenNail combine(ScreenNail other) { 92 if (other == null) { 93 return this; 94 } 95 96 if (!(other instanceof BitmapScreenNail)) { 97 recycle(); 98 return other; 99 } 100 101 // Now both are BitmapScreenNail. Move over the information about width, 102 // height, and Bitmap, then recycle the other. 103 BitmapScreenNail newer = (BitmapScreenNail) other; 104 mWidth = newer.mWidth; 105 mHeight = newer.mHeight; 106 if (newer.mTexture != null) { 107 recycleBitmap(MediaItem.getThumbPool(), mBitmap); 108 if (mTexture != null) mTexture.recycle(); 109 mBitmap = newer.mBitmap; 110 mTexture = newer.mTexture; 111 newer.mBitmap = null; 112 newer.mTexture = null; 113 } 114 newer.recycle(); 115 return this; 116 } 117 118 public void updatePlaceholderSize(int width, int height) { 119 if (mBitmap != null) return; 120 if (width == 0 || height == 0) return; 121 setSize(width, height); 122 } 123 124 @Override 125 public int getWidth() { 126 return mWidth; 127 } 128 129 @Override 130 public int getHeight() { 131 return mHeight; 132 } 133 134 @Override 135 public void noDraw() { 136 } 137 138 @Override 139 public void recycle() { 140 if (mTexture != null) { 141 mTexture.recycle(); 142 mTexture = null; 143 } 144 recycleBitmap(MediaItem.getThumbPool(), mBitmap); 145 mBitmap = null; 146 } 147 148 public static void disableDrawPlaceholder() { 149 mDrawPlaceholder = false; 150 } 151 152 public static void enableDrawPlaceholder() { 153 mDrawPlaceholder = true; 154 } 155 156 @Override 157 public void draw(GLCanvas canvas, int x, int y, int width, int height) { 158 if (mTexture == null || !mTexture.isReady()) { 159 if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { 160 mAnimationStartTime = ANIMATION_NEEDED; 161 } 162 if(mDrawPlaceholder) { 163 canvas.fillRect(x, y, width, height, mPlaceholderColor); 164 } 165 return; 166 } 167 168 if (mAnimationStartTime == ANIMATION_NEEDED) { 169 mAnimationStartTime = AnimationTime.get(); 170 } 171 172 if (isAnimating()) { 173 mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, 174 width, height); 175 } else { 176 mTexture.draw(canvas, x, y, width, height); 177 } 178 } 179 180 @Override 181 public void draw(GLCanvas canvas, RectF source, RectF dest) { 182 if (mTexture == null || !mTexture.isReady()) { 183 canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), 184 mPlaceholderColor); 185 return; 186 } 187 188 mTexture.draw(canvas, source, dest); 189 } 190 191 public boolean isAnimating() { 192 if (mAnimationStartTime < 0) return false; 193 if (AnimationTime.get() - mAnimationStartTime >= DURATION) { 194 mAnimationStartTime = ANIMATION_DONE; 195 return false; 196 } 197 return true; 198 } 199 200 private float getRatio() { 201 float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; 202 return Utils.clamp(1.0f - r, 0.0f, 1.0f); 203 } 204 205 public boolean isShowingPlaceholder() { 206 return (mBitmap == null) || isAnimating(); 207 } 208 209 public TiledTexture getTexture() { 210 return mTexture; 211 } 212} 213