Utilities.java revision aafa03cbb925c74be1c13f8bb99d928be429e62f
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 17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.content.Context; 20aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.content.res.Resources; 2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Bitmap; 221291a8c236c84451321438cb68855f6f2eb24959Joe Onoratoimport android.graphics.BlurMaskFilter; 2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas; 2456d8291af6a28c6ba64113120efdf84a785e816cJoe Onoratoimport android.graphics.ColorMatrix; 2556d8291af6a28c6ba64113120efdf84a785e816cJoe Onoratoimport android.graphics.ColorMatrixColorFilter; 2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Paint; 27bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.graphics.PaintFlagsDrawFilter; 281291a8c236c84451321438cb68855f6f2eb24959Joe Onoratoimport android.graphics.PorterDuff; 2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect; 30bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.graphics.RectF; 31cdd117935f51d66f6f212387300d851f81aa071fMike Reedimport android.graphics.TableMaskFilter; 32bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.graphics.Typeface; 33aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.graphics.drawable.BitmapDrawable; 34aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.graphics.drawable.Drawable; 35aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.graphics.drawable.PaintDrawable; 36bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.text.StaticLayout; 37bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.text.TextPaint; 38aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.text.Layout.Alignment; 3932ce7f17a85abf9b175f773371308876f7401547Dianne Hackbornimport android.util.DisplayMetrics; 40bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onoratoimport android.util.Log; 4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 42edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guyimport com.android.launcher.R; 43edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Various utilities shared amongst the Launcher's classes. 4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectfinal class Utilities { 481291a8c236c84451321438cb68855f6f2eb24959Joe Onorato private static final String TAG = "Launcher.Utilities"; 491291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 509392a75d0493fc9aacbb1e6e63518b0fa66cc3b9Joe Onorato private static final boolean TEXT_BURN = false; 519392a75d0493fc9aacbb1e6e63518b0fa66cc3b9Joe Onorato 5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static int sIconWidth = -1; 5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static int sIconHeight = -1; 546665c0f1fec6ec0962896622986340081df992e7Joe Onorato private static int sIconTextureWidth = -1; 556665c0f1fec6ec0962896622986340081df992e7Joe Onorato private static int sIconTextureHeight = -1; 5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final Paint sPaint = new Paint(); 581291a8c236c84451321438cb68855f6f2eb24959Joe Onorato private static final Paint sBlurPaint = new Paint(); 59eb8325a9e24cda47720152e1e95f5d86ab11f200Joe Onorato private static final Paint sGlowColorPressedPaint = new Paint(); 60c61cff9299a54599c2b214de7c819b6be0412f4eJoe Onorato private static final Paint sGlowColorFocusedPaint = new Paint(); 6156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato private static final Paint sDisabledPaint = new Paint(); 6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final Rect sBounds = new Rect(); 6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final Rect sOldBounds = new Rect(); 6489911d2450f5db92d79e3bcefa9d324e9e8c4900Romain Guy private static final Canvas sCanvas = new Canvas(); 6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static { 6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Paint.FILTER_BITMAP_FLAG)); 6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static Bitmap centerToFit(Bitmap bitmap, int width, int height, Context context) { 7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int bitmapWidth = bitmap.getWidth(); 7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int bitmapHeight = bitmap.getHeight(); 7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (bitmapWidth < width || bitmapHeight < height) { 7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int color = context.getResources().getColor(R.color.window_background); 7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Bitmap centered = Bitmap.createBitmap(bitmapWidth < width ? width : bitmapWidth, 7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project bitmapHeight < height ? height : bitmapHeight, Bitmap.Config.RGB_565); 8032ce7f17a85abf9b175f773371308876f7401547Dianne Hackborn centered.setDensity(bitmap.getDensity()); 8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Canvas canvas = new Canvas(centered); 8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project canvas.drawColor(color); 8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project canvas.drawBitmap(bitmap, (width - bitmapWidth) / 2.0f, (height - bitmapHeight) / 2.0f, 8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project null); 8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project bitmap = centered; 8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return bitmap; 9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 926665c0f1fec6ec0962896622986340081df992e7Joe Onorato static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; 936665c0f1fec6ec0962896622986340081df992e7Joe Onorato static int sColorIndex = 0; 946665c0f1fec6ec0962896622986340081df992e7Joe Onorato 956665c0f1fec6ec0962896622986340081df992e7Joe Onorato /** 966665c0f1fec6ec0962896622986340081df992e7Joe Onorato * Returns a bitmap suitable for the all apps view. The bitmap will be a power 976665c0f1fec6ec0962896622986340081df992e7Joe Onorato * of two sized ARGB_8888 bitmap that can be used as a gl texture. 986665c0f1fec6ec0962896622986340081df992e7Joe Onorato */ 990589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato static Bitmap createIconBitmap(Drawable icon, Context context) { 1006665c0f1fec6ec0962896622986340081df992e7Joe Onorato synchronized (sCanvas) { // we share the statics :-( 1016665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (sIconWidth == -1) { 1026665c0f1fec6ec0962896622986340081df992e7Joe Onorato initStatics(context); 1036665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1046665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1056665c0f1fec6ec0962896622986340081df992e7Joe Onorato int width = sIconWidth; 1066665c0f1fec6ec0962896622986340081df992e7Joe Onorato int height = sIconHeight; 1076665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1086665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (icon instanceof PaintDrawable) { 1096665c0f1fec6ec0962896622986340081df992e7Joe Onorato PaintDrawable painter = (PaintDrawable) icon; 1106665c0f1fec6ec0962896622986340081df992e7Joe Onorato painter.setIntrinsicWidth(width); 1116665c0f1fec6ec0962896622986340081df992e7Joe Onorato painter.setIntrinsicHeight(height); 1126665c0f1fec6ec0962896622986340081df992e7Joe Onorato } else if (icon instanceof BitmapDrawable) { 1136665c0f1fec6ec0962896622986340081df992e7Joe Onorato // Ensure the bitmap has a density. 1146665c0f1fec6ec0962896622986340081df992e7Joe Onorato BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; 1156665c0f1fec6ec0962896622986340081df992e7Joe Onorato Bitmap bitmap = bitmapDrawable.getBitmap(); 1166665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { 1176665c0f1fec6ec0962896622986340081df992e7Joe Onorato bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics()); 1186665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1196665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1206665c0f1fec6ec0962896622986340081df992e7Joe Onorato int sourceWidth = icon.getIntrinsicWidth(); 1216665c0f1fec6ec0962896622986340081df992e7Joe Onorato int sourceHeight = icon.getIntrinsicHeight(); 1226665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1236665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (sourceWidth > 0 && sourceWidth > 0) { 1246665c0f1fec6ec0962896622986340081df992e7Joe Onorato // There are intrinsic sizes. 12589911d2450f5db92d79e3bcefa9d324e9e8c4900Romain Guy if (width < sourceWidth || height < sourceHeight) { 1266665c0f1fec6ec0962896622986340081df992e7Joe Onorato // It's too big, scale it down. 1276665c0f1fec6ec0962896622986340081df992e7Joe Onorato final float ratio = (float) sourceWidth / sourceHeight; 1286665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (sourceWidth > sourceHeight) { 1296665c0f1fec6ec0962896622986340081df992e7Joe Onorato height = (int) (width / ratio); 1306665c0f1fec6ec0962896622986340081df992e7Joe Onorato } else if (sourceHeight > sourceWidth) { 1316665c0f1fec6ec0962896622986340081df992e7Joe Onorato width = (int) (height * ratio); 1326665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1336665c0f1fec6ec0962896622986340081df992e7Joe Onorato } else if (sourceWidth < width && sourceHeight < height) { 1346665c0f1fec6ec0962896622986340081df992e7Joe Onorato // It's small, use the size they gave us. 1356665c0f1fec6ec0962896622986340081df992e7Joe Onorato width = sourceWidth; 13689911d2450f5db92d79e3bcefa9d324e9e8c4900Romain Guy height = sourceHeight; 1376665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1386665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1396665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1406665c0f1fec6ec0962896622986340081df992e7Joe Onorato // no intrinsic size --> use default size 1416665c0f1fec6ec0962896622986340081df992e7Joe Onorato int textureWidth = sIconTextureWidth; 1426665c0f1fec6ec0962896622986340081df992e7Joe Onorato int textureHeight = sIconTextureHeight; 1436665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1446665c0f1fec6ec0962896622986340081df992e7Joe Onorato final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, 1456665c0f1fec6ec0962896622986340081df992e7Joe Onorato Bitmap.Config.ARGB_8888); 1466665c0f1fec6ec0962896622986340081df992e7Joe Onorato final Canvas canvas = sCanvas; 1476665c0f1fec6ec0962896622986340081df992e7Joe Onorato canvas.setBitmap(bitmap); 1486665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1496665c0f1fec6ec0962896622986340081df992e7Joe Onorato final int left = (textureWidth-width) / 2; 1506665c0f1fec6ec0962896622986340081df992e7Joe Onorato final int top = (textureHeight-height) / 2; 1516665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1526665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (false) { 1536665c0f1fec6ec0962896622986340081df992e7Joe Onorato // draw a big box for the icon for debugging 1546665c0f1fec6ec0962896622986340081df992e7Joe Onorato canvas.drawColor(sColors[sColorIndex]); 1556665c0f1fec6ec0962896622986340081df992e7Joe Onorato if (++sColorIndex >= sColors.length) sColorIndex = 0; 1566665c0f1fec6ec0962896622986340081df992e7Joe Onorato Paint debugPaint = new Paint(); 1576665c0f1fec6ec0962896622986340081df992e7Joe Onorato debugPaint.setColor(0xffcccc00); 1586665c0f1fec6ec0962896622986340081df992e7Joe Onorato canvas.drawRect(left, top, left+width, top+height, debugPaint); 1596665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1606665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1616665c0f1fec6ec0962896622986340081df992e7Joe Onorato sOldBounds.set(icon.getBounds()); 1626665c0f1fec6ec0962896622986340081df992e7Joe Onorato icon.setBounds(left, top, left+width, top+height); 1636665c0f1fec6ec0962896622986340081df992e7Joe Onorato icon.draw(canvas); 1646665c0f1fec6ec0962896622986340081df992e7Joe Onorato icon.setBounds(sOldBounds); 1656665c0f1fec6ec0962896622986340081df992e7Joe Onorato 1666665c0f1fec6ec0962896622986340081df992e7Joe Onorato return bitmap; 1676665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1686665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 1696665c0f1fec6ec0962896622986340081df992e7Joe Onorato 170c61cff9299a54599c2b214de7c819b6be0412f4eJoe Onorato static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight, 171eb8325a9e24cda47720152e1e95f5d86ab11f200Joe Onorato boolean pressed, Bitmap src) { 1721291a8c236c84451321438cb68855f6f2eb24959Joe Onorato synchronized (sCanvas) { // we share the statics :-( 1731291a8c236c84451321438cb68855f6f2eb24959Joe Onorato if (sIconWidth == -1) { 1741291a8c236c84451321438cb68855f6f2eb24959Joe Onorato // We can't have gotten to here without src being initialized, which 1751291a8c236c84451321438cb68855f6f2eb24959Joe Onorato // comes from this file already. So just assert. 1761291a8c236c84451321438cb68855f6f2eb24959Joe Onorato //initStatics(context); 1771291a8c236c84451321438cb68855f6f2eb24959Joe Onorato throw new RuntimeException("Assertion failed: Utilities not initialized"); 1781291a8c236c84451321438cb68855f6f2eb24959Joe Onorato } 1791291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 1801291a8c236c84451321438cb68855f6f2eb24959Joe Onorato dest.drawColor(0, PorterDuff.Mode.CLEAR); 181b4ecab24dbff6e6dc9e7929655a55199fc32e8ddJason Sams 1821291a8c236c84451321438cb68855f6f2eb24959Joe Onorato int[] xy = new int[2]; 183cdd117935f51d66f6f212387300d851f81aa071fMike Reed Bitmap mask = src.extractAlpha(sBlurPaint, xy); 1841291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 185cdd117935f51d66f6f212387300d851f81aa071fMike Reed float px = (destWidth - src.getWidth()) / 2; 186cdd117935f51d66f6f212387300d851f81aa071fMike Reed float py = (destHeight - src.getHeight()) / 2; 187c61cff9299a54599c2b214de7c819b6be0412f4eJoe Onorato dest.drawBitmap(mask, px + xy[0], py + xy[1], 188eb8325a9e24cda47720152e1e95f5d86ab11f200Joe Onorato pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint); 1891291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 1901291a8c236c84451321438cb68855f6f2eb24959Joe Onorato mask.recycle(); 1911291a8c236c84451321438cb68855f6f2eb24959Joe Onorato } 1921291a8c236c84451321438cb68855f6f2eb24959Joe Onorato } 1936665c0f1fec6ec0962896622986340081df992e7Joe Onorato 19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Returns a Bitmap representing the thumbnail of the specified Bitmap. 19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * The size of the thumbnail is defined by the dimension 19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * android.R.dimen.launcher_application_icon_size. 19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param bitmap The bitmap to get a thumbnail of. 20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @return A thumbnail for the specified bitmap or the bitmap itself if the 20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * thumbnail could not be created. 20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 2050589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) { 2069c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato synchronized (sCanvas) { // we share the statics :-( 2079c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato if (sIconWidth == -1) { 2086665c0f1fec6ec0962896622986340081df992e7Joe Onorato initStatics(context); 2099c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato } 21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 2110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) { 2120589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato return bitmap; 2130589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } else { 2140589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato return createIconBitmap(new BitmapDrawable(bitmap), context); 21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 218bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 21956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato static Bitmap drawDisabledBitmap(Bitmap bitmap, Context context) { 22056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato synchronized (sCanvas) { // we share the statics :-( 22156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato if (sIconWidth == -1) { 22256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato initStatics(context); 22356d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato } 22456d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato final Bitmap disabled = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 22556d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato Bitmap.Config.ARGB_8888); 22656d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato final Canvas canvas = sCanvas; 22756d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato canvas.setBitmap(disabled); 22856d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato 22956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato canvas.drawBitmap(bitmap, 0.0f, 0.0f, sDisabledPaint); 23056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato 23156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato return disabled; 23256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato } 23356d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato } 23456d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato 2356665c0f1fec6ec0962896622986340081df992e7Joe Onorato private static void initStatics(Context context) { 2366665c0f1fec6ec0962896622986340081df992e7Joe Onorato final Resources resources = context.getResources(); 2371291a8c236c84451321438cb68855f6f2eb24959Joe Onorato final DisplayMetrics metrics = resources.getDisplayMetrics(); 2381291a8c236c84451321438cb68855f6f2eb24959Joe Onorato final float density = metrics.density; 2391291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 2406665c0f1fec6ec0962896622986340081df992e7Joe Onorato sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size); 241b4ecab24dbff6e6dc9e7929655a55199fc32e8ddJason Sams sIconTextureWidth = sIconTextureHeight = sIconWidth + 2; 2421291a8c236c84451321438cb68855f6f2eb24959Joe Onorato 243a4c0cb965575b7a0832d92bc0b33e06c7c66cb10Joe Onorato sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL)); 244eb8325a9e24cda47720152e1e95f5d86ab11f200Joe Onorato sGlowColorPressedPaint.setColor(0xffffc300); 245eb8325a9e24cda47720152e1e95f5d86ab11f200Joe Onorato sGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); 246c61cff9299a54599c2b214de7c819b6be0412f4eJoe Onorato sGlowColorFocusedPaint.setColor(0xffff8e00); 247c61cff9299a54599c2b214de7c819b6be0412f4eJoe Onorato sGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); 24856d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato 24956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato ColorMatrix cm = new ColorMatrix(); 25056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato cm.setSaturation(0.2f); 25156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm)); 25256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato sDisabledPaint.setAlpha(0x88); 2536665c0f1fec6ec0962896622986340081df992e7Joe Onorato } 2546665c0f1fec6ec0962896622986340081df992e7Joe Onorato 255bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato static class BubbleText { 256bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato private static final int MAX_LINES = 2; 257bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 25888f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final TextPaint mTextPaint; 259bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 26088f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final RectF mBubbleRect = new RectF(); 261bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 26288f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final float mTextWidth; 26388f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mLeading; 26488f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mFirstLineY; 26588f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mLineHeight; 26688f38d186bcba897ef4222d23515f127c77358aaRomain Guy 26788f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mBitmapWidth; 26888f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mBitmapHeight; 26988f38d186bcba897ef4222d23515f127c77358aaRomain Guy private final int mDensity; 270bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 271bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato BubbleText(Context context) { 272bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato final Resources resources = context.getResources(); 273bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 27488f38d186bcba897ef4222d23515f127c77358aaRomain Guy final DisplayMetrics metrics = resources.getDisplayMetrics(); 27588f38d186bcba897ef4222d23515f127c77358aaRomain Guy final float scale = metrics.density; 27688f38d186bcba897ef4222d23515f127c77358aaRomain Guy mDensity = metrics.densityDpi; 277bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 278970516430064068a1513b7489848339829b7971aKenny Root final float paddingLeft = 2.0f * scale; 279970516430064068a1513b7489848339829b7971aKenny Root final float paddingRight = 2.0f * scale; 280442eda2cc1956003b2366c3060f8c0dbae024710Romain Guy final float cellWidth = resources.getDimension(R.dimen.title_texture_width); 281bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 282bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato RectF bubbleRect = mBubbleRect; 283bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato bubbleRect.left = 0; 284bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato bubbleRect.top = 0; 285c0c4fe39166b3ed8b9bb19129a890922d93f7a92Romain Guy bubbleRect.right = (int) cellWidth; 286bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 287970516430064068a1513b7489848339829b7971aKenny Root mTextWidth = cellWidth - paddingLeft - paddingRight; 288bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 289bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato TextPaint textPaint = mTextPaint = new TextPaint(); 290efabe00e4a51bb792366c459d6acc46832e61fdcJoe Onorato textPaint.setTypeface(Typeface.DEFAULT); 291efabe00e4a51bb792366c459d6acc46832e61fdcJoe Onorato textPaint.setTextSize(13*scale); 292bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato textPaint.setColor(0xffffffff); 29343e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato textPaint.setAntiAlias(true); 2949392a75d0493fc9aacbb1e6e63518b0fa66cc3b9Joe Onorato if (TEXT_BURN) { 2959392a75d0493fc9aacbb1e6e63518b0fa66cc3b9Joe Onorato textPaint.setShadowLayer(8, 0, 0, 0xff000000); 2969392a75d0493fc9aacbb1e6e63518b0fa66cc3b9Joe Onorato } 297bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 298bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato float ascent = -textPaint.ascent(); 299bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato float descent = textPaint.descent(); 30043e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato float leading = 0.0f;//(ascent+descent) * 0.1f; 301bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato mLeading = (int)(leading + 0.5f); 302bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato mFirstLineY = (int)(leading + ascent + 0.5f); 303bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato mLineHeight = (int)(leading + ascent + descent + 0.5f); 304bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 305442eda2cc1956003b2366c3060f8c0dbae024710Romain Guy mBitmapWidth = (int)(mBubbleRect.width() + 0.5f); 30643e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f)); 307bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 308fccc8dfc8a442b8d5ea415e1cba7ffde349319d9Joe Onorato mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0); 309fccc8dfc8a442b8d5ea415e1cba7ffde349319d9Joe Onorato 310080d9b614e609826dce2606f9e474af674ead933Joe Onorato if (false) { 311080d9b614e609826dce2606f9e474af674ead933Joe Onorato Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight=" 312080d9b614e609826dce2606f9e474af674ead933Joe Onorato + mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f)) 313080d9b614e609826dce2606f9e474af674ead933Joe Onorato + " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f))); 314080d9b614e609826dce2606f9e474af674ead933Joe Onorato } 315bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 316bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 317bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato /** You own the bitmap after this and you must call recycle on it. */ 318bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato Bitmap createTextBitmap(String text) { 3196ec11bc3a80341206be9506619deb7f9171d38c9Jason Sams Bitmap b = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ALPHA_8); 32088f38d186bcba897ef4222d23515f127c77358aaRomain Guy b.setDensity(mDensity); 321bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato Canvas c = new Canvas(b); 322bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 323bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato StaticLayout layout = new StaticLayout(text, mTextPaint, (int)mTextWidth, 324bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato Alignment.ALIGN_CENTER, 1, 0, true); 325bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato int lineCount = layout.getLineCount(); 326bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato if (lineCount > MAX_LINES) { 327bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato lineCount = MAX_LINES; 328bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 329fd22dac33e535779d1006fcfe22ef2b95152d916Jason Sams //if (!TEXT_BURN && lineCount > 0) { 330fd22dac33e535779d1006fcfe22ef2b95152d916Jason Sams //RectF bubbleRect = mBubbleRect; 331fd22dac33e535779d1006fcfe22ef2b95152d916Jason Sams //bubbleRect.bottom = height(lineCount); 332fd22dac33e535779d1006fcfe22ef2b95152d916Jason Sams //c.drawRoundRect(bubbleRect, mCornerRadius, mCornerRadius, mRectPaint); 333fd22dac33e535779d1006fcfe22ef2b95152d916Jason Sams //} 334bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato for (int i=0; i<lineCount; i++) { 335fccc8dfc8a442b8d5ea415e1cba7ffde349319d9Joe Onorato //int x = (int)((mBubbleRect.width() - layout.getLineMax(i)) / 2.0f); 336fccc8dfc8a442b8d5ea415e1cba7ffde349319d9Joe Onorato //int y = mFirstLineY + (i * mLineHeight); 33788f38d186bcba897ef4222d23515f127c77358aaRomain Guy final String lineText = text.substring(layout.getLineStart(i), layout.getLineEnd(i)); 338fccc8dfc8a442b8d5ea415e1cba7ffde349319d9Joe Onorato int x = (int)(mBubbleRect.left 33988f38d186bcba897ef4222d23515f127c77358aaRomain Guy + ((mBubbleRect.width() - mTextPaint.measureText(lineText)) * 0.5f)); 340bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato int y = mFirstLineY + (i * mLineHeight); 34188f38d186bcba897ef4222d23515f127c77358aaRomain Guy c.drawText(lineText, x, y, mTextPaint); 342bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 343bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 344bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato return b; 345bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 34643e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato 34743e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato private int height(int lineCount) { 34843e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato return (int)((lineCount * mLineHeight) + mLeading + mLeading + 0.0f); 34943e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato } 35043e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato 35143e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato int getBubbleWidth() { 35243e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato return (int)(mBubbleRect.width() + 0.5f); 35343e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato } 35443e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato 35543e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato int getMaxBubbleHeight() { 35643e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato return height(MAX_LINES); 35743e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato } 35843e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato 35943e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato int getBitmapWidth() { 36043e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato return mBitmapWidth; 36143e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato } 36243e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato 36343e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato int getBitmapHeight() { 36443e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato return mBitmapHeight; 36543e7bcf0ad7b487df9244bc5491695b130d331c7Joe Onorato } 366bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 367bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato 368bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato /** Only works for positive numbers. */ 369bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato static int roundToPow2(int n) { 370bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato int orig = n; 371bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato n >>= 1; 372bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato int mask = 0x8000000; 373bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato while (mask != 0 && (n & mask) == 0) { 374bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato mask >>= 1; 375bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 376bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato while (mask != 0) { 377bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato n |= mask; 378bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato mask >>= 1; 379bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 380bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato n += 1; 381bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato if (n != orig) { 382bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato n <<= 1; 383bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 384bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato return n; 385bf15cb44cc8e5ea9a19ab8aaee8e02c96bd6130cJoe Onorato } 38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 387