Merge "Optimizing some icon generation code in bubble" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac622814ba
@@ -19,14 +19,14 @@ package com.android.wm.shell.bubbles;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Color;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import com.android.launcher3.icons.BaseIconFactory;
|
import com.android.launcher3.icons.BaseIconFactory;
|
||||||
import com.android.launcher3.icons.BitmapInfo;
|
import com.android.launcher3.icons.BitmapInfo;
|
||||||
import com.android.launcher3.icons.ShadowGenerator;
|
|
||||||
import com.android.wm.shell.R;
|
import com.android.wm.shell.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,78 +44,77 @@ public class BubbleBadgeIconFactory extends BaseIconFactory {
|
|||||||
* will include the workprofile indicator on the badge if appropriate.
|
* will include the workprofile indicator on the badge if appropriate.
|
||||||
*/
|
*/
|
||||||
BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
|
BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
|
||||||
ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize);
|
|
||||||
Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize);
|
|
||||||
|
|
||||||
if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
|
if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
|
||||||
userBadgedBitmap = Bitmap.createScaledBitmap(
|
AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon;
|
||||||
getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */
|
userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground());
|
||||||
userBadgedAppIcon.getIntrinsicWidth()),
|
|
||||||
mIconBitmapSize, mIconBitmapSize, /* filter */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isImportantConversation) {
|
if (isImportantConversation) {
|
||||||
final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
|
userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon);
|
||||||
com.android.internal.R.dimen.importance_ring_stroke_width);
|
}
|
||||||
final int importantConversationColor = mContext.getResources().getColor(
|
Bitmap userBadgedBitmap = createIconBitmap(
|
||||||
R.color.important_conversation, null);
|
userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW);
|
||||||
Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
|
|
||||||
userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
|
|
||||||
Canvas c = new Canvas(badgeAndRing);
|
|
||||||
|
|
||||||
Paint ringPaint = new Paint();
|
|
||||||
ringPaint.setStyle(Paint.Style.FILL);
|
|
||||||
ringPaint.setColor(importantConversationColor);
|
|
||||||
ringPaint.setAntiAlias(true);
|
|
||||||
c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint);
|
|
||||||
|
|
||||||
final int bitmapTop = (int) ringStrokeWidth;
|
|
||||||
final int bitmapLeft = (int) ringStrokeWidth;
|
|
||||||
final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth;
|
|
||||||
final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth;
|
|
||||||
|
|
||||||
Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth,
|
|
||||||
bitmapHeight, /* filter */ true);
|
|
||||||
c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null);
|
|
||||||
|
|
||||||
shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
|
|
||||||
return createIconBitmap(badgeAndRing);
|
|
||||||
} else {
|
|
||||||
Canvas c = new Canvas();
|
|
||||||
c.setBitmap(userBadgedBitmap);
|
|
||||||
shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
|
|
||||||
return createIconBitmap(userBadgedBitmap);
|
return createIconBitmap(userBadgedBitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CircularRingDrawable extends CircularAdaptiveIcon {
|
||||||
|
|
||||||
|
final int mImportantConversationColor;
|
||||||
|
final Rect mTempBounds = new Rect();
|
||||||
|
|
||||||
|
final Drawable mDr;
|
||||||
|
|
||||||
|
CircularRingDrawable(Drawable dr) {
|
||||||
|
super(null, null);
|
||||||
|
mDr = dr;
|
||||||
|
mImportantConversationColor = mContext.getResources().getColor(
|
||||||
|
R.color.important_conversation, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) {
|
@Override
|
||||||
Drawable foreground = icon.getForeground();
|
public void draw(Canvas canvas) {
|
||||||
Drawable background = icon.getBackground();
|
int save = canvas.save();
|
||||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
canvas.clipPath(getIconMask());
|
||||||
Canvas canvas = new Canvas();
|
canvas.drawColor(mImportantConversationColor);
|
||||||
canvas.setBitmap(bitmap);
|
int ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
|
||||||
|
com.android.internal.R.dimen.importance_ring_stroke_width);
|
||||||
// Clip canvas to circle.
|
mTempBounds.set(getBounds());
|
||||||
Path circlePath = new Path();
|
mTempBounds.inset(ringStrokeWidth, ringStrokeWidth);
|
||||||
circlePath.addCircle(/* x */ size / 2f,
|
mDr.setBounds(mTempBounds);
|
||||||
/* y */ size / 2f,
|
mDr.draw(canvas);
|
||||||
/* radius */ size / 2f,
|
canvas.restoreToCount(save);
|
||||||
Path.Direction.CW);
|
}
|
||||||
canvas.clipPath(circlePath);
|
}
|
||||||
|
|
||||||
// Draw background.
|
private static class CircularAdaptiveIcon extends AdaptiveIconDrawable {
|
||||||
background.setBounds(0, 0, size, size);
|
|
||||||
background.draw(canvas);
|
final Path mPath = new Path();
|
||||||
|
|
||||||
// Draw foreground. The foreground and background drawables are derived from adaptive icons
|
CircularAdaptiveIcon(Drawable bg, Drawable fg) {
|
||||||
// Some icon shapes fill more space than others, so adaptive icons are normalized to about
|
super(bg, fg);
|
||||||
// the same size. This size is smaller than the original bounds, so we estimate
|
}
|
||||||
// the difference in this offset.
|
|
||||||
int offset = size / 5;
|
@Override
|
||||||
foreground.setBounds(-offset, -offset, size + offset, size + offset);
|
public Path getIconMask() {
|
||||||
foreground.draw(canvas);
|
mPath.reset();
|
||||||
|
Rect bounds = getBounds();
|
||||||
canvas.setBitmap(null);
|
mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW);
|
||||||
return bitmap;
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
int save = canvas.save();
|
||||||
|
canvas.clipPath(getIconMask());
|
||||||
|
|
||||||
|
canvas.drawColor(Color.BLACK);
|
||||||
|
Drawable d;
|
||||||
|
if ((d = getBackground()) != null) {
|
||||||
|
d.draw(canvas);
|
||||||
|
}
|
||||||
|
if ((d = getForeground()) != null) {
|
||||||
|
d.draw(canvas);
|
||||||
|
}
|
||||||
|
canvas.restoreToCount(save);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.LauncherApps;
|
import android.content.pm.LauncherApps;
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
|
|
||||||
@@ -65,4 +66,19 @@ public class BubbleIconFactory extends BaseIconFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the bitmap for the provided drawable and returns the scale used for
|
||||||
|
* drawing the actual drawable.
|
||||||
|
*/
|
||||||
|
public Bitmap createIconBitmap(@NonNull Drawable icon, float[] outScale) {
|
||||||
|
if (outScale == null) {
|
||||||
|
outScale = new float[1];
|
||||||
|
}
|
||||||
|
icon = normalizeAndWrapToAdaptiveIcon(icon,
|
||||||
|
true /* shrinkNonAdaptiveIcons */,
|
||||||
|
null /* outscale */,
|
||||||
|
outScale);
|
||||||
|
return createIconBitmap(icon, outScale[0], BITMAP_GENERATION_MODE_WITH_SHADOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,15 +195,18 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
b.isImportantConversation());
|
b.isImportantConversation());
|
||||||
info.badgeBitmap = badgeBitmapInfo.icon;
|
info.badgeBitmap = badgeBitmapInfo.icon;
|
||||||
// Raw badge bitmap never includes the important conversation ring
|
// Raw badge bitmap never includes the important conversation ring
|
||||||
info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon;
|
info.mRawBadgeBitmap = b.isImportantConversation()
|
||||||
info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon;
|
? badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon
|
||||||
|
: badgeBitmapInfo.icon;
|
||||||
|
|
||||||
|
float[] bubbleBitmapScale = new float[1];
|
||||||
|
info.bubbleBitmap = iconFactory.createIconBitmap(bubbleDrawable, bubbleBitmapScale);
|
||||||
|
|
||||||
// Dot color & placement
|
// Dot color & placement
|
||||||
Path iconPath = PathParser.createPathFromPathData(
|
Path iconPath = PathParser.createPathFromPathData(
|
||||||
c.getResources().getString(com.android.internal.R.string.config_icon_mask));
|
c.getResources().getString(com.android.internal.R.string.config_icon_mask));
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
float scale = iconFactory.getNormalizer().getScale(bubbleDrawable,
|
float scale = bubbleBitmapScale[0];
|
||||||
null /* outBounds */, null /* path */, null /* outMaskShape */);
|
|
||||||
float radius = DEFAULT_PATH_SIZE / 2f;
|
float radius = DEFAULT_PATH_SIZE / 2f;
|
||||||
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
||||||
radius /* pivot y */);
|
radius /* pivot y */);
|
||||||
|
|||||||
Reference in New Issue
Block a user