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 17 package com.android.gallery3d.ui; 18 19 import android.graphics.Bitmap; 20 import android.graphics.RectF; 21 22 import com.android.gallery3d.common.Utils; 23 import com.android.photos.data.GalleryBitmapPool; 24 import com.android.gallery3d.glrenderer.GLCanvas; 25 import com.android.gallery3d.glrenderer.TiledTexture; 26 27 // This is a ScreenNail wraps a Bitmap. There are some extra functions: 28 // 29 // - If we need to draw before the bitmap is available, we draw a rectange of 30 // placeholder color (gray). 31 // 32 // - When the the bitmap is available, and we have drawn the placeholder color 33 // before, we will do a fade-in animation. 34 public class TiledScreenNail implements ScreenNail { 35 @SuppressWarnings("unused") 36 private static final String TAG = "TiledScreenNail"; 37 38 // The duration of the fading animation in milliseconds 39 private static final int DURATION = 180; 40 41 private static int sMaxSide = 640; 42 43 // These are special values for mAnimationStartTime 44 private static final long ANIMATION_NOT_NEEDED = -1; 45 private static final long ANIMATION_NEEDED = -2; 46 private static final long ANIMATION_DONE = -3; 47 48 private int mWidth; 49 private int mHeight; 50 private long mAnimationStartTime = ANIMATION_NOT_NEEDED; 51 52 private Bitmap mBitmap; 53 private TiledTexture mTexture; 54 TiledScreenNail(Bitmap bitmap)55 public TiledScreenNail(Bitmap bitmap) { 56 mWidth = bitmap.getWidth(); 57 mHeight = bitmap.getHeight(); 58 mBitmap = bitmap; 59 mTexture = new TiledTexture(bitmap); 60 } 61 TiledScreenNail(int width, int height)62 public TiledScreenNail(int width, int height) { 63 setSize(width, height); 64 } 65 66 // This gets overridden by bitmap_screennail_placeholder 67 // in GalleryUtils.initialize 68 private static int mPlaceholderColor = 0xFF222222; 69 private static boolean mDrawPlaceholder = true; 70 setPlaceholderColor(int color)71 public static void setPlaceholderColor(int color) { 72 mPlaceholderColor = color; 73 } 74 setSize(int width, int height)75 private void setSize(int width, int height) { 76 if (width == 0 || height == 0) { 77 width = sMaxSide; 78 height = sMaxSide * 3 / 4; 79 } 80 float scale = Math.min(1, (float) sMaxSide / Math.max(width, height)); 81 mWidth = Math.round(scale * width); 82 mHeight = Math.round(scale * height); 83 } 84 85 // Combines the two ScreenNails. 86 // Returns the used one and recycle the unused one. combine(ScreenNail other)87 public ScreenNail combine(ScreenNail other) { 88 if (other == null) { 89 return this; 90 } 91 92 if (!(other instanceof TiledScreenNail)) { 93 recycle(); 94 return other; 95 } 96 97 // Now both are TiledScreenNail. Move over the information about width, 98 // height, and Bitmap, then recycle the other. 99 TiledScreenNail newer = (TiledScreenNail) other; 100 mWidth = newer.mWidth; 101 mHeight = newer.mHeight; 102 if (newer.mTexture != null) { 103 if (mBitmap != null) GalleryBitmapPool.getInstance().put(mBitmap); 104 if (mTexture != null) mTexture.recycle(); 105 mBitmap = newer.mBitmap; 106 mTexture = newer.mTexture; 107 newer.mBitmap = null; 108 newer.mTexture = null; 109 } 110 newer.recycle(); 111 return this; 112 } 113 updatePlaceholderSize(int width, int height)114 public void updatePlaceholderSize(int width, int height) { 115 if (mBitmap != null) return; 116 if (width == 0 || height == 0) return; 117 setSize(width, height); 118 } 119 120 @Override getWidth()121 public int getWidth() { 122 return mWidth; 123 } 124 125 @Override getHeight()126 public int getHeight() { 127 return mHeight; 128 } 129 130 @Override noDraw()131 public void noDraw() { 132 } 133 134 @Override recycle()135 public void recycle() { 136 if (mTexture != null) { 137 mTexture.recycle(); 138 mTexture = null; 139 } 140 if (mBitmap != null) { 141 GalleryBitmapPool.getInstance().put(mBitmap); 142 mBitmap = null; 143 } 144 } 145 disableDrawPlaceholder()146 public static void disableDrawPlaceholder() { 147 mDrawPlaceholder = false; 148 } 149 enableDrawPlaceholder()150 public static void enableDrawPlaceholder() { 151 mDrawPlaceholder = true; 152 } 153 154 @Override draw(GLCanvas canvas, int x, int y, int width, int height)155 public void draw(GLCanvas canvas, int x, int y, int width, int height) { 156 if (mTexture == null || !mTexture.isReady()) { 157 if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { 158 mAnimationStartTime = ANIMATION_NEEDED; 159 } 160 if(mDrawPlaceholder) { 161 canvas.fillRect(x, y, width, height, mPlaceholderColor); 162 } 163 return; 164 } 165 166 if (mAnimationStartTime == ANIMATION_NEEDED) { 167 mAnimationStartTime = AnimationTime.get(); 168 } 169 170 if (isAnimating()) { 171 mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, 172 width, height); 173 } else { 174 mTexture.draw(canvas, x, y, width, height); 175 } 176 } 177 178 @Override draw(GLCanvas canvas, RectF source, RectF dest)179 public void draw(GLCanvas canvas, RectF source, RectF dest) { 180 if (mTexture == null || !mTexture.isReady()) { 181 canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), 182 mPlaceholderColor); 183 return; 184 } 185 186 mTexture.draw(canvas, source, dest); 187 } 188 isAnimating()189 public boolean isAnimating() { 190 // The TiledTexture may not be uploaded completely yet. 191 // In that case, we count it as animating state and we will draw 192 // the placeholder in TileImageView. 193 if (mTexture == null || !mTexture.isReady()) return true; 194 if (mAnimationStartTime < 0) return false; 195 if (AnimationTime.get() - mAnimationStartTime >= DURATION) { 196 mAnimationStartTime = ANIMATION_DONE; 197 return false; 198 } 199 return true; 200 } 201 getRatio()202 private float getRatio() { 203 float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; 204 return Utils.clamp(1.0f - r, 0.0f, 1.0f); 205 } 206 isShowingPlaceholder()207 public boolean isShowingPlaceholder() { 208 return (mBitmap == null) || isAnimating(); 209 } 210 getTexture()211 public TiledTexture getTexture() { 212 return mTexture; 213 } 214 setMaxSide(int size)215 public static void setMaxSide(int size) { 216 sMaxSide = size; 217 } 218 } 219