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