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