summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2013-03-15 15:33:38 -0700
committerRuben Brunk <rubenbrunk@google.com>2013-03-15 18:01:51 -0700
commitf88f1d99563ddcfe15fed8fe98a293c0a5de0d82 (patch)
treefe03efc0eb2ba7e9cbeb0a0cd35fe879c5e0c532 /src
parent0fe391a43d0c549fa0effddd21ece4eb4ba86194 (diff)
downloadandroid_packages_apps_Snap-f88f1d99563ddcfe15fed8fe98a293c0a5de0d82.tar.gz
android_packages_apps_Snap-f88f1d99563ddcfe15fed8fe98a293c0a5de0d82.tar.bz2
android_packages_apps_Snap-f88f1d99563ddcfe15fed8fe98a293c0a5de0d82.zip
Refactoring iconbutton.
Change-Id: Ie1538d978605ae28bb4fa6779eb2802794a35312
Diffstat (limited to 'src')
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java5
-rw-r--r--src/com/android/gallery3d/filtershow/tools/IconFactory.java108
-rw-r--r--src/com/android/gallery3d/filtershow/ui/FilterIconButton.java6
-rw-r--r--src/com/android/gallery3d/filtershow/ui/IconButton.java150
4 files changed, 190 insertions, 79 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 2c1a847f8..ef3e3d5ce 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -255,6 +255,11 @@ public class ImageLoader {
try {
is = mContext.getContentResolver().openInputStream(uri);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
+ Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
+ // return null if bounds are not entirely within the bitmap
+ if (!r.contains(bounds)) {
+ return null;
+ }
return decoder.decodeRegion(bounds, options);
} catch (FileNotFoundException e) {
Log.e(LOGTAG, "FileNotFoundException: " + uri);
diff --git a/src/com/android/gallery3d/filtershow/tools/IconFactory.java b/src/com/android/gallery3d/filtershow/tools/IconFactory.java
new file mode 100644
index 000000000..ccc49e13d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/IconFactory.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 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.gallery3d.filtershow.tools;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+
+/**
+ * A factory class for producing bitmaps to use as UI icons.
+ */
+public class IconFactory {
+
+ /**
+ * Builds an icon with the dimensions iconWidth:iconHeight. If scale is set
+ * the source image is stretched to fit within the given dimensions;
+ * otherwise, the source image is cropped to the proper aspect ratio.
+ *
+ * @param sourceImage image to create an icon from.
+ * @param iconWidth width of the icon bitmap.
+ * @param iconHeight height of the icon bitmap.
+ * @param scale if true, stretch sourceImage to fit the icon dimensions.
+ * @return an icon bitmap with the dimensions iconWidth:iconHeight.
+ */
+ public static Bitmap createIcon(Bitmap sourceImage, int iconWidth, int iconHeight,
+ boolean scale) {
+ if (sourceImage == null) {
+ throw new IllegalArgumentException("Null argument to buildIcon");
+ }
+
+ int sourceWidth = sourceImage.getWidth();
+ int sourceHeight = sourceImage.getHeight();
+
+ if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) {
+ throw new IllegalArgumentException("Bitmap with dimension 0 used as input");
+ }
+
+ Bitmap icon = Bitmap.createBitmap(iconWidth, iconHeight,
+ Bitmap.Config.ARGB_8888);
+ drawIcon(icon, sourceImage, scale);
+ return icon;
+ }
+
+ /**
+ * Draws an icon in the destination bitmap. If scale is set the source image
+ * is stretched to fit within the destination dimensions; otherwise, the
+ * source image is cropped to the proper aspect ratio.
+ *
+ * @param dest bitmap into which to draw the icon.
+ * @param sourceImage image to create an icon from.
+ * @param scale if true, stretch sourceImage to fit the destination.
+ */
+ public static void drawIcon(Bitmap dest, Bitmap sourceImage, boolean scale) {
+ if (dest == null || sourceImage == null) {
+ throw new IllegalArgumentException("Null argument to buildIcon");
+ }
+
+ int sourceWidth = sourceImage.getWidth();
+ int sourceHeight = sourceImage.getHeight();
+ int iconWidth = dest.getWidth();
+ int iconHeight = dest.getHeight();
+
+ if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) {
+ throw new IllegalArgumentException("Bitmap with dimension 0 used as input");
+ }
+
+ Rect destRect = new Rect(0, 0, iconWidth, iconHeight);
+ Canvas canvas = new Canvas(dest);
+
+ Rect srcRect = null;
+ if (scale) {
+ // scale image to fit in icon (stretches if aspect isn't the same)
+ srcRect = new Rect(0, 0, sourceWidth, sourceHeight);
+ } else {
+ // crop image to aspect ratio iconWidth:iconHeight
+ float wScale = sourceWidth / (float) iconWidth;
+ float hScale = sourceHeight / (float) iconHeight;
+ float s = Math.min(hScale, wScale);
+
+ float iw = iconWidth * s;
+ float ih = iconHeight * s;
+
+ float borderW = (sourceWidth - iw) / 2.0f;
+ float borderH = (sourceHeight - ih) / 2.0f;
+ RectF rec = new RectF(borderW, borderH, borderW + iw, borderH + ih);
+ srcRect = new Rect();
+ rec.roundOut(srcRect);
+ }
+
+ canvas.drawBitmap(sourceImage, srcRect, destRect, new Paint());
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java b/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
index 59c18e0f4..3e210a0dc 100644
--- a/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
+++ b/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
@@ -32,6 +31,7 @@ import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.imageshow.GeometryListener;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.presets.ImagePreset;
+import com.android.gallery3d.filtershow.tools.IconFactory;
// TODO: merge back IconButton and FilterIconButton?
public class FilterIconButton extends IconButton implements View.OnClickListener,
@@ -119,8 +119,8 @@ public class FilterIconButton extends IconButton implements View.OnClickListener
} else {
mIconBitmap = bmap;
if (mOverlayBitmap != null) {
- Rect destination = new Rect(0, 0, mIconBitmap.getWidth(), mIconBitmap.getHeight());
- drawImage(mIconBitmap, mOverlayBitmap, destination);
+ // Draw overlay bitmap over icon
+ IconFactory.drawIcon(mIconBitmap, mOverlayBitmap, false);
}
setIcon(mIconBitmap);
}
diff --git a/src/com/android/gallery3d/filtershow/ui/IconButton.java b/src/com/android/gallery3d/filtershow/ui/IconButton.java
index 2484d5feb..e7087bdfe 100644
--- a/src/com/android/gallery3d/filtershow/ui/IconButton.java
+++ b/src/com/android/gallery3d/filtershow/ui/IconButton.java
@@ -19,12 +19,16 @@ package com.android.gallery3d.filtershow.ui;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.Button;
+import com.android.gallery3d.filtershow.tools.IconFactory;
+import com.android.photos.data.GalleryBitmapPool;
+
/**
* Class of buttons with both an image icon and text.
*/
@@ -54,8 +58,8 @@ public class IconButton extends Button {
/**
* Set the image that the button icon will use. The image bitmap will be scaled
- * and cropped into the largest square bitmap that will fit cleanly within the
- * IconButton's layout.
+ * and cropped into the largest bitmap with dimensions given by getGoodIconSideSize()
+ * that will fit cleanly within the IconButton's layout.
*
* @param image image that icon will be set to before next draw.
*/
@@ -66,14 +70,63 @@ public class IconButton extends Button {
}
/**
+ * Finds a side lengths for the icon that fits within the button.
+ * Only call after layout. The default implementation returns the best
+ * side lengths for a square icon.
+ * <p>
+ * Override this to make non-square icons or icons with different padding
+ * constraints.
+ *
+ * @return an array of ints representing the icon dimensions [ width, height ]
+ */
+ protected int[] getGoodIconSideSize() {
+ Paint p = getPaint();
+ Rect bounds = new Rect();
+ // find text bounds
+ String s = getText().toString();
+ p.getTextBounds(s, 0, s.length(), bounds);
+
+ int inner_padding = 2 * getCompoundDrawablePadding();
+
+ // find total vertical space available for the icon
+ int vert = getHeight() - getPaddingTop() - getPaddingBottom() - bounds.height()
+ - inner_padding;
+
+ // find total horizontal space available for the icon
+ int horiz = getWidth() - getPaddingLeft() - getPaddingRight() - inner_padding;
+
+ int defaultSize = Math.min(vert, horiz);
+ return new int[] { defaultSize, defaultSize };
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ if (w != oldw || h != oldh) {
+ stale_icon = true;
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (stale_icon && mImageMirror != null && mImageMirror.getHeight() > 0
+ && mImageMirror.getWidth() > 0) {
+ stale_icon = !makeAndSetIcon(mImageMirror);
+ }
+ super.onDraw(canvas);
+ }
+
+ // Internal methods
+
+ /**
* Creates and sets button icon. Only call after layout.
*
* @param image bitmap to use as icon
*/
private boolean makeAndSetIcon(Bitmap image) {
- int size = getGoodIconSideSize();
- if (size > 0) {
- return setImageIcon(makeImageIcon(image, size, size));
+ int[] sizes = getGoodIconSideSize();
+ if (sizes != null && sizes.length >= 2 && sizes[0] > 0 && sizes[1] > 0) {
+ return setImageIcon(makeImageIcon(image, sizes[0], sizes[1]));
}
return false;
}
@@ -87,6 +140,10 @@ public class IconButton extends Button {
if (image == null) {
return false;
}
+ if(mIcon != null && mIcon.getConfig() == Bitmap.Config.ARGB_8888) {
+ GalleryBitmapPool.getInstance().put(mIcon);
+ mIcon = null;
+ }
mIcon = image;
this.setCompoundDrawablesWithIntrinsicBounds(null,
new BitmapDrawable(getResources(), mIcon), null, null);
@@ -102,78 +159,19 @@ public class IconButton extends Button {
* @return the scaled/cropped icon bitmap
*/
private Bitmap makeImageIcon(Bitmap image, int width, int height) {
- Rect destination = new Rect(0, 0, width, height);
- Bitmap bmap = Bitmap.createBitmap(width, height,
- Bitmap.Config.ARGB_8888);
- drawImage(bmap, image, destination);
- return bmap;
- }
-
- /**
- * Finds a side length for the (square) icon that fits within the button.
- * Only call after layout.
- *
- * @return icon side length
- */
- private int getGoodIconSideSize() {
- Paint p = getPaint();
- Rect bounds = new Rect();
- String s = getText().toString();
- p.getTextBounds(s, 0, s.length(), bounds);
- int inner_padding = 2 * getCompoundDrawablePadding();
- int vert = getHeight() - getPaddingTop() - getPaddingBottom() - bounds.height()
- - inner_padding;
- int horiz = getWidth() - getPaddingLeft() - getPaddingRight() - inner_padding;
- return Math.min(vert, horiz);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- if (w != oldw || h != oldh) {
- stale_icon = true;
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (stale_icon && mImageMirror != null && mImageMirror.getHeight() > 0
- && mImageMirror.getWidth() > 0) {
- stale_icon = !makeAndSetIcon(mImageMirror);
+ if (image == null || image.getHeight() < 1 || image.getWidth() < 1 ||
+ width < 1 || height < 1) {
+ throw new IllegalArgumentException("input is null, or has invalid dimensions");
}
- super.onDraw(canvas);
- }
-
- /**
- * Draws the src image into the destination rectangle within the dst bitmap.
- * If src is a non-square image, clips to be a square before drawing into dst.
- *
- * @param dst bitmap being drawn on.
- * @param src bitmap to draw into dst.
- * @param destination square in dst in which to draw src.
- */
- protected static void drawImage(Bitmap dst, Bitmap src, Rect destination) {
- if (src != null && dst != null && src.getWidth() > 0 && dst.getWidth() > 0
- && src.getHeight() > 0 && dst.getHeight() > 0) {
- Canvas canvas = new Canvas(dst);
- int iw = src.getWidth();
- int ih = src.getHeight();
- int x = 0;
- int y = 0;
- int size = 0;
- Rect source = null;
- if (iw > ih) {
- size = ih;
- x = (int) ((iw - size) / 2.0f);
- y = 0;
- } else {
- size = iw;
- x = 0;
- y = (int) ((ih - size) / 2.0f);
- }
- source = new Rect(x, y, x + size, y + size);
- canvas.drawBitmap(src, source, destination, new Paint());
+ Bitmap icon = null;
+ icon = GalleryBitmapPool.getInstance().get(width, height);
+ if (icon == null) {
+ icon = IconFactory.createIcon(image, width, height, false);
+ } else {
+ assert(icon.getWidth() == width && icon.getHeight() == height);
+ icon.eraseColor(Color.TRANSPARENT);
+ IconFactory.drawIcon(icon, image, false);
}
+ return icon;
}
-
}