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..3b40421073e9000005f930192303160ef7ee7e03 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,14 @@ 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 MAX_INNER_SIZE_RATIO = 1.25f; |
+ 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 { |
@@ -113,10 +114,10 @@ public class ShortcutHelper { |
} |
/** |
- * Called when we have to fire an Intent to add a shortcut to the homescreen. |
+ * Called when we have to fire an Intent to add a shortcut to the home screen. |
* If the webpage indicated that it was capable of functioning as a webapp, it is added as a |
* shortcut to a webapp Activity rather than as a general bookmark. User is sent to the |
- * homescreen as soon as the shortcut is created. |
+ * home screen as soon as the shortcut is created. |
*/ |
@SuppressWarnings("unused") |
@CalledByNative |
@@ -146,7 +147,7 @@ public class ShortcutHelper { |
shortcutIntent = createShortcutIntent(url); |
} |
- // Always attach a source (one of add to homescreen menu item, app banner, or unknown) to |
+ // Always attach a source (one of add to home screen menu item, app banner, or unknown) to |
// the intent. This allows us to distinguish where a shortcut was added from in metrics. |
shortcutIntent.putExtra(EXTRA_SOURCE, source); |
shortcutIntent.setPackage(context.getPackageName()); |
@@ -211,7 +212,7 @@ public class ShortcutHelper { |
} |
/** |
- * Shortcut intent for icon on homescreen. |
+ * Shortcut intent for icon on home screen. |
* @param url Url of the shortcut. |
* @return Intent for onclick action of the shortcut. |
*/ |
@@ -222,9 +223,9 @@ public class ShortcutHelper { |
} |
/** |
- * Utility method to check if a shortcut can be added to the homescreen. |
+ * Utility method to check if a shortcut can be added to the home screen. |
* @param context Context used to get the package manager. |
- * @return if a shortcut can be added to the homescreen under the current profile. |
+ * @return if a shortcut can be added to the home screen under the current profile. |
*/ |
public static boolean isAddToHomeIntentSupported(Context context) { |
PackageManager pm = context.getPackageManager(); |
@@ -235,68 +236,114 @@ public class ShortcutHelper { |
} |
/** |
- * Returns whether the given icon matches the size requirements to be used on the homescreen. |
+ * Returns whether the given icon matches the size requirements to be used on the home screen. |
* @param context Context used to create the intent. |
- * @param icon Image representing the shortcut. |
- * @return whether the given icon matches the size requirements to be used on the homescreen. |
+ * @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 home screen. |
*/ |
@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 createHomeScreenIconFromWebIcon(Context context, Bitmap webIcon) { |
+ // getLauncherLargeIconSize() is just a guess at the launcher icon size, and is often |
+ // wrong -- the launcher can show icons at any size it pleases. Instead of resizing the |
+ // 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() * MAX_INNER_SIZE_RATIO); |
+ 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; |
} |
@@ -384,7 +431,7 @@ public class ShortcutHelper { |
* icon and the ideal and minimum sizes of the splash screen image in that order. |
*/ |
@CalledByNative |
- private static int[] getHomescreenIconAndSplashImageSizes(Context context) { |
+ private static int[] getHomeScreenIconAndSplashImageSizes(Context context) { |
// This ordering must be kept up to date with the C++ ShortcutHelper. |
return new int[] { |
getIdealHomescreenIconSizeInDp(context), |
@@ -411,58 +458,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); |
- } |
} |