blob: bd913d4f6922c743039dc957dcb5ec3cdbd40206 [file] [log] [blame]
/*
* Copyright (C) 2013 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.ui;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import com.android.camera.FocusOverlayManager;
import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
import com.android.camera2.R;
/**
* Displays a focus indicator.
*/
public class FocusOverlay extends View implements FocusOverlayManager.FocusUI {
private static final Log.Tag TAG = new Log.Tag("FocusOverlay");
/** System Properties switch to enable debugging focus UI. */
private static final boolean CAPTURE_DEBUG_UI = DebugPropertyHelper.showCaptureDebugUI();
private final static int FOCUS_DURATION_MS = 500;
private final static int FOCUS_INDICATOR_ROTATION_DEGREES = 50;
private final Drawable mFocusIndicator;
private Drawable mFocusOuterRing;
private final Rect mBounds = new Rect();
private final ValueAnimator mFocusAnimation = new ValueAnimator();
private Paint mDebugSolidPaint;
private Paint mDebugCornersPaint;
private Paint mDebugTextPaint;
private int mDebugStartColor;
private int mDebugSuccessColor;
private int mDebugFailColor;
private Rect mFocusDebugSolidRect;
private Rect mFocusDebugCornersRect;
private boolean mIsPassiveScan;
private String mDebugMessage;
private int mPositionX;
private int mPositionY;
private int mAngle;
private final int mFocusIndicatorSize;
private boolean mShowIndicator;
private final int mFocusOuterRingSize;
public FocusOverlay(Context context, AttributeSet attrs) {
super(context, attrs);
mFocusIndicator = getResources().getDrawable(R.drawable.focus_ring_touch_inner);
mFocusIndicatorSize = getResources().getDimensionPixelSize(R.dimen.focus_inner_ring_size);
mFocusOuterRing = getResources().getDrawable(R.drawable.focus_ring_touch_outer);
mFocusOuterRingSize = getResources().getDimensionPixelSize(R.dimen.focus_outer_ring_size);
if (CAPTURE_DEBUG_UI) {
Resources res = getResources();
mDebugStartColor = res.getColor(R.color.focus_debug);
mDebugSuccessColor = res.getColor(R.color.focus_debug_success);
mDebugFailColor = res.getColor(R.color.focus_debug_fail);
mDebugTextPaint= new Paint();
mDebugTextPaint.setColor(res.getColor(R.color.focus_debug_text));
mDebugTextPaint.setStyle(Paint.Style.FILL);
mDebugSolidPaint = new Paint();
mDebugSolidPaint.setColor(res.getColor(R.color.focus_debug));
mDebugSolidPaint.setAntiAlias(true);
mDebugSolidPaint.setStyle(Paint.Style.STROKE);
mDebugSolidPaint.setStrokeWidth(res.getDimension(R.dimen.focus_debug_stroke));
mDebugCornersPaint = new Paint(mDebugSolidPaint);
mDebugCornersPaint.setColor(res.getColor(R.color.focus_debug));
mFocusDebugSolidRect = new Rect();
mFocusDebugCornersRect = new Rect();
}
}
@Override
public boolean hasFaces() {
// TODO: Add face detection support.
return false;
}
@Override
public void clearFocus() {
mShowIndicator = false;
if (CAPTURE_DEBUG_UI) {
setVisibility(INVISIBLE);
}
}
@Override
public void setFocusPosition(int x, int y, boolean isPassiveScan) {
setFocusPosition(x, y, isPassiveScan, 0, 0);
}
@Override
public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize) {
mIsPassiveScan = isPassiveScan;
mPositionX = x;
mPositionY = y;
mBounds.set(x - mFocusIndicatorSize / 2, y - mFocusIndicatorSize / 2,
x + mFocusIndicatorSize / 2, y + mFocusIndicatorSize / 2);
mFocusIndicator.setBounds(mBounds);
mFocusOuterRing.setBounds(x - mFocusOuterRingSize / 2, y - mFocusOuterRingSize / 2,
x + mFocusOuterRingSize / 2, y + mFocusOuterRingSize / 2);
if (CAPTURE_DEBUG_UI) {
mFocusOuterRing.setBounds(0, 0, 0, 0);
if (isPassiveScan) {
// Use AE rect only.
mFocusDebugSolidRect.setEmpty();
int avg = (aFsize + aEsize) / 2;
mFocusDebugCornersRect.set(x - avg / 2, y - avg / 2, x + avg / 2, y + avg / 2);
} else {
mFocusDebugSolidRect.set(x - aFsize / 2, y - aFsize / 2, x + aFsize / 2,
y + aFsize / 2);
// If AE region is different size than AF region and active scan.
if (aFsize != aEsize) {
mFocusDebugCornersRect.set(x - aEsize / 2, y - aEsize / 2, x + aEsize / 2,
y + aEsize / 2);
} else {
mFocusDebugCornersRect.setEmpty();
}
}
mDebugSolidPaint.setColor(mDebugStartColor);
mDebugCornersPaint.setColor(mDebugStartColor);
}
if (getVisibility() != VISIBLE) {
setVisibility(VISIBLE);
}
invalidate();
}
/**
* This is called in:
* <ul>
* <li>API1 non-CAF after autoFocus().</li>
* <li>API1 CAF mode for onAutoFocusMoving(true).</li>
* <li>API2 for transition to ACTIVE_SCANNING or PASSIVE_SCANNING.</li>
* <ul>
* TODO after PhotoModule/GcamModule deprecation: Do not use this for CAF.
*/
@Override
public void onFocusStarted() {
mShowIndicator = true;
mFocusAnimation.setIntValues(0, FOCUS_INDICATOR_ROTATION_DEGREES);
mFocusAnimation.setDuration(FOCUS_DURATION_MS);
mFocusAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAngle = (Integer) animation.getAnimatedValue();
invalidate();
}
});
mFocusAnimation.start();
if (CAPTURE_DEBUG_UI) {
mDebugMessage = null;
}
}
/**
* This is called in:
* <ul>
* <li>API1 non-CAF for onAutoFocus(true).</li>
* <li>API2 non-CAF for transition to FOCUSED_LOCKED.</li>
* <li>API1 CAF mode for onAutoFocusMoving(false).</li>
* <ul>
* TODO after PhotoModule/GcamModule deprecation: Do not use this for CAF.
*/
@Override
public void onFocusSucceeded() {
mFocusAnimation.cancel();
mShowIndicator = false;
if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
mDebugSolidPaint.setColor(mDebugSuccessColor);
}
invalidate();
}
/**
* This is called in:
* <ul>
* <li>API1 non-CAF for onAutoFocus(false).</li>
* <li>API2 non-CAF for transition to NOT_FOCUSED_LOCKED.</li>
* <ul>
*/
@Override
public void onFocusFailed() {
mFocusAnimation.cancel();
mShowIndicator = false;
if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
mDebugSolidPaint.setColor(mDebugFailColor);
}
invalidate();
}
/**
* This is called in:
* API2 for CAF state changes to PASSIVE_FOCUSED or PASSIVE_UNFOCUSED.
*/
@Override
public void setPassiveFocusSuccess(boolean success) {
mFocusAnimation.cancel();
mShowIndicator = false;
if (CAPTURE_DEBUG_UI) {
mDebugCornersPaint.setColor(success ? mDebugSuccessColor : mDebugFailColor);
}
invalidate();
}
@Override
public void showDebugMessage(String message) {
if (CAPTURE_DEBUG_UI) {
mDebugMessage = message;
}
}
@Override
public void pauseFaceDetection() {
// TODO: Add face detection support.
}
@Override
public void resumeFaceDetection() {
// TODO: Add face detection support.
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mShowIndicator) {
mFocusOuterRing.draw(canvas);
canvas.save();
canvas.rotate(mAngle, mPositionX, mPositionY);
mFocusIndicator.draw(canvas);
canvas.restore();
}
if (CAPTURE_DEBUG_UI) {
canvas.drawRect(mFocusDebugSolidRect, mDebugSolidPaint);
float delta = 0.1f * mFocusDebugCornersRect.width();
float left = mFocusDebugCornersRect.left;
float top = mFocusDebugCornersRect.top;
float right = mFocusDebugCornersRect.right;
float bot = mFocusDebugCornersRect.bottom;
canvas.drawLines(new float[]{left, top + delta, left, top, left, top, left + delta, top}, mDebugCornersPaint);
canvas.drawLines(new float[]{right, top + delta, right, top, right, top, right - delta, top}, mDebugCornersPaint);
canvas.drawLines(new float[]{left, bot - delta, left, bot, left, bot, left + delta, bot}, mDebugCornersPaint);
canvas.drawLines(new float[]{right, bot - delta, right, bot, right, bot, right - delta, bot}, mDebugCornersPaint);
if (mDebugMessage != null) {
mDebugTextPaint.setTextSize(40);
canvas.drawText(mDebugMessage, left - 4, bot + 44, mDebugTextPaint);
}
}
}
}