diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:20 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:20 -0800 |
commit | b64d345c9d51cabce43b5191532a0c185d2a70a5 (patch) | |
tree | cb393a35078ffef3dc6d6c0cfa0d9cd349e8cf08 /src/com/android/camera/HighlightView.java | |
parent | becfb351a5bc43050128f44eb1bcfbcc0c6dcb7a (diff) | |
download | LegacyCamera-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.java | 428 |
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(); +} |