Bug 1406338 - Part 1: Support applying specific text size while creating a favicon. r?nechen
MozReview-Commit-ID: Dcx1RgcRdka
--- a/mobile/android/base/java/org/mozilla/gecko/icons/IconRequest.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/IconRequest.java
@@ -26,30 +26,34 @@ public class IconRequest {
/* package-private */ TreeSet<IconDescriptor> icons;
/* package-private */ boolean skipNetwork;
/* package-private */ boolean backgroundThread;
/* package-private */ boolean skipDisk;
/* package-private */ boolean skipMemory;
/* package-private */ int targetSize;
/* package-private */ int minimumSizePxAfterScaling;
/* package-private */ boolean prepareOnly;
+ /* package-private */ float textSize;
private IconCallback callback;
/* package-private */ IconRequest(Context context) {
this.context = context.getApplicationContext();
this.icons = new TreeSet<>(new IconDescriptorComparator());
// Setting some sensible defaults.
this.privileged = false;
this.skipMemory = false;
this.skipDisk = false;
this.skipNetwork = false;
this.targetSize = context.getResources().getDimensionPixelSize(R.dimen.favicon_bg);
this.minimumSizePxAfterScaling = 0;
this.prepareOnly = false;
+
+ // textSize is only used in IconGenerator.java for creating a icon with specific text size.
+ this.textSize = 0;
}
/**
* Execute this request and try to load an icon. Once an icon has been loaded successfully the
* callback will be executed.
*
* The returned Future can be used to cancel the job.
*/
@@ -141,16 +145,24 @@ public class IconRequest {
/**
* Get an iterator to iterate over all icon descriptors associated with this request.
*/
public Iterator<IconDescriptor> getIconIterator() {
return icons.iterator();
}
/**
+ * Get the required text size of the icon created by
+ * {@link org.mozilla.gecko.icons.loader.IconGenerator}.
+ */
+ public float getTextSize() {
+ return textSize;
+ }
+
+ /**
* Create a builder to modify this request.
*
* Calling methods on the builder will modify this object and not create a copy.
*/
public IconRequestBuilder modify() {
return new IconRequestBuilder(this);
}
--- a/mobile/android/base/java/org/mozilla/gecko/icons/IconRequestBuilder.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/IconRequestBuilder.java
@@ -102,16 +102,24 @@ public class IconRequestBuilder {
* preferred Android launcher icon size.
*/
public IconRequestBuilder forLauncherIcon() {
internal.targetSize = GeckoAppShell.getPreferredIconSize();
return this;
}
/**
+ * The icon will be scaled to the given size.
+ */
+ public IconRequestBuilder targetSize(final int targetSize) {
+ internal.targetSize = targetSize;
+ return this;
+ }
+
+ /**
* The icon will be used in Activity Stream: a minimum size for the icon will be set.
*/
public IconRequestBuilder forActivityStream() {
// This value was set anecdotally: 16px icons scaled up both look blurry and
// don't fill the space well. 32px icons look good enough.
internal.minimumSizePxAfterScaling = 32 * ResizingProcessor.MAX_SCALE_FACTOR;
return this;
}
@@ -132,16 +140,25 @@ public class IconRequestBuilder {
* perform a lookup of the URL but doesn't want to load the icon yet.
*/
public IconRequestBuilder prepareOnly() {
internal.prepareOnly = true;
return this;
}
/**
+ * The text size will be resized to the given size, and this field is only used by
+ * {@link org.mozilla.gecko.icons.loader.IconGenerator} for creating a new icon.
+ */
+ public IconRequestBuilder textSize(final float textSize) {
+ internal.textSize = textSize;
+ return this;
+ }
+
+ /**
* Return the request built with this builder.
*/
@CheckResult
public IconRequest build() {
if (TextUtils.isEmpty(internal.pageUrl)) {
throw new IllegalStateException("Page URL is required");
}
@@ -151,16 +168,17 @@ public class IconRequestBuilder {
request.icons = new TreeSet<>(internal.icons);
request.skipNetwork = internal.skipNetwork;
request.backgroundThread = internal.backgroundThread;
request.skipDisk = internal.skipDisk;
request.skipMemory = internal.skipMemory;
request.targetSize = internal.targetSize;
request.minimumSizePxAfterScaling = internal.minimumSizePxAfterScaling;
request.prepareOnly = internal.prepareOnly;
+ request.textSize = internal.textSize;
return request;
}
/**
* This is a no-op method.
*
* All builder methods are annotated with @CheckResult to denote that the
* methods return the builder object and that it is typically an error to not call another method
--- a/mobile/android/base/java/org/mozilla/gecko/icons/loader/IconGenerator.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/loader/IconGenerator.java
@@ -44,44 +44,55 @@ public class IconGenerator implements Ic
@Override
public IconResponse load(IconRequest request) {
if (request.getIconCount() > 1) {
// There are still other icons to try. We will only generate an icon if there's only one
// icon left and all previous loaders have failed (assuming this is the last one).
return null;
}
- return generate(request.getContext(), request.getPageUrl());
+ return generate(request.getContext(), request.getPageUrl(), request.getTargetSize(), request.getTextSize());
+ }
+
+ public static IconResponse generate(Context context, String pageURL) {
+ return generate(context, pageURL, 0, 0);
}
/**
* Generate default favicon for the given page URL.
*/
- public static IconResponse generate(Context context, String pageURL) {
+ public static IconResponse generate(final Context context, final String pageURL,
+ int widthAndHeight, float textSize) {
final Resources resources = context.getResources();
- final int widthAndHeight = resources.getDimensionPixelSize(R.dimen.favicon_bg);
+ if (widthAndHeight == 0) {
+ widthAndHeight = resources.getDimensionPixelSize(R.dimen.favicon_bg);
+ }
final int roundedCorners = resources.getDimensionPixelOffset(R.dimen.favicon_corner_radius);
final Bitmap favicon = Bitmap.createBitmap(widthAndHeight, widthAndHeight, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(favicon);
final int color = pickColor(pageURL);
final Paint paint = new Paint();
paint.setColor(color);
canvas.drawRoundRect(new RectF(0, 0, widthAndHeight, widthAndHeight), roundedCorners, roundedCorners, paint);
paint.setColor(Color.WHITE);
final String character = getRepresentativeCharacter(pageURL);
- // The text size is calculated dynamically based on the target icon size (1/8th). For an icon
- // size of 112dp we'd use a text size of 14dp (112 / 8).
- final float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, widthAndHeight / 8, context.getResources().getDisplayMetrics());
+ if (textSize == 0) {
+ // The text size is calculated dynamically based on the target icon size (1/8th). For an icon
+ // size of 112dp we'd use a text size of 14dp (112 / 8).
+ textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ widthAndHeight / 8,
+ resources.getDisplayMetrics());
+ }
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(textSize);
paint.setAntiAlias(true);
canvas.drawText(character,
canvas.getWidth() / 2,
(int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)),