1 /*
2  * Copyright (C) 2012 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.anim;
18 
19 import android.view.animation.AccelerateInterpolator;
20 import android.view.animation.DecelerateInterpolator;
21 import android.view.animation.Interpolator;
22 
23 import com.android.gallery3d.glrenderer.GLCanvas;
24 import com.android.gallery3d.glrenderer.RawTexture;
25 import com.android.gallery3d.ui.GLView;
26 import com.android.gallery3d.ui.TiledScreenNail;
27 
28 public class StateTransitionAnimation extends Animation {
29 
30     public static class Spec {
31         public static final Spec OUTGOING;
32         public static final Spec INCOMING;
33         public static final Spec PHOTO_INCOMING;
34 
35         private static final Interpolator DEFAULT_INTERPOLATOR =
36                 new DecelerateInterpolator();
37 
38         public int duration = 330;
39         public float backgroundAlphaFrom = 0;
40         public float backgroundAlphaTo = 0;
41         public float backgroundScaleFrom = 0;
42         public float backgroundScaleTo = 0;
43         public float contentAlphaFrom = 1;
44         public float contentAlphaTo = 1;
45         public float contentScaleFrom = 1;
46         public float contentScaleTo = 1;
47         public float overlayAlphaFrom = 0;
48         public float overlayAlphaTo = 0;
49         public float overlayScaleFrom = 0;
50         public float overlayScaleTo = 0;
51         public Interpolator interpolator = DEFAULT_INTERPOLATOR;
52 
53         static {
54             OUTGOING = new Spec();
55             OUTGOING.backgroundAlphaFrom = 0.5f;
56             OUTGOING.backgroundAlphaTo = 0f;
57             OUTGOING.backgroundScaleFrom = 1f;
58             OUTGOING.backgroundScaleTo = 0f;
59             OUTGOING.contentAlphaFrom = 0.5f;
60             OUTGOING.contentAlphaTo = 1f;
61             OUTGOING.contentScaleFrom = 3f;
62             OUTGOING.contentScaleTo = 1f;
63 
64             INCOMING = new Spec();
65             INCOMING.overlayAlphaFrom = 1f;
66             INCOMING.overlayAlphaTo = 0f;
67             INCOMING.overlayScaleFrom = 1f;
68             INCOMING.overlayScaleTo = 3f;
69             INCOMING.contentAlphaFrom = 0f;
70             INCOMING.contentAlphaTo = 1f;
71             INCOMING.contentScaleFrom = 0.25f;
72             INCOMING.contentScaleTo = 1f;
73 
74             PHOTO_INCOMING = INCOMING;
75         }
76 
specForTransition(Transition t)77         private static Spec specForTransition(Transition t) {
78             switch (t) {
79                 case Outgoing:
80                     return Spec.OUTGOING;
81                 case Incoming:
82                     return Spec.INCOMING;
83                 case PhotoIncoming:
84                     return Spec.PHOTO_INCOMING;
85                 case None:
86                 default:
87                     return null;
88             }
89         }
90     }
91 
92     public static enum Transition { None, Outgoing, Incoming, PhotoIncoming }
93 
94     private final Spec mTransitionSpec;
95     private float mCurrentContentScale;
96     private float mCurrentContentAlpha;
97     private float mCurrentBackgroundScale;
98     private float mCurrentBackgroundAlpha;
99     private float mCurrentOverlayScale;
100     private float mCurrentOverlayAlpha;
101     private RawTexture mOldScreenTexture;
102 
StateTransitionAnimation(Transition t, RawTexture oldScreen)103     public StateTransitionAnimation(Transition t, RawTexture oldScreen) {
104         this(Spec.specForTransition(t), oldScreen);
105     }
106 
StateTransitionAnimation(Spec spec, RawTexture oldScreen)107     public StateTransitionAnimation(Spec spec, RawTexture oldScreen) {
108         mTransitionSpec = spec != null ? spec : Spec.OUTGOING;
109         setDuration(mTransitionSpec.duration);
110         setInterpolator(mTransitionSpec.interpolator);
111         mOldScreenTexture = oldScreen;
112         TiledScreenNail.disableDrawPlaceholder();
113     }
114 
115     @Override
calculate(long currentTimeMillis)116     public boolean calculate(long currentTimeMillis) {
117         boolean retval = super.calculate(currentTimeMillis);
118         if (!isActive()) {
119             if (mOldScreenTexture != null) {
120                 mOldScreenTexture.recycle();
121                 mOldScreenTexture = null;
122             }
123             TiledScreenNail.enableDrawPlaceholder();
124         }
125         return retval;
126     }
127 
128     @Override
onCalculate(float progress)129     protected void onCalculate(float progress) {
130         mCurrentContentScale = mTransitionSpec.contentScaleFrom
131                 + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress;
132         mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom
133                 + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress;
134         mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom
135                 + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom)
136                 * progress;
137         mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom
138                 + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom)
139                 * progress;
140         mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom
141                 + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress;
142         mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom
143                 + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress;
144     }
145 
applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear)146     private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) {
147         if (mOldScreenTexture == null)
148             return;
149         if (clear) canvas.clearBuffer(view.getBackgroundColor());
150         canvas.save();
151         canvas.setAlpha(alpha);
152         int xOffset = view.getWidth() / 2;
153         int yOffset = view.getHeight() / 2;
154         canvas.translate(xOffset, yOffset);
155         canvas.scale(scale, scale, 1);
156         mOldScreenTexture.draw(canvas, -xOffset, -yOffset);
157         canvas.restore();
158     }
159 
applyBackground(GLView view, GLCanvas canvas)160     public void applyBackground(GLView view, GLCanvas canvas) {
161         if (mCurrentBackgroundAlpha > 0f) {
162             applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true);
163         }
164     }
165 
applyContentTransform(GLView view, GLCanvas canvas)166     public void applyContentTransform(GLView view, GLCanvas canvas) {
167         int xOffset = view.getWidth() / 2;
168         int yOffset = view.getHeight() / 2;
169         canvas.translate(xOffset, yOffset);
170         canvas.scale(mCurrentContentScale, mCurrentContentScale, 1);
171         canvas.translate(-xOffset, -yOffset);
172         canvas.setAlpha(mCurrentContentAlpha);
173     }
174 
applyOverlay(GLView view, GLCanvas canvas)175     public void applyOverlay(GLView view, GLCanvas canvas) {
176         if (mCurrentOverlayAlpha > 0f) {
177             applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false);
178         }
179     }
180 }
181