BitmapScreenNail.java revision 3ea0bfbcbea64276595029878d37f25bf4fbb881
197dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant/* 297dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * Copyright (C) 2012 The Android Open Source Project 397dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * 497dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * Licensed under the Apache License, Version 2.0 (the "License"); 5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant * you may not use this file except in compliance with the License. 6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant * You may obtain a copy of the License at 797dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * 897dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * http://www.apache.org/licenses/LICENSE-2.0 997dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * 1097dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * Unless required by applicable law or agreed to in writing, software 1197dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * distributed under the License is distributed on an "AS IS" BASIS, 1297dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * See the License for the specific language governing permissions and 1497dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant * limitations under the License. 1597dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant */ 1697dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant 1797dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantpackage com.android.gallery3d.ui; 1897dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant 1997dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantimport android.graphics.Bitmap; 2097dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantimport android.graphics.RectF; 2197dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant 2297dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantimport com.android.gallery3d.common.Utils; 2397dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantimport com.android.gallery3d.data.BitmapPool; 2497dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantimport com.android.gallery3d.data.MediaItem; 2597dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant 2697dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// This is a ScreenNail wraps a Bitmap. There are some extra functions: 2797dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// 2897dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// - If we need to draw before the bitmap is available, we draw a rectange of 2997dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// placeholder color (gray). 3097dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// 3197dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// - When the the bitmap is available, and we have drawn the placeholder color 3297dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant// before, we will do a fade-in animation. 3397dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnantpublic class BitmapScreenNail implements ScreenNail { 3497dc2f35c3d0d797ece43f5598023c6952144f37Howard Hinnant @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 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 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 = 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 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 public static void setMaxSide(int size) { 214 sMaxSide = size; 215 } 216} 217