Utilities.java revision 31dd503c6aa69018e694d91724d46db49ea09327
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpackage com.android.launcher;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.drawable.Drawable;
2031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.drawable.PaintDrawable;
2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Bitmap;
2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.PixelFormat;
2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.PaintFlagsDrawFilter;
2531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Paint;
2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.Resources;
2831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Various utilities shared amongst the Launcher's classes.
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectfinal class Utilities {
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static int sIconWidth = -1;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static int sIconHeight = -1;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final Paint sPaint = new Paint();
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final Rect sBounds = new Rect();
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final Rect sOldBounds = new Rect();
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static Canvas sCanvas = new Canvas();
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    static {
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Paint.FILTER_BITMAP_FLAG));
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    static Bitmap centerToFit(Bitmap bitmap, int width, int height, Context context) {
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int bitmapWidth = bitmap.getWidth();
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int bitmapHeight = bitmap.getHeight();
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (bitmapWidth < width || bitmapHeight < height) {
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int color = context.getResources().getColor(R.color.window_background);
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Bitmap centered = Bitmap.createBitmap(bitmapWidth < width ? width : bitmapWidth,
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    bitmapHeight < height ? height : bitmapHeight, Bitmap.Config.RGB_565);
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Canvas canvas = new Canvas(centered);
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            canvas.drawColor(color);
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            canvas.drawBitmap(bitmap, (width - bitmapWidth) / 2.0f, (height - bitmapHeight) / 2.0f,
5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    null);
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            bitmap = centered;
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return bitmap;
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Returns a Drawable representing the thumbnail of the specified Drawable.
6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The size of the thumbnail is defined by the dimension
7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * android.R.dimen.launcher_application_icon_size.
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * This method is not thread-safe and should be invoked on the UI thread only.
7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param icon The icon to get a thumbnail of.
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return A thumbnail for the specified icon or the icon itself if the
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *         thumbnail could not be created.
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    static Drawable createIconThumbnail(Drawable icon, Context context) {
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (sIconWidth == -1) {
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Resources resources = context.getResources();
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sIconWidth = sIconHeight = (int) resources.getDimension(
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    android.R.dimen.app_icon_size);
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int width = sIconWidth;
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int height = sIconHeight;
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int iconWidth = icon.getIntrinsicWidth();
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int iconHeight = icon.getIntrinsicHeight();
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (icon instanceof PaintDrawable) {
9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            PaintDrawable painter = (PaintDrawable) icon;
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            painter.setIntrinsicWidth(width);
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            painter.setIntrinsicHeight(height);
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (width > 0 && height > 0) {
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (width < iconWidth || height < iconHeight) {
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final float ratio = (float) iconWidth / iconHeight;
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (iconWidth > iconHeight) {
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    height = (int) (width / ratio);
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else if (iconHeight > iconWidth) {
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    width = (int) (height * ratio);
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Canvas canvas = sCanvas;
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                canvas.setBitmap(thumb);
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Copy the old bounds to restore them later
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // If we were to do oldBounds = icon.getBounds(),
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // the call to setBounds() that follows would
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // change the same instance and we would lose the
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // old bounds
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                sOldBounds.set(icon.getBounds());
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final int x = (sIconWidth - width) / 2;
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final int y = (sIconHeight - height) / 2;
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.setBounds(x, y, x + width, y + height);
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.draw(canvas);
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.setBounds(sOldBounds);
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon = new FastBitmapDrawable(thumb);
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if (iconWidth < width && iconHeight < height) {
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Bitmap.Config c = Bitmap.Config.ARGB_8888;
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final Canvas canvas = sCanvas;
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                canvas.setBitmap(thumb);
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                sOldBounds.set(icon.getBounds());
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final int x = (width - iconWidth) / 2;
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final int y = (height - iconHeight) / 2;
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.setBounds(x, y, x + iconWidth, y + iconHeight);
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.draw(canvas);
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon.setBounds(sOldBounds);
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                icon = new FastBitmapDrawable(thumb);
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return icon;
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Returns a Bitmap representing the thumbnail of the specified Bitmap.
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The size of the thumbnail is defined by the dimension
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * android.R.dimen.launcher_application_icon_size.
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * This method is not thread-safe and should be invoked on the UI thread only.
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param bitmap The bitmap to get a thumbnail of.
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return A thumbnail for the specified bitmap or the bitmap itself if the
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *         thumbnail could not be created.
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (sIconWidth == -1) {
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Resources resources = context.getResources();
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sIconWidth = sIconHeight = (int) resources.getDimension(
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    android.R.dimen.app_icon_size);
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int width = sIconWidth;
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int height = sIconHeight;
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int bitmapWidth = bitmap.getWidth();
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int bitmapHeight = bitmap.getHeight();
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (width > 0 && height > 0 && (width < bitmapWidth || height < bitmapHeight)) {
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final float ratio = (float) bitmapWidth / bitmapHeight;
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (bitmapWidth > bitmapHeight) {
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                height = (int) (width / ratio);
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if (bitmapHeight > bitmapWidth) {
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                width = (int) (height * ratio);
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ?
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    bitmap.getConfig() : Bitmap.Config.ARGB_8888;
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Canvas canvas = sCanvas;
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Paint paint = sPaint;
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            canvas.setBitmap(thumb);
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            paint.setDither(false);
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            paint.setFilterBitmap(true);
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sBounds.set((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return thumb;
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return bitmap;
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
196