14d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb/* 24d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * Copyright (C) 2012 The Android Open Source Project 34d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * 44d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * Licensed under the Apache License, Version 2.0 (the "License"); 54d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * you may not use this file except in compliance with the License. 64d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * You may obtain a copy of the License at 74d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * 84d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * http://www.apache.org/licenses/LICENSE-2.0 94d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * 104d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * Unless required by applicable law or agreed to in writing, software 114d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * distributed under the License is distributed on an "AS IS" BASIS, 124d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * See the License for the specific language governing permissions and 144d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb * limitations under the License. 154d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb */ 164d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 174d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbpackage com.android.camera.ui; 184d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 194d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.content.Context; 204d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.content.res.Resources; 214d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.graphics.Canvas; 224d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.graphics.Color; 234d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.graphics.Paint; 245ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolbimport android.graphics.Rect; 254d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport android.view.ScaleGestureDetector; 264d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 274d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbimport com.android.camera.R; 284d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 294d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolbpublic class ZoomRenderer extends OverlayRenderer 304d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb implements ScaleGestureDetector.OnScaleGestureListener { 314d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 324d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private static final String TAG = "CAM_Zoom"; 334d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 344d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private int mMaxZoom; 355ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb private int mMinZoom; 364d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private OnZoomChangedListener mListener; 374d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 384d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private ScaleGestureDetector mDetector; 394d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private Paint mPaint; 405ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb private Paint mTextPaint; 414d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private int mCircleSize; 424d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private int mCenterX; 434d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private int mCenterY; 444d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private float mMaxCircle; 454d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb private float mMinCircle; 460f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb private int mInnerStroke; 470f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb private int mOuterStroke; 485ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb private int mZoomSig; 495ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb private int mZoomFraction; 505ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb private Rect mTextBounds; 514d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 524d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public interface OnZoomChangedListener { 534d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb void onZoomStart(); 544d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb void onZoomEnd(); 554d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb void onZoomValueChanged(int index); // only for immediate zoom 564d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 574d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 584d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public ZoomRenderer(Context ctx) { 594d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb Resources res = ctx.getResources(); 604d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mPaint = new Paint(); 614d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mPaint.setAntiAlias(true); 624d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mPaint.setColor(Color.WHITE); 634d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mPaint.setStyle(Paint.Style.STROKE); 645ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint = new Paint(mPaint); 655ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint.setStyle(Paint.Style.FILL); 665ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint.setTextSize(res.getDimensionPixelSize(R.dimen.zoom_font_size)); 675ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint.setTextAlign(Paint.Align.LEFT); 685ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint.setAlpha(192); 690f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke); 700f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke); 714d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mDetector = new ScaleGestureDetector(ctx, this); 724d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mMinCircle = res.getDimensionPixelSize(R.dimen.zoom_ring_min); 735ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextBounds = new Rect(); 74ad639dff251233032734106afe4fe51a52be3721Michael Kolb setVisible(false); 754d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 764d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 774d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb // set from module 785ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb public void setZoomMax(int zoomMaxIndex) { 795ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mMaxZoom = zoomMaxIndex; 805ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mMinZoom = 0; 814d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 824d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 830af8a3b2ce98424614dd2ac33ec896142851dab5Michael Kolb public void setZoom(int index) { 840af8a3b2ce98424614dd2ac33ec896142851dab5Michael Kolb mCircleSize = (int) (mMinCircle + index * (mMaxCircle - mMinCircle) / (mMaxZoom - mMinZoom)); 850af8a3b2ce98424614dd2ac33ec896142851dab5Michael Kolb } 860af8a3b2ce98424614dd2ac33ec896142851dab5Michael Kolb 875ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb public void setZoomValue(int value) { 885ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb value = value / 10; 895ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mZoomSig = value / 10; 905ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mZoomFraction = value % 10; 914d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 924d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 934d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public void setOnZoomChangeListener(OnZoomChangedListener listener) { 944d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mListener = listener; 954d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 964d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 974d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb @Override 984d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public void layout(int l, int t, int r, int b) { 994d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb super.layout(l, t, r, b); 1004d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mCenterX = (r - l) / 2; 1014d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mCenterY = (b - t) / 2; 1024d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mMaxCircle = Math.min(getWidth(), getHeight()); 1034d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mMaxCircle = (mMaxCircle - mMinCircle) / 2; 1044d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1054d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1064d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public boolean isScaling() { 1074d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb return mDetector.isInProgress(); 1084d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1094d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1104d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb @Override 1114d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public void onDraw(Canvas canvas) { 1120f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb mPaint.setStrokeWidth(mInnerStroke); 1130f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb canvas.drawCircle(mCenterX, mCenterY, mMinCircle, mPaint); 1140f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb canvas.drawCircle(mCenterX, mCenterY, mMaxCircle, mPaint); 1150f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb canvas.drawLine(mCenterX - mMinCircle, mCenterY, 1160f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb mCenterX - mMaxCircle - 4, mCenterY, mPaint); 1170f1cc66c395becb393ccd99d92475329bc6bdef5Michael Kolb mPaint.setStrokeWidth(mOuterStroke); 118ad639dff251233032734106afe4fe51a52be3721Michael Kolb canvas.drawCircle((float) mCenterX, (float) mCenterY, 119ad639dff251233032734106afe4fe51a52be3721Michael Kolb (float) mCircleSize, mPaint); 1205ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb String txt = mZoomSig+"."+mZoomFraction+"x"; 1215ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint.getTextBounds(txt, 0, txt.length(), mTextBounds); 1225ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb canvas.drawText(txt, mCenterX - mTextBounds.centerX(), mCenterY - mTextBounds.centerY(), 1235ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mTextPaint); 1244d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1254d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1264d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb @Override 1274d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public boolean onScale(ScaleGestureDetector detector) { 1288fd37ebbf180eb58f77ce80b07f2fd26f2bfd52aMichael Kolb final float sf = detector.getScaleFactor(); 1298fd37ebbf180eb58f77ce80b07f2fd26f2bfd52aMichael Kolb float circle = (int) (mCircleSize * sf * sf); 1305ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb circle = Math.max(mMinCircle, circle); 1315ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb circle = Math.min(mMaxCircle, circle); 1325ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb if (mListener != null && (int) circle != mCircleSize) { 1335ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mCircleSize = (int) circle; 1345ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle)); 1355ed54678384a922550428bb7ba1a3f2475c70bd3Michael Kolb mListener.onZoomValueChanged(zoom); 1364d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1374d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb return true; 1384d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1394d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1404d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb @Override 1414d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public boolean onScaleBegin(ScaleGestureDetector detector) { 142ad639dff251233032734106afe4fe51a52be3721Michael Kolb setVisible(true); 1434d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb if (mListener != null) { 1444d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mListener.onZoomStart(); 1454d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 146ad639dff251233032734106afe4fe51a52be3721Michael Kolb update(); 1474d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb return true; 1484d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1494d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1504d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb @Override 1514d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb public void onScaleEnd(ScaleGestureDetector detector) { 152ad639dff251233032734106afe4fe51a52be3721Michael Kolb setVisible(false); 1534d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb if (mListener != null) { 1544d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb mListener.onZoomEnd(); 1554d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1564d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb } 1574d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb 1584d628bcbaf4e6f2330dc9619f2129770863666dcMichael Kolb} 159