Home | History | Annotate | Download | only in camera
      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.view.animation.AccelerateDecelerateInterpolator;
     21 import android.view.animation.AccelerateInterpolator;
     22 import android.view.animation.DecelerateInterpolator;
     23 import android.view.animation.Interpolator;
     24 
     25 import com.android.gallery3d.ui.GLCanvas;
     26 import com.android.gallery3d.ui.RawTexture;
     27 
     28 /**
     29  * Class to handle the capture animation.
     30  */
     31 public class CaptureAnimManager {
     32 
     33     private static final String TAG = "CaptureAnimManager";
     34     private static final float ZOOM_DELTA = 0.2f;  // The amount of change for zooming out.
     35     private static final float ZOOM_IN_BEGIN = 1f - ZOOM_DELTA;  // Pre-calculated value for
     36                                                                  // convenience.
     37     private static final float CAPTURE_ANIM_DURATION = 700;  // milliseconds.
     38     private static final float GAP_RATIO = 0.1f;  // The gap between preview and review based
     39                                                   // on the view dimension.
     40     private static final float TOTAL_RATIO = 1f + GAP_RATIO;
     41 
     42     private final Interpolator mZoomOutInterpolator = new DecelerateInterpolator();
     43     private final Interpolator mZoomInInterpolator = new AccelerateInterpolator();
     44     private final Interpolator mSlideInterpolator = new AccelerateDecelerateInterpolator();
     45 
     46     private int mAnimOrientation;  // Could be 0, 90, 180 or 270 degrees.
     47     private long mAnimStartTime;  // milliseconds.
     48     private float mCenterX;  // The center of the whole view including preview and review.
     49     private float mCenterY;
     50     private float mCenterDelta;  // The amount of the center will move after whole animation.
     51     private float mGap;  // mGap = (width or height) * GAP_RATIO. (depends on orientation)
     52     private int mDrawWidth;
     53     private int mDrawHeight;
     54     private float mHalfGap;  // mHalfGap = mGap / 2f.
     55 
     56     /* preview: camera preview view.
     57      * review: view of picture just taken.
     58      */
     59     public CaptureAnimManager() {
     60     }
     61 
     62     public void setOrientation(int animOrientation) {
     63         mAnimOrientation = animOrientation;
     64     }
     65 
     66     // x, y, w and h: the rectangle area where the animation takes place.
     67     // transformMatrix: used to show the texture.
     68     public void startAnimation(int x, int y, int w, int h) {
     69         mAnimStartTime = SystemClock.uptimeMillis();
     70         // Set the views to the initial positions.
     71         mDrawWidth = w;
     72         mDrawHeight = h;
     73         switch (mAnimOrientation) {
     74             case 0:  // Preview is on the left.
     75                 mGap = w * GAP_RATIO;
     76                 mHalfGap = mGap / 2f;
     77                 mCenterX = x - mHalfGap;
     78                 mCenterDelta = w * (TOTAL_RATIO);
     79                 mCenterY = y + h / 2f;
     80                 break;
     81             case 90:  // Preview is below.
     82                 mGap = h * GAP_RATIO;
     83                 mHalfGap = mGap / 2f;
     84                 mCenterY = y + h + mHalfGap;
     85                 mCenterDelta = -h * (TOTAL_RATIO);
     86                 mCenterX = x + w / 2f;
     87                 break;
     88             case 180:  // Preview on the right.
     89                 mGap = w * GAP_RATIO;
     90                 mHalfGap = mGap / 2f;
     91                 mCenterX = x + mHalfGap;
     92                 mCenterDelta = -w * (TOTAL_RATIO);
     93                 mCenterY = y + h / 2f;
     94                 break;
     95             case 270:  // Preview is above.
     96                 mGap = h * GAP_RATIO;
     97                 mHalfGap = mGap / 2f;
     98                 mCenterY = y - mHalfGap;
     99                 mCenterDelta = h * (TOTAL_RATIO);
    100                 mCenterX = x + w / 2f;
    101                 break;
    102         }
    103     }
    104 
    105     // Returns true if the animation has been drawn.
    106     public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview,
    107                 RawTexture review) {
    108         long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;
    109         if (timeDiff > CAPTURE_ANIM_DURATION) return false;
    110         float fraction = timeDiff / CAPTURE_ANIM_DURATION;
    111         float scale = calculateScale(fraction);
    112         float centerX = mCenterX;
    113         float centerY = mCenterY;
    114         if (mAnimOrientation == 0 || mAnimOrientation == 180) {
    115             centerX = mCenterX + mCenterDelta * mSlideInterpolator.getInterpolation(fraction);
    116         } else {
    117             centerY = mCenterY + mCenterDelta * mSlideInterpolator.getInterpolation(fraction);
    118         }
    119 
    120         float height = mDrawHeight * scale;
    121         float width = mDrawWidth * scale;
    122         int previewX = (int) centerX;
    123         int previewY = (int) centerY;
    124         int reviewX = (int) centerX;
    125         int reviewY = (int) centerY;
    126         switch (mAnimOrientation) {
    127             case 0:
    128                 previewX = Math.round(centerX - width - mHalfGap * scale);
    129                 previewY = Math.round(centerY - height / 2f);
    130                 reviewX = Math.round(centerX + mHalfGap * scale);
    131                 reviewY = previewY;
    132                 break;
    133             case 90:
    134                 previewY = Math.round(centerY + mHalfGap * scale);
    135                 previewX = Math.round(centerX - width / 2f);
    136                 reviewY = Math.round(centerY - height - mHalfGap * scale);
    137                 reviewX = previewX;
    138                 break;
    139             case 180:
    140                 previewX = Math.round(centerX + width + mHalfGap * scale);
    141                 previewY = Math.round(centerY - height / 2f);
    142                 reviewX = Math.round(centerX - mHalfGap * scale);
    143                 reviewY = previewY;
    144                 break;
    145             case 270:
    146                 previewY = Math.round(centerY - height - mHalfGap * scale);
    147                 previewX = Math.round(centerX - width / 2f);
    148                 reviewY = Math.round(centerY + mHalfGap * scale);
    149                 reviewX = previewX;
    150                 break;
    151         }
    152         float alpha = canvas.getAlpha();
    153         canvas.setAlpha(fraction);
    154         preview.directDraw(canvas, previewX, previewY, Math.round(width), Math.round(height));
    155         canvas.setAlpha(alpha);
    156 
    157         review.draw(canvas, reviewX, reviewY, (int) width, (int) height);
    158         return true;
    159     }
    160 
    161     // Calculate the zoom factor based on the given time fraction.
    162     private float calculateScale(float fraction) {
    163         float value = 1f;
    164         if (fraction <= 0.5f) {
    165             // Zoom in for the beginning.
    166             value = 1f - ZOOM_DELTA * mZoomOutInterpolator.getInterpolation(
    167                     fraction * 2);
    168         } else {
    169             // Zoom out for the last.
    170             value = ZOOM_IN_BEGIN + ZOOM_DELTA * mZoomInInterpolator.getInterpolation(
    171                     (fraction - 0.5f) * 2f);
    172         }
    173         return value;
    174     }
    175 }
    176