Skip to content

Commit

Permalink
Bug 783921 - Fix homescreen icon scaling. r=mfinkle
Browse files Browse the repository at this point in the history
Wes Johnston committed Sep 12, 2012

Verified

This commit was signed with the committer’s verified signature.
msoucy Matt Soucy
1 parent 09b9096 commit 3e41736
Showing 2 changed files with 69 additions and 50 deletions.
93 changes: 49 additions & 44 deletions mobile/android/base/GeckoAppShell.java
Original file line number Diff line number Diff line change
@@ -838,9 +838,7 @@ static void createShortcut(String aTitle, String aURI, String aIconData, String
Log.e(LOGTAG, "createShortcut with no unique URI should not be used for aType = webapp!");
}

byte[] raw = Base64.decode(aIconData.substring(22), Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(raw, 0, raw.length);
createShortcut(aTitle, aURI, aURI, bitmap, aType);
createShortcut(aTitle, aURI, aURI, aIconData, aType);
}

// internal, for non-webapps
@@ -957,77 +955,84 @@ public void run() {
});
}

static public int getPreferredIconSize() {
if (android.os.Build.VERSION.SDK_INT >= 11) {
ActivityManager am = (ActivityManager)GeckoApp.mAppContext.getSystemService(Context.ACTIVITY_SERVICE);
return am.getLauncherLargeIconSize();
} else {
switch (getDpi()) {
case DisplayMetrics.DENSITY_MEDIUM:
return 48;
case DisplayMetrics.DENSITY_XHIGH:
return 96;
case DisplayMetrics.DENSITY_HIGH:
default:
return 72;
}
}
}

static private Bitmap getLauncherIcon(Bitmap aSource, String aType) {
final int kOffset = 6;
final int kRadius = 5;
int kIconSize;
int kOverlaySize;
switch (getDpi()) {
case DisplayMetrics.DENSITY_MEDIUM:
kIconSize = 48;
kOverlaySize = 32;
break;
case DisplayMetrics.DENSITY_XHIGH:
kIconSize = 96;
kOverlaySize = 48;
break;
case DisplayMetrics.DENSITY_HIGH:
default:
kIconSize = 72;
kOverlaySize = 32;
}

Bitmap bitmap = Bitmap.createBitmap(kIconSize, kIconSize, Bitmap.Config.ARGB_8888);
int size = getPreferredIconSize();
int insetSize = aSource != null ? size*2/3 : size;

Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);

if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
Rect iconBounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect iconBounds = new Rect(0, 0, size, size);
canvas.drawBitmap(aSource, null, iconBounds, null);
return bitmap;
}

// draw a base color
Paint paint = new Paint();
if (aSource == null) {
// if we aren't drawing a favicon, just use an orange color
float[] hsv = new float[3];
hsv[0] = 32.0f;
hsv[1] = 1.0f;
hsv[2] = 1.0f;
paint.setColor(Color.HSVToColor(hsv));
canvas.drawRoundRect(new RectF(kOffset, kOffset, kIconSize - kOffset, kIconSize - kOffset), kRadius, kRadius, paint);
canvas.drawRoundRect(new RectF(kOffset, kOffset, size - kOffset, size - kOffset), kRadius, kRadius, paint);
} else {
// otherwise use the dominant color from the icon + a layer of transparent white to lighten it somewhat
int color = BitmapUtils.getDominantColor(aSource);
paint.setColor(color);
canvas.drawRoundRect(new RectF(kOffset, kOffset, kIconSize - kOffset, kIconSize - kOffset), kRadius, kRadius, paint);
canvas.drawRoundRect(new RectF(kOffset, kOffset, size - kOffset, size - kOffset), kRadius, kRadius, paint);
paint.setColor(Color.argb(100, 255, 255, 255));
canvas.drawRoundRect(new RectF(kOffset, kOffset, kIconSize - kOffset, kIconSize - kOffset), kRadius, kRadius, paint);
canvas.drawRoundRect(new RectF(kOffset, kOffset, size - kOffset, size - kOffset), kRadius, kRadius, paint);
}

// draw the overlay
Bitmap overlay = BitmapFactory.decodeResource(GeckoApp.mAppContext.getResources(), R.drawable.home_bg);
canvas.drawBitmap(overlay, null, new Rect(0, 0, kIconSize, kIconSize), null);
canvas.drawBitmap(overlay, null, new Rect(0, 0, size, size), null);

// draw the bitmap
// draw the favicon
if (aSource == null)
aSource = BitmapFactory.decodeResource(GeckoApp.mAppContext.getResources(), R.drawable.home_star);

if (aSource.getWidth() < kOverlaySize || aSource.getHeight() < kOverlaySize) {
canvas.drawBitmap(aSource,
null,
new Rect(kIconSize/2 - kOverlaySize/2,
kIconSize/2 - kOverlaySize/2,
kIconSize/2 + kOverlaySize/2,
kIconSize/2 + kOverlaySize/2),
null);
} else {
canvas.drawBitmap(aSource,
null,
new Rect(kIconSize/2 - aSource.getWidth()/2,
kIconSize/2 - aSource.getHeight()/2,
kIconSize/2 + aSource.getWidth()/2,
kIconSize/2 + aSource.getHeight()/2),
null);
}
// by default, we scale the icon to this size
int sWidth = insetSize/2;
int sHeight = sWidth;

if (aSource.getWidth() > insetSize || aSource.getHeight() > insetSize) {
// however, if the icon is larger than our minimum, we allow it to be drawn slightly larger
// (but not necessarily at its full resolution)
sWidth = Math.min(size/3, aSource.getWidth()/2);
sHeight = Math.min(size/3, aSource.getHeight()/2);
}

int halfSize = size/2;
canvas.drawBitmap(aSource,
null,
new Rect(halfSize - sWidth,
halfSize - sHeight,
halfSize + sWidth,
halfSize + sHeight),
null);

return bitmap;
}
26 changes: 20 additions & 6 deletions mobile/android/chrome/content/browser.js
Original file line number Diff line number Diff line change
@@ -6358,18 +6358,32 @@ var WebappsUI = {
});
},

get iconSize() {
let iconSize = 64;
try {
Cu.import("resource://gre/modules/JNI.jsm");
let jni = new JNI();
let cls = jni.findClass("org.mozilla.gecko.GeckoAppShell");
let method = jni.getStaticMethodID(cls, "getPreferredIconSize", "()I");
iconSize = jni.callStaticIntMethod(cls, method, null);
jni.close();
} catch(ex) {
console.log(ex);
}

delete this.iconSize;
return this.iconSize = iconSize;
},

makeBase64Icon: function loadAndMakeBase64Icon(aIconURL, aCallbackFunction) {
// The images are 64px, but Android will resize as needed.
// Bigger is better than too small.
const kIconSize = 64;
let size = this.iconSize;

let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");

canvas.width = canvas.height = kIconSize;
canvas.width = canvas.height = size;
let ctx = canvas.getContext("2d");
let favicon = new Image();
favicon.onload = function() {
ctx.drawImage(favicon, 0, 0, kIconSize, kIconSize);
ctx.drawImage(favicon, 0, 0, size, size);
let base64icon = canvas.toDataURL("image/png", "");
canvas = null;
aCallbackFunction.call(null, base64icon);

0 comments on commit 3e41736

Please sign in to comment.