diff options
Diffstat (limited to 'src/com/android/camera/ui/focus/FocusRingView.java')
-rw-r--r-- | src/com/android/camera/ui/focus/FocusRingView.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/com/android/camera/ui/focus/FocusRingView.java b/src/com/android/camera/ui/focus/FocusRingView.java new file mode 100644 index 000000000..14a7f6cc9 --- /dev/null +++ b/src/com/android/camera/ui/focus/FocusRingView.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2014 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.focus; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.RectF; +import android.graphics.Region; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +import com.android.camera.ui.motion.AnimationClock.SystemTimeClock; +import com.android.camera.ui.motion.DynamicAnimator; +import com.android.camera.ui.motion.Invalidator; +import com.android.camera.ui.motion.LinearScale; + +import org.codeaurora.snapcam.R; + +/** + * Custom view for running the focus ring animations. + */ +public class FocusRingView extends View implements Invalidator, FocusRing { + private static final String TAG = "FocusRingView"; + private static final float FADE_IN_DURATION_MILLIS = 1000f; + private static final float FADE_OUT_DURATION_MILLIS = 250f; + + private final AutoFocusRing mAutoFocusRing; + private final ManualFocusRing mManualFocusRing; + private final DynamicAnimator mAnimator; + private final LinearScale mRatioScale; + private final float mDefaultRadiusPx; + + private FocusRingRenderer currentFocusAnimation; + private boolean isFirstDraw; + private float mLastRadiusPx; + + private RectF mPreviewSize; + + public FocusRingView(Context context, AttributeSet attrs) { + super(context, attrs); + + Resources res = getResources(); + Paint paint = makePaint(res, R.color.focus_color); + + float focusCircleMinSize = res.getDimensionPixelSize(R.dimen.focus_circle_min_size); + float focusCircleMaxSize = res.getDimensionPixelSize(R.dimen.focus_circle_max_size); + mDefaultRadiusPx = res.getDimensionPixelSize(R.dimen.focus_circle_initial_size); + + mRatioScale = new LinearScale(0, 1, focusCircleMinSize, focusCircleMaxSize); + mAnimator = new DynamicAnimator(this, new SystemTimeClock()); + + mAutoFocusRing = new AutoFocusRing(mAnimator, paint, + FADE_IN_DURATION_MILLIS, + FADE_OUT_DURATION_MILLIS); + mManualFocusRing = new ManualFocusRing(mAnimator, paint, + FADE_OUT_DURATION_MILLIS); + + mAnimator.animations.add(mAutoFocusRing); + mAnimator.animations.add(mManualFocusRing); + + isFirstDraw = true; + mLastRadiusPx = mDefaultRadiusPx; + } + + @Override + public boolean isPassiveFocusRunning() { + return mAutoFocusRing.isActive(); + } + + @Override + public boolean isActiveFocusRunning() { + return mManualFocusRing.isActive(); + } + + @Override + public void startPassiveFocus() { + mAnimator.invalidate(); + long tMs = mAnimator.getTimeMillis(); + + if (mManualFocusRing.isActive() && !mManualFocusRing.isExiting()) { + mManualFocusRing.stop(tMs); + } + + mAutoFocusRing.start(tMs, mLastRadiusPx, mLastRadiusPx); + currentFocusAnimation = mAutoFocusRing; + } + + @Override + public void startActiveFocus() { + mAnimator.invalidate(); + long tMs = mAnimator.getTimeMillis(); + + if (mAutoFocusRing.isActive() && !mAutoFocusRing.isExiting()) { + mAutoFocusRing.stop(tMs); + } + + mManualFocusRing.start(tMs, 0.0f, mLastRadiusPx); + currentFocusAnimation = mManualFocusRing; + } + + @Override + public void stopFocusAnimations() { + long tMs = mAnimator.getTimeMillis(); + if (mManualFocusRing.isActive() && !mManualFocusRing.isExiting() + && !mManualFocusRing.isEntering()) { + mManualFocusRing.exit(tMs); + } + + if (mAutoFocusRing.isActive() && !mAutoFocusRing.isExiting()) { + mAutoFocusRing.exit(tMs); + } + } + + @Override + public void setFocusLocation(float viewX, float viewY) { + mAutoFocusRing.setCenterX((int) viewX); + mAutoFocusRing.setCenterY((int) viewY); + mManualFocusRing.setCenterX((int) viewX); + mManualFocusRing.setCenterY((int) viewY); + } + + @Override + public void centerFocusLocation() { + Point center = computeCenter(); + mAutoFocusRing.setCenterX(center.x); + mAutoFocusRing.setCenterY(center.y); + mManualFocusRing.setCenterX(center.x); + mManualFocusRing.setCenterY(center.y); + } + + @Override + public void setRadiusRatio(float ratio) { + setRadius(mRatioScale.scale(mRatioScale.clamp(ratio))); + } + + @Override + public void configurePreviewDimensions(RectF previewArea) { + mPreviewSize = previewArea; + mLastRadiusPx = mDefaultRadiusPx; + + if (!isFirstDraw) { + centerAutofocusRing(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (isFirstDraw) { + isFirstDraw = false; + centerAutofocusRing(); + } + + if (mPreviewSize != null) { + canvas.clipRect(mPreviewSize, Region.Op.REPLACE); + } + + mAnimator.draw(canvas); + } + + private void setRadius(float radiusPx) { + long tMs = mAnimator.getTimeMillis(); + // Some devices return zero for invalid or "unknown" diopter values. + if (currentFocusAnimation != null && radiusPx > 0.1f) { + currentFocusAnimation.setRadius(tMs, radiusPx); + mLastRadiusPx = radiusPx; + } + } + + private void centerAutofocusRing() { + Point center = computeCenter(); + mAutoFocusRing.setCenterX(center.x); + mAutoFocusRing.setCenterY(center.y); + } + + private Point computeCenter() { + if (mPreviewSize != null && (mPreviewSize.width() * mPreviewSize.height() > 0.01f)) { + Log.i(TAG, "Computing center via preview size."); + return new Point((int) mPreviewSize.centerX(), (int) mPreviewSize.centerY()); + } + Log.i(TAG, "Computing center via view bounds."); + return new Point(getWidth() / 2, getHeight() / 2); + } + + private Paint makePaint(Resources res, int color) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setColor(res.getColor(color)); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeWidth(res.getDimension(R.dimen.focus_circle_stroke)); + return paint; + } +} |