/* * 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.graphics.Color; import android.os.SystemClock; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import com.android.gallery3d.glrenderer.GLCanvas; import com.android.gallery3d.glrenderer.RawTexture; /** * Class to handle the capture animation. */ public class CaptureAnimManager { @SuppressWarnings("unused") private static final String TAG = "CAM_Capture"; // times mark endpoint of animation phase private static final int TIME_FLASH = 200; private static final int TIME_HOLD = 400; private static final int TIME_SLIDE = 800; private static final int TIME_HOLD2 = 3300; private static final int TIME_SLIDE2 = 4100; private static final int ANIM_BOTH = 0; private static final int ANIM_FLASH = 1; private static final int ANIM_SLIDE = 2; private static final int ANIM_HOLD2 = 3; private static final int ANIM_SLIDE2 = 4; private final Interpolator mSlideInterpolator = new DecelerateInterpolator(); private int mAnimOrientation; // Could be 0, 90, 180 or 270 degrees. private long mAnimStartTime; // milliseconds. private float mX; // The center of the whole view including preview and review. private float mY; private int mDrawWidth; private int mDrawHeight; private int mAnimType; private int mHoldX; private int mHoldY; private int mHoldW; private int mHoldH; private int mOffset = 80; /* preview: camera preview view. * review: view of picture just taken. */ public CaptureAnimManager() { } public void setOrientation(int displayRotation) { mAnimOrientation = (360 - displayRotation) % 360; } public void animateSlide() { if (mAnimType != ANIM_FLASH) { return; } mAnimType = ANIM_SLIDE; mAnimStartTime = SystemClock.uptimeMillis(); } public void animateFlash() { mAnimType = ANIM_FLASH; } public void animateFlashAndSlide() { mAnimType = ANIM_BOTH; } // x, y, w and h: the rectangle area where the animation takes place. public void startAnimation(int x, int y, int w, int h) { mAnimStartTime = SystemClock.uptimeMillis(); // Set the views to the initial positions. mDrawWidth = w; mDrawHeight = h; mX = x; mY = y; mHoldW = (int) (mDrawWidth * 0.7f); mHoldH = (int) (mDrawHeight * 0.7f); switch (mAnimOrientation) { case 0: // Preview is on the left. mHoldX = x + w - mOffset; mHoldY = y + (mDrawHeight - mHoldH) / 2; break; case 90: // Preview is below. mHoldX = x + (mDrawWidth - mHoldW + 1) / 2; mHoldY = y + mOffset- mHoldH; break; case 180: // Preview on the right. mHoldX = x - w + mOffset; mHoldY = y + (mDrawHeight - mHoldH) / 2; break; case 270: // Preview is above. mHoldX = x + (mDrawWidth - mHoldW + 1) / 2; mHoldY = y + h - mOffset; break; } } // Returns true if the animation has been drawn. public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview, RawTexture review) { long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime; // Check if the animation is over if (mAnimType == ANIM_SLIDE && timeDiff > TIME_SLIDE2 - TIME_HOLD) return false; if (mAnimType == ANIM_BOTH && timeDiff > TIME_SLIDE2) return false; // determine phase and time in phase int animStep = mAnimType; if (mAnimType == ANIM_SLIDE) { timeDiff += TIME_HOLD; } if (mAnimType == ANIM_SLIDE || mAnimType == ANIM_BOTH) { if (timeDiff < TIME_HOLD) { animStep = ANIM_FLASH; } else if (timeDiff < TIME_SLIDE) { animStep = ANIM_SLIDE; timeDiff -= TIME_HOLD; } else if (timeDiff < TIME_HOLD2) { animStep = ANIM_HOLD2; timeDiff -= TIME_SLIDE; } else { // SLIDE2 animStep = ANIM_SLIDE2; timeDiff -= TIME_HOLD2; } } if (animStep == ANIM_FLASH) { review.draw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); if (timeDiff < TIME_FLASH) { float f = 0.3f - 0.3f * timeDiff / TIME_FLASH; int color = Color.argb((int) (255 * f), 255, 255, 255); canvas.fillRect(mX, mY, mDrawWidth, mDrawHeight, color); } } else if (animStep == ANIM_SLIDE) { float fraction = mSlideInterpolator.getInterpolation((float) (timeDiff) / (TIME_SLIDE - TIME_HOLD)); float x = mX; float y = mY; float w = 0; float h = 0; x = interpolate(mX, mHoldX, fraction); y = interpolate(mY, mHoldY, fraction); w = interpolate(mDrawWidth, mHoldW, fraction); h = interpolate(mDrawHeight, mHoldH, fraction); preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); review.draw(canvas, (int) x, (int) y, (int) w, (int) h); } else if (animStep == ANIM_HOLD2) { preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); review.draw(canvas, mHoldX, mHoldY, mHoldW, mHoldH); } else if (animStep == ANIM_SLIDE2) { float fraction = (float)(timeDiff) / (TIME_SLIDE2 - TIME_HOLD2); float x = mHoldX; float y = mHoldY; float d = mOffset * fraction; switch (mAnimOrientation) { case 0: x = mHoldX + d; break; case 180: x = mHoldX - d; break; case 90: y = mHoldY - d; break; case 270: y = mHoldY + d; break; } preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); review.draw(canvas, (int) x, (int) y, mHoldW, mHoldH); } return true; } private static float interpolate(float start, float end, float fraction) { return start + (end - start) * fraction; } }