CircularBitmapDrawable.java revision ad6ca3f895022ded1a11f3eedc50d70ea90cd4da
1/* 2 * Copyright (C) 2014 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.bitmap.drawable; 18 19import android.content.res.Resources; 20import android.graphics.Bitmap; 21import android.graphics.BitmapShader; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.graphics.ColorFilter; 25import android.graphics.Matrix; 26import android.graphics.Paint; 27import android.graphics.Paint.Style; 28import android.graphics.Rect; 29import android.graphics.Shader.TileMode; 30 31import com.android.bitmap.BitmapCache; 32 33/** 34 * Custom BasicBitmapDrawable implementation for circular images. 35 * 36 * This draws all bitmaps as a circle with an optional border stroke. 37 */ 38public class CircularBitmapDrawable extends BasicBitmapDrawable { 39 private static Matrix sMatrix = new Matrix(); 40 41 private final Paint mBitmapPaint = new Paint(); 42 private final Paint mBorderPaint = new Paint(); 43 44 private float mBorderWidth; 45 46 public CircularBitmapDrawable(Resources res, 47 BitmapCache cache, boolean limitDensity) { 48 super(res, cache, limitDensity); 49 50 mBitmapPaint.setAntiAlias(true); 51 mBitmapPaint.setFilterBitmap(true); 52 mBitmapPaint.setDither(true); 53 54 mBorderPaint.setColor(Color.TRANSPARENT); 55 mBorderPaint.setStyle(Style.STROKE); 56 mBorderPaint.setStrokeWidth(mBorderWidth); 57 mBorderPaint.setAntiAlias(true); 58 } 59 60 /** 61 * Set the border stroke width of this drawable. 62 */ 63 public void setBorderWidth(final float borderWidth) { 64 final boolean changed = mBorderPaint.getStrokeWidth() != borderWidth; 65 mBorderPaint.setStrokeWidth(borderWidth); 66 mBorderWidth = borderWidth; 67 68 if (changed) { 69 invalidateSelf(); 70 } 71 } 72 73 /** 74 * Set the border stroke color of this drawable. Set to {@link Color#TRANSPARENT} to disable. 75 */ 76 public void setBorderColor(final int color) { 77 final boolean changed = mBorderPaint.getColor() != color; 78 mBorderPaint.setColor(color); 79 80 if (changed) { 81 invalidateSelf(); 82 } 83 } 84 85 @Override 86 protected void onDrawBitmap(final Canvas canvas, final Rect src, 87 final Rect dst) { 88 onDrawCircularBitmap(getBitmap().bmp, canvas, src, dst); 89 } 90 91 /** 92 * Call this method with a given bitmap to draw it onto the given canvas, masked by a circular 93 * BitmapShader. 94 */ 95 protected void onDrawCircularBitmap(final Bitmap bitmap, final Canvas canvas, 96 final Rect src, final Rect dst) { 97 // Draw bitmap through shader first. 98 BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, 99 TileMode.CLAMP); 100 sMatrix.reset(); 101 102 // Fit bitmap to bounds. 103 float scale = Math.max((float) dst.width() / src.width(), 104 (float) dst.height() / src.height()); 105 sMatrix.postScale(scale, scale); 106 107 // Translate bitmap to dst bounds. 108 sMatrix.postTranslate(dst.left, dst.top); 109 110 shader.setLocalMatrix(sMatrix); 111 mBitmapPaint.setShader(shader); 112 canvas.drawCircle(dst.centerX(), dst.centerY(), dst.width() / 2, 113 mBitmapPaint); 114 115 // Then draw the border. 116 canvas.drawCircle(dst.centerX(), dst.centerY(), 117 dst.width() / 2f - mBorderWidth / 2, mBorderPaint); 118 } 119 120 @Override 121 public void setAlpha(int alpha) { 122 super.setAlpha(alpha); 123 124 final int old = mBitmapPaint.getAlpha(); 125 mBitmapPaint.setAlpha(alpha); 126 if (alpha != old) { 127 invalidateSelf(); 128 } 129 } 130 131 @Override 132 public void setColorFilter(ColorFilter cf) { 133 super.setColorFilter(cf); 134 mPaint.setColorFilter(cf); 135 } 136} 137