1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.PointF;
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
222b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.anim.CanvasAnimation;
232b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.anim.FloatAnimation;
24a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.BitmapTexture;
25a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.GLCanvas;
262b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Random;
282b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class SlideshowView extends GLView {
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @SuppressWarnings("unused")
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "SlideshowView";
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int SLIDESHOW_DURATION = 3500;
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int TRANSITION_DURATION = 1000;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final float SCALE_SPEED = 0.20f ;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final float MOVE_SPEED = SCALE_SPEED;
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mCurrentRotation;
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private BitmapTexture mCurrentTexture;
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private SlideshowAnimation mCurrentAnimation;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mPrevRotation;
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private BitmapTexture mPrevTexture;
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private SlideshowAnimation mPrevAnimation;
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final FloatAnimation mTransitionAnimation =
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            new FloatAnimation(0, 1, TRANSITION_DURATION);
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Random mRandom = new Random();
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void next(Bitmap bitmap, int rotation) {
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mTransitionAnimation.start();
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mPrevTexture != null) {
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevTexture.getBitmap().recycle();
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevTexture.recycle();
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mPrevTexture = mCurrentTexture;
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mPrevAnimation = mCurrentAnimation;
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mPrevRotation = mCurrentRotation;
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCurrentRotation = rotation;
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCurrentTexture = new BitmapTexture(bitmap);
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (((rotation / 90) & 0x01) == 0) {
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentAnimation = new SlideshowAnimation(
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mCurrentTexture.getWidth(), mCurrentTexture.getHeight(),
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mRandom);
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentAnimation = new SlideshowAnimation(
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mCurrentTexture.getHeight(), mCurrentTexture.getWidth(),
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mRandom);
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCurrentAnimation.start();
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        invalidate();
79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void release() {
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mPrevTexture != null) {
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevTexture.recycle();
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevTexture = null;
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mCurrentTexture != null) {
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentTexture.recycle();
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentTexture = null;
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void render(GLCanvas canvas) {
947d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang        long animTime = AnimationTime.get();
957d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang        boolean requestRender = mTransitionAnimation.calculate(animTime);
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        float alpha = mPrevTexture == null ? 1f : mTransitionAnimation.get();
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mPrevTexture != null && alpha != 1f) {
997d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang            requestRender |= mPrevAnimation.calculate(animTime);
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.setAlpha(1f - alpha);
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevAnimation.apply(canvas);
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.rotate(mPrevRotation, 0, 0, 1);
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mPrevTexture.draw(canvas, -mPrevTexture.getWidth() / 2,
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    -mPrevTexture.getHeight() / 2);
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.restore();
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mCurrentTexture != null) {
1097d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang            requestRender |= mCurrentAnimation.calculate(animTime);
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.setAlpha(alpha);
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentAnimation.apply(canvas);
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.rotate(mCurrentRotation, 0, 0, 1);
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCurrentTexture.draw(canvas, -mCurrentTexture.getWidth() / 2,
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    -mCurrentTexture.getHeight() / 2);
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.restore();
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (requestRender) invalidate();
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private class SlideshowAnimation extends CanvasAnimation {
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final int mWidth;
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final int mHeight;
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final PointF mMovingVector;
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private float mProgress;
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public SlideshowAnimation(int width, int height, Random random) {
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mWidth = width;
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mHeight = height;
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMovingVector = new PointF(
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    MOVE_SPEED * mWidth * (random.nextFloat() - 0.5f),
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    MOVE_SPEED * mHeight * (random.nextFloat() - 0.5f));
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            setDuration(SLIDESHOW_DURATION);
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void apply(GLCanvas canvas) {
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int viewWidth = getWidth();
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int viewHeight = getHeight();
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1427e6537ca106a80aeb4a52182b31ddc9aa642abe5Bobby Georgescu            float initScale = Math.min((float)
1437e6537ca106a80aeb4a52182b31ddc9aa642abe5Bobby Georgescu                    viewWidth / mWidth, (float) viewHeight / mHeight);
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            float scale = initScale * (1 + SCALE_SPEED * mProgress);
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            float centerX = viewWidth / 2 + mMovingVector.x * mProgress;
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            float centerY = viewHeight / 2 + mMovingVector.y * mProgress;
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
149174cac8f92029fc2829c94f274e70793ae948931Chih-Chung Chang            canvas.translate(centerX, centerY);
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.scale(scale, scale, 0);
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int getCanvasSaveFlags() {
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return GLCanvas.SAVE_FLAG_MATRIX;
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        protected void onCalculate(float progress) {
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mProgress = progress;
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
164