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