1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.icons;
17 
18 import android.content.Context;
19 import android.content.res.Resources;
20 import android.graphics.Bitmap;
21 import android.graphics.BlendMode;
22 import android.graphics.BlendModeColorFilter;
23 import android.graphics.Canvas;
24 import android.graphics.ColorFilter;
25 import android.graphics.Paint;
26 import android.graphics.Rect;
27 
28 /**
29  * Class to handle monochrome themed app icons
30  */
31 @SuppressWarnings("NewApi")
32 public class ThemedIconDrawable extends FastBitmapDrawable {
33 
34     public static final String TAG = "ThemedIconDrawable";
35 
36     final BitmapInfo bitmapInfo;
37     final int colorFg, colorBg;
38 
39     // The foreground/monochrome icon for the app
40     private final Bitmap mMonoIcon;
41     private final Paint mMonoPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
42 
43     private final Bitmap mBgBitmap;
44     private final Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
45 
46     private final ColorFilter mBgFilter, mMonoFilter;
47 
ThemedIconDrawable(ThemedConstantState constantState)48     protected ThemedIconDrawable(ThemedConstantState constantState) {
49         super(constantState.mBitmap, constantState.colorFg);
50         bitmapInfo = constantState.bitmapInfo;
51         colorBg = constantState.colorBg;
52         colorFg = constantState.colorFg;
53 
54         mMonoIcon = bitmapInfo.mMono;
55         mMonoFilter = new BlendModeColorFilter(colorFg, BlendMode.SRC_IN);
56         mMonoPaint.setColorFilter(mMonoFilter);
57 
58         mBgBitmap = bitmapInfo.mWhiteShadowLayer;
59         mBgFilter = new BlendModeColorFilter(colorBg, BlendMode.SRC_IN);
60         mBgPaint.setColorFilter(mBgFilter);
61     }
62 
63     @Override
drawInternal(Canvas canvas, Rect bounds)64     protected void drawInternal(Canvas canvas, Rect bounds) {
65         canvas.drawBitmap(mBgBitmap, null, bounds, mBgPaint);
66         canvas.drawBitmap(mMonoIcon, null, bounds, mMonoPaint);
67     }
68 
69     @Override
updateFilter()70     protected void updateFilter() {
71         super.updateFilter();
72         int alpha = mIsDisabled ? (int) (mDisabledAlpha * FULLY_OPAQUE) : FULLY_OPAQUE;
73         mBgPaint.setAlpha(alpha);
74         mBgPaint.setColorFilter(mIsDisabled ? new BlendModeColorFilter(
75                 getDisabledColor(colorBg), BlendMode.SRC_IN) : mBgFilter);
76 
77         mMonoPaint.setAlpha(alpha);
78         mMonoPaint.setColorFilter(mIsDisabled ? new BlendModeColorFilter(
79                 getDisabledColor(colorFg), BlendMode.SRC_IN) : mMonoFilter);
80     }
81 
82     @Override
isThemed()83     public boolean isThemed() {
84         return true;
85     }
86 
87     @Override
newConstantState()88     public FastBitmapConstantState newConstantState() {
89         return new ThemedConstantState(bitmapInfo, colorBg, colorFg);
90     }
91 
92     static class ThemedConstantState extends FastBitmapConstantState {
93 
94         final BitmapInfo bitmapInfo;
95         final int colorFg, colorBg;
96 
ThemedConstantState(BitmapInfo bitmapInfo, int colorBg, int colorFg)97         public ThemedConstantState(BitmapInfo bitmapInfo, int colorBg, int colorFg) {
98             super(bitmapInfo.icon, bitmapInfo.color);
99             this.bitmapInfo = bitmapInfo;
100             this.colorBg = colorBg;
101             this.colorFg = colorFg;
102         }
103 
104         @Override
createDrawable()105         public FastBitmapDrawable createDrawable() {
106             return new ThemedIconDrawable(this);
107         }
108     }
109 
newDrawable(BitmapInfo info, Context context)110     public static FastBitmapDrawable newDrawable(BitmapInfo info, Context context) {
111         int[] colors = getColors(context);
112         return new ThemedConstantState(info, colors[0], colors[1]).newDrawable();
113     }
114 
115     /**
116      * Get an int array representing background and foreground colors for themed icons
117      */
getColors(Context context)118     public static int[] getColors(Context context) {
119         Resources res = context.getResources();
120         int[] colors = new int[2];
121         colors[0] = res.getColor(R.color.themed_icon_background_color);
122         colors[1] = res.getColor(R.color.themed_icon_color);
123         return colors;
124     }
125 
126     @Override
getIconColor()127     public int getIconColor() {
128         return colorFg;
129     }
130 }
131