Home | History | Annotate | Download | only in wallpaper
      1 /*
      2  * Copyright (C) 2009 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.cooliris.wallpaper;
     18 
     19 //import android.app.Service;
     20 import com.cooliris.media.Vector3f;
     21 
     22 import android.content.Context;
     23 import android.graphics.Bitmap;
     24 import android.graphics.Canvas;
     25 import android.graphics.Color;
     26 import android.graphics.Paint;
     27 import android.graphics.PorterDuffColorFilter;
     28 import android.graphics.Rect;
     29 import android.graphics.RectF;
     30 import android.os.Handler;
     31 import android.os.SystemClock;
     32 import android.view.SurfaceHolder;
     33 import android.view.SurfaceView;
     34 import android.graphics.PorterDuff.Mode;
     35 
     36 public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
     37     public Slideshow(Context context) {
     38         super(context);
     39         SurfaceHolder holder = getHolder();
     40         holder.addCallback(this);
     41     }
     42 
     43     public static final int SLIDESHOW_DURATION = 2000;
     44 
     45     public interface DataSource {
     46         /**
     47          *
     48          * @param currentSlideshowCounter
     49          * @return
     50          */
     51         Bitmap getBitmapForIndex(Context context, int currentSlideshowCounter);
     52     }
     53 
     54     private final Handler mHandler = new Handler();
     55     private final Runnable mDrawFrame = new Runnable() {
     56         public void run() {
     57             drawFrame();
     58         }
     59     };
     60     private static final Paint sPaint = new Paint();
     61     static {
     62         sPaint.setFilterBitmap(true);
     63         sPaint.setDither(true);
     64     }
     65     private boolean mVisible = true;
     66     private DataSource mSource;
     67     private int mCurrentSlideshowCounter;
     68     private Bitmap mBitmap;
     69     private Rect mRect;
     70     private RectF mFrameRect;
     71     private static final Vector3f sGrow = new Vector3f();
     72     private Bitmap mQueuedBitmap;
     73     private Rect mQueuedRect;
     74     private RectF mQueuedFrameRect;
     75     private static final Vector3f sQueuedGrow = new Vector3f();
     76 
     77     private long mPrevTime;
     78     private long mTimeElapsed;
     79 
     80     public void setDataSource(DataSource source) {
     81         mSource = source;
     82     }
     83 
     84     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
     85         mHandler.post(mDrawFrame);
     86         if (mBitmap != null) {
     87             mRect = getRectToFitBitmap(mBitmap.getWidth(), mBitmap.getHeight(), width, height);
     88             mFrameRect.right = width;
     89             mFrameRect.bottom = height;
     90         }
     91         if (mQueuedBitmap != null) {
     92             mQueuedRect = getRectToFitBitmap(mQueuedBitmap.getWidth(), mQueuedBitmap.getHeight(), width, height);
     93             mQueuedFrameRect.right = width;
     94             mQueuedFrameRect.bottom = height;
     95         }
     96     }
     97 
     98     public void surfaceCreated(SurfaceHolder holder) {
     99         // We may need to make calls to super once this is a subclass of
    100         // WallpaperService.
    101         mHandler.post(mDrawFrame);
    102     }
    103 
    104     public void surfaceDestroyed(SurfaceHolder holder) {
    105 
    106     }
    107 
    108     public void drawFrame() {
    109         final SurfaceHolder holder = getHolder();
    110         Rect frame = holder.getSurfaceFrame();
    111         final Paint paint = sPaint;
    112         Canvas c = null;
    113         try {
    114             c = holder.lockCanvas();
    115             if (c != null) {
    116                 long now = SystemClock.uptimeMillis();
    117                 long delta = now - mPrevTime;
    118                 if (delta > 50)
    119                     delta = 50;
    120                 mTimeElapsed += delta;
    121                 mPrevTime = now;
    122                 performSetup(frame.width(), frame.height());
    123                 // We draw the source bitmap
    124                 if (mBitmap != null) {
    125                     if (mTimeElapsed > SLIDESHOW_DURATION) {
    126                         float alpha = ((float) (mTimeElapsed - SLIDESHOW_DURATION)) / 2000.0f;
    127                         paint.setColorFilter(null);
    128                         if (alpha < 1.0f) {
    129                             // int val = (int)(255 * (1.0f - alpha));
    130                             // int srcColor = Color.argb(val, 0, 0, 0);
    131                             // PorterDuffColorFilter colorFilter = new
    132                             // PorterDuffColorFilter(srcColor, Mode.SRC_IN);
    133                             // paint.setColorFilter(null);
    134                         }
    135                         c.drawBitmap(mBitmap, mRect, mFrameRect, paint);
    136                         if (alpha < 1.0f) {
    137                             int val = (int) (255 * alpha);
    138                             int srcColor = Color.argb(val, 0, 0, 0);
    139                             PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(srcColor, Mode.DST_IN);
    140                             paint.setColorFilter(colorFilter);
    141                         }
    142 
    143                         c.drawBitmap(mQueuedBitmap, mQueuedRect, mQueuedFrameRect, paint);
    144                         performUpdate(mQueuedFrameRect, sQueuedGrow, delta);
    145                         if (alpha >= 1.0f) {
    146                             // We switch the image.
    147                             mRect = mQueuedRect;
    148                             mBitmap = mQueuedBitmap;
    149                             mFrameRect = mQueuedFrameRect;
    150                             sGrow.set(sQueuedGrow);
    151                             mQueuedBitmap = null;
    152                             mQueuedRect = null;
    153                             mQueuedFrameRect = null;
    154                             mTimeElapsed = 0;
    155                         }
    156                     } else {
    157                         paint.setColorFilter(null);
    158                         c.drawBitmap(mBitmap, mRect, mFrameRect, paint);
    159                     }
    160                     performUpdate(mFrameRect, sGrow, delta);
    161                 }
    162 
    163             }
    164         } finally {
    165             if (c != null)
    166                 holder.unlockCanvasAndPost(c);
    167         }
    168         mHandler.removeCallbacks(mDrawFrame);
    169         if (mVisible) {
    170             mHandler.postDelayed(mDrawFrame, 20);
    171         }
    172     }
    173 
    174     private void performUpdate(RectF rect, Vector3f grow, long delta) {
    175         float timeElapsed = ((float) (delta)) / 1000.0f;
    176         float amountToGrowX = timeElapsed * (rect.width() / 15.0f);
    177         float amountToGrowY = amountToGrowX * (rect.height() / rect.width());
    178         rect.top -= amountToGrowY * grow.x;
    179         rect.left -= amountToGrowX * grow.y;
    180 
    181         rect.bottom += amountToGrowY * (1 - grow.x);
    182         rect.right += amountToGrowX * (1 - grow.y);
    183     }
    184 
    185     private void performSetup(int viewWidth, int viewHeight) {
    186         if (mBitmap == null) {
    187             mBitmap = getRandomBitmap();
    188             if (mBitmap != null) {
    189                 mRect = getRectToFitBitmap(mBitmap.getWidth(), mBitmap.getHeight(), viewWidth, viewHeight);
    190                 mFrameRect = new RectF();
    191                 mFrameRect.right = viewWidth;
    192                 mFrameRect.bottom = viewHeight;
    193                 sGrow.set((float) Math.random(), (float) Math.random(), 0);
    194             }
    195         }
    196         if (mQueuedBitmap == null) {
    197             mQueuedBitmap = getRandomBitmap();
    198             if (mQueuedBitmap == null) {
    199                 mQueuedBitmap = mBitmap;
    200             }
    201             if (mQueuedBitmap != null) {
    202                 mQueuedRect = getRectToFitBitmap(mQueuedBitmap.getWidth(), mQueuedBitmap.getHeight(), viewWidth, viewHeight);
    203                 mQueuedFrameRect = new RectF();
    204                 mQueuedFrameRect.right = viewWidth;
    205                 mQueuedFrameRect.bottom = viewHeight;
    206                 sQueuedGrow.set((float) Math.random(), (float) Math.random(), 0);
    207             }
    208         }
    209     }
    210 
    211     private Rect getRectToFitBitmap(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) {
    212         Rect rect = new Rect();
    213         float viewAspect = (float) viewHeight / viewWidth;
    214         float newWidth = bitmapWidth * viewAspect;
    215         if (bitmapHeight < newWidth) {
    216             // Vertically constrained.
    217             newWidth = bitmapHeight / viewAspect;
    218             rect.set((int) (bitmapWidth / 2 - newWidth / 2), 0, (int) (bitmapWidth / 2 + newWidth / 2), bitmapHeight);
    219         } else {
    220             // Horizontally constrained
    221             float newHeight = bitmapWidth * viewAspect;
    222             rect.set(0, (int) (bitmapHeight / 2 - newHeight / 2), bitmapWidth, (int) (bitmapHeight / 2 + newHeight / 2));
    223         }
    224         return rect;
    225     }
    226 
    227     private Bitmap getRandomBitmap() {
    228         if (mSource != null) {
    229             return mSource.getBitmapForIndex(getContext(), mCurrentSlideshowCounter++);
    230         }
    231         return null;
    232     }
    233 
    234     public void onVisibilityChanged(boolean visible) {
    235         mVisible = visible;
    236         if (!visible) {
    237             mHandler.removeCallbacks(mDrawFrame);
    238         }
    239         drawFrame();
    240     }
    241 
    242 }
    243