• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.content.res.TypedArray;
21 import android.graphics.Bitmap;
22 import android.graphics.Color;
23 import android.graphics.Matrix;
24 import android.graphics.Path;
25 import android.graphics.Rect;
26 import android.graphics.Region;
27 import android.graphics.RegionIterator;
28 import android.graphics.drawable.AdaptiveIconDrawable;
29 import android.graphics.drawable.ColorDrawable;
30 import android.util.Log;
31 
32 import androidx.annotation.ColorInt;
33 import androidx.annotation.NonNull;
34 import androidx.core.graphics.PathParser;
35 
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 
39 public class GraphicsUtils {
40 
41     private static final String TAG = "GraphicsUtils";
42     private static final float MASK_SIZE = 100f;
43 
44     public static Runnable sOnNewBitmapRunnable = () -> { };
45 
46     /**
47      * Set the alpha component of {@code color} to be {@code alpha}. Unlike the support lib version,
48      * it bounds the alpha in valid range instead of throwing an exception to allow for safer
49      * interpolation of color animations
50      */
51     @ColorInt
setColorAlphaBound(int color, int alpha)52     public static int setColorAlphaBound(int color, int alpha) {
53         if (alpha < 0) {
54             alpha = 0;
55         } else if (alpha > 255) {
56             alpha = 255;
57         }
58         return (color & 0x00ffffff) | (alpha << 24);
59     }
60 
61     /**
62      * Compresses the bitmap to a byte array for serialization.
63      */
flattenBitmap(Bitmap bitmap)64     public static byte[] flattenBitmap(Bitmap bitmap) {
65         ByteArrayOutputStream out = new ByteArrayOutputStream(getExpectedBitmapSize(bitmap));
66         try {
67             bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
68             out.flush();
69             out.close();
70             return out.toByteArray();
71         } catch (IOException e) {
72             Log.w(TAG, "Could not write bitmap");
73             return null;
74         }
75     }
76 
77     /**
78      * Try go guesstimate how much space the icon will take when serialized to avoid unnecessary
79      * allocations/copies during the write (4 bytes per pixel).
80      */
getExpectedBitmapSize(Bitmap bitmap)81     static int getExpectedBitmapSize(Bitmap bitmap) {
82         return bitmap.getWidth() * bitmap.getHeight() * 4;
83     }
84 
getArea(Region r)85     public static int getArea(Region r) {
86         RegionIterator itr = new RegionIterator(r);
87         int area = 0;
88         Rect tempRect = new Rect();
89         while (itr.next(tempRect)) {
90             area += tempRect.width() * tempRect.height();
91         }
92         return area;
93     }
94 
95     /**
96      * Utility method to track new bitmap creation
97      */
noteNewBitmapCreated()98     public static void noteNewBitmapCreated() {
99         sOnNewBitmapRunnable.run();
100     }
101 
102 
103     /**
104      * Returns the default path to be used by an icon
105      */
getShapePath(@onNull Context context, int size)106     public static Path getShapePath(@NonNull Context context, int size) {
107         if (IconProvider.CONFIG_ICON_MASK_RES_ID != Resources.ID_NULL) {
108             Path path = PathParser.createPathFromPathData(
109                     context.getString(IconProvider.CONFIG_ICON_MASK_RES_ID));
110             if (path != null) {
111                 if (size != MASK_SIZE) {
112                     Matrix m = new Matrix();
113                     float scale = ((float) size) / MASK_SIZE;
114                     m.setScale(scale, scale);
115                     path.transform(m);
116                 }
117                 return path;
118             }
119         }
120         AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
121                 new ColorDrawable(Color.BLACK), new ColorDrawable(Color.BLACK));
122         drawable.setBounds(0, 0, size, size);
123         return new Path(drawable.getIconMask());
124     }
125 
126     /**
127      * Returns the color associated with the attribute
128      */
getAttrColor(Context context, int attr)129     public static int getAttrColor(Context context, int attr) {
130         TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
131         int colorAccent = ta.getColor(0, 0);
132         ta.recycle();
133         return colorAccent;
134     }
135 
136     /**
137      * Returns the alpha corresponding to the theme attribute {@param attr}
138      */
getFloat(Context context, int attr, float defValue)139     public static float getFloat(Context context, int attr, float defValue) {
140         TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
141         float value = ta.getFloat(0, defValue);
142         ta.recycle();
143         return value;
144     }
145 }
146