TiledScreenNail.java revision d71a718afe02282153d86b78f6a44c4783203d54
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 TiledScreenNail implements ScreenNail { 34 @SuppressWarnings("unused") 35 private static final String TAG = "TiledScreenNail"; 36 37 // The duration of the fading animation in milliseconds 38 private static final int DURATION = 180; 39 40 private static int sMaxSide = 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 TiledScreenNail(Bitmap bitmap) { 55 mWidth = bitmap.getWidth(); 56 mHeight = bitmap.getHeight(); 57 mBitmap = bitmap; 58 mTexture = new TiledTexture(bitmap); 59 } 60 61 public TiledScreenNail(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 = sMaxSide; 77 height = sMaxSide * 3 / 4; 78 } 79 float scale = Math.min(1, (float) sMaxSide / 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 TiledScreenNail)) { 97 recycle(); 98 return other; 99 } 100 101 // Now both are TiledScreenNail. Move over the information about width, 102 // height, and Bitmap, then recycle the other. 103 TiledScreenNail newer = (TiledScreenNail) 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 // The TiledTexture may not be uploaded completely yet. 193 // In that case, we count it as animating state and we will draw 194 // the placeholder in TileImageView. 195 if (mTexture == null || !mTexture.isReady()) return true; 196 if (mAnimationStartTime < 0) return false; 197 if (AnimationTime.get() - mAnimationStartTime >= DURATION) { 198 mAnimationStartTime = ANIMATION_DONE; 199 return false; 200 } 201 return true; 202 } 203 204 private float getRatio() { 205 float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; 206 return Utils.clamp(1.0f - r, 0.0f, 1.0f); 207 } 208 209 public boolean isShowingPlaceholder() { 210 return (mBitmap == null) || isAnimating(); 211 } 212 213 public TiledTexture getTexture() { 214 return mTexture; 215 } 216 217 public static void setMaxSide(int size) { 218 sMaxSide = size; 219 } 220} 221