blob: 28e923e67abe9b2c305d0942bb5d29ea807726fa [file] [log] [blame]
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001/*
2 * Copyright (C) 2008 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
Daniel Sandler325dc232013-06-05 22:57:57 -040017package com.android.launcher3;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080018
Sunny Goyal508da152014-08-14 10:53:27 -070019import android.animation.ObjectAnimator;
20import android.animation.TimeInterpolator;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080021import android.graphics.Bitmap;
22import android.graphics.Canvas;
Sunny Goyal508da152014-08-14 10:53:27 -070023import android.graphics.Color;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080024import android.graphics.ColorFilter;
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070025import android.graphics.ColorMatrix;
26import android.graphics.ColorMatrixColorFilter;
Winson Chung45e1d6e2010-11-09 17:19:49 -080027import android.graphics.Paint;
28import android.graphics.PixelFormat;
Sunny Goyal508da152014-08-14 10:53:27 -070029import android.graphics.PorterDuff;
30import android.graphics.PorterDuffColorFilter;
Winson Chung45e1d6e2010-11-09 17:19:49 -080031import android.graphics.Rect;
32import android.graphics.drawable.Drawable;
Sunny Goyal508da152014-08-14 10:53:27 -070033import android.util.SparseArray;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080034
Hyunyoung Song3f471442015-04-08 19:01:34 -070035public class FastBitmapDrawable extends Drawable {
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070036
Sunny Goyal508da152014-08-14 10:53:27 -070037 static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() {
38
39 @Override
40 public float getInterpolation(float input) {
41 if (input < 0.05f) {
42 return input / 0.05f;
43 } else if (input < 0.3f){
44 return 1;
45 } else {
46 return (1 - input) / 0.7f;
47 }
48 }
49 };
50 static final long CLICK_FEEDBACK_DURATION = 2000;
51
52 private static final int PRESSED_BRIGHTNESS = 100;
Sunny Goyal95abbb32014-08-04 10:53:22 -070053 private static ColorMatrix sGhostModeMatrix;
54 private static final ColorMatrix sTempMatrix = new ColorMatrix();
55
Sunny Goyal508da152014-08-14 10:53:27 -070056 /**
57 * Store the brightness colors filters to optimize animations during icon press. This
58 * only works for non-ghost-mode icons.
59 */
60 private static final SparseArray<ColorFilter> sCachedBrightnessFilter =
61 new SparseArray<ColorFilter>();
62
Sunny Goyal95abbb32014-08-04 10:53:22 -070063 private static final int GHOST_MODE_MIN_COLOR_RANGE = 130;
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070064
65 private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
Sunny Goyal508da152014-08-14 10:53:27 -070066 private final Bitmap mBitmap;
Winson Chung29d6fea2010-12-01 15:47:31 -080067 private int mAlpha;
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070068
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070069 private int mBrightness = 0;
Sunny Goyal95abbb32014-08-04 10:53:22 -070070 private boolean mGhostModeEnabled = false;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080071
Sunny Goyal508da152014-08-14 10:53:27 -070072 private boolean mPressed = false;
73 private ObjectAnimator mPressedAnimator;
74
Hyunyoung Song3f471442015-04-08 19:01:34 -070075 public FastBitmapDrawable(Bitmap b) {
Winson Chungeeb5bbc2013-11-13 15:47:05 -080076 mAlpha = 255;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080077 mBitmap = b;
Winson Chung268f1c52013-11-18 14:04:41 -080078 setBounds(0, 0, b.getWidth(), b.getHeight());
The Android Open Source Project31dd5032009-03-03 19:32:27 -080079 }
80
81 @Override
82 public void draw(Canvas canvas) {
Winson Chung45e1d6e2010-11-09 17:19:49 -080083 final Rect r = getBounds();
Winson Chung8a196352013-05-28 16:12:55 -070084 // Draw the bitmap into the bounding rect
85 canvas.drawBitmap(mBitmap, null, r, mPaint);
The Android Open Source Project31dd5032009-03-03 19:32:27 -080086 }
87
88 @Override
Adam Cohenbadf71e2011-05-26 19:08:29 -070089 public void setColorFilter(ColorFilter cf) {
Sunny Goyalc5c60ad2014-07-14 12:02:01 -070090 // No op
Adam Cohenbadf71e2011-05-26 19:08:29 -070091 }
92
93 @Override
The Android Open Source Project31dd5032009-03-03 19:32:27 -080094 public int getOpacity() {
95 return PixelFormat.TRANSLUCENT;
96 }
97
98 @Override
99 public void setAlpha(int alpha) {
Winson Chung29d6fea2010-12-01 15:47:31 -0800100 mAlpha = alpha;
Winson Chungb3347bb2010-08-19 14:51:28 -0700101 mPaint.setAlpha(alpha);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800102 }
103
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700104 @Override
Adam Cohen76fc0852011-06-17 13:26:23 -0700105 public void setFilterBitmap(boolean filterBitmap) {
106 mPaint.setFilterBitmap(filterBitmap);
Winson Chung6e1c0d32013-10-25 15:24:24 -0700107 mPaint.setAntiAlias(filterBitmap);
Adam Cohen76fc0852011-06-17 13:26:23 -0700108 }
109
Winson Chung29d6fea2010-12-01 15:47:31 -0800110 public int getAlpha() {
111 return mAlpha;
112 }
113
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800114 @Override
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800115 public int getIntrinsicWidth() {
Sunny Goyalc424f222014-09-05 07:04:59 -0700116 return mBitmap.getWidth();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800117 }
118
119 @Override
120 public int getIntrinsicHeight() {
Sunny Goyalc424f222014-09-05 07:04:59 -0700121 return mBitmap.getHeight();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800122 }
123
124 @Override
125 public int getMinimumWidth() {
Winson Chungeeb5bbc2013-11-13 15:47:05 -0800126 return getBounds().width();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800127 }
128
129 @Override
130 public int getMinimumHeight() {
Winson Chungeeb5bbc2013-11-13 15:47:05 -0800131 return getBounds().height();
Joe Onorato0589f0f2010-02-08 13:44:00 -0800132 }
133
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800134 public Bitmap getBitmap() {
135 return mBitmap;
136 }
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700137
Sunny Goyal95abbb32014-08-04 10:53:22 -0700138 /**
139 * When enabled, the icon is grayed out and the contrast is increased to give it a 'ghost'
140 * appearance.
141 */
142 public void setGhostModeEnabled(boolean enabled) {
143 if (mGhostModeEnabled != enabled) {
144 mGhostModeEnabled = enabled;
145 updateFilter();
146 }
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700147 }
148
Sunny Goyal508da152014-08-14 10:53:27 -0700149 public void setPressed(boolean pressed) {
150 if (mPressed != pressed) {
151 mPressed = pressed;
152 if (mPressed) {
153 mPressedAnimator = ObjectAnimator
154 .ofInt(this, "brightness", PRESSED_BRIGHTNESS)
155 .setDuration(CLICK_FEEDBACK_DURATION);
156 mPressedAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR);
157 mPressedAnimator.start();
158 } else if (mPressedAnimator != null) {
159 mPressedAnimator.cancel();
160 setBrightness(0);
161 }
162 }
163 invalidateSelf();
164 }
165
Sunny Goyal95abbb32014-08-04 10:53:22 -0700166 public boolean isGhostModeEnabled() {
167 return mGhostModeEnabled;
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700168 }
169
170 public int getBrightness() {
171 return mBrightness;
172 }
173
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700174 public void setBrightness(int brightness) {
Sunny Goyal95abbb32014-08-04 10:53:22 -0700175 if (mBrightness != brightness) {
176 mBrightness = brightness;
177 updateFilter();
Sunny Goyal508da152014-08-14 10:53:27 -0700178 invalidateSelf();
Sunny Goyal95abbb32014-08-04 10:53:22 -0700179 }
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700180 }
181
182 private void updateFilter() {
Sunny Goyal95abbb32014-08-04 10:53:22 -0700183 if (mGhostModeEnabled) {
184 if (sGhostModeMatrix == null) {
185 sGhostModeMatrix = new ColorMatrix();
186 sGhostModeMatrix.setSaturation(0);
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700187
Sunny Goyal95abbb32014-08-04 10:53:22 -0700188 // For ghost mode, set the color range to [GHOST_MODE_MIN_COLOR_RANGE, 255]
189 float range = (255 - GHOST_MODE_MIN_COLOR_RANGE) / 255.0f;
190 sTempMatrix.set(new float[] {
191 range, 0, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
192 0, range, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
193 0, 0, range, 0, GHOST_MODE_MIN_COLOR_RANGE,
194 0, 0, 0, 1, 0 });
195 sGhostModeMatrix.preConcat(sTempMatrix);
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700196 }
Sunny Goyal95abbb32014-08-04 10:53:22 -0700197
198 if (mBrightness == 0) {
199 mPaint.setColorFilter(new ColorMatrixColorFilter(sGhostModeMatrix));
200 } else {
201 setBrightnessMatrix(sTempMatrix, mBrightness);
202 sTempMatrix.postConcat(sGhostModeMatrix);
203 mPaint.setColorFilter(new ColorMatrixColorFilter(sTempMatrix));
204 }
205 } else if (mBrightness != 0) {
Sunny Goyal508da152014-08-14 10:53:27 -0700206 ColorFilter filter = sCachedBrightnessFilter.get(mBrightness);
207 if (filter == null) {
208 filter = new PorterDuffColorFilter(Color.argb(mBrightness, 255, 255, 255),
209 PorterDuff.Mode.SRC_ATOP);
210 sCachedBrightnessFilter.put(mBrightness, filter);
211 }
212 mPaint.setColorFilter(filter);
Sunny Goyalc5c60ad2014-07-14 12:02:01 -0700213 } else {
214 mPaint.setColorFilter(null);
215 }
216 }
Sunny Goyal95abbb32014-08-04 10:53:22 -0700217
218 private static void setBrightnessMatrix(ColorMatrix matrix, int brightness) {
219 // Brightness: C-new = C-old*(1-amount) + amount
220 float scale = 1 - brightness / 255.0f;
221 matrix.setScale(scale, scale, scale, 1);
222 float[] array = matrix.getArray();
223
224 // Add the amount to RGB components of the matrix, as per the above formula.
225 // Fifth elements in the array correspond to the constant being added to
226 // red, blue, green, and alpha channel respectively.
227 array[4] = brightness;
228 array[9] = brightness;
229 array[14] = brightness;
230 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800231}