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
17package com.android.gallery3d.ui;
18
19import android.graphics.Bitmap;
20import android.graphics.PointF;
21
22import com.android.gallery3d.anim.CanvasAnimation;
23import com.android.gallery3d.anim.FloatAnimation;
24import com.android.gallery3d.glrenderer.BitmapTexture;
25import com.android.gallery3d.glrenderer.GLCanvas;
26
27import java.util.Random;
28
29public 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
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
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
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
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
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
154        public int getCanvasSaveFlags() {
155            return GLCanvas.SAVE_FLAG_MATRIX;
156        }
157
158        @Override
159        protected void onCalculate(float progress) {
160            mProgress = progress;
161        }
162    }
163}
164