summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/ImageViewTouchBase.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:49 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:49 -0800
commitbecfb351a5bc43050128f44eb1bcfbcc0c6dcb7a (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/com/android/camera/ImageViewTouchBase.java
parenta6aa03f5bd2270bcc52ba1899c22d881955e8e7e (diff)
downloadLegacyCamera-becfb351a5bc43050128f44eb1bcfbcc0c6dcb7a.zip
LegacyCamera-becfb351a5bc43050128f44eb1bcfbcc0c6dcb7a.tar.gz
LegacyCamera-becfb351a5bc43050128f44eb1bcfbcc0c6dcb7a.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src/com/android/camera/ImageViewTouchBase.java')
-rw-r--r--src/com/android/camera/ImageViewTouchBase.java559
1 files changed, 0 insertions, 559 deletions
diff --git a/src/com/android/camera/ImageViewTouchBase.java b/src/com/android/camera/ImageViewTouchBase.java
deleted file mode 100644
index 1774e46..0000000
--- a/src/com/android/camera/ImageViewTouchBase.java
+++ /dev/null
@@ -1,559 +0,0 @@
-package com.android.camera;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.Log;
-import android.view.animation.Animation;
-import android.view.animation.TranslateAnimation;
-import android.view.KeyEvent;
-import android.widget.ImageView;
-
-abstract public class ImageViewTouchBase extends ImageView {
- private static final String TAG = "ImageViewTouchBase";
-
- // if we're animating these images, it may be faster to cache the image
- // at its target size first. to do this set this variable to true.
- // currently we're not animating images, so we don't need to do this
- // extra work.
- private final boolean USE_PERFECT_FIT_OPTIMIZATION = false;
-
- // This is the base transformation which is used to show the image
- // initially. The current computation for this shows the image in
- // it's entirety, letterboxing as needed. One could chose to
- // show the image as cropped instead.
- //
- // This matrix is recomputed when we go from the thumbnail image to
- // the full size image.
- protected Matrix mBaseMatrix = new Matrix();
-
- // This is the supplementary transformation which reflects what
- // the user has done in terms of zooming and panning.
- //
- // This matrix remains the same when we go from the thumbnail image
- // to the full size image.
- protected Matrix mSuppMatrix = new Matrix();
-
- // This is the final matrix which is computed as the concatentation
- // of the base matrix and the supplementary matrix.
- private Matrix mDisplayMatrix = new Matrix();
-
- // Temporary buffer used for getting the values out of a matrix.
- private float[] mMatrixValues = new float[9];
-
- // The current bitmap being displayed.
- protected Bitmap mBitmapDisplayed;
-
- // The thumbnail bitmap.
- protected Bitmap mThumbBitmap;
-
- // The full size bitmap which should be used once we start zooming.
- private Bitmap mFullBitmap;
-
- // The bitmap which is exactly sized to what we need. The decoded bitmap is
- // drawn into the mPerfectFitBitmap so that animation is faster.
- protected Bitmap mPerfectFitBitmap;
-
- // True if the image is the thumbnail.
- protected boolean mBitmapIsThumbnail;
-
- // True if the user is zooming -- use the full size image
- protected boolean mIsZooming;
-
- // Paint to use to clear the "mPerfectFitBitmap"
- protected Paint mPaint = new Paint();
-
- static boolean sNewZoomControl = false;
-
- int mThisWidth = -1, mThisHeight = -1;
-
- float mMaxZoom;
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- mThisWidth = right - left;
- mThisHeight = bottom - top;
- Runnable r = mOnLayoutRunnable;
- if (r != null) {
- mOnLayoutRunnable = null;
- r.run();
- }
- if (mBitmapDisplayed != null) {
- setBaseMatrix(mBitmapDisplayed, mBaseMatrix);
- setImageMatrix(getImageViewMatrix());
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && getScale() > 1.0f) {
- // If we're zoomed in, pressing Back jumps out to show the entire image, otherwise Back
- // returns the user to the gallery.
- zoomTo(1.0f);
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- protected Handler mHandler = new Handler();
-
- protected int mLastXTouchPos;
- protected int mLastYTouchPos;
-
- protected boolean doesScrolling() {
- return true;
- }
-
- // Translate a given point through a given matrix.
- static private void translatePoint(Matrix matrix, float [] xy) {
- matrix.mapPoints(xy);
- }
-
- // Return the mapped x coordinate through the matrix.
- static int mapXPoint(Matrix matrix, int point) {
- // Matrix's mapPoints takes an array of x/y coordinates.
- // That's why we have to allocte an array of length two
- // even though we don't use the y coordinate.
- float [] xy = new float[2];
- xy[0] = point;
- xy[1] = 0F;
- matrix.mapPoints(xy);
- return (int) xy[0];
- }
-
- @Override
- public void setImageBitmap(Bitmap bitmap) {
- throw new NullPointerException();
- }
-
- public void setImageBitmap(Bitmap bitmap, boolean isThumbnail) {
- super.setImageBitmap(bitmap);
- Drawable d = getDrawable();
- if (d != null)
- d.setDither(true);
- mBitmapDisplayed = bitmap;
- mBitmapIsThumbnail = isThumbnail;
- }
-
- protected boolean usePerfectFitBitmap() {
- return USE_PERFECT_FIT_OPTIMIZATION && !mIsZooming;
- }
-
- public void recycleBitmaps() {
- if (mFullBitmap != null) {
- if (Config.LOGV)
- Log.v(TAG, "recycling mFullBitmap " + mFullBitmap + "; this == " + this.hashCode());
- mFullBitmap.recycle();
- mFullBitmap = null;
- }
- if (mThumbBitmap != null) {
- if (Config.LOGV)
- Log.v(TAG, "recycling mThumbBitmap" + mThumbBitmap + "; this == " + this.hashCode());
- mThumbBitmap.recycle();
- mThumbBitmap = null;
- }
-
- // mBitmapDisplayed is either mPerfectFitBitmap or mFullBitmap (in the case of zooming)
- setImageBitmap(null, true);
- }
-
- public void clear() {
- mBitmapDisplayed = null;
- recycleBitmaps();
- }
-
- private Runnable mOnLayoutRunnable = null;
-
- public void setImageBitmapResetBase(final Bitmap bitmap, final boolean resetSupp, final boolean isThumb) {
- if ((bitmap != null) && (bitmap == mPerfectFitBitmap)) {
- // TODO: this should be removed in production
- throw new IllegalArgumentException("bitmap must not be mPerfectFitBitmap");
- }
-
- final int viewWidth = getWidth();
- final int viewHeight = getHeight();
-
- if (viewWidth <= 0) {
- mOnLayoutRunnable = new Runnable() {
- public void run() {
- setImageBitmapResetBase(bitmap, resetSupp, isThumb);
- }
- };
- return;
- }
-
- if (isThumb && mThumbBitmap != bitmap) {
- if (mThumbBitmap != null) {
- mThumbBitmap.recycle();
- }
- mThumbBitmap = bitmap;
- } else if (!isThumb && mFullBitmap != bitmap) {
- if (mFullBitmap != null) {
- mFullBitmap.recycle();
- }
- mFullBitmap = bitmap;
- }
- mBitmapIsThumbnail = isThumb;
-
- if (bitmap != null) {
- if (!usePerfectFitBitmap()) {
- setScaleType(ImageView.ScaleType.MATRIX);
- setBaseMatrix(bitmap, mBaseMatrix);
- setImageBitmap(bitmap, isThumb);
- } else {
- Matrix matrix = new Matrix();
- setBaseMatrix(bitmap, matrix);
- if ((mPerfectFitBitmap == null) ||
- mPerfectFitBitmap.getWidth() != mThisWidth ||
- mPerfectFitBitmap.getHeight() != mThisHeight) {
- if (mPerfectFitBitmap != null) {
- if (Config.LOGV)
- Log.v(TAG, "recycling mPerfectFitBitmap " + mPerfectFitBitmap.hashCode());
- mPerfectFitBitmap.recycle();
- }
- mPerfectFitBitmap = Bitmap.createBitmap(mThisWidth, mThisHeight, Bitmap.Config.RGB_565);
- }
- Canvas canvas = new Canvas(mPerfectFitBitmap);
- // clear the bitmap which may be bigger than the image and
- // contain the the previous image.
- canvas.drawColor(0xFF000000);
-
- final int bw = bitmap.getWidth();
- final int bh = bitmap.getHeight();
- final float widthScale = Math.min(viewWidth / (float)bw, 1.0f);
- final float heightScale = Math.min(viewHeight/ (float)bh, 1.0f);
- int translateX, translateY;
- if (widthScale > heightScale) {
- translateX = (int)((viewWidth -(float)bw*heightScale)*0.5f);
- translateY = (int)((viewHeight-(float)bh*heightScale)*0.5f);
- } else {
- translateX = (int)((viewWidth -(float)bw*widthScale)*0.5f);
- translateY = (int)((viewHeight-(float)bh*widthScale)*0.5f);
- }
-
- android.graphics.Rect src = new android.graphics.Rect(0, 0, bw, bh);
- android.graphics.Rect dst = new android.graphics.Rect(
- translateX, translateY,
- mThisWidth - translateX, mThisHeight - translateY);
- canvas.drawBitmap(bitmap, src, dst, mPaint);
-
- setImageBitmap(mPerfectFitBitmap, isThumb);
- setScaleType(ImageView.ScaleType.MATRIX);
- setImageMatrix(null);
- }
- } else {
- mBaseMatrix.reset();
- setImageBitmap(null, isThumb);
- }
-
- if (resetSupp)
- mSuppMatrix.reset();
- setImageMatrix(getImageViewMatrix());
- mMaxZoom = maxZoom();
- }
-
- // Center as much as possible in one or both axis. Centering is
- // defined as follows: if the image is scaled down below the
- // view's dimensions then center it (literally). If the image
- // is scaled larger than the view and is translated out of view
- // then translate it back into view (i.e. eliminate black bars).
- protected void center(boolean vertical, boolean horizontal, boolean animate) {
- if (mBitmapDisplayed == null)
- return;
-
- Matrix m = getImageViewMatrix();
-
- float [] topLeft = new float[] { 0, 0 };
- float [] botRight = new float[] { mBitmapDisplayed.getWidth(), mBitmapDisplayed.getHeight() };
-
- translatePoint(m, topLeft);
- translatePoint(m, botRight);
-
- float height = botRight[1] - topLeft[1];
- float width = botRight[0] - topLeft[0];
-
- float deltaX = 0, deltaY = 0;
-
- if (vertical) {
- int viewHeight = getHeight();
- if (height < viewHeight) {
- deltaY = (viewHeight - height)/2 - topLeft[1];
- } else if (topLeft[1] > 0) {
- deltaY = -topLeft[1];
- } else if (botRight[1] < viewHeight) {
- deltaY = getHeight() - botRight[1];
- }
- }
-
- if (horizontal) {
- int viewWidth = getWidth();
- if (width < viewWidth) {
- deltaX = (viewWidth - width)/2 - topLeft[0];
- } else if (topLeft[0] > 0) {
- deltaX = -topLeft[0];
- } else if (botRight[0] < viewWidth) {
- deltaX = viewWidth - botRight[0];
- }
- }
-
- postTranslate(deltaX, deltaY);
- if (animate) {
- Animation a = new TranslateAnimation(-deltaX, 0, -deltaY, 0);
- a.setStartTime(SystemClock.elapsedRealtime());
- a.setDuration(250);
- setAnimation(a);
- }
- setImageMatrix(getImageViewMatrix());
- }
-
- public void copyFrom(ImageViewTouchBase other) {
- mSuppMatrix.set(other.mSuppMatrix);
- mBaseMatrix.set(other.mBaseMatrix);
-
- if (mThumbBitmap != null)
- mThumbBitmap.recycle();
-
- if (mFullBitmap != null)
- mFullBitmap.recycle();
-
- // copy the data
- mThumbBitmap = other.mThumbBitmap;
- mFullBitmap = null;
-
- if (other.mFullBitmap != null)
- other.mFullBitmap.recycle();
-
- // transfer "ownership"
- other.mThumbBitmap = null;
- other.mFullBitmap = null;
- other.mBitmapIsThumbnail = true;
-
- setImageMatrix(other.getImageMatrix());
- setScaleType(other.getScaleType());
-
- setImageBitmapResetBase(mThumbBitmap, true, true);
- }
-
- @Override
- public void setImageDrawable(android.graphics.drawable.Drawable d) {
- super.setImageDrawable(d);
- }
-
- public ImageViewTouchBase(Context context) {
- super(context);
- init();
- }
-
- public ImageViewTouchBase(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- private void init() {
- setScaleType(ImageView.ScaleType.MATRIX);
- mPaint.setDither(true);
- mPaint.setFilterBitmap(true);
- }
-
- protected float getValue(Matrix matrix, int whichValue) {
- matrix.getValues(mMatrixValues);
- return mMatrixValues[whichValue];
- }
-
- // Get the scale factor out of the matrix.
- protected float getScale(Matrix matrix) {
- return getValue(matrix, Matrix.MSCALE_X);
- }
-
- protected float getScale() {
- return getScale(mSuppMatrix);
- }
-
- protected float getTranslateX() {
- return getValue(mSuppMatrix, Matrix.MTRANS_X);
- }
-
- protected float getTranslateY() {
- return getValue(mSuppMatrix, Matrix.MTRANS_Y);
- }
-
- // Setup the base matrix so that the image is centered and scaled properly.
- private void setBaseMatrix(Bitmap bitmap, Matrix matrix) {
- float viewWidth = getWidth();
- float viewHeight = getHeight();
-
- matrix.reset();
- float widthScale = Math.min(viewWidth / (float)bitmap.getWidth(), 1.0f);
- float heightScale = Math.min(viewHeight / (float)bitmap.getHeight(), 1.0f);
- float scale;
- if (widthScale > heightScale) {
- scale = heightScale;
- } else {
- scale = widthScale;
- }
- matrix.setScale(scale, scale);
- matrix.postTranslate(
- (viewWidth - ((float)bitmap.getWidth() * scale))/2F,
- (viewHeight - ((float)bitmap.getHeight() * scale))/2F);
- }
-
- // Combine the base matrix and the supp matrix to make the final matrix.
- protected Matrix getImageViewMatrix() {
- mDisplayMatrix.set(mBaseMatrix);
- mDisplayMatrix.postConcat(mSuppMatrix);
- return mDisplayMatrix;
- }
-
- private void onZoom() {
- mIsZooming = true;
- if (mFullBitmap != null && mFullBitmap != mBitmapDisplayed) {
- setImageBitmapResetBase(mFullBitmap, false, mBitmapIsThumbnail);
- }
- }
-
- private String describe(Bitmap b) {
- StringBuilder sb = new StringBuilder();
- if (b == null) {
- sb.append("NULL");
- } else if (b.isRecycled()) {
- sb.append(String.format("%08x: RECYCLED", b.hashCode()));
- } else {
- sb.append(String.format("%08x: LIVE", b.hashCode()));
- sb.append(String.format("%d x %d (size == %d)", b.getWidth(), b.getHeight(), b.getWidth()*b.getHeight()*2));
- }
- return sb.toString();
- }
-
- public void dump() {
- if (Config.LOGV) {
- Log.v(TAG, "dump ImageViewTouchBase " + this);
- Log.v(TAG, "... mBitmapDisplayed = " + describe(mBitmapDisplayed));
- Log.v(TAG, "... mThumbBitmap = " + describe(mThumbBitmap));
- Log.v(TAG, "... mFullBitmap = " + describe(mFullBitmap));
- Log.v(TAG, "... mPerfectFitBitmap = " + describe(mPerfectFitBitmap));
- Log.v(TAG, "... mIsThumb = " + mBitmapIsThumbnail);
- }
- }
-
- static final float sPanRate = 7;
- static final float sScaleRate = 1.25F;
-
- // Sets the maximum zoom, which is a scale relative to the base matrix. It is calculated to show
- // the image at 400% zoom regardless of screen or image orientation. If in the future we decode
- // the full 3 megapixel image, rather than the current 1024x768, this should be changed down to
- // 200%.
- protected float maxZoom() {
- if (mBitmapDisplayed == null)
- return 1F;
-
- float fw = (float) mBitmapDisplayed.getWidth() / (float)mThisWidth;
- float fh = (float) mBitmapDisplayed.getHeight() / (float)mThisHeight;
- float max = Math.max(fw, fh) * 4;
-// Log.v(TAG, "Bitmap " + mBitmapDisplayed.getWidth() + "x" + mBitmapDisplayed.getHeight() +
-// " view " + mThisWidth + "x" + mThisHeight + " max zoom " + max);
- return max;
- }
-
- protected void zoomTo(float scale, float centerX, float centerY) {
- if (scale > mMaxZoom) {
- scale = mMaxZoom;
- }
- onZoom();
-
- float oldScale = getScale();
- float deltaScale = scale / oldScale;
-
- mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
- setImageMatrix(getImageViewMatrix());
- center(true, true, false);
- }
-
- protected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) {
- final float incrementPerMs = (scale - getScale()) / durationMs;
- final float oldScale = getScale();
- final long startTime = System.currentTimeMillis();
-
- mHandler.post(new Runnable() {
- public void run() {
- long now = System.currentTimeMillis();
- float currentMs = Math.min(durationMs, (float)(now - startTime));
- float target = oldScale + (incrementPerMs * currentMs);
- zoomTo(target, centerX, centerY);
-
- if (currentMs < durationMs) {
- mHandler.post(this);
- }
- }
- });
- }
-
- protected void zoomTo(float scale) {
- float width = getWidth();
- float height = getHeight();
-
- zoomTo(scale, width/2F, height/2F);
- }
-
- protected void zoomIn() {
- zoomIn(sScaleRate);
- }
-
- protected void zoomOut() {
- zoomOut(sScaleRate);
- }
-
- protected void zoomIn(float rate) {
- if (getScale() >= mMaxZoom) {
- return; // Don't let the user zoom into the molecular level.
- }
- if (mBitmapDisplayed == null) {
- return;
- }
- float width = getWidth();
- float height = getHeight();
-
- mSuppMatrix.postScale(rate, rate, width/2F, height/2F);
- setImageMatrix(getImageViewMatrix());
-
- onZoom();
- }
-
- protected void zoomOut(float rate) {
- if (mBitmapDisplayed == null) {
- return;
- }
-
- float width = getWidth();
- float height = getHeight();
-
- Matrix tmp = new Matrix(mSuppMatrix);
- tmp.postScale(1F/sScaleRate, 1F/sScaleRate, width/2F, height/2F);
- if (getScale(tmp) < 1F) {
- mSuppMatrix.setScale(1F, 1F, width/2F, height/2F);
- } else {
- mSuppMatrix.postScale(1F/rate, 1F/rate, width/2F, height/2F);
- }
- setImageMatrix(getImageViewMatrix());
- center(true, true, false);
-
- onZoom();
- }
-
- protected void postTranslate(float dx, float dy) {
- mSuppMatrix.postTranslate(dx, dy);
- }
-
- protected void panBy(float dx, float dy) {
- postTranslate(dx, dy);
- setImageMatrix(getImageViewMatrix());
- }
-}
-