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 
17 package com.android.camera.ui;
18 
19 import com.android.camera.R;
20 import com.android.camera.Util;
21 
22 import android.content.Context;
23 import android.graphics.Canvas;
24 import android.graphics.Matrix;
25 import android.graphics.RectF;
26 import android.graphics.drawable.Drawable;
27 import android.hardware.Camera.Face;
28 import android.util.AttributeSet;
29 import android.util.Log;
30 import android.view.View;
31 
32 public 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 
FaceView(Context context, AttributeSet attrs)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 
setFaces(Face[] faces)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 
setDisplayOrientation(int orientation)66     public void setDisplayOrientation(int orientation) {
67         mDisplayOrientation = orientation;
68         if (LOGV) Log.v(TAG, "mDisplayOrientation=" + orientation);
69     }
70 
setOrientation(int orientation)71     public void setOrientation(int orientation) {
72         mOrientation = orientation;
73         invalidate();
74     }
75 
setMirror(boolean mirror)76     public void setMirror(boolean mirror) {
77         mMirror = mirror;
78         if (LOGV) Log.v(TAG, "mMirror=" + mirror);
79     }
80 
faceExists()81     public boolean faceExists() {
82         return (mFaces != null && mFaces.length > 0);
83     }
84 
85     @Override
showStart()86     public void showStart() {
87         mFaceIndicator = mDrawableFocusing;
88         invalidate();
89     }
90 
91     @Override
showSuccess()92     public void showSuccess() {
93         mFaceIndicator = mDrawableFocused;
94         invalidate();
95     }
96 
97     @Override
showFail()98     public void showFail() {
99         mFaceIndicator = mDrawableFocusFailed;
100         invalidate();
101     }
102 
103     @Override
clear()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 
pause()112     public void pause() {
113         mPause = true;
114     }
115 
resume()116     public void resume() {
117         mPause = false;
118     }
119 
120     @Override
onDraw(Canvas canvas)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