Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| index 3df4198f801d93f73568c09760bfeb5318d5dc37..d05a0329201b7d59eb967e7a05f0ebd32c2ce832 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| @@ -26,8 +26,6 @@ import android.os.Handler; |
| import android.os.Looper; |
| import android.text.TextUtils; |
| import android.util.Base64; |
| -import android.util.DisplayMetrics; |
| -import android.util.TypedValue; |
| import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.base.ApplicationStatus; |
| @@ -77,11 +75,13 @@ public class ShortcutHelper { |
| // There is no public string defining this intent so if Home changes the value, we |
| // have to update this string. |
| private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; |
| - private static final int INSET_DIMENSION_FOR_TOUCHICON = 1; |
| - private static final int TOUCHICON_BORDER_RADII_DP = 4; |
| - private static final int GENERATED_ICON_SIZE_DP = 40; |
| - private static final int GENERATED_ICON_ROUNDED_CORNERS_DP = 2; |
| - private static final int GENERATED_ICON_FONT_SIZE_DP = 16; |
| + |
| + // These sizes are from the Material spec for icons: |
| + // https://www.google.com/design/spec/style/icons.html#icons-product-icons |
| + private static final float ICON_PADDING_RATIO = 2.0f / 44.0f; |
| + private static final float ICON_CORNER_RADIUS_RATIO = 1.0f / 16.0f; |
| + private static final float GENERATED_ICON_PADDING_RATIO = 1.0f / 12.0f; |
| + private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f; |
| /** Broadcasts Intents out Android for adding the shortcut. */ |
| public static class Delegate { |
| @@ -237,66 +237,112 @@ public class ShortcutHelper { |
| /** |
| * Returns whether the given icon matches the size requirements to be used on the homescreen. |
| * @param context Context used to create the intent. |
| - * @param icon Image representing the shortcut. |
| + * @param width Icon width, in pixels. |
| + * @param height Icon height, in pixels. |
| * @return whether the given icon matches the size requirements to be used on the homescreen. |
| */ |
| @CalledByNative |
| - public static boolean isIconLargeEnoughForLauncher(Context context, Bitmap icon) { |
| + public static boolean isIconLargeEnoughForLauncher(Context context, int width, int height) { |
| ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); |
| final int minimalSize = am.getLauncherLargeIconSize() / 2; |
| - return icon.getWidth() >= minimalSize && icon.getHeight() >= minimalSize; |
| + return width >= minimalSize && height >= minimalSize; |
| } |
| /** |
| - * Returns the given icon after applying same changes to match the launcher design |
| - * requirements. |
| + * Adapts a website's icon (e.g. favicon or touch icon) to the Material design style guidelines |
| + * for home screen icons. This involves adding some padding and rounding the corners. |
| + * |
| * @param context Context used to create the intent. |
| - * @param icon Image representing the shortcut. |
| + * @param webIcon The website's favicon or touch icon. |
| * @return Bitmap Either the touch-icon or the newly created favicon. |
| */ |
| @CalledByNative |
| - public static Bitmap modifyIconForLauncher(Context context, Bitmap icon) { |
| - assert isIconLargeEnoughForLauncher(context, icon); |
| + public static Bitmap generateHomescreenIconFromWebIcon(Context context, Bitmap webIcon) { |
|
gone
2015/10/29 20:51:25
nit: generateHomeScreenIcon because Android laughe
newt (away)
2015/10/29 21:30:25
Replaced most instances of "homescreen" with "home
|
| + // getLauncherLargeIconSize() is just a guess at the launcher icon size, and is often |
| + // wrong -- the launcher can shows icons at any size it pleases. Instead of resizing the |
|
gone
2015/10/29 20:51:25
nit: can show
newt (away)
2015/10/29 21:30:24
Done.
|
| + // icon to the supposed launcher size and then having the launcher resize the icon again, |
| + // just leave the icon at its original size and let the launcher do a single rescaling. |
| + // Unless the icon is much too big; then scale it down here too. |
| + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); |
| + int maxInnerSize = Math.round(am.getLauncherLargeIconSize() * 1.25f); |
|
gone
2015/10/29 20:51:25
nit: make a constant
newt (away)
2015/10/29 21:30:24
Done.
|
| + int innerSize = Math.min(maxInnerSize, Math.max(webIcon.getWidth(), webIcon.getHeight())); |
| + int padding = Math.round(ICON_PADDING_RATIO * innerSize); |
| + int outerSize = innerSize + 2 * padding; |
| Bitmap bitmap = null; |
| - ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); |
| - final int iconSize = am.getLauncherLargeIconSize(); |
| try { |
| - bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); |
| - Canvas canvas = new Canvas(bitmap); |
| - drawTouchIconToCanvas(context, icon, canvas); |
| - canvas.setBitmap(null); |
| + bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARGB_8888); |
| } catch (OutOfMemoryError e) { |
| - Log.w(TAG, "OutOfMemoryError while trying to draw bitmap on canvas."); |
| + Log.w(TAG, "OutOfMemoryError while creating bitmap for home screen icon."); |
| + return webIcon; |
| } |
| + |
| + // Draw the web icon with padding around it. |
| + Canvas canvas = new Canvas(bitmap); |
| + Rect innerBounds = new Rect(padding, padding, outerSize - padding, outerSize - padding); |
| + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| + paint.setFilterBitmap(true); |
| + canvas.drawBitmap(webIcon, null, innerBounds, paint); |
| + |
| + // Round the corners. |
| + int cornerRadius = Math.round(ICON_CORNER_RADIUS_RATIO * outerSize); |
| + Path path = new Path(); |
| + path.setFillType(Path.FillType.INVERSE_WINDING); |
| + RectF innerBoundsF = new RectF(innerBounds); |
| + path.addRoundRect(innerBoundsF, cornerRadius, cornerRadius, Path.Direction.CW); |
| + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); |
| + canvas.drawPath(path, paint); |
| + |
| return bitmap; |
| } |
| /** |
| - * Generates an icon to be used on the launcher. |
| + * Generates a generic icon to be used in the launcher. This is just a rounded rectangle with |
| + * a letter in the middle taken from the website's domain name. |
| + * |
| * @param context Context used to create the intent. |
| * @param url URL of the shortcut. |
| - * @param rValue Red component of the dominant icon color. |
| - * @param gValue Green component of the dominant icon color. |
| - * @param bValue Blue component of the dominant icon color. |
| + * @param red Red component of the dominant icon color. |
| + * @param green Green component of the dominant icon color. |
| + * @param blue Blue component of the dominant icon color. |
| * @return Bitmap Either the touch-icon or the newly created favicon. |
| */ |
| @CalledByNative |
| - public static Bitmap generateLauncherIcon(Context context, String url, int rValue, |
| - int gValue, int bValue) { |
| - Bitmap bitmap = null; |
| + public static Bitmap generateHomescreenIcon(Context context, String url, int red, int green, |
| + int blue) { |
| ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); |
| - final int iconSize = am.getLauncherLargeIconSize(); |
| + final int outerSize = am.getLauncherLargeIconSize(); |
| final int iconDensity = am.getLauncherLargeIconDensity(); |
| + |
| + Bitmap bitmap = null; |
| try { |
| - bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); |
| - Canvas canvas = new Canvas(bitmap); |
| - drawWidgetBackgroundToCanvas(context, canvas, iconDensity, url, |
| - Color.rgb(rValue, gValue, bValue)); |
| - canvas.setBitmap(null); |
| + bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARGB_8888); |
| } catch (OutOfMemoryError e) { |
| Log.w(TAG, "OutOfMemoryError while trying to draw bitmap on canvas."); |
| + return null; |
| } |
| + |
| + Canvas canvas = new Canvas(bitmap); |
| + |
| + // Draw the drop shadow. |
| + int padding = (int) (GENERATED_ICON_PADDING_RATIO * outerSize); |
| + Rect outerBounds = new Rect(0, 0, outerSize, outerSize); |
| + Bitmap bookmarkWidgetBg = |
| + getBitmapFromResourceId(context, R.mipmap.bookmark_widget_bg, iconDensity); |
| + Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); |
| + canvas.drawBitmap(bookmarkWidgetBg, null, outerBounds, paint); |
| + |
| + // Draw the rounded rectangle and letter. |
| + int innerSize = outerSize - 2 * padding; |
| + int cornerRadius = Math.round(ICON_CORNER_RADIUS_RATIO * outerSize); |
| + int fontSize = Math.round(GENERATED_ICON_FONT_SIZE_RATIO * outerSize); |
| + int color = Color.rgb(red, green, blue); |
| + RoundedIconGenerator generator = new RoundedIconGenerator( |
| + innerSize, innerSize, cornerRadius, color, fontSize); |
| + Bitmap icon = generator.generateIconForUrl(url); |
| + if (icon == null) return null; // Bookmark URL does not have a domain. |
| + canvas.drawBitmap(icon, padding, padding, null); |
| + |
| return bitmap; |
| } |
| @@ -411,58 +457,4 @@ public class ShortcutHelper { |
| assert false : "The drawable was not a bitmap drawable as expected"; |
| return null; |
| } |
| - |
| - /** |
| - * Use touch-icon or higher-resolution favicon and round the corners. |
| - * @param context Context used to get resources. |
| - * @param touchIcon Touch icon bitmap. |
| - * @param canvas Canvas that holds the touch icon. |
| - */ |
| - private static void drawTouchIconToCanvas(Context context, Bitmap touchIcon, Canvas canvas) { |
| - Rect iconBounds = new Rect(0, 0, canvas.getWidth(), canvas.getHeight()); |
| - Rect src = new Rect(0, 0, touchIcon.getWidth(), touchIcon.getHeight()); |
| - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| - paint.setFilterBitmap(true); |
| - canvas.drawBitmap(touchIcon, src, iconBounds, paint); |
| - // Convert dp to px. |
| - int borderRadii = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, |
| - TOUCHICON_BORDER_RADII_DP, context.getResources().getDisplayMetrics()); |
| - Path path = new Path(); |
| - path.setFillType(Path.FillType.INVERSE_WINDING); |
| - RectF rect = new RectF(iconBounds); |
| - rect.inset(INSET_DIMENSION_FOR_TOUCHICON, INSET_DIMENSION_FOR_TOUCHICON); |
| - path.addRoundRect(rect, borderRadii, borderRadii, Path.Direction.CW); |
| - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); |
| - canvas.drawPath(path, paint); |
| - } |
| - |
| - /** |
| - * Draw document icon to canvas. |
| - * @param context Context used to get bitmap resources. |
| - * @param canvas Canvas that holds the document icon. |
| - * @param iconDensity Density information to get bitmap resources. |
| - * @param url URL of the shortcut. |
| - * @param color Color for the document icon's folding and the bottom strip. |
| - */ |
| - private static void drawWidgetBackgroundToCanvas( |
| - Context context, Canvas canvas, int iconDensity, String url, int color) { |
| - Rect iconBounds = new Rect(0, 0, canvas.getWidth(), canvas.getHeight()); |
| - Bitmap bookmarkWidgetBg = |
| - getBitmapFromResourceId(context, R.mipmap.bookmark_widget_bg, iconDensity); |
| - |
| - Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); |
| - canvas.drawBitmap(bookmarkWidgetBg, null, iconBounds, paint); |
| - |
| - float density = (float) iconDensity / DisplayMetrics.DENSITY_MEDIUM; |
| - int iconSize = (int) (GENERATED_ICON_SIZE_DP * density); |
| - int iconRoundedEdge = (int) (GENERATED_ICON_ROUNDED_CORNERS_DP * density); |
| - int iconFontSize = (int) (GENERATED_ICON_FONT_SIZE_DP * density); |
| - |
| - RoundedIconGenerator generator = new RoundedIconGenerator( |
| - iconSize, iconSize, iconRoundedEdge, color, iconFontSize); |
| - Bitmap icon = generator.generateIconForUrl(url); |
| - if (icon == null) return; // Bookmark URL does not have a domain. |
| - canvas.drawBitmap(icon, iconBounds.exactCenterX() - icon.getWidth() / 2.0f, |
| - iconBounds.exactCenterY() - icon.getHeight() / 2.0f, null); |
| - } |
| } |