Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 17 | package com.android.camera; |
| 18 | |
| 19 | import android.content.Context; |
| 20 | import android.graphics.Bitmap; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 21 | import android.graphics.Matrix; |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 22 | import android.graphics.RectF; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 23 | import android.graphics.drawable.Drawable; |
| 24 | import android.os.Handler; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 25 | import android.util.AttributeSet; |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 26 | import android.view.KeyEvent; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 27 | import android.widget.ImageView; |
| 28 | |
Ray Chen | 23c51b7 | 2009-04-10 03:41:00 -0700 | [diff] [blame] | 29 | abstract class ImageViewTouchBase extends ImageView { |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 30 | |
| 31 | @SuppressWarnings("unused") |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 32 | private static final String TAG = "ImageViewTouchBase"; |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 33 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 34 | // This is the base transformation which is used to show the image |
| 35 | // initially. The current computation for this shows the image in |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 36 | // it's entirety, letterboxing as needed. One could choose to |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 37 | // show the image as cropped instead. |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 38 | // |
| 39 | // This matrix is recomputed when we go from the thumbnail image to |
| 40 | // the full size image. |
| 41 | protected Matrix mBaseMatrix = new Matrix(); |
| 42 | |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 43 | // This is the supplementary transformation which reflects what |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 44 | // the user has done in terms of zooming and panning. |
| 45 | // |
| 46 | // This matrix remains the same when we go from the thumbnail image |
| 47 | // to the full size image. |
| 48 | protected Matrix mSuppMatrix = new Matrix(); |
| 49 | |
| 50 | // This is the final matrix which is computed as the concatentation |
| 51 | // of the base matrix and the supplementary matrix. |
Owen Lin | bbc560b | 2009-04-17 11:31:27 +0800 | [diff] [blame] | 52 | private final Matrix mDisplayMatrix = new Matrix(); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 53 | |
| 54 | // Temporary buffer used for getting the values out of a matrix. |
Owen Lin | bbc560b | 2009-04-17 11:31:27 +0800 | [diff] [blame] | 55 | private final float[] mMatrixValues = new float[9]; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 56 | |
| 57 | // The current bitmap being displayed. |
Chih-Chung Chang | 522e836 | 2009-08-26 16:12:34 +0800 | [diff] [blame] | 58 | protected final RotateBitmap mBitmapDisplayed = new RotateBitmap(null); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 59 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 60 | int mThisWidth = -1, mThisHeight = -1; |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 61 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 62 | float mMaxZoom; |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 63 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 64 | // ImageViewTouchBase will pass a Bitmap to the Recycler if it has finished |
| 65 | // its use of that Bitmap. |
| 66 | public interface Recycler { |
| 67 | public void recycle(Bitmap b); |
| 68 | } |
| 69 | |
| 70 | public void setRecycler(Recycler r) { |
| 71 | mRecycler = r; |
| 72 | } |
| 73 | |
| 74 | private Recycler mRecycler; |
| 75 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 76 | @Override |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 77 | protected void onLayout(boolean changed, int left, int top, |
| 78 | int right, int bottom) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 79 | super.onLayout(changed, left, top, right, bottom); |
| 80 | mThisWidth = right - left; |
| 81 | mThisHeight = bottom - top; |
| 82 | Runnable r = mOnLayoutRunnable; |
| 83 | if (r != null) { |
| 84 | mOnLayoutRunnable = null; |
| 85 | r.run(); |
| 86 | } |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 87 | if (mBitmapDisplayed.getBitmap() != null) { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 88 | getProperBaseMatrix(mBitmapDisplayed, mBaseMatrix); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 89 | setImageMatrix(getImageViewMatrix()); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | @Override |
| 94 | public boolean onKeyDown(int keyCode, KeyEvent event) { |
Chih-Chung Chang | 0b8028e | 2009-09-25 15:12:14 -0700 | [diff] [blame] | 95 | if (keyCode == KeyEvent.KEYCODE_BACK |
| 96 | && event.getRepeatCount() == 0) { |
| 97 | event.startTracking(); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 98 | return true; |
| 99 | } |
| 100 | return super.onKeyDown(keyCode, event); |
| 101 | } |
| 102 | |
Chih-Chung Chang | 0b8028e | 2009-09-25 15:12:14 -0700 | [diff] [blame] | 103 | @Override |
| 104 | public boolean onKeyUp(int keyCode, KeyEvent event) { |
| 105 | if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() |
| 106 | && !event.isCanceled()) { |
| 107 | if (getScale() > 1.0f) { |
| 108 | // If we're zoomed in, pressing Back jumps out to show the |
| 109 | // entire image, otherwise Back returns the user to the gallery. |
| 110 | zoomTo(1.0f); |
| 111 | return true; |
| 112 | } |
| 113 | } |
| 114 | return super.onKeyUp(keyCode, event); |
| 115 | } |
| 116 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 117 | protected Handler mHandler = new Handler(); |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 118 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 119 | protected int mLastXTouchPos; |
| 120 | protected int mLastYTouchPos; |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 121 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 122 | @Override |
| 123 | public void setImageBitmap(Bitmap bitmap) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 124 | setImageBitmap(bitmap, 0); |
| 125 | } |
| 126 | |
| 127 | private void setImageBitmap(Bitmap bitmap, int rotation) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 128 | super.setImageBitmap(bitmap); |
| 129 | Drawable d = getDrawable(); |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 130 | if (d != null) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 131 | d.setDither(true); |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 132 | } |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 133 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 134 | Bitmap old = mBitmapDisplayed.getBitmap(); |
| 135 | mBitmapDisplayed.setBitmap(bitmap); |
| 136 | mBitmapDisplayed.setRotation(rotation); |
| 137 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 138 | if (old != null && old != bitmap && mRecycler != null) { |
| 139 | mRecycler.recycle(old); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 140 | } |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 141 | } |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 142 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 143 | public void clear() { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 144 | setImageBitmapResetBase(null, true); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 145 | } |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 146 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 147 | private Runnable mOnLayoutRunnable = null; |
| 148 | |
| 149 | // This function changes bitmap, reset base matrix according to the size |
| 150 | // of the bitmap, and optionally reset the supplementary matrix. |
| 151 | public void setImageBitmapResetBase(final Bitmap bitmap, |
| 152 | final boolean resetSupp) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 153 | setImageRotateBitmapResetBase(new RotateBitmap(bitmap), resetSupp); |
| 154 | } |
| 155 | |
| 156 | public void setImageRotateBitmapResetBase(final RotateBitmap bitmap, |
| 157 | final boolean resetSupp) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 158 | final int viewWidth = getWidth(); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 159 | |
| 160 | if (viewWidth <= 0) { |
| 161 | mOnLayoutRunnable = new Runnable() { |
| 162 | public void run() { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 163 | setImageRotateBitmapResetBase(bitmap, resetSupp); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 164 | } |
| 165 | }; |
| 166 | return; |
| 167 | } |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 168 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 169 | if (bitmap.getBitmap() != null) { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 170 | getProperBaseMatrix(bitmap, mBaseMatrix); |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 171 | setImageBitmap(bitmap.getBitmap(), bitmap.getRotation()); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 172 | } else { |
| 173 | mBaseMatrix.reset(); |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 174 | setImageBitmap(null); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 175 | } |
| 176 | |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 177 | if (resetSupp) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 178 | mSuppMatrix.reset(); |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 179 | } |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 180 | setImageMatrix(getImageViewMatrix()); |
| 181 | mMaxZoom = maxZoom(); |
| 182 | } |
| 183 | |
| 184 | // Center as much as possible in one or both axis. Centering is |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 185 | // defined as follows: if the image is scaled down below the |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 186 | // view's dimensions then center it (literally). If the image |
| 187 | // is scaled larger than the view and is translated out of view |
| 188 | // then translate it back into view (i.e. eliminate black bars). |
Chih-Chung Chang | 97fc201 | 2009-06-25 11:31:11 +0800 | [diff] [blame] | 189 | protected void center(boolean horizontal, boolean vertical) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 190 | if (mBitmapDisplayed.getBitmap() == null) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 191 | return; |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 192 | } |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 193 | |
| 194 | Matrix m = getImageViewMatrix(); |
| 195 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 196 | RectF rect = new RectF(0, 0, |
| 197 | mBitmapDisplayed.getBitmap().getWidth(), |
| 198 | mBitmapDisplayed.getBitmap().getHeight()); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 199 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 200 | m.mapRect(rect); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 201 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 202 | float height = rect.height(); |
| 203 | float width = rect.width(); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 204 | |
| 205 | float deltaX = 0, deltaY = 0; |
| 206 | |
| 207 | if (vertical) { |
| 208 | int viewHeight = getHeight(); |
| 209 | if (height < viewHeight) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 210 | deltaY = (viewHeight - height) / 2 - rect.top; |
| 211 | } else if (rect.top > 0) { |
| 212 | deltaY = -rect.top; |
| 213 | } else if (rect.bottom < viewHeight) { |
| 214 | deltaY = getHeight() - rect.bottom; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 215 | } |
| 216 | } |
| 217 | |
| 218 | if (horizontal) { |
| 219 | int viewWidth = getWidth(); |
| 220 | if (width < viewWidth) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 221 | deltaX = (viewWidth - width) / 2 - rect.left; |
| 222 | } else if (rect.left > 0) { |
| 223 | deltaX = -rect.left; |
| 224 | } else if (rect.right < viewWidth) { |
| 225 | deltaX = viewWidth - rect.right; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 226 | } |
| 227 | } |
| 228 | |
| 229 | postTranslate(deltaX, deltaY); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 230 | setImageMatrix(getImageViewMatrix()); |
| 231 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 232 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 233 | public ImageViewTouchBase(Context context) { |
| 234 | super(context); |
| 235 | init(); |
| 236 | } |
| 237 | |
| 238 | public ImageViewTouchBase(Context context, AttributeSet attrs) { |
| 239 | super(context, attrs); |
| 240 | init(); |
| 241 | } |
| 242 | |
| 243 | private void init() { |
| 244 | setScaleType(ImageView.ScaleType.MATRIX); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | protected float getValue(Matrix matrix, int whichValue) { |
| 248 | matrix.getValues(mMatrixValues); |
| 249 | return mMatrixValues[whichValue]; |
| 250 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 251 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 252 | // Get the scale factor out of the matrix. |
| 253 | protected float getScale(Matrix matrix) { |
| 254 | return getValue(matrix, Matrix.MSCALE_X); |
| 255 | } |
| 256 | |
| 257 | protected float getScale() { |
| 258 | return getScale(mSuppMatrix); |
| 259 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 260 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 261 | // Setup the base matrix so that the image is centered and scaled properly. |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 262 | private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 263 | float viewWidth = getWidth(); |
| 264 | float viewHeight = getHeight(); |
| 265 | |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 266 | float w = bitmap.getWidth(); |
| 267 | float h = bitmap.getHeight(); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 268 | matrix.reset(); |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 269 | |
Chih-Chung Chang | 1f463a6 | 2009-07-30 17:59:09 +0800 | [diff] [blame] | 270 | // We limit up-scaling to 2x otherwise the result may look bad if it's |
| 271 | // a small icon. |
| 272 | float widthScale = Math.min(viewWidth / w, 2.0f); |
| 273 | float heightScale = Math.min(viewHeight / h, 2.0f); |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 274 | float scale = Math.min(widthScale, heightScale); |
| 275 | |
| 276 | matrix.postConcat(bitmap.getRotateMatrix()); |
| 277 | matrix.postScale(scale, scale); |
| 278 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 279 | matrix.postTranslate( |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 280 | (viewWidth - w * scale) / 2F, |
| 281 | (viewHeight - h * scale) / 2F); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 282 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 283 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 284 | // Combine the base matrix and the supp matrix to make the final matrix. |
| 285 | protected Matrix getImageViewMatrix() { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 286 | // The final matrix is computed as the concatentation of the base matrix |
| 287 | // and the supplementary matrix. |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 288 | mDisplayMatrix.set(mBaseMatrix); |
| 289 | mDisplayMatrix.postConcat(mSuppMatrix); |
| 290 | return mDisplayMatrix; |
| 291 | } |
| 292 | |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 293 | static final float SCALE_RATE = 1.25F; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 294 | |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 295 | // Sets the maximum zoom, which is a scale relative to the base matrix. It |
| 296 | // is calculated to show the image at 400% zoom regardless of screen or |
| 297 | // image orientation. If in the future we decode the full 3 megapixel image, |
| 298 | // rather than the current 1024x768, this should be changed down to 200%. |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 299 | protected float maxZoom() { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 300 | if (mBitmapDisplayed.getBitmap() == null) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 301 | return 1F; |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 302 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 303 | |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 304 | float fw = (float) mBitmapDisplayed.getWidth() / (float) mThisWidth; |
| 305 | float fh = (float) mBitmapDisplayed.getHeight() / (float) mThisHeight; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 306 | float max = Math.max(fw, fh) * 4; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 307 | return max; |
| 308 | } |
| 309 | |
| 310 | protected void zoomTo(float scale, float centerX, float centerY) { |
| 311 | if (scale > mMaxZoom) { |
| 312 | scale = mMaxZoom; |
| 313 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 314 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 315 | float oldScale = getScale(); |
| 316 | float deltaScale = scale / oldScale; |
| 317 | |
| 318 | mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY); |
| 319 | setImageMatrix(getImageViewMatrix()); |
Chih-Chung Chang | 0a475e1 | 2009-04-16 11:42:12 +0800 | [diff] [blame] | 320 | center(true, true); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 321 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 322 | |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 323 | protected void zoomTo(final float scale, final float centerX, |
| 324 | final float centerY, final float durationMs) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 325 | final float incrementPerMs = (scale - getScale()) / durationMs; |
| 326 | final float oldScale = getScale(); |
| 327 | final long startTime = System.currentTimeMillis(); |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 328 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 329 | mHandler.post(new Runnable() { |
| 330 | public void run() { |
| 331 | long now = System.currentTimeMillis(); |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 332 | float currentMs = Math.min(durationMs, now - startTime); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 333 | float target = oldScale + (incrementPerMs * currentMs); |
| 334 | zoomTo(target, centerX, centerY); |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 335 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 336 | if (currentMs < durationMs) { |
| 337 | mHandler.post(this); |
| 338 | } |
| 339 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 340 | }); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 341 | } |
| 342 | |
| 343 | protected void zoomTo(float scale) { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 344 | float cx = getWidth() / 2F; |
| 345 | float cy = getHeight() / 2F; |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 346 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 347 | zoomTo(scale, cx, cy); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 348 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 349 | |
Chih-Chung Chang | eb9b537 | 2009-09-10 12:36:52 +0800 | [diff] [blame] | 350 | protected void zoomToPoint(float scale, float pointX, float pointY) { |
| 351 | float cx = getWidth() / 2F; |
| 352 | float cy = getHeight() / 2F; |
| 353 | |
| 354 | panBy(cx - pointX, cy - pointY); |
| 355 | zoomTo(scale, cx, cy); |
| 356 | } |
| 357 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 358 | protected void zoomIn() { |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 359 | zoomIn(SCALE_RATE); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 360 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 361 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 362 | protected void zoomOut() { |
Chih-Chung Chang | 063f09d | 2009-04-01 04:02:00 -0700 | [diff] [blame] | 363 | zoomOut(SCALE_RATE); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 364 | } |
| 365 | |
| 366 | protected void zoomIn(float rate) { |
| 367 | if (getScale() >= mMaxZoom) { |
| 368 | return; // Don't let the user zoom into the molecular level. |
| 369 | } |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 370 | if (mBitmapDisplayed.getBitmap() == null) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 371 | return; |
| 372 | } |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 373 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 374 | float cx = getWidth() / 2F; |
| 375 | float cy = getHeight() / 2F; |
| 376 | |
| 377 | mSuppMatrix.postScale(rate, rate, cx, cy); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 378 | setImageMatrix(getImageViewMatrix()); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | protected void zoomOut(float rate) { |
Ray Chen | 012d0f3 | 2009-07-20 16:33:41 +0800 | [diff] [blame] | 382 | if (mBitmapDisplayed.getBitmap() == null) { |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 383 | return; |
| 384 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 385 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 386 | float cx = getWidth() / 2F; |
| 387 | float cy = getHeight() / 2F; |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 388 | |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 389 | // Zoom out to at most 1x. |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 390 | Matrix tmp = new Matrix(mSuppMatrix); |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 391 | tmp.postScale(1F / rate, 1F / rate, cx, cy); |
| 392 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 393 | if (getScale(tmp) < 1F) { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 394 | mSuppMatrix.setScale(1F, 1F, cx, cy); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 395 | } else { |
Chih-Chung Chang | 7db87ab | 2009-04-12 21:42:43 -0700 | [diff] [blame] | 396 | mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 397 | } |
| 398 | setImageMatrix(getImageViewMatrix()); |
Chih-Chung Chang | 0a475e1 | 2009-04-16 11:42:12 +0800 | [diff] [blame] | 399 | center(true, true); |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 400 | } |
Owen Lin | 937fc48 | 2009-04-14 02:02:51 -0700 | [diff] [blame] | 401 | |
The Android Open Source Project | b64d345 | 2009-03-03 19:32:20 -0800 | [diff] [blame] | 402 | protected void postTranslate(float dx, float dy) { |
| 403 | mSuppMatrix.postTranslate(dx, dy); |
| 404 | } |
| 405 | |
| 406 | protected void panBy(float dx, float dy) { |
| 407 | postTranslate(dx, dy); |
| 408 | setImageMatrix(getImageViewMatrix()); |
| 409 | } |
| 410 | } |