summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/HighlightView.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:32:20 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:32:20 -0800
commitb64d345c9d51cabce43b5191532a0c185d2a70a5 (patch)
treecb393a35078ffef3dc6d6c0cfa0d9cd349e8cf08 /src/com/android/camera/HighlightView.java
parentbecfb351a5bc43050128f44eb1bcfbcc0c6dcb7a (diff)
downloadLegacyCamera-b64d345c9d51cabce43b5191532a0c185d2a70a5.zip
LegacyCamera-b64d345c9d51cabce43b5191532a0c185d2a70a5.tar.gz
LegacyCamera-b64d345c9d51cabce43b5191532a0c185d2a70a5.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src/com/android/camera/HighlightView.java')
-rw-r--r--src/com/android/camera/HighlightView.java428
1 files changed, 428 insertions, 0 deletions
diff --git a/src/com/android/camera/HighlightView.java b/src/com/android/camera/HighlightView.java
new file mode 100644
index 0000000..408beab
--- /dev/null
+++ b/src/com/android/camera/HighlightView.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.drawable.Drawable;
+import android.util.Config;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+
+
+public class HighlightView
+{
+ private static final String TAG = "CropImage";
+ View mContext;
+ Path mPath;
+ Rect mViewDrawingRect = new Rect();
+
+ int mMotionMode;
+
+ public static final int GROW_NONE = (1 << 0);
+ public static final int GROW_LEFT_EDGE = (1 << 1);
+ public static final int GROW_RIGHT_EDGE = (1 << 2);
+ public static final int GROW_TOP_EDGE = (1 << 3);
+ public static final int GROW_BOTTOM_EDGE = (1 << 4);
+ public static final int MOVE = (1 << 5);
+
+ public HighlightView(View ctx)
+ {
+ super();
+ mContext = ctx;
+ mPath = new Path();
+ }
+
+ private void initHighlightView() {
+ android.content.res.Resources resources = mContext.getResources();
+ mResizeDrawableWidth = resources.getDrawable(R.drawable.camera_crop_width);
+ mResizeDrawableHeight = resources.getDrawable(R.drawable.camera_crop_height);
+ mResizeDrawableDiagonal = resources.getDrawable(R.drawable.indicator_autocrop);
+ }
+
+ boolean mIsFocused;
+ boolean mHidden;
+
+ public boolean hasFocus() {
+ return mIsFocused;
+ }
+
+ public void setFocus(boolean f) {
+ mIsFocused = f;
+ }
+
+ public void setHidden(boolean hidden) {
+ mHidden = hidden;
+ }
+
+ protected void draw(Canvas canvas) {
+ if (mHidden)
+ return;
+
+ canvas.save();
+ mPath.reset();
+ if (!hasFocus()) {
+ mOutlinePaint.setColor(0xFF000000);
+ canvas.drawRect(mDrawRect, mOutlinePaint);
+ } else {
+ mContext.getDrawingRect(mViewDrawingRect);
+ if (mCircle) {
+ float width = mDrawRect.width() - (getPaddingLeft() + getPaddingRight());
+ float height = mDrawRect.height() - (getPaddingTop() + getPaddingBottom());
+ mPath.addCircle(
+ mDrawRect.left + getPaddingLeft() + (width / 2),
+ mDrawRect.top + getPaddingTop() + (height / 2),
+ width / 2,
+ Path.Direction.CW);
+ mOutlinePaint.setColor(0xFFEF04D6);
+ } else {
+ mPath.addRect(new RectF(mDrawRect), Path.Direction.CW);
+ mOutlinePaint.setColor(0xFFFF8A00);
+ }
+ canvas.clipPath(mPath, Region.Op.DIFFERENCE);
+ canvas.drawRect(mViewDrawingRect, hasFocus() ? mFocusPaint : mNoFocusPaint);
+
+ canvas.restore();
+ canvas.drawPath(mPath, mOutlinePaint);
+
+ if (mMode == ModifyMode.Grow) {
+ if (mCircle) {
+ int width = mResizeDrawableDiagonal.getIntrinsicWidth();
+ int height = mResizeDrawableDiagonal.getIntrinsicHeight();
+
+ int d = (int) Math.round(Math.cos(/*45deg*/Math.PI/4D) * (mDrawRect.width() / 2D));
+ int x = mDrawRect.left + (mDrawRect.width() / 2) + d - width/2;
+ int y = mDrawRect.top + (mDrawRect.height() / 2) - d - height/2;
+ mResizeDrawableDiagonal.setBounds(x, y, x + mResizeDrawableDiagonal.getIntrinsicWidth(), y + mResizeDrawableDiagonal.getIntrinsicHeight());
+ mResizeDrawableDiagonal.draw(canvas);
+ } else {
+ int left = mDrawRect.left + 1;
+ int right = mDrawRect.right + 1;
+ int top = mDrawRect.top + 4;
+ int bottom = mDrawRect.bottom + 3;
+
+ int widthWidth = mResizeDrawableWidth.getIntrinsicWidth() / 2;
+ int widthHeight = mResizeDrawableWidth.getIntrinsicHeight()/ 2;
+ int heightHeight = mResizeDrawableHeight.getIntrinsicHeight()/ 2;
+ int heightWidth = mResizeDrawableHeight.getIntrinsicWidth()/ 2;
+
+ int xMiddle = mDrawRect.left + ((mDrawRect.right - mDrawRect.left) / 2);
+ int yMiddle = mDrawRect.top + ((mDrawRect.bottom - mDrawRect.top ) / 2);
+
+ mResizeDrawableWidth.setBounds(left-widthWidth, yMiddle-widthHeight, left+widthWidth, yMiddle+widthHeight);
+ mResizeDrawableWidth.draw(canvas);
+
+ mResizeDrawableWidth.setBounds(right-widthWidth, yMiddle-widthHeight, right+widthWidth, yMiddle+widthHeight);
+ mResizeDrawableWidth.draw(canvas);
+
+ mResizeDrawableHeight.setBounds(xMiddle-heightWidth, top-heightHeight, xMiddle+heightWidth, top+heightHeight);
+ mResizeDrawableHeight.draw(canvas);
+
+ mResizeDrawableHeight.setBounds(xMiddle-heightWidth, bottom-heightHeight, xMiddle+heightWidth, bottom+heightHeight);
+ mResizeDrawableHeight.draw(canvas);
+ }
+ }
+ }
+
+ }
+
+ float getPaddingTop() { return 0F; }
+ float getPaddingBottom() { return 0F; }
+ float getPaddingLeft() { return 0F; }
+ float getPaddingRight() { return 0F; }
+
+ public ModifyMode getMode() {
+ return mMode;
+ }
+
+ public void setMode(ModifyMode mode)
+ {
+ if (mode != mMode) {
+ mMode = mode;
+ mContext.invalidate();
+ }
+ }
+
+ public int getHit(float x, float y) {
+ Rect r = computeLayout();
+ final float hysteresis = 20F;
+ int retval = GROW_NONE;
+
+ if (mCircle) {
+ float distX = x - r.centerX();
+ float distY = y - r.centerY();
+ int distanceFromCenter = (int) Math.sqrt(distX*distX + distY*distY);
+ int radius = (int) (mDrawRect.width() - getPaddingLeft()) / 2;
+ int delta = distanceFromCenter - radius;
+ if (Math.abs(delta) <= hysteresis) {
+ if (Math.abs(distY) > Math.abs(distX)) {
+ if (distY < 0)
+ retval = GROW_TOP_EDGE;
+ else
+ retval = GROW_BOTTOM_EDGE;
+ } else {
+ if (distX < 0)
+ retval = GROW_LEFT_EDGE;
+ else
+ retval = GROW_RIGHT_EDGE;
+ }
+ } else if (distanceFromCenter < radius) {
+ retval = MOVE;
+ } else {
+ retval = GROW_NONE;
+ }
+// Log.v(TAG, "radius: " + radius + "; touchRadius: " + distanceFromCenter + "; distX: " + distX + "; distY: " + distY + "; retval: " + retval);
+ } else {
+ boolean verticalCheck = (y >= r.top - hysteresis) && (y < r.bottom + hysteresis);
+ boolean horizCheck = (x >= r.left - hysteresis) && (x < r.right + hysteresis);
+
+ if ((Math.abs(r.left - x) < hysteresis) && verticalCheck)
+ retval |= GROW_LEFT_EDGE;
+ if ((Math.abs(r.right - x) < hysteresis) && verticalCheck)
+ retval |= GROW_RIGHT_EDGE;
+ if ((Math.abs(r.top - y) < hysteresis) && horizCheck)
+ retval |= GROW_TOP_EDGE;
+ if ((Math.abs(r.bottom - y) < hysteresis) && horizCheck)
+ retval |= GROW_BOTTOM_EDGE;
+
+ if (retval == GROW_NONE && r.contains((int)x, (int)y))
+ retval = MOVE;
+ }
+ return retval;
+ }
+
+ void handleMotion(int edge, float dx, float dy) {
+ Rect r = computeLayout();
+ if (edge == GROW_NONE) {
+ return;
+ } else if (edge == MOVE) {
+ moveBy(dx * (mCropRect.width() / r.width()),
+ dy * (mCropRect.height() / r.height()));
+ } else {
+ if (((GROW_LEFT_EDGE | GROW_RIGHT_EDGE) & edge) == 0)
+ dx = 0;
+
+ if (((GROW_TOP_EDGE | GROW_BOTTOM_EDGE) & edge) == 0)
+ dy = 0;
+
+ float xDelta = dx * (mCropRect.width() / r.width());
+ float yDelta = dy * (mCropRect.height() / r.height());
+ growBy((((edge & GROW_LEFT_EDGE) != 0) ? -1 : 1) * xDelta,
+ (((edge & GROW_TOP_EDGE) != 0) ? -1 : 1) * yDelta);
+
+ }
+// Log.v(TAG, "ratio is now " + this.mCropRect.width() / this.mCropRect.height());
+ }
+
+ void moveBy(float dx, float dy) {
+ Rect invalRect = new Rect(mDrawRect);
+
+ mCropRect.offset(dx, dy);
+ mCropRect.offset(
+ Math.max(0, mImageRect.left - mCropRect.left),
+ Math.max(0, mImageRect.top - mCropRect.top));
+
+ mCropRect.offset(
+ Math.min(0, mImageRect.right - mCropRect.right),
+ Math.min(0, mImageRect.bottom - mCropRect.bottom));
+
+ mDrawRect = computeLayout();
+ invalRect.union(mDrawRect);
+ invalRect.inset(-10, -10);
+ mContext.invalidate(invalRect);
+ }
+
+ private void shift(RectF r, float dx, float dy) {
+ r.left += dx;
+ r.right += dx;
+ r.top += dy;
+ r.bottom += dy;
+ }
+
+ void growBy(float dx, float dy) {
+// Log.v(TAG, "growBy: " + dx + " " + dy + "; rect w/h is " + mCropRect.width() + " / " + mCropRect.height());
+ if (mMaintainAspectRatio) {
+ if (dx != 0) {
+ dy = dx / mInitialAspectRatio;
+ } else if (dy != 0) {
+ dx = dy * mInitialAspectRatio;
+ }
+ }
+
+ RectF r = new RectF(mCropRect);
+ if (dx > 0F && r.width() + 2 * dx > mImageRect.width()) {
+ float adjustment = (mImageRect.width() - r.width()) / 2F;
+ dx = adjustment;
+ if (mMaintainAspectRatio)
+ dy = dx / mInitialAspectRatio;
+ }
+ if (dy > 0F && r.height() + 2 * dy > mImageRect.height()) {
+ float adjustment = (mImageRect.height() - r.height()) / 2F;
+ dy = adjustment;
+ if (mMaintainAspectRatio)
+ dx = dy * mInitialAspectRatio;
+ }
+
+ r.inset(-dx, -dy);
+
+ float widthCap = 25F;
+ if (r.width() < 25) {
+ r.inset(-(25F-r.width())/2F, 0F);
+ }
+ float heightCap = mMaintainAspectRatio ? (widthCap / mInitialAspectRatio) : widthCap;
+ if (r.height() < heightCap) {
+ r.inset(0F, -(heightCap-r.height())/2F);
+ }
+
+ if (r.left < mImageRect.left) {
+ shift(r, mImageRect.left - r.left, 0F);
+ } else if (r.right > mImageRect.right) {
+ shift(r, -(r.right - mImageRect.right), 0);
+ }
+ if (r.top < mImageRect.top) {
+ shift(r, 0F, mImageRect.top - r.top);
+ } else if (r.bottom > mImageRect.bottom) {
+ shift(r, 0F, -(r.bottom - mImageRect.bottom));
+ }
+/*
+ RectF rCandidate = new RectF(r);
+ r.intersect(mImageRect);
+ if (mMaintainAspectRatio) {
+ if (r.left != rCandidate.left) {
+ Log.v(TAG, "bail 1");
+ return;
+ }
+ if (r.right != rCandidate.right) {
+ Log.v(TAG, "bail 2");
+ return;
+ }
+ if (r.top != rCandidate.top) {
+ Log.v(TAG, "bail 3");
+ return;
+ }
+ if (r.bottom != rCandidate.bottom) {
+ Log.v(TAG, "bail 4");
+ return;
+ }
+ }
+*/
+ mCropRect.set(r);
+ mDrawRect = computeLayout();
+ mContext.invalidate();
+ }
+
+ public Rect getCropRect() {
+ return new Rect((int)mCropRect.left, (int)mCropRect.top, (int)mCropRect.right, (int)mCropRect.bottom);
+ }
+
+ private Rect computeLayout() {
+ RectF r = new RectF(mCropRect.left, mCropRect.top, mCropRect.right, mCropRect.bottom);
+ mMatrix.mapRect(r);
+ return new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right), Math.round(r.bottom));
+ }
+
+ public void invalidate() {
+ mDrawRect = computeLayout();
+ }
+
+ public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean circle, boolean maintainAspectRatio) {
+ if (Config.LOGV) Log.v(TAG, "setup... " + imageRect + "; " + cropRect + "; maintain " + maintainAspectRatio + "; circle " + circle);
+ if (circle)
+ maintainAspectRatio = true;
+ mMatrix = new Matrix(m);
+
+ mCropRect = cropRect;
+ mImageRect = new RectF(imageRect);
+ mMaintainAspectRatio = maintainAspectRatio;
+ mCircle = circle;
+
+ mInitialAspectRatio = mCropRect.width() / mCropRect.height();
+ mDrawRect = computeLayout();
+
+ mFocusPaint.setARGB(125, 50, 50, 50);
+ mNoFocusPaint.setARGB(125, 50, 50, 50);
+ mOutlinePaint.setStrokeWidth(3F);
+ mOutlinePaint.setStyle(Paint.Style.STROKE);
+ mOutlinePaint.setAntiAlias(true);
+
+ mMode = ModifyMode.None;
+ initHighlightView();
+ }
+
+ public void modify(int keyCode, long repeatCount)
+ {
+ float factor = Math.max(.01F, Math.min(.1F, repeatCount * .01F));
+ float widthUnits = factor * (float)mContext.getWidth();
+ float heightUnits = widthUnits;
+
+ switch (keyCode)
+ {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (mMode == ModifyMode.Move)
+ moveBy(-widthUnits, 0);
+ else if (mMode == ModifyMode.Grow)
+ growBy(-widthUnits, 0);
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (mMode == ModifyMode.Move)
+ moveBy(widthUnits, 0);
+ else if (mMode == ModifyMode.Grow)
+ growBy(widthUnits, 0);
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (mMode == ModifyMode.Move)
+ moveBy(0, -heightUnits);
+ else if (mMode == ModifyMode.Grow)
+ growBy(0, -heightUnits);
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (mMode == ModifyMode.Move)
+ moveBy(0, heightUnits);
+ else if (mMode == ModifyMode.Grow)
+ growBy(0, heightUnits);
+ break;
+ }
+ }
+
+ enum ModifyMode { None, Move,Grow };
+
+ ModifyMode mMode = ModifyMode.None;
+
+ Rect mDrawRect;
+ RectF mImageRect;
+ RectF mCropRect;
+ Matrix mMatrix;
+
+ boolean mMaintainAspectRatio = false;
+ float mInitialAspectRatio;
+ boolean mCircle = false;
+
+ Drawable mResizeDrawableWidth, mResizeDrawableHeight, mResizeDrawableDiagonal;
+
+ Paint mFocusPaint = new Paint();
+ Paint mNoFocusPaint = new Paint();
+ Paint mOutlinePaint = new Paint();
+}