Home | History | Annotate | Download | only in policy
      1 /*
      2  * Copyright (C) 2008 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 
     17 package com.android.server.policy;
     18 
     19 import android.graphics.drawable.BitmapDrawable;
     20 import android.graphics.drawable.Drawable;
     21 import android.graphics.drawable.PaintDrawable;
     22 import android.graphics.drawable.StateListDrawable;
     23 import android.graphics.Bitmap;
     24 import android.graphics.BlurMaskFilter;
     25 import android.graphics.Canvas;
     26 import android.graphics.ColorMatrix;
     27 import android.graphics.Paint;
     28 import android.graphics.PaintFlagsDrawFilter;
     29 import android.graphics.PorterDuff;
     30 import android.graphics.Rect;
     31 import android.graphics.TableMaskFilter;
     32 import android.util.DisplayMetrics;
     33 import android.util.TypedValue;
     34 import android.content.res.Resources;
     35 import android.content.Context;
     36 
     37 /**
     38  * Various utilities shared amongst the Launcher's classes.
     39  */
     40 public final class IconUtilities {
     41     private static final String TAG = "IconUtilities";
     42 
     43     private static final int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
     44 
     45     private int mIconWidth = -1;
     46     private int mIconHeight = -1;
     47     private int mIconTextureWidth = -1;
     48     private int mIconTextureHeight = -1;
     49 
     50     private final Paint mPaint = new Paint();
     51     private final Paint mBlurPaint = new Paint();
     52     private final Paint mGlowColorPressedPaint = new Paint();
     53     private final Paint mGlowColorFocusedPaint = new Paint();
     54     private final Rect mOldBounds = new Rect();
     55     private final Canvas mCanvas = new Canvas();
     56     private final DisplayMetrics mDisplayMetrics;
     57 
     58     private int mColorIndex = 0;
     59 
     60     public IconUtilities(Context context) {
     61         final Resources resources = context.getResources();
     62         DisplayMetrics metrics = mDisplayMetrics = resources.getDisplayMetrics();
     63         final float density = metrics.density;
     64         final float blurPx = 5 * density;
     65 
     66         mIconWidth = mIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
     67         mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);
     68 
     69         mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
     70 
     71         TypedValue value = new TypedValue();
     72         mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute(
     73                 android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300);
     74         mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
     75         mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute(
     76                 android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00);
     77         mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
     78 
     79         ColorMatrix cm = new ColorMatrix();
     80         cm.setSaturation(0.2f);
     81 
     82         mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
     83                 Paint.FILTER_BITMAP_FLAG));
     84     }
     85 
     86     public Drawable createIconDrawable(Drawable src) {
     87         Bitmap scaled = createIconBitmap(src);
     88 
     89         StateListDrawable result = new StateListDrawable();
     90 
     91         result.addState(new int[] { android.R.attr.state_focused },
     92                 new BitmapDrawable(createSelectedBitmap(scaled, false)));
     93         result.addState(new int[] { android.R.attr.state_pressed },
     94                 new BitmapDrawable(createSelectedBitmap(scaled, true)));
     95         result.addState(new int[0], new BitmapDrawable(scaled));
     96 
     97         result.setBounds(0, 0, mIconTextureWidth, mIconTextureHeight);
     98         return result;
     99     }
    100 
    101     /**
    102      * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
    103      * of two sized ARGB_8888 bitmap that can be used as a gl texture.
    104      */
    105     public Bitmap createIconBitmap(Drawable icon) {
    106         int width = mIconWidth;
    107         int height = mIconHeight;
    108 
    109         if (icon instanceof PaintDrawable) {
    110             PaintDrawable painter = (PaintDrawable) icon;
    111             painter.setIntrinsicWidth(width);
    112             painter.setIntrinsicHeight(height);
    113         } else if (icon instanceof BitmapDrawable) {
    114             // Ensure the bitmap has a density.
    115             BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
    116             Bitmap bitmap = bitmapDrawable.getBitmap();
    117             if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
    118                 bitmapDrawable.setTargetDensity(mDisplayMetrics);
    119             }
    120         }
    121         int sourceWidth = icon.getIntrinsicWidth();
    122         int sourceHeight = icon.getIntrinsicHeight();
    123 
    124         if (sourceWidth > 0 && sourceHeight > 0) {
    125             // There are intrinsic sizes.
    126             if (width < sourceWidth || height < sourceHeight) {
    127                 // It's too big, scale it down.
    128                 final float ratio = (float) sourceWidth / sourceHeight;
    129                 if (sourceWidth > sourceHeight) {
    130                     height = (int) (width / ratio);
    131                 } else if (sourceHeight > sourceWidth) {
    132                     width = (int) (height * ratio);
    133                 }
    134             } else if (sourceWidth < width && sourceHeight < height) {
    135                 // It's small, use the size they gave us.
    136                 width = sourceWidth;
    137                 height = sourceHeight;
    138             }
    139         }
    140 
    141         // no intrinsic size --> use default size
    142         int textureWidth = mIconTextureWidth;
    143         int textureHeight = mIconTextureHeight;
    144 
    145         final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
    146                 Bitmap.Config.ARGB_8888);
    147         final Canvas canvas = mCanvas;
    148         canvas.setBitmap(bitmap);
    149 
    150         final int left = (textureWidth-width) / 2;
    151         final int top = (textureHeight-height) / 2;
    152 
    153         if (false) {
    154             // draw a big box for the icon for debugging
    155             canvas.drawColor(sColors[mColorIndex]);
    156             if (++mColorIndex >= sColors.length) mColorIndex = 0;
    157             Paint debugPaint = new Paint();
    158             debugPaint.setColor(0xffcccc00);
    159             canvas.drawRect(left, top, left+width, top+height, debugPaint);
    160         }
    161 
    162         mOldBounds.set(icon.getBounds());
    163         icon.setBounds(left, top, left+width, top+height);
    164         icon.draw(canvas);
    165         icon.setBounds(mOldBounds);
    166 
    167         return bitmap;
    168     }
    169 
    170     private Bitmap createSelectedBitmap(Bitmap src, boolean pressed) {
    171         final Bitmap result = Bitmap.createBitmap(mIconTextureWidth, mIconTextureHeight,
    172                 Bitmap.Config.ARGB_8888);
    173         final Canvas dest = new Canvas(result);
    174 
    175         dest.drawColor(0, PorterDuff.Mode.CLEAR);
    176 
    177         int[] xy = new int[2];
    178         Bitmap mask = src.extractAlpha(mBlurPaint, xy);
    179 
    180         dest.drawBitmap(mask, xy[0], xy[1],
    181                 pressed ? mGlowColorPressedPaint : mGlowColorFocusedPaint);
    182 
    183         mask.recycle();
    184 
    185         dest.drawBitmap(src, 0, 0, mPaint);
    186         dest.setBitmap(null);
    187 
    188         return result;
    189     }
    190 }
    191