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