• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.Configuration;
20 import android.graphics.Bitmap;
21 import android.graphics.Bitmap.Config;
22 import android.graphics.Canvas;
23 
24 import androidx.annotation.IntDef;
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 
28 import com.android.launcher3.util.FlagOp;
29 
30 public class BitmapInfo {
31 
32     static final int FLAG_WORK = 1 << 0;
33     static final int FLAG_INSTANT = 1 << 1;
34     static final int FLAG_CLONE = 1 << 2;
35     @IntDef(flag = true, value = {
36             FLAG_WORK,
37             FLAG_INSTANT,
38             FLAG_CLONE
39     })
40     @interface BitmapInfoFlags {}
41 
42     public static final int FLAG_THEMED = 1 << 0;
43     public static final int FLAG_NO_BADGE = 1 << 1;
44     @IntDef(flag = true, value = {
45             FLAG_THEMED,
46             FLAG_NO_BADGE,
47     })
48     public @interface DrawableCreationFlags {}
49 
50     public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
51     public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON);
52 
53     public static final String TAG = "BitmapInfo";
54 
55     public final Bitmap icon;
56     public final int color;
57 
58     @Nullable
59     protected Bitmap mMono;
60     protected Bitmap mWhiteShadowLayer;
61 
62     public @BitmapInfoFlags int flags;
63     private BitmapInfo badgeInfo;
64 
BitmapInfo(Bitmap icon, int color)65     public BitmapInfo(Bitmap icon, int color) {
66         this.icon = icon;
67         this.color = color;
68     }
69 
withBadgeInfo(BitmapInfo badgeInfo)70     public BitmapInfo withBadgeInfo(BitmapInfo badgeInfo) {
71         BitmapInfo result = clone();
72         result.badgeInfo = badgeInfo;
73         return result;
74     }
75 
76     /**
77      * Returns a bitmapInfo with the flagOP applied
78      */
withFlags(@onNull FlagOp op)79     public BitmapInfo withFlags(@NonNull FlagOp op) {
80         if (op == FlagOp.NO_OP) {
81             return this;
82         }
83         BitmapInfo result = clone();
84         result.flags = op.apply(result.flags);
85         return result;
86     }
87 
copyInternalsTo(BitmapInfo target)88     protected BitmapInfo copyInternalsTo(BitmapInfo target) {
89         target.mMono = mMono;
90         target.mWhiteShadowLayer = mWhiteShadowLayer;
91         target.flags = flags;
92         target.badgeInfo = badgeInfo;
93         return target;
94     }
95 
96     @Override
clone()97     public BitmapInfo clone() {
98         return copyInternalsTo(new BitmapInfo(icon, color));
99     }
100 
setMonoIcon(Bitmap mono, BaseIconFactory iconFactory)101     public void setMonoIcon(Bitmap mono, BaseIconFactory iconFactory) {
102         mMono = mono;
103         mWhiteShadowLayer = iconFactory.getWhiteShadowLayer();
104     }
105 
106     /**
107      * Ideally icon should not be null, except in cases when generating hardware bitmap failed
108      */
isNullOrLowRes()109     public final boolean isNullOrLowRes() {
110         return icon == null || icon == LOW_RES_ICON;
111     }
112 
isLowRes()113     public final boolean isLowRes() {
114         return LOW_RES_ICON == icon;
115     }
116 
117     /**
118      * BitmapInfo can be stored on disk or other persistent storage
119      */
canPersist()120     public boolean canPersist() {
121         return !isNullOrLowRes();
122     }
123 
getMono()124     public Bitmap getMono() {
125         return mMono;
126     }
127 
128     /**
129      * Creates a drawable for the provided BitmapInfo
130      */
newIcon(Context context)131     public FastBitmapDrawable newIcon(Context context) {
132         return newIcon(context, 0);
133     }
134 
135     /**
136      * Creates a drawable for the provided BitmapInfo
137      */
newIcon(Context context, @DrawableCreationFlags int creationFlags)138     public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) {
139         FastBitmapDrawable drawable;
140         if (isLowRes()) {
141             drawable = new PlaceHolderIconDrawable(this, context);
142         } else  if ((creationFlags & FLAG_THEMED) != 0 && mMono != null) {
143             drawable = ThemedIconDrawable.newDrawable(this, context);
144         } else {
145             drawable = new FastBitmapDrawable(this);
146         }
147         applyFlags(context, drawable, creationFlags);
148         return drawable;
149     }
150 
applyFlags(Context context, FastBitmapDrawable drawable, @DrawableCreationFlags int creationFlags)151     protected void applyFlags(Context context, FastBitmapDrawable drawable,
152             @DrawableCreationFlags int creationFlags) {
153         drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f);
154         if ((creationFlags & FLAG_NO_BADGE) == 0) {
155             if (badgeInfo != null) {
156                 drawable.setBadge(badgeInfo.newIcon(context, creationFlags));
157             } else if ((flags & FLAG_INSTANT) != 0) {
158                 drawable.setBadge(context.getDrawable(drawable.isThemed()
159                         ? R.drawable.ic_instant_app_badge_themed
160                         : R.drawable.ic_instant_app_badge));
161             } else if ((flags & FLAG_WORK) != 0) {
162                 drawable.setBadge(context.getDrawable(drawable.isThemed()
163                         ? R.drawable.ic_work_app_badge_themed
164                         : R.drawable.ic_work_app_badge));
165             } else if ((flags & FLAG_CLONE) != 0) {
166                 drawable.setBadge(context.getDrawable(drawable.isThemed()
167                         ? R.drawable.ic_clone_app_badge_themed
168                         : R.drawable.ic_clone_app_badge));
169             }
170         }
171     }
172 
fromBitmap(@onNull Bitmap bitmap)173     public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
174         return of(bitmap, 0);
175     }
176 
of(@onNull Bitmap bitmap, int color)177     public static BitmapInfo of(@NonNull Bitmap bitmap, int color) {
178         return new BitmapInfo(bitmap, color);
179     }
180 
181     /**
182      * Interface to be implemented by drawables to provide a custom BitmapInfo
183      */
184     public interface Extender {
185 
186         /**
187          * Called for creating a custom BitmapInfo
188          */
getExtendedInfo(Bitmap bitmap, int color, BaseIconFactory iconFactory, float normalizationScale)189         BitmapInfo getExtendedInfo(Bitmap bitmap, int color,
190                 BaseIconFactory iconFactory, float normalizationScale);
191 
192         /**
193          * Called to draw the UI independent of any runtime configurations like time or theme
194          */
drawForPersistence(Canvas canvas)195         void drawForPersistence(Canvas canvas);
196     }
197 }
198