summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/SwitchAnimManager.java
blob: 6ec88223e4c5e0c7c005863e03d526bb43e100dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.camera;

import android.os.SystemClock;
import android.util.Log;

import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.glrenderer.RawTexture;

/**
 * Class to handle the animation when switching between back and front cameras.
 * An image of the previous camera zooms in and fades out. The preview of the
 * new camera zooms in and fades in. The image of the previous camera is called
 * review in this class.
 */
public class SwitchAnimManager {
    private static final String TAG = "SwitchAnimManager";
    // The amount of change for zooming in and out.
    private static final float ZOOM_DELTA_PREVIEW = 0.2f;
    private static final float ZOOM_DELTA_REVIEW = 0.5f;
    private static final float ANIMATION_DURATION = 400;  // ms
    public static final float INITIAL_DARKEN_ALPHA = 0.8f;

    private long mAnimStartTime;  // milliseconds.
    // The drawing width and height of the review image. This is saved when the
    // texture is copied.
    private int mReviewDrawingWidth;
    private int mReviewDrawingHeight;
    // The maximum width of the camera screen nail width from onDraw. We need to
    // know how much the preview is scaled and scale the review the same amount.
    // For example, the preview is not full screen in film strip mode.
    private int mPreviewFrameLayoutWidth;

    public SwitchAnimManager() {
    }

    public void setReviewDrawingSize(int width, int height) {
        mReviewDrawingWidth = width;
        mReviewDrawingHeight = height;
    }

    // width: the width of PreviewFrameLayout view.
    // height: the height of PreviewFrameLayout view. Not used. Kept for
    //         consistency.
    public void setPreviewFrameLayoutSize(int width, int height) {
        mPreviewFrameLayoutWidth = width;
    }

    // w and h: the rectangle area where the animation takes place.
    public void startAnimation() {
        mAnimStartTime = SystemClock.uptimeMillis();
    }

    // Returns true if the animation has been drawn.
    // preview: camera preview view.
    // review: snapshot of the preview before switching the camera.
    public boolean drawAnimation(GLCanvas canvas, int x, int y, int width,
            int height, CameraScreenNail preview, RawTexture review) {
        long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;
        if (timeDiff > ANIMATION_DURATION) return false;
        float fraction = timeDiff / ANIMATION_DURATION;

        // Calculate the position and the size of the preview.
        float centerX = x + width / 2f;
        float centerY = y + height / 2f;
        float previewAnimScale = 1 - ZOOM_DELTA_PREVIEW * (1 - fraction);
        float previewWidth = width * previewAnimScale;
        float previewHeight = height * previewAnimScale;
        int previewX = Math.round(centerX - previewWidth / 2);
        int previewY = Math.round(centerY - previewHeight / 2);

        // Calculate the position and the size of the review.
        float reviewAnimScale = 1 + ZOOM_DELTA_REVIEW * fraction;

        // Calculate how much preview is scaled.
        // The scaling is done by PhotoView in Gallery so we don't have the
        // scaling information but only the width and the height passed to this
        // method. The inference of the scale ratio is done by matching the
        // current width and the original width we have at first when the camera
        // layout is inflated.
        float scaleRatio = 1;
        if (mPreviewFrameLayoutWidth != 0) {
            scaleRatio = (float) width / mPreviewFrameLayoutWidth;
        } else {
            Log.e(TAG, "mPreviewFrameLayoutWidth is 0.");
        }
        float reviewWidth = mReviewDrawingWidth * reviewAnimScale * scaleRatio;
        float reviewHeight = mReviewDrawingHeight * reviewAnimScale * scaleRatio;
        int reviewX = Math.round(centerX - reviewWidth / 2);
        int reviewY = Math.round(centerY - reviewHeight / 2);

        // Draw the preview.
        float alpha = canvas.getAlpha();
        canvas.setAlpha(fraction); // fade in
        preview.directDraw(canvas, previewX, previewY, Math.round(previewWidth),
                Math.round(previewHeight));

        // Draw the review.
        canvas.setAlpha((1f - fraction) * INITIAL_DARKEN_ALPHA); // fade out
        review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth),
                Math.round(reviewHeight));
        canvas.setAlpha(alpha);
        return true;
    }

    public boolean drawDarkPreview(GLCanvas canvas, int x, int y, int width,
            int height, RawTexture review) {
        // Calculate the position and the size.
        float centerX = x + width / 2f;
        float centerY = y + height / 2f;
        float scaleRatio = 1;
        if (mPreviewFrameLayoutWidth != 0) {
            scaleRatio = (float) width / mPreviewFrameLayoutWidth;
        } else {
            Log.e(TAG, "mPreviewFrameLayoutWidth is 0.");
        }
        float reviewWidth = mReviewDrawingWidth * scaleRatio;
        float reviewHeight = mReviewDrawingHeight * scaleRatio;
        int reviewX = Math.round(centerX - reviewWidth / 2);
        int reviewY = Math.round(centerY - reviewHeight / 2);

        // Draw the review.
        float alpha = canvas.getAlpha();
        canvas.setAlpha(INITIAL_DARKEN_ALPHA);
        review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth),
                Math.round(reviewHeight));
        canvas.setAlpha(alpha);
        return true;
    }

}