HolographicOutlineHelper.java revision 64a3cd4f204dd5f3676249d50aa0881b2e279b1f
15f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka/* 25f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * Copyright (C) 2008 The Android Open Source Project 35f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * 45f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 55f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * you may not use this file except in compliance with the License. 65f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * You may obtain a copy of the License at 75f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * 85f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * http://www.apache.org/licenses/LICENSE-2.0 95f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * 105f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * Unless required by applicable law or agreed to in writing, software 115f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 125f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * See the License for the specific language governing permissions and 145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * limitations under the License. 155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka */ 165f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 175f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkapackage com.android.launcher2; 185f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 195f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.Bitmap; 205f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.BlurMaskFilter; 215f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.Canvas; 225f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.Paint; 235f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.PorterDuff; 245f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkaimport android.graphics.PorterDuffXfermode; 255f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 265f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurkapublic class HolographicOutlineHelper { 275f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka private final Paint mHolographicPaint = new Paint(); 2864a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung private final Paint mExpensiveBlurPaint = new Paint(); 295f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka private final Paint mErasePaint = new Paint(); 305f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 3164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung private static final BlurMaskFilter mThickOuterBlurMaskFilter = new BlurMaskFilter(6.0f, 3264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung BlurMaskFilter.Blur.OUTER); 3364a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung private static final BlurMaskFilter mThinOuterBlurMaskFilter = new BlurMaskFilter(1.0f, 3464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung BlurMaskFilter.Blur.OUTER); 3564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung private static final BlurMaskFilter mThickInnerBlurMaskFilter = new BlurMaskFilter(4.0f, 3664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung BlurMaskFilter.Blur.NORMAL); 375f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 3864a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung public static float DEFAULT_STROKE_WIDTH = 6.0f; 3964a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung 4064a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung HolographicOutlineHelper() { 415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mHolographicPaint.setFilterBitmap(true); 425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mHolographicPaint.setAntiAlias(true); 4364a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mExpensiveBlurPaint.setFilterBitmap(true); 445f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 455f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mErasePaint.setFilterBitmap(true); 465f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mErasePaint.setAntiAlias(true); 475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 495f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka /** 505f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * Returns the interpolated holographic highlight alpha for the effect we want when scrolling 515f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * pages. 525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka */ 535f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka public float highlightAlphaInterpolator(float r) { 5464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung float maxAlpha = 0.8f; 55e8878e3c5ac2b426be931018493ce82bd9c90378Winson Chung return (float) Math.pow(maxAlpha * (1.0f - r), 1.5f); 565f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 575f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 585f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka /** 595f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka * Returns the interpolated view alpha for the effect we want when scrolling pages. 605f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka */ 615f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka public float viewAlphaInterpolator(float r) { 62e8878e3c5ac2b426be931018493ce82bd9c90378Winson Chung final float pivot = 0.95f; 635f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka if (r < pivot) { 64e8878e3c5ac2b426be931018493ce82bd9c90378Winson Chung return (float) Math.pow(r / pivot, 1.5f); 655f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } else { 665f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka return 1.0f; 675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka /** 7164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung * Applies a more expensive and accurate outline to whatever is currently drawn in a specified 7264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung * bitmap. 735f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka */ 7464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color, 7564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung int outlineColor) { 7664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // calculate the outer blur first 7764a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mExpensiveBlurPaint.setMaskFilter(mThickOuterBlurMaskFilter); 7864a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung int[] outerBlurOffset = new int[2]; 7964a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung Bitmap thickOuterBlur = srcDst.extractAlpha(mExpensiveBlurPaint, outerBlurOffset); 8064a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mExpensiveBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter); 8164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung int[] thinOuterBlurOffset = new int[2]; 8264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung Bitmap thinOuterBlur = srcDst.extractAlpha(mExpensiveBlurPaint, thinOuterBlurOffset); 835f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 8464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // calculate the inner blur 8564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT); 8664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mExpensiveBlurPaint.setMaskFilter(mThickInnerBlurMaskFilter); 8764a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung int[] thickInnerBlurOffset = new int[2]; 8864a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung Bitmap thickInnerBlur = srcDst.extractAlpha(mExpensiveBlurPaint, thickInnerBlurOffset); 895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 9064a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // mask out the inner blur 9164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.setBitmap(thickInnerBlur); 9264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawBitmap(srcDst, -thickInnerBlurOffset[0], 9364a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung -thickInnerBlurOffset[1], mErasePaint); 9464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(), 9564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mErasePaint); 9664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1], 9764a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mErasePaint); 985f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 9964a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // draw the inner and outer blur 10064a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.setBitmap(srcDst); 10164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); 10264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mHolographicPaint.setColor(color); 10364a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1], 10464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mHolographicPaint); 10564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1], 10664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mHolographicPaint); 10764a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung 10864a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // draw the bright outline 10964a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mHolographicPaint.setColor(outlineColor); 11064a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung srcDstCanvas.drawBitmap(thinOuterBlur, thinOuterBlurOffset[0], thinOuterBlurOffset[1], 11164a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung mHolographicPaint); 11264a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung 11364a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung // cleanup 11464a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung thinOuterBlur.recycle(); 11564a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung thickOuterBlur.recycle(); 11664a3cd4f204dd5f3676249d50aa0881b2e279b1fWinson Chung thickInnerBlur.recycle(); 1175f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 1185f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka}