/*
* 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.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.SystemClock;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.android.gallery3d.R;
import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.glrenderer.NinePatchTexture;
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 volatile 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;
private int mMarginRight;
private int mMarginTop;
private int mSize;
private Resources mResources;
private NinePatchTexture mBorder;
private int mShadowSize;
public static int getAnimationDuration() {
return TIME_SLIDE2;
}
/* preview: camera preview view.
* review: view of picture just taken.
*/
public CaptureAnimManager(Context ctx) {
mBorder = new NinePatchTexture(ctx, R.drawable.capture_thumbnail_shadow);
mResources = ctx.getResources();
}
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;
}
public void startAnimation() {
mAnimStartTime = SystemClock.uptimeMillis();
}
private void setAnimationGeometry(int x, int y, int w, int h) {
mMarginRight = mResources.getDimensionPixelSize(R.dimen.capture_margin_right);
mMarginTop = mResources.getDimensionPixelSize(R.dimen.capture_margin_top);
mSize = mResources.getDimensionPixelSize(R.dimen.capture_size);
mShadowSize = mResources.getDimensionPixelSize(R.dimen.capture_border);
mOffset = mMarginRight + mSize;
// Set the views to the initial positions.
mDrawWidth = w;
mDrawHeight = h;
mX = x;
mY = y;
mHoldW = mSize;
mHoldH = mSize;
switch (mAnimOrientation) {
case 0: // Preview is on the left.
mHoldX = x + w - mMarginRight - mSize;
mHoldY = y + mMarginTop;
break;
case 90: // Preview is below.
mHoldX = x + mMarginTop;
mHoldY = y + mMarginRight;
break;
case 180: // Preview on the right.
mHoldX = x + mMarginRight;
mHoldY = y + h - mMarginTop - mSize;
break;
case 270: // Preview is above.
mHoldX = x + w - mMarginTop - mSize;
mHoldY = y + h - mMarginRight - mSize;
break;
}
}
// Returns true if the animation has been drawn.
public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview,
RawTexture review, int lx, int ly, int lw, int lh) {
setAnimationGeometry(lx, ly, lw, lh);
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);
mBorder.draw(canvas, (int) mHoldX - mShadowSize, (int) mHoldY - mShadowSize,
(int) mHoldW + 2 * mShadowSize, (int) mHoldH + 2 * mShadowSize);
} 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);
mBorder.draw(canvas, (int) x - mShadowSize, (int) y - mShadowSize,
(int) mHoldW + 2 * mShadowSize, (int) mHoldH + 2 * mShadowSize);
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;
}
}