1 /*
2  * Copyright (C) 2010 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.PointF;
21 
22 import com.android.gallery3d.anim.CanvasAnimation;
23 import com.android.gallery3d.anim.FloatAnimation;
24 import com.android.gallery3d.glrenderer.BitmapTexture;
25 import com.android.gallery3d.glrenderer.GLCanvas;
26 
27 import java.util.Random;
28 
29 public class SlideshowView extends GLView {
30     @SuppressWarnings("unused")
31     private static final String TAG = "SlideshowView";
32 
33     private static final int SLIDESHOW_DURATION = 3500;
34     private static final int TRANSITION_DURATION = 1000;
35 
36     private static final float SCALE_SPEED = 0.20f ;
37     private static final float MOVE_SPEED = SCALE_SPEED;
38 
39     private int mCurrentRotation;
40     private BitmapTexture mCurrentTexture;
41     private SlideshowAnimation mCurrentAnimation;
42 
43     private int mPrevRotation;
44     private BitmapTexture mPrevTexture;
45     private SlideshowAnimation mPrevAnimation;
46 
47     private final FloatAnimation mTransitionAnimation =
48             new FloatAnimation(0, 1, TRANSITION_DURATION);
49 
50     private Random mRandom = new Random();
51 
next(Bitmap bitmap, int rotation)52     public void next(Bitmap bitmap, int rotation) {
53 
54         mTransitionAnimation.start();
55 
56         if (mPrevTexture != null) {
57             mPrevTexture.getBitmap().recycle();
58             mPrevTexture.recycle();
59         }
60 
61         mPrevTexture = mCurrentTexture;
62         mPrevAnimation = mCurrentAnimation;
63         mPrevRotation = mCurrentRotation;
64 
65         mCurrentRotation = rotation;
66         mCurrentTexture = new BitmapTexture(bitmap);
67         if (((rotation / 90) & 0x01) == 0) {
68             mCurrentAnimation = new SlideshowAnimation(
69                     mCurrentTexture.getWidth(), mCurrentTexture.getHeight(),
70                     mRandom);
71         } else {
72             mCurrentAnimation = new SlideshowAnimation(
73                     mCurrentTexture.getHeight(), mCurrentTexture.getWidth(),
74                     mRandom);
75         }
76         mCurrentAnimation.start();
77 
78         invalidate();
79     }
80 
release()81     public void release() {
82         if (mPrevTexture != null) {
83             mPrevTexture.recycle();
84             mPrevTexture = null;
85         }
86         if (mCurrentTexture != null) {
87             mCurrentTexture.recycle();
88             mCurrentTexture = null;
89         }
90     }
91 
92     @Override
render(GLCanvas canvas)93     protected void render(GLCanvas canvas) {
94         long animTime = AnimationTime.get();
95         boolean requestRender = mTransitionAnimation.calculate(animTime);
96         float alpha = mPrevTexture == null ? 1f : mTransitionAnimation.get();
97 
98         if (mPrevTexture != null && alpha != 1f) {
99             requestRender |= mPrevAnimation.calculate(animTime);
100             canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
101             canvas.setAlpha(1f - alpha);
102             mPrevAnimation.apply(canvas);
103             canvas.rotate(mPrevRotation, 0, 0, 1);
104             mPrevTexture.draw(canvas, -mPrevTexture.getWidth() / 2,
105                     -mPrevTexture.getHeight() / 2);
106             canvas.restore();
107         }
108         if (mCurrentTexture != null) {
109             requestRender |= mCurrentAnimation.calculate(animTime);
110             canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
111             canvas.setAlpha(alpha);
112             mCurrentAnimation.apply(canvas);
113             canvas.rotate(mCurrentRotation, 0, 0, 1);
114             mCurrentTexture.draw(canvas, -mCurrentTexture.getWidth() / 2,
115                     -mCurrentTexture.getHeight() / 2);
116             canvas.restore();
117         }
118         if (requestRender) invalidate();
119     }
120 
121     private class SlideshowAnimation extends CanvasAnimation {
122         private final int mWidth;
123         private final int mHeight;
124 
125         private final PointF mMovingVector;
126         private float mProgress;
127 
SlideshowAnimation(int width, int height, Random random)128         public SlideshowAnimation(int width, int height, Random random) {
129             mWidth = width;
130             mHeight = height;
131             mMovingVector = new PointF(
132                     MOVE_SPEED * mWidth * (random.nextFloat() - 0.5f),
133                     MOVE_SPEED * mHeight * (random.nextFloat() - 0.5f));
134             setDuration(SLIDESHOW_DURATION);
135         }
136 
137         @Override
apply(GLCanvas canvas)138         public void apply(GLCanvas canvas) {
139             int viewWidth = getWidth();
140             int viewHeight = getHeight();
141 
142             float initScale = Math.min((float)
143                     viewWidth / mWidth, (float) viewHeight / mHeight);
144             float scale = initScale * (1 + SCALE_SPEED * mProgress);
145 
146             float centerX = viewWidth / 2 + mMovingVector.x * mProgress;
147             float centerY = viewHeight / 2 + mMovingVector.y * mProgress;
148 
149             canvas.translate(centerX, centerY);
150             canvas.scale(scale, scale, 0);
151         }
152 
153         @Override
getCanvasSaveFlags()154         public int getCanvasSaveFlags() {
155             return GLCanvas.SAVE_FLAG_MATRIX;
156         }
157 
158         @Override
onCalculate(float progress)159         protected void onCalculate(float progress) {
160             mProgress = progress;
161         }
162     }
163 }
164