Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java +67 −68 Original line number Diff line number Diff line Loading @@ -19,14 +19,14 @@ package com.android.wm.shell.bubbles; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Color; import android.graphics.Path; import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.Drawable; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.ShadowGenerator; import com.android.wm.shell.R; /** Loading @@ -44,78 +44,77 @@ public class BubbleBadgeIconFactory extends BaseIconFactory { * will include the workprofile indicator on the badge if appropriate. */ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) { ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize); Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize); if (userBadgedAppIcon instanceof AdaptiveIconDrawable) { userBadgedBitmap = Bitmap.createScaledBitmap( getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */ userBadgedAppIcon.getIntrinsicWidth()), mIconBitmapSize, mIconBitmapSize, /* filter */ true); AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon; userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground()); } if (isImportantConversation) { final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width); final int importantConversationColor = mContext.getResources().getColor( R.color.important_conversation, null); 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); userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon); } Bitmap userBadgedBitmap = createIconBitmap( userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW); 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); } @Override public void draw(Canvas canvas) { int save = canvas.save(); canvas.clipPath(getIconMask()); canvas.drawColor(mImportantConversationColor); int ringStrokeWidth = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width); mTempBounds.set(getBounds()); mTempBounds.inset(ringStrokeWidth, ringStrokeWidth); mDr.setBounds(mTempBounds); mDr.draw(canvas); canvas.restoreToCount(save); } } private static class CircularAdaptiveIcon extends AdaptiveIconDrawable { final Path mPath = new Path(); CircularAdaptiveIcon(Drawable bg, Drawable fg) { super(bg, fg); } @Override public Path getIconMask() { mPath.reset(); Rect bounds = getBounds(); mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW); return mPath; } private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) { Drawable foreground = icon.getForeground(); Drawable background = icon.getBackground(); Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(); canvas.setBitmap(bitmap); // Clip canvas to circle. Path circlePath = new Path(); circlePath.addCircle(/* x */ size / 2f, /* y */ size / 2f, /* radius */ size / 2f, Path.Direction.CW); canvas.clipPath(circlePath); // Draw background. background.setBounds(0, 0, size, size); background.draw(canvas); // Draw foreground. The foreground and background drawables are derived from adaptive icons // Some icon shapes fill more space than others, so adaptive icons are normalized to about // the same size. This size is smaller than the original bounds, so we estimate // the difference in this offset. int offset = size / 5; foreground.setBounds(-offset, -offset, size + offset, size + offset); foreground.draw(canvas); canvas.setBitmap(null); return bitmap; @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); } } } libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; Loading Loading @@ -65,4 +66,19 @@ public class BubbleIconFactory extends BaseIconFactory { 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); } } libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +7 −4 Original line number Diff line number Diff line Loading @@ -195,15 +195,18 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask b.isImportantConversation()); info.badgeBitmap = badgeBitmapInfo.icon; // Raw badge bitmap never includes the important conversation ring info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon; info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon; info.mRawBadgeBitmap = b.isImportantConversation() ? badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon : badgeBitmapInfo.icon; float[] bubbleBitmapScale = new float[1]; info.bubbleBitmap = iconFactory.createIconBitmap(bubbleDrawable, bubbleBitmapScale); // Dot color & placement Path iconPath = PathParser.createPathFromPathData( c.getResources().getString(com.android.internal.R.string.config_icon_mask)); Matrix matrix = new Matrix(); float scale = iconFactory.getNormalizer().getScale(bubbleDrawable, null /* outBounds */, null /* path */, null /* outMaskShape */); float scale = bubbleBitmapScale[0]; float radius = DEFAULT_PATH_SIZE / 2f; matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */, radius /* pivot y */); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java +67 −68 Original line number Diff line number Diff line Loading @@ -19,14 +19,14 @@ package com.android.wm.shell.bubbles; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Color; import android.graphics.Path; import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.Drawable; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.ShadowGenerator; import com.android.wm.shell.R; /** Loading @@ -44,78 +44,77 @@ public class BubbleBadgeIconFactory extends BaseIconFactory { * will include the workprofile indicator on the badge if appropriate. */ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) { ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize); Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize); if (userBadgedAppIcon instanceof AdaptiveIconDrawable) { userBadgedBitmap = Bitmap.createScaledBitmap( getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */ userBadgedAppIcon.getIntrinsicWidth()), mIconBitmapSize, mIconBitmapSize, /* filter */ true); AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon; userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground()); } if (isImportantConversation) { final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width); final int importantConversationColor = mContext.getResources().getColor( R.color.important_conversation, null); 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); userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon); } Bitmap userBadgedBitmap = createIconBitmap( userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW); 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); } @Override public void draw(Canvas canvas) { int save = canvas.save(); canvas.clipPath(getIconMask()); canvas.drawColor(mImportantConversationColor); int ringStrokeWidth = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width); mTempBounds.set(getBounds()); mTempBounds.inset(ringStrokeWidth, ringStrokeWidth); mDr.setBounds(mTempBounds); mDr.draw(canvas); canvas.restoreToCount(save); } } private static class CircularAdaptiveIcon extends AdaptiveIconDrawable { final Path mPath = new Path(); CircularAdaptiveIcon(Drawable bg, Drawable fg) { super(bg, fg); } @Override public Path getIconMask() { mPath.reset(); Rect bounds = getBounds(); mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW); return mPath; } private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) { Drawable foreground = icon.getForeground(); Drawable background = icon.getBackground(); Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(); canvas.setBitmap(bitmap); // Clip canvas to circle. Path circlePath = new Path(); circlePath.addCircle(/* x */ size / 2f, /* y */ size / 2f, /* radius */ size / 2f, Path.Direction.CW); canvas.clipPath(circlePath); // Draw background. background.setBounds(0, 0, size, size); background.draw(canvas); // Draw foreground. The foreground and background drawables are derived from adaptive icons // Some icon shapes fill more space than others, so adaptive icons are normalized to about // the same size. This size is smaller than the original bounds, so we estimate // the difference in this offset. int offset = size / 5; foreground.setBounds(-offset, -offset, size + offset, size + offset); foreground.draw(canvas); canvas.setBitmap(null); return bitmap; @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); } } }
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; Loading Loading @@ -65,4 +66,19 @@ public class BubbleIconFactory extends BaseIconFactory { 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); } }
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +7 −4 Original line number Diff line number Diff line Loading @@ -195,15 +195,18 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask b.isImportantConversation()); info.badgeBitmap = badgeBitmapInfo.icon; // Raw badge bitmap never includes the important conversation ring info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon; info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon; info.mRawBadgeBitmap = b.isImportantConversation() ? badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon : badgeBitmapInfo.icon; float[] bubbleBitmapScale = new float[1]; info.bubbleBitmap = iconFactory.createIconBitmap(bubbleDrawable, bubbleBitmapScale); // Dot color & placement Path iconPath = PathParser.createPathFromPathData( c.getResources().getString(com.android.internal.R.string.config_icon_mask)); Matrix matrix = new Matrix(); float scale = iconFactory.getNormalizer().getScale(bubbleDrawable, null /* outBounds */, null /* path */, null /* outMaskShape */); float scale = bubbleBitmapScale[0]; float radius = DEFAULT_PATH_SIZE / 2f; matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */, radius /* pivot y */); Loading