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.camera;
18 
19 import android.os.SystemClock;
20 import android.util.Log;
21 
22 import com.android.gallery3d.glrenderer.GLCanvas;
23 import com.android.gallery3d.glrenderer.RawTexture;
24 
25 /**
26  * Class to handle the animation when switching between back and front cameras.
27  * An image of the previous camera zooms in and fades out. The preview of the
28  * new camera zooms in and fades in. The image of the previous camera is called
29  * review in this class.
30  */
31 public class SwitchAnimManager {
32     private static final String TAG = "SwitchAnimManager";
33     // The amount of change for zooming in and out.
34     private static final float ZOOM_DELTA_PREVIEW = 0.2f;
35     private static final float ZOOM_DELTA_REVIEW = 0.5f;
36     private static final float ANIMATION_DURATION = 400;  // ms
37     public static final float INITIAL_DARKEN_ALPHA = 0.8f;
38 
39     private long mAnimStartTime;  // milliseconds.
40     // The drawing width and height of the review image. This is saved when the
41     // texture is copied.
42     private int mReviewDrawingWidth;
43     private int mReviewDrawingHeight;
44     // The maximum width of the camera screen nail width from onDraw. We need to
45     // know how much the preview is scaled and scale the review the same amount.
46     // For example, the preview is not full screen in film strip mode.
47     private int mPreviewFrameLayoutWidth;
48 
SwitchAnimManager()49     public SwitchAnimManager() {
50     }
51 
setReviewDrawingSize(int width, int height)52     public void setReviewDrawingSize(int width, int height) {
53         mReviewDrawingWidth = width;
54         mReviewDrawingHeight = height;
55     }
56 
57     // width: the width of PreviewFrameLayout view.
58     // height: the height of PreviewFrameLayout view. Not used. Kept for
59     //         consistency.
setPreviewFrameLayoutSize(int width, int height)60     public void setPreviewFrameLayoutSize(int width, int height) {
61         mPreviewFrameLayoutWidth = width;
62     }
63 
64     // w and h: the rectangle area where the animation takes place.
startAnimation()65     public void startAnimation() {
66         mAnimStartTime = SystemClock.uptimeMillis();
67     }
68 
69     // Returns true if the animation has been drawn.
70     // preview: camera preview view.
71     // review: snapshot of the preview before switching the camera.
drawAnimation(GLCanvas canvas, int x, int y, int width, int height, CameraScreenNail preview, RawTexture review)72     public boolean drawAnimation(GLCanvas canvas, int x, int y, int width,
73             int height, CameraScreenNail preview, RawTexture review) {
74         long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;
75         if (timeDiff > ANIMATION_DURATION) return false;
76         float fraction = timeDiff / ANIMATION_DURATION;
77 
78         // Calculate the position and the size of the preview.
79         float centerX = x + width / 2f;
80         float centerY = y + height / 2f;
81         float previewAnimScale = 1 - ZOOM_DELTA_PREVIEW * (1 - fraction);
82         float previewWidth = width * previewAnimScale;
83         float previewHeight = height * previewAnimScale;
84         int previewX = Math.round(centerX - previewWidth / 2);
85         int previewY = Math.round(centerY - previewHeight / 2);
86 
87         // Calculate the position and the size of the review.
88         float reviewAnimScale = 1 + ZOOM_DELTA_REVIEW * fraction;
89 
90         // Calculate how much preview is scaled.
91         // The scaling is done by PhotoView in Gallery so we don't have the
92         // scaling information but only the width and the height passed to this
93         // method. The inference of the scale ratio is done by matching the
94         // current width and the original width we have at first when the camera
95         // layout is inflated.
96         float scaleRatio = 1;
97         if (mPreviewFrameLayoutWidth != 0) {
98             scaleRatio = (float) width / mPreviewFrameLayoutWidth;
99         } else {
100             Log.e(TAG, "mPreviewFrameLayoutWidth is 0.");
101         }
102         float reviewWidth = mReviewDrawingWidth * reviewAnimScale * scaleRatio;
103         float reviewHeight = mReviewDrawingHeight * reviewAnimScale * scaleRatio;
104         int reviewX = Math.round(centerX - reviewWidth / 2);
105         int reviewY = Math.round(centerY - reviewHeight / 2);
106 
107         // Draw the preview.
108         float alpha = canvas.getAlpha();
109         canvas.setAlpha(fraction); // fade in
110         preview.directDraw(canvas, previewX, previewY, Math.round(previewWidth),
111                 Math.round(previewHeight));
112 
113         // Draw the review.
114         canvas.setAlpha((1f - fraction) * INITIAL_DARKEN_ALPHA); // fade out
115         review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth),
116                 Math.round(reviewHeight));
117         canvas.setAlpha(alpha);
118         return true;
119     }
120 
drawDarkPreview(GLCanvas canvas, int x, int y, int width, int height, RawTexture review)121     public boolean drawDarkPreview(GLCanvas canvas, int x, int y, int width,
122             int height, RawTexture review) {
123         // Calculate the position and the size.
124         float centerX = x + width / 2f;
125         float centerY = y + height / 2f;
126         float scaleRatio = 1;
127         if (mPreviewFrameLayoutWidth != 0) {
128             scaleRatio = (float) width / mPreviewFrameLayoutWidth;
129         } else {
130             Log.e(TAG, "mPreviewFrameLayoutWidth is 0.");
131         }
132         float reviewWidth = mReviewDrawingWidth * scaleRatio;
133         float reviewHeight = mReviewDrawingHeight * scaleRatio;
134         int reviewX = Math.round(centerX - reviewWidth / 2);
135         int reviewY = Math.round(centerY - reviewHeight / 2);
136 
137         // Draw the review.
138         float alpha = canvas.getAlpha();
139         canvas.setAlpha(INITIAL_DARKEN_ALPHA);
140         review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth),
141                 Math.round(reviewHeight));
142         canvas.setAlpha(alpha);
143         return true;
144     }
145 
146 }
147