package carbon.drawable;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.SparseArray;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
public class VectorDrawable extends Drawable implements AlphaDrawable {
private VectorState state;
private Bitmap bitmap;
private ColorStateList tint = ColorStateList.valueOf(0x00ffffff); // TODO: maybe tint should be a part of VectorState?
private static SparseArray<SVG> cache = new SparseArray<>();
public static void clearCache() {
cache.clear();
}
public VectorDrawable(SVG svg, int intWidth, int intHeight) {
state = new VectorState(svg, intWidth, intHeight);
setBounds(0, 0, state.intWidth, state.intHeight);
}
public VectorDrawable(Resources res, int resId) {
if (resId == 0)
return;
try {
SVG svg = cache.get(resId);
if (svg == null) {
svg = SVG.getFromResource(res, resId);
cache.put(resId, svg);
}
float density = res.getDisplayMetrics().density;
float width = svg.getDocumentViewBox().width();
float height = svg.getDocumentViewBox().height();
int intWidth = (int) (width * density);
int intHeight = (int) (height * density);
state = new VectorState(svg, intWidth, intHeight);
setBounds(0, 0, state.intWidth, state.intHeight);
} catch (SVGParseException e) {
}
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
int width = right - left;
int height = bottom - top;
if (state.svg == null || width == 0 || height == 0 || (bitmap != null && bitmap.getWidth() == width && bitmap.getHeight() == height))
return;
state.svg.setDocumentWidth(width);
state.svg.setDocumentHeight(height);
bitmap = null;
super.setBounds(left, top, right, bottom);
}
@Override
public void draw(@NonNull Canvas canvas) {
int width = getBounds().width();
int height = getBounds().height();
if (width <= 0 || height <= 0)
return;
if (bitmap == null) {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
state.svg.renderToCanvas(new Canvas(bitmap));
}
canvas.drawBitmap(bitmap, getBounds().left, getBounds().top, state.paint);
}
@Override
public void setAlpha(int alpha) {
state.paint.setAlpha(alpha);
}
@Override
public int getAlpha() {
return state.paint.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
state.paint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicWidth() {
return state.intWidth;
}
@Override
public int getIntrinsicHeight() {
return state.intHeight;
}
@Override
public ConstantState getConstantState() {
return state;
}
@NonNull
@Override
public Drawable mutate() {
return new VectorDrawable(state.svg, state.intWidth, state.intHeight);
}
private class VectorState extends ConstantState {
SVG svg;
private Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
int intWidth, intHeight;
public VectorState(SVG svg, int intWidth, int intHeight) {
this.svg = svg;
this.intWidth = intWidth;
this.intHeight = intHeight;
}
public VectorState(VectorState state) {
svg = state.svg;
intWidth = state.intWidth;
intHeight = state.intHeight;
paint = state.paint;
}
@NonNull
@Override
public Drawable newDrawable() {
return new VectorDrawable(svg, intWidth, intHeight);
}
@Override
public int getChangingConfigurations() {
return 0;
}
}
@Override
public void setTint(int tintColor) {
tint = ColorStateList.valueOf(tintColor);
state.paint.setColorFilter(new LightingColorFilter(0, tint.getColorForState(getState(), tint.getDefaultColor())));
}
@Override
public void setTintList(ColorStateList tint) {
this.tint = tint;
state.paint.setColorFilter(new LightingColorFilter(0, tint.getColorForState(getState(), tint.getDefaultColor())));
}
@Override
public boolean setState(@NonNull int[] stateSet) {
boolean changed = super.setState(stateSet);
if (changed)
state.paint.setColorFilter(new LightingColorFilter(0, tint.getColorForState(getState(), tint.getDefaultColor())));
return changed;
}
}