1/*
2 * Copyright (C) 2011 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.ui;
18
19import com.android.camera.R;
20import com.android.camera.Util;
21
22import android.content.Context;
23import android.graphics.Canvas;
24import android.graphics.Matrix;
25import android.graphics.RectF;
26import android.graphics.drawable.Drawable;
27import android.hardware.Camera.Face;
28import android.util.AttributeSet;
29import android.util.Log;
30import android.view.View;
31
32public class FaceView extends View implements FocusIndicator, Rotatable {
33    private final String TAG = "FaceView";
34    private final boolean LOGV = false;
35    // The value for android.hardware.Camera.setDisplayOrientation.
36    private int mDisplayOrientation;
37    // The orientation compensation for the face indicator to make it look
38    // correctly in all device orientations. Ex: if the value is 90, the
39    // indicator should be rotated 90 degrees counter-clockwise.
40    private int mOrientation;
41    private boolean mMirror;
42    private boolean mPause;
43    private Matrix mMatrix = new Matrix();
44    private RectF mRect = new RectF();
45    private Face[] mFaces;
46    private Drawable mFaceIndicator;
47    private final Drawable mDrawableFocusing;
48    private final Drawable mDrawableFocused;
49    private final Drawable mDrawableFocusFailed;
50
51    public FaceView(Context context, AttributeSet attrs) {
52        super(context, attrs);
53        mDrawableFocusing = getResources().getDrawable(R.drawable.ic_focus_focusing);
54        mDrawableFocused = getResources().getDrawable(R.drawable.ic_focus_face_focused);
55        mDrawableFocusFailed = getResources().getDrawable(R.drawable.ic_focus_failed);
56        mFaceIndicator = mDrawableFocusing;
57    }
58
59    public void setFaces(Face[] faces) {
60        if (LOGV) Log.v(TAG, "Num of faces=" + faces.length);
61        if (mPause) return;
62        mFaces = faces;
63        invalidate();
64    }
65
66    public void setDisplayOrientation(int orientation) {
67        mDisplayOrientation = orientation;
68        if (LOGV) Log.v(TAG, "mDisplayOrientation=" + orientation);
69    }
70
71    public void setOrientation(int orientation) {
72        mOrientation = orientation;
73        invalidate();
74    }
75
76    public void setMirror(boolean mirror) {
77        mMirror = mirror;
78        if (LOGV) Log.v(TAG, "mMirror=" + mirror);
79    }
80
81    public boolean faceExists() {
82        return (mFaces != null && mFaces.length > 0);
83    }
84
85    @Override
86    public void showStart() {
87        mFaceIndicator = mDrawableFocusing;
88        invalidate();
89    }
90
91    @Override
92    public void showSuccess() {
93        mFaceIndicator = mDrawableFocused;
94        invalidate();
95    }
96
97    @Override
98    public void showFail() {
99        mFaceIndicator = mDrawableFocusFailed;
100        invalidate();
101    }
102
103    @Override
104    public void clear() {
105        // Face indicator is displayed during preview. Do not clear the
106        // drawable.
107        mFaceIndicator = mDrawableFocusing;
108        mFaces = null;
109        invalidate();
110    }
111
112    public void pause() {
113        mPause = true;
114    }
115
116    public void resume() {
117        mPause = false;
118    }
119
120    @Override
121    protected void onDraw(Canvas canvas) {
122        if (mFaces != null && mFaces.length > 0) {
123            // Prepare the matrix.
124            Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, getWidth(), getHeight());
125
126            // Focus indicator is directional. Rotate the matrix and the canvas
127            // so it looks correctly in all orientations.
128            canvas.save();
129            mMatrix.postRotate(mOrientation); // postRotate is clockwise
130            canvas.rotate(-mOrientation); // rotate is counter-clockwise (for canvas)
131            for (int i = 0; i < mFaces.length; i++) {
132                // Transform the coordinates.
133                mRect.set(mFaces[i].rect);
134                if (LOGV) Util.dumpRect(mRect, "Original rect");
135                mMatrix.mapRect(mRect);
136                if (LOGV) Util.dumpRect(mRect, "Transformed rect");
137
138                mFaceIndicator.setBounds(Math.round(mRect.left), Math.round(mRect.top),
139                        Math.round(mRect.right), Math.round(mRect.bottom));
140                mFaceIndicator.draw(canvas);
141            }
142            canvas.restore();
143        }
144        super.onDraw(canvas);
145    }
146}
147