Home | History | Annotate | Download | only in ui
      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 
     55     public TiledScreenNail(Bitmap bitmap) {
     56         mWidth = bitmap.getWidth();
     57         mHeight = bitmap.getHeight();
     58         mBitmap = bitmap;
     59         mTexture = new TiledTexture(bitmap);
     60     }
     61 
     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 
     71     public static void setPlaceholderColor(int color) {
     72         mPlaceholderColor = color;
     73     }
     74 
     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.
     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 
    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
    121     public int getWidth() {
    122         return mWidth;
    123     }
    124 
    125     @Override
    126     public int getHeight() {
    127         return mHeight;
    128     }
    129 
    130     @Override
    131     public void noDraw() {
    132     }
    133 
    134     @Override
    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 
    146     public static void disableDrawPlaceholder() {
    147         mDrawPlaceholder = false;
    148     }
    149 
    150     public static void enableDrawPlaceholder() {
    151         mDrawPlaceholder = true;
    152     }
    153 
    154     @Override
    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
    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 
    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 
    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 
    207     public boolean isShowingPlaceholder() {
    208         return (mBitmap == null) || isAnimating();
    209     }
    210 
    211     public TiledTexture getTexture() {
    212         return mTexture;
    213     }
    214 
    215     public static void setMaxSide(int size) {
    216         sMaxSide = size;
    217     }
    218 }
    219