blob: bf4c05ac3c1ab01c3d88de813fe001e31884e79c [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
58 private static final MaskFilter sFineClipTable = TableMaskFilter.CreateClipTable(0, 20);
59 private static final MaskFilter sCoarseClipTable = TableMaskFilter.CreateClipTable(0, 200);
60
61 private int[] mTempOffset = new int[2];
Michael Jurka5f1c5092010-09-03 14:15:02 -070062
Winson Chung64a3cd42010-09-17 16:47:33 -070063 HolographicOutlineHelper() {
Michael Jurka5f1c5092010-09-03 14:15:02 -070064 mHolographicPaint.setFilterBitmap(true);
65 mHolographicPaint.setAntiAlias(true);
Joe Onorato4be866d2010-10-10 11:26:02 -070066 mBlurPaint.setFilterBitmap(true);
67 mBlurPaint.setAntiAlias(true);
Michael Jurka5f1c5092010-09-03 14:15:02 -070068 mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
69 mErasePaint.setFilterBitmap(true);
70 mErasePaint.setAntiAlias(true);
Adam Cohen5bb50bd2010-12-03 11:39:55 -080071 MaskFilter alphaClipTable = TableMaskFilter.CreateClipTable(180, 255);
72 mAlphaClipPaint.setMaskFilter(alphaClipTable);
Michael Jurka5f1c5092010-09-03 14:15:02 -070073 }
74
Michael Jurka5f1c5092010-09-03 14:15:02 -070075 /**
76 * Returns the interpolated holographic highlight alpha for the effect we want when scrolling
77 * pages.
78 */
79 public float highlightAlphaInterpolator(float r) {
Winson Chung64a3cd42010-09-17 16:47:33 -070080 float maxAlpha = 0.8f;
Winson Chunge8878e32010-09-15 20:37:09 -070081 return (float) Math.pow(maxAlpha * (1.0f - r), 1.5f);
Michael Jurka5f1c5092010-09-03 14:15:02 -070082 }
83
84 /**
85 * Returns the interpolated view alpha for the effect we want when scrolling pages.
86 */
87 public float viewAlphaInterpolator(float r) {
Winson Chunge8878e32010-09-15 20:37:09 -070088 final float pivot = 0.95f;
Michael Jurka5f1c5092010-09-03 14:15:02 -070089 if (r < pivot) {
Winson Chunge8878e32010-09-15 20:37:09 -070090 return (float) Math.pow(r / pivot, 1.5f);
Michael Jurka5f1c5092010-09-03 14:15:02 -070091 } else {
92 return 1.0f;
93 }
94 }
95
Patrick Dubroy8e58e912010-10-14 13:21:48 -070096 /**
97 * Apply an outer blur to the given bitmap.
98 * You should use OUTER_BLUR_RADIUS to ensure that the bitmap is big enough to draw
99 * the blur without clipping.
100 */
101 void applyOuterBlur(Bitmap bitmap, Canvas canvas, int color) {
Joe Onorato4be866d2010-10-10 11:26:02 -0700102 mBlurPaint.setMaskFilter(sThickOuterBlurMaskFilter);
103 Bitmap glow = bitmap.extractAlpha(mBlurPaint, mTempOffset);
104
105 // Use the clip table to make the glow heavier closer to the outline
106 mHolographicPaint.setMaskFilter(sCoarseClipTable);
107 mHolographicPaint.setAlpha(150);
108 mHolographicPaint.setColor(color);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800109
Joe Onorato4be866d2010-10-10 11:26:02 -0700110 canvas.drawBitmap(glow, mTempOffset[0], mTempOffset[1], mHolographicPaint);
111 glow.recycle();
112 }
113
114 /**
Winson Chung64a3cd42010-09-17 16:47:33 -0700115 * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
116 * bitmap.
Michael Jurka5f1c5092010-09-03 14:15:02 -0700117 */
Winson Chung64a3cd42010-09-17 16:47:33 -0700118 void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800119 int outlineColor, int thickness) {
120
121 // We start by removing most of the alpha channel so as to ignore shadows, and
122 // other types of partial transparency when defining the shape of the object
123 Bitmap glowShape = srcDst.extractAlpha(mAlphaClipPaint, mTempOffset);
124
Winson Chung64a3cd42010-09-17 16:47:33 -0700125 // calculate the outer blur first
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800126 mBlurPaint.setMaskFilter(thickness == THICK ? sThickOuterBlurMaskFilter :
127 sMediumOuterBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700128 int[] outerBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800129 Bitmap thickOuterBlur = glowShape.extractAlpha(mBlurPaint, outerBlurOffset);
Joe Onorato4be866d2010-10-10 11:26:02 -0700130 mBlurPaint.setMaskFilter(sThinOuterBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700131 int[] thinOuterBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800132 Bitmap thinOuterBlur = glowShape.extractAlpha(mBlurPaint, thinOuterBlurOffset);
Winson Chung64a3cd42010-09-17 16:47:33 -0700133
134 // calculate the inner blur
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800135 srcDstCanvas.setBitmap(glowShape);
Winson Chung64a3cd42010-09-17 16:47:33 -0700136 srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800137 mBlurPaint.setMaskFilter(thickness == THICK ? sThickInnerBlurMaskFilter :
138 sMediumInnerBlurMaskFilter);
Winson Chung64a3cd42010-09-17 16:47:33 -0700139 int[] thickInnerBlurOffset = new int[2];
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800140 Bitmap thickInnerBlur = glowShape.extractAlpha(mBlurPaint, thickInnerBlurOffset);
Winson Chung64a3cd42010-09-17 16:47:33 -0700141
142 // mask out the inner blur
143 srcDstCanvas.setBitmap(thickInnerBlur);
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800144 srcDstCanvas.drawBitmap(glowShape, -thickInnerBlurOffset[0],
Winson Chung64a3cd42010-09-17 16:47:33 -0700145 -thickInnerBlurOffset[1], mErasePaint);
146 srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(),
147 mErasePaint);
148 srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1],
149 mErasePaint);
150
151 // draw the inner and outer blur
152 srcDstCanvas.setBitmap(srcDst);
153 srcDstCanvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700154 mHolographicPaint.setColor(color);
Winson Chung64a3cd42010-09-17 16:47:33 -0700155 srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
156 mHolographicPaint);
157 srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
158 mHolographicPaint);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700159
Winson Chung64a3cd42010-09-17 16:47:33 -0700160 // draw the bright outline
161 mHolographicPaint.setColor(outlineColor);
162 srcDstCanvas.drawBitmap(thinOuterBlur, thinOuterBlurOffset[0], thinOuterBlurOffset[1],
163 mHolographicPaint);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700164
Winson Chung64a3cd42010-09-17 16:47:33 -0700165 // cleanup
166 thinOuterBlur.recycle();
167 thickOuterBlur.recycle();
168 thickInnerBlur.recycle();
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800169 glowShape.recycle();
Michael Jurka5f1c5092010-09-03 14:15:02 -0700170 }
Adam Cohen5bb50bd2010-12-03 11:39:55 -0800171
172 void applyThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
173 int outlineColor) {
174 applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, THICK);
175 }
176
177 void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
178 int outlineColor) {
179 applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, MEDIUM);
180 }
181
Winson Chung7da10252010-10-28 16:07:04 -0700182}