Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit facc40b2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Optimizing some icon generation code in bubble" into tm-qpr-dev am:...

Merge "Optimizing some icon generation code in bubble" into tm-qpr-dev am: ac622814 am: b980cc92

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19528335



Change-Id: Iff15694693a68995f9ee2b4e4242adc36af90982
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 46a3f202 b980cc92
Loading
Loading
Loading
Loading
+67 −68
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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);
        }
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -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;

@@ -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);
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -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 */);