blob: 0311afa461306aeab37bb54372a5d546efbe341d [file] [log] [blame]
Michael Jurka5f1c5092010-09-03 14:15:02 -07001/*
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
17package com.android.launcher2;
18
19import android.graphics.Bitmap;
20import android.graphics.BlurMaskFilter;
21import android.graphics.Canvas;
Joe Onorato4be866d2010-10-10 11:26:02 -070022import android.graphics.MaskFilter;
Michael Jurka5f1c5092010-09-03 14:15:02 -070023import android.graphics.Paint;
Michael Jurka5f1c5092010-09-03 14:15:02 -070024import android.graphics.PorterDuff;
25import android.graphics.PorterDuffXfermode;
Joe Onorato4be866d2010-10-10 11:26:02 -070026import android.graphics.TableMaskFilter;
Michael Jurka5f1c5092010-09-03 14:15:02 -070027
28public class HolographicOutlineHelper {
Michael Jurka5f1c5092010-09-03 14:15:02 -070029 private final Paint mHolographicPaint = new Paint();
Joe Onorato4be866d2010-10-10 11:26:02 -070030 private final Paint mBlurPaint = new Paint();
Michael Jurka5f1c5092010-09-03 14:15:02 -070031 private final Paint mErasePaint = new Paint();
Adam Cohen5bb50bd2010-12-03 11:39:55 -080032 private final Paint mAlphaClipPaint = new Paint();
Michael Jurka5f1c5092010-09-03 14:15:02 -070033
Patrick Dubroy8e58e912010-10-14 13:21:48 -070034 public static final int OUTER_BLUR_RADIUS;
Joe Onorato4be866d2010-10-10 11:26:02 -070035
Patrick Dubroy8e58e912010-10-14 13:21:48 -070036 private static final BlurMaskFilter sThickOuterBlurMaskFilter;
37 private static final BlurMaskFilter sMediumOuterBlurMaskFilter;
38 private static final BlurMaskFilter sThinOuterBlurMaskFilter;
39 private static final BlurMaskFilter sThickInnerBlurMaskFilter;
Adam Cohen5bb50bd2010-12-03 11:39:55 -080040 private static final BlurMaskFilter sMediumInnerBlurMaskFilter;
41
42 private static final int THICK = 0;
43 private static final int MEDIUM = 1;
Patrick Dubroy8e58e912010-10-14 13:21:48 -070044
45 static {
46 final float scale = LauncherApplication.getScreenDensity();
47
48 OUTER_BLUR_RADIUS = (int) (scale * 6.0f);
49
50 sThickOuterBlurMaskFilter = new BlurMaskFilter(OUTER_BLUR_RADIUS,
51 BlurMaskFilter.Blur.OUTER);
52 sMediumOuterBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.OUTER);
53 sThinOuterBlurMaskFilter = new BlurMaskFilter(scale * 1.0f, BlurMaskFilter.Blur.OUTER);
54 sThickInnerBlurMaskFilter = new BlurMaskFilter(scale * 4.0f, BlurMaskFilter.Blur.NORMAL);
Adam Cohen5bb50bd2010-12-03 11:39:55 -080055 sMediumInnerBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.NORMAL);
Patrick Dubroy8e58e912010-10-14 13:21:48 -070056 }
Joe Onorato4be866d2010-10-10 11:26:02 -070057
Joe Onorato4be866d2010-10-10 11:26:02 -070058 private static final MaskFilter sCoarseClipTable = TableMaskFilter.CreateClipTable(0, 200);
59
60 private int[] mTempOffset = new int[2];
Michael Jurka5f1c5092010-09-03 14:15:02 -070061
Winson Chung64a3cd42010-09-17 16:47:33 -070062 HolographicOutlineHelper() {
Michael Jurka5f1c5092010-09-03 14:15:02 -070063 mHolographicPaint.setFilterBitmap(true);
64 mHolographicPaint.setAntiAlias(true);
Joe Onorato4be866d2010-10-10 11:26:02 -070065 mBlurPaint.setFilterBitmap(true);
66 mBlurPaint.setAntiAlias(true);
Michael Jurka5f1c5092010-09-03 14:15:02 -070067 mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
68 mErasePaint.setFilterBitmap(true);
69 mErasePaint.setAntiAlias(true);
Adam Cohen5bb50bd2010-12-03 11:39:55 -080070 MaskFilter alphaClipTable = TableMaskFilter.CreateClipTable(180, 255);
71 mAlphaClipPaint.setMaskFilter(alphaClipTable);
Michael Jurka5f1c5092010-09-03 14:15:02 -070072 }
73
Michael Jurka5f1c5092010-09-03 14:15:02 -070074 /**
75 * Returns the interpolated holographic highlight alpha for the effect we want when scrolling
76 * pages.
77 */
78 public float highlightAlphaInterpolator(float r) {
Winson Chung64a3cd42010-09-17 16:47:33 -070079 float maxAlpha = 0.8f;
Winson Chunge8878e32010-09-15 20:37:09 -070080 return (float) Math.pow(maxAlpha * (1.0f - r), 1.5f);
Michael Jurka5f1c5092010-09-03 14:15:02 -070081 }
82
83 /**
84 * Returns the interpolated view alpha for the effect we want when scrolling pages.
85 */
86 public float viewAlphaInterpolator(float r) {
Winson Chunge8878e32010-09-15 20:37:09 -070087 final float pivot = 0.95f;
Michael Jurka5f1c5092010-09-03 14:15:02 -070088 if (r < pivot) {
Winson Chunge8878e32010-09-15 20:37:09 -070089 return (float) Math.pow(r / pivot, 1.5f);
Michael Jurka5f1c5092010-09-03 14:15:02 -070090 } else {
91 return 1.0f;
92 }
93 }
94
Patrick Dubroy8e58e912010-10-14 13:21:48 -070095 /**
96 * Apply an outer blur to the given bitmap.
97 * You should use OUTER_BLUR_RADIUS to ensure that the bitmap is big enough to draw
98 * the blur without clipping.
99 */
100 void applyOuterBlur(Bitmap bitmap, Canvas canvas, int color) {
Joe Onorato4be866d2010-10-10 11:26:02 -0700101 mBlurPaint.setMaskFilter(sThickOuterBlurMaskFilter);
102 Bitmap glow = bitmap.extractAlpha(mBlurPaint, mTempOffset);
103
104 // Use the clip table to make the glow heavier closer to the outline
105 mHolographicPaint.setMaskFilter(sCoarseClipTable);
106 mHolographicPaint.setAlpha(150);
107 mHolographicPaint.setColor(color);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800108
Joe Onorato4be866d2010-10-10 11:26:02 -0700109 canvas.drawBitmap(glow, mTempOffset[0], mTempOffset[1], mHolographicPaint);
110 glow.recycle();
111 }
112
113 /**
Winson Chung64a3cd42010-09-17 16:47:33 -0700114 * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
115 * bitmap.
Michael Jurka5f1c5092010-09-03 14:15:02 -0700116 */
Winson Chung64a3cd42010-09-17 16:47:33 -0700117 void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800118 int outlineColor, int thickness) {
119
120 // We start by removing most of the alpha channel so as to ignore shadows, and
121 // other types of partial transparency when defining the shape of the object
122 Bitmap glowShape = srcDst.extractAlpha(mAlphaClipPaint, mTempOffset);
123
Winson Chung64a3cd42010-09-17 16:47:33 -0700124 // calculate the outer blur first
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800125 mBlurPaint.setMaskFilter(thickness == THICK ? sThickOuterBlurMaskFilter :
126 sMediumOuterBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700127 int[] outerBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800128 Bitmap thickOuterBlur = glowShape.extractAlpha(mBlurPaint, outerBlurOffset);
Joe Onorato4be866d2010-10-10 11:26:02 -0700129 mBlurPaint.setMaskFilter(sThinOuterBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700130 int[] thinOuterBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800131 Bitmap thinOuterBlur = glowShape.extractAlpha(mBlurPaint, thinOuterBlurOffset);
Winson Chung64a3cd42010-09-17 16:47:33 -0700132
133 // calculate the inner blur
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800134 srcDstCanvas.setBitmap(glowShape);
Winson Chung64a3cd42010-09-17 16:47:33 -0700135 srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800136 mBlurPaint.setMaskFilter(thickness == THICK ? sThickInnerBlurMaskFilter :
137 sMediumInnerBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700138 int[] thickInnerBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800139 Bitmap thickInnerBlur = glowShape.extractAlpha(mBlurPaint, thickInnerBlurOffset);
Winson Chung64a3cd42010-09-17 16:47:33 -0700140
141 // mask out the inner blur
142 srcDstCanvas.setBitmap(thickInnerBlur);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800143 srcDstCanvas.drawBitmap(glowShape, -thickInnerBlurOffset[0],
Winson Chung64a3cd42010-09-17 16:47:33 -0700144 -thickInnerBlurOffset[1], mErasePaint);
145 srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(),
146 mErasePaint);
147 srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1],
148 mErasePaint);
149
150 // draw the inner and outer blur
151 srcDstCanvas.setBitmap(srcDst);
152 srcDstCanvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700153 mHolographicPaint.setColor(color);
Winson Chung64a3cd42010-09-17 16:47:33 -0700154 srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
155 mHolographicPaint);
156 srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
157 mHolographicPaint);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700158
Winson Chung64a3cd42010-09-17 16:47:33 -0700159 // draw the bright outline
160 mHolographicPaint.setColor(outlineColor);
161 srcDstCanvas.drawBitmap(thinOuterBlur, thinOuterBlurOffset[0], thinOuterBlurOffset[1],
162 mHolographicPaint);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700163
Winson Chung64a3cd42010-09-17 16:47:33 -0700164 // cleanup
165 thinOuterBlur.recycle();
166 thickOuterBlur.recycle();
167 thickInnerBlur.recycle();
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800168 glowShape.recycle();
Michael Jurka5f1c5092010-09-03 14:15:02 -0700169 }
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800170
171 void applyThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
172 int outlineColor) {
173 applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, THICK);
174 }
175
176 void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
177 int outlineColor) {
178 applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, MEDIUM);
179 }
180
Winson Chung7da10252010-10-28 16:07:04 -0700181}