package com.aviary.android.feather.graphics;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable.Orientation;
/**
* Draw a linear gradient.
*
* @author alessandro
*/
public class LinearGradientDrawable extends Drawable {
private final Paint mFillPaint = new Paint( Paint.ANTI_ALIAS_FLAG );
private float mCornerRadius = 0;
private boolean mRectIsDirty = true;
private int mAlpha = 0xFF; // modified by the caller
private boolean mDither = true;
private ColorFilter mColorFilter;
private Orientation mOrientation = Orientation.LEFT_RIGHT;
private int[] mColors;
private float[] mPositions;
private final RectF mRect = new RectF();
/**
* Instantiates a new linear gradient drawable.
*
* @param orientation
* the orientation
* @param colors
* the colors
* @param positions
* the positions
*/
public LinearGradientDrawable( Orientation orientation, int[] colors, float[] positions ) {
mOrientation = orientation;
mColors = colors;
mPositions = positions;
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#draw(android.graphics.Canvas)
*/
@Override
public void draw( Canvas canvas ) {
if ( !ensureValidRect() ) return;
mFillPaint.setAlpha( mAlpha );
mFillPaint.setDither( mDither );
mFillPaint.setColorFilter( mColorFilter );
if ( mCornerRadius > 0 ) {
float rad = mCornerRadius;
float r = Math.min( mRect.width(), mRect.height() ) * 0.5f;
if ( rad > r ) {
rad = r;
}
canvas.drawRoundRect( mRect, rad, rad, mFillPaint );
} else {
canvas.drawRect( mRect, mFillPaint );
}
}
/**
* Ensure valid rect.
*
* @return true, if successful
*/
private boolean ensureValidRect() {
if ( mRectIsDirty ) {
mRectIsDirty = false;
Rect bounds = getBounds();
float inset = 0;
mRect.set( bounds.left + inset, bounds.top + inset, bounds.right - inset, bounds.bottom - inset );
final int[] colors = mColors;
if ( colors != null ) {
RectF r = mRect;
float x0, x1, y0, y1;
final float level = 1.0f;
switch ( mOrientation ) {
case TOP_BOTTOM:
x0 = r.left;
y0 = r.top;
x1 = x0;
y1 = level * r.bottom;
break;
case TR_BL:
x0 = r.right;
y0 = r.top;
x1 = level * r.left;
y1 = level * r.bottom;
break;
case RIGHT_LEFT:
x0 = r.right;
y0 = r.top;
x1 = level * r.left;
y1 = y0;
break;
case BR_TL:
x0 = r.right;
y0 = r.bottom;
x1 = level * r.left;
y1 = level * r.top;
break;
case BOTTOM_TOP:
x0 = r.left;
y0 = r.bottom;
x1 = x0;
y1 = level * r.top;
break;
case BL_TR:
x0 = r.left;
y0 = r.bottom;
x1 = level * r.right;
y1 = level * r.top;
break;
case LEFT_RIGHT:
x0 = r.left;
y0 = r.top;
x1 = level * r.right;
y1 = y0;
break;
default:/* TL_BR */
x0 = r.left;
y0 = r.top;
x1 = level * r.right;
y1 = level * r.bottom;
break;
}
mFillPaint.setShader( new LinearGradient( x0, y0, x1, y1, colors, mPositions, Shader.TileMode.CLAMP ) );
}
}
return !mRect.isEmpty();
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#onBoundsChange(android.graphics.Rect)
*/
@Override
protected void onBoundsChange( Rect r ) {
super.onBoundsChange( r );
mRectIsDirty = true;
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#getOpacity()
*/
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#setAlpha(int)
*/
@Override
public void setAlpha( int alpha ) {
if ( alpha != mAlpha ) {
mAlpha = alpha;
invalidateSelf();
}
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#setDither(boolean)
*/
@Override
public void setDither( boolean dither ) {
if ( dither != mDither ) {
mDither = dither;
invalidateSelf();
}
}
/*
* (non-Javadoc)
*
* @see android.graphics.drawable.Drawable#setColorFilter(android.graphics.ColorFilter)
*/
@Override
public void setColorFilter( ColorFilter cf ) {
if ( cf != mColorFilter ) {
mColorFilter = cf;
invalidateSelf();
}
}
/**
* Sets the corner radius.
*
* @param radius
* the new corner radius
*/
public void setCornerRadius( float radius ) {
mCornerRadius = radius;
invalidateSelf();
}
}