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