CaptureAnimManager.java revision 351b7a85f40c6a2bcb5fb0e7eeb61002c376bb29
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 17package com.android.camera; 18 19import android.view.animation.AccelerateDecelerateInterpolator; 20import android.view.animation.AccelerateInterpolator; 21import android.view.animation.DecelerateInterpolator; 22import android.view.animation.Interpolator; 23import android.os.SystemClock; 24 25import com.android.gallery3d.ui.GLCanvas; 26import com.android.gallery3d.ui.Raw2DTexture; 27 28/** 29 * Class to handle the capture animation. 30 */ 31public 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 = 800; // 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 int mDrawX; 55 private int mDrawY; 56 private float mHalfGap; // mHalfGap = mGap / 2f. 57 private float[] mTextureTransformMatrix; 58 59 /* preview: camera preview view. 60 * review: view of picture just taken. 61 */ 62 public CaptureAnimManager() { 63 } 64 65 public void setOrientation(int animOrientation) { 66 mAnimOrientation = animOrientation; 67 } 68 69 // x, y, h and h: the rectangle area where the animation takes place in. 70 // transformMatrix: used to show the texture. 71 public void startAnimation(int x, int y, int w, int h, float[] transformMatrix) { 72 mAnimStartTime = SystemClock.uptimeMillis(); 73 mTextureTransformMatrix = transformMatrix; 74 // Set the views to the initial positions. 75 mDrawWidth = w; 76 mDrawHeight = h; 77 mDrawX = x; 78 mDrawY = y; 79 switch (mAnimOrientation) { 80 case 0: // Preview is on the left. 81 mGap = w * GAP_RATIO; 82 mHalfGap = mGap / 2f; 83 mCenterX = x - mHalfGap; 84 mCenterDelta = w * (TOTAL_RATIO); 85 mCenterY = y + h / 2f; 86 break; 87 case 90: // Preview is below. 88 mGap = h * GAP_RATIO; 89 mHalfGap = mGap / 2f; 90 mCenterY = y + h + mHalfGap; 91 mCenterDelta = -h * (TOTAL_RATIO); 92 mCenterX = x + w / 2f; 93 break; 94 case 180: // Preview on the right. 95 mGap = w * GAP_RATIO; 96 mHalfGap = mGap / 2f; 97 mCenterX = x + mHalfGap; 98 mCenterDelta = -w * (TOTAL_RATIO); 99 mCenterY = y + h / 2f; 100 break; 101 case 270: // Preview is above. 102 mGap = h * GAP_RATIO; 103 mHalfGap = mGap / 2f; 104 mCenterY = y - mHalfGap; 105 mCenterDelta = h * (TOTAL_RATIO); 106 mCenterX = x + w / 2f; 107 break; 108 } 109 } 110 111 // Returns true if the animation has been drawn. 112 public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview, 113 Raw2DTexture review) { 114 long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;; 115 if (timeDiff > CAPTURE_ANIM_DURATION) return false; 116 float fraction = timeDiff / CAPTURE_ANIM_DURATION; 117 float scale = calculateScale(fraction); 118 float centerX = mCenterX; 119 float centerY = mCenterY; 120 if (mAnimOrientation == 0 || mAnimOrientation == 180) { 121 centerX = mCenterX + mCenterDelta * mSlideInterpolator.getInterpolation(fraction); 122 } else { 123 centerY = mCenterY + mCenterDelta * mSlideInterpolator.getInterpolation(fraction); 124 } 125 126 float height = mDrawHeight * scale; 127 float width = mDrawWidth * scale; 128 int previewX = (int) centerX; 129 int previewY = (int) centerY; 130 int reviewX = (int) centerX; 131 int reviewY = (int) centerY; 132 switch (mAnimOrientation) { 133 case 0: 134 previewX = Math.round(centerX - width - mHalfGap * scale); 135 previewY = Math.round(centerY - height / 2f); 136 reviewX = Math.round(centerX + mHalfGap * scale); 137 reviewY = previewY; 138 break; 139 case 90: 140 previewY = Math.round(centerY + mHalfGap * scale); 141 previewX = Math.round(centerX - width / 2f); 142 reviewY = Math.round(centerY - height - mHalfGap * scale); 143 reviewX = previewX; 144 break; 145 case 180: 146 previewX = Math.round(centerX + width + mHalfGap * scale); 147 previewY = Math.round(centerY - height / 2f); 148 reviewX = Math.round(centerX - mHalfGap * scale); 149 reviewY = previewY; 150 break; 151 case 270: 152 previewY = Math.round(centerY - height - mHalfGap * scale); 153 previewX = Math.round(centerX - width / 2f); 154 reviewY = Math.round(centerY + mHalfGap * scale); 155 reviewX = previewX; 156 break; 157 } 158 float alpha = canvas.getAlpha(); 159 canvas.setAlpha(fraction); 160 preview.directDraw(canvas, previewX, previewY, Math.round(width), Math.round(height)); 161 canvas.setAlpha(alpha); 162 163 // Flip animation texture vertically. OpenGL uses bottom left point as the origin (0,0). 164 canvas.save(GLCanvas.SAVE_FLAG_MATRIX); 165 int cx = Math.round(reviewX + width / 2); 166 int cy = Math.round(reviewY + height / 2); 167 canvas.translate(cx, cy); 168 canvas.scale(1, -1, 1); 169 canvas.translate(-cx, -cy); 170 canvas.drawTexture(review, mTextureTransformMatrix, 171 reviewX, reviewY, (int) width, (int) height); 172 canvas.restore(); 173 174 return true; 175 } 176 177 // Calculate the zoom factor based on the given time fraction. 178 private float calculateScale(float fraction) { 179 float value = 1f; 180 if (fraction <= 0.5f) { 181 // Zoom in for the beginning. 182 value = 1f - ZOOM_DELTA * mZoomOutInterpolator.getInterpolation( 183 fraction * 2); 184 } else { 185 // Zoom out for the last. 186 value = ZOOM_IN_BEGIN + ZOOM_DELTA * mZoomInInterpolator.getInterpolation( 187 (fraction - 0.5f) * 2f); 188 } 189 return value; 190 } 191} 192