Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2016 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 
     17 package com.android.launcher3.graphics;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.graphics.Bitmap;
     22 import android.graphics.Canvas;
     23 import android.graphics.Color;
     24 import android.graphics.Path;
     25 import android.graphics.Rect;
     26 import android.graphics.drawable.BitmapDrawable;
     27 import android.graphics.drawable.Drawable;
     28 import android.os.Process;
     29 import android.os.UserHandle;
     30 import android.support.annotation.UiThread;
     31 import android.util.Log;
     32 
     33 import com.android.launcher3.FastBitmapDrawable;
     34 import com.android.launcher3.ItemInfo;
     35 import com.android.launcher3.R;
     36 import com.android.launcher3.Utilities;
     37 import com.android.launcher3.allapps.AllAppsBackgroundDrawable;
     38 
     39 import java.util.HashMap;
     40 
     41 /**
     42  * Factory for creating new drawables.
     43  */
     44 public class DrawableFactory {
     45 
     46     private static final String TAG = "DrawableFactory";
     47 
     48     private static DrawableFactory sInstance;
     49     private static final Object LOCK = new Object();
     50 
     51     private Path mPreloadProgressPath;
     52 
     53     public static DrawableFactory get(Context context) {
     54         synchronized (LOCK) {
     55             if (sInstance == null) {
     56                 sInstance = Utilities.getOverrideObject(DrawableFactory.class,
     57                         context.getApplicationContext(), R.string.drawable_factory_class);
     58             }
     59             return sInstance;
     60         }
     61     }
     62 
     63     protected final UserHandle mMyUser = Process.myUserHandle();
     64     protected final HashMap<UserHandle, Bitmap> mUserBadges = new HashMap<>();
     65 
     66     /**
     67      * Returns a FastBitmapDrawable with the icon.
     68      */
     69     public FastBitmapDrawable newIcon(Bitmap icon, ItemInfo info) {
     70         return new FastBitmapDrawable(icon);
     71     }
     72 
     73     /**
     74      * Returns a FastBitmapDrawable with the icon.
     75      */
     76     public PreloadIconDrawable newPendingIcon(Bitmap icon, Context context) {
     77         if (mPreloadProgressPath == null) {
     78             mPreloadProgressPath = getPreloadProgressPath(context);
     79         }
     80         return new PreloadIconDrawable(icon, mPreloadProgressPath, context);
     81     }
     82 
     83 
     84     protected Path getPreloadProgressPath(Context context) {
     85         if (Utilities.isAtLeastO()) {
     86             try {
     87                 // Try to load the path from Mask Icon
     88                 Drawable icon = context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper);
     89                 icon.setBounds(0, 0,
     90                         PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE);
     91                 return (Path) icon.getClass().getMethod("getIconMask").invoke(icon);
     92             } catch (Exception e) {
     93                 Log.e(TAG, "Error loading mask icon", e);
     94             }
     95         }
     96 
     97         // Create a circle static from top center and going clockwise.
     98         Path p = new Path();
     99         p.moveTo(PreloadIconDrawable.PATH_SIZE / 2, 0);
    100         p.addArc(0, 0, PreloadIconDrawable.PATH_SIZE, PreloadIconDrawable.PATH_SIZE, -90, 360);
    101         return p;
    102     }
    103 
    104     public AllAppsBackgroundDrawable getAllAppsBackground(Context context) {
    105         return new AllAppsBackgroundDrawable(context);
    106     }
    107 
    108     /**
    109      * Returns a drawable that can be used as a badge for the user or null.
    110      */
    111     @UiThread
    112     public Drawable getBadgeForUser(UserHandle user, Context context) {
    113         if (mMyUser.equals(user)) {
    114             return null;
    115         }
    116 
    117         Bitmap badgeBitmap = getUserBadge(user, context);
    118         FastBitmapDrawable d = new FastBitmapDrawable(badgeBitmap);
    119         d.setFilterBitmap(true);
    120         d.setBounds(0, 0, badgeBitmap.getWidth(), badgeBitmap.getHeight());
    121         return d;
    122     }
    123 
    124     protected synchronized Bitmap getUserBadge(UserHandle user, Context context) {
    125         Bitmap badgeBitmap = mUserBadges.get(user);
    126         if (badgeBitmap != null) {
    127             return badgeBitmap;
    128         }
    129 
    130         final Resources res = context.getApplicationContext().getResources();
    131         int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size);
    132         badgeBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888);
    133 
    134         Drawable drawable = context.getPackageManager().getUserBadgedDrawableForDensity(
    135                 new BitmapDrawable(res, badgeBitmap), user, new Rect(0, 0, badgeSize, badgeSize),
    136                 0);
    137         if (drawable instanceof BitmapDrawable) {
    138             badgeBitmap = ((BitmapDrawable) drawable).getBitmap();
    139         } else {
    140             badgeBitmap.eraseColor(Color.TRANSPARENT);
    141             Canvas c = new Canvas(badgeBitmap);
    142             drawable.setBounds(0, 0, badgeSize, badgeSize);
    143             drawable.draw(c);
    144             c.setBitmap(null);
    145         }
    146 
    147         mUserBadges.put(user, badgeBitmap);
    148         return badgeBitmap;
    149     }
    150 }
    151