mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-04-28 20:27:58 +03:00
318 lines
9 KiB
Java
318 lines
9 KiB
Java
package android.graphics.drawable;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.Arrays;
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
import android.content.res.ColorStateList;
|
|
import android.content.res.Resources;
|
|
import android.content.res.XmlResourceParser;
|
|
import android.content.res.Resources.Theme;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Color;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.GskCanvas;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffColorFilter;
|
|
import android.graphics.Rect;
|
|
import android.util.AttributeSet;
|
|
import android.util.TypedValue;
|
|
|
|
public class Drawable {
|
|
public static interface Callback {
|
|
public void invalidateDrawable(Drawable drawable);
|
|
public void scheduleDrawable(Drawable drawable, Runnable runnable, long time);
|
|
public void unscheduleDrawable(Drawable drawable, Runnable runnable);
|
|
}
|
|
|
|
static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
|
|
|
|
private Rect mBounds = new Rect();
|
|
private int[] mStateSet = new int[0];
|
|
public long paintable;
|
|
|
|
private Callback callback = null;
|
|
|
|
public Drawable() {
|
|
this.paintable = native_constructor();
|
|
}
|
|
|
|
public Drawable(long paintable) {
|
|
this.paintable = paintable;
|
|
}
|
|
|
|
public int getChangingConfigurations() {
|
|
return 0;
|
|
}
|
|
|
|
public void setChangingConfigurations(int bitmap) {}
|
|
|
|
public ConstantState getConstantState() {
|
|
return new ConstantState() {
|
|
|
|
@Override
|
|
public Drawable newDrawable(Resources res) {
|
|
return Drawable.this;
|
|
}
|
|
|
|
@Override
|
|
public Drawable newDrawable() {
|
|
return Drawable.this;
|
|
}
|
|
|
|
@Override
|
|
public int getChangingConfigurations() {
|
|
return Drawable.this.getChangingConfigurations();
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
public static abstract class ConstantState {
|
|
|
|
public abstract Drawable newDrawable(Resources res);
|
|
|
|
public abstract Drawable newDrawable();
|
|
|
|
public abstract int getChangingConfigurations();
|
|
}
|
|
|
|
public void setBounds(int left, int top, int right, int bottom) {
|
|
boolean changed = left != mBounds.left || top != mBounds.top || right != mBounds.right || bottom != mBounds.bottom;
|
|
mBounds.set(left, top, right, bottom);
|
|
if (changed)
|
|
onBoundsChange(mBounds);
|
|
}
|
|
|
|
public final Rect getBounds() {
|
|
return mBounds;
|
|
}
|
|
|
|
public void draw(Canvas canvas) {
|
|
if (canvas instanceof GskCanvas) {
|
|
if (mBounds.left != 0 || mBounds.top != 0)
|
|
canvas.translate(mBounds.left, mBounds.top);
|
|
native_draw(paintable, ((GskCanvas)canvas).snapshot, mBounds.width(), mBounds.height());
|
|
if (mBounds.left != 0 || mBounds.top != 0)
|
|
canvas.translate(-mBounds.left, -mBounds.top);
|
|
}
|
|
}
|
|
|
|
public boolean setState(int[] stateSet) {
|
|
if (!Arrays.equals(this.mStateSet, stateSet)) {
|
|
this.mStateSet = stateSet;
|
|
return onStateChange(stateSet);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int[] getState() {
|
|
return mStateSet;
|
|
}
|
|
|
|
public void setCallback(Callback callback) {
|
|
this.callback = callback;
|
|
}
|
|
|
|
public Callback getCallback() {
|
|
return this.callback;
|
|
}
|
|
|
|
public void invalidateSelf() {
|
|
native_invalidate(paintable);
|
|
|
|
/* this shouldn't ever be needed with Gtk, but let's play it safe for now */
|
|
if (this.callback != null) {
|
|
callback.invalidateDrawable(this);
|
|
}
|
|
}
|
|
|
|
public void scheduleSelf(Runnable runnable, long time) {
|
|
if (this.callback != null) {
|
|
callback.scheduleDrawable(this, runnable, time);
|
|
}
|
|
}
|
|
|
|
public void unscheduleSelf(Runnable runnable) {
|
|
if (this.callback != null) {
|
|
callback.unscheduleDrawable(this, runnable);
|
|
}
|
|
}
|
|
|
|
public boolean isVisible() {
|
|
return false;
|
|
}
|
|
|
|
public boolean setVisible (boolean visible, boolean restart) {
|
|
return false;
|
|
}
|
|
|
|
public void clearColorFilter() {}
|
|
|
|
public final int getLevel() {return 0;}
|
|
public final boolean setLevel(int level) {return false;}
|
|
|
|
public void setBounds(Rect bounds) {
|
|
setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
|
}
|
|
|
|
public void setColorFilter(int color, PorterDuff.Mode mode) {
|
|
setColorFilter(new PorterDuffColorFilter(color, mode));
|
|
}
|
|
public void setColorFilter(ColorFilter filter) {}
|
|
|
|
public Drawable mutate() {
|
|
return this;
|
|
}
|
|
|
|
public int getIntrinsicWidth() {return -1;}
|
|
public int getIntrinsicHeight() {return -1;}
|
|
|
|
public void setTintList(ColorStateList tint) {}
|
|
|
|
public void setTint(int tint) {
|
|
setTintList(ColorStateList.valueOf(tint));
|
|
}
|
|
|
|
PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint, PorterDuff.Mode tintMode) {
|
|
System.out.println("updateTintFilter("+tintFilter+", "+tint+", "+tintMode+")");
|
|
if (tint == null || tintMode == null) {
|
|
return null;
|
|
}
|
|
final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
|
|
if (tintFilter == null || tintFilter.getColor() != color || tintFilter.getMode() != tintMode) {
|
|
return new PorterDuffColorFilter(color, tintMode);
|
|
}
|
|
return tintFilter;
|
|
}
|
|
|
|
public boolean isStateful() {
|
|
return false;
|
|
}
|
|
|
|
public void setTintMode(PorterDuff.Mode tintMode) {}
|
|
|
|
public boolean isProjected () {return false;}
|
|
|
|
public static Drawable createFromXml(Resources resources, XmlResourceParser parser) throws XmlPullParserException, IOException {
|
|
int type;
|
|
while ((type=parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
|
|
if (type != XmlPullParser.START_TAG)
|
|
throw new XmlPullParserException("No start tag found");
|
|
|
|
return createFromXmlInner(resources, parser, parser, null);
|
|
}
|
|
|
|
public static Drawable createFromXmlInner(Resources resources, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
|
|
return createFromXmlInner(resources, parser, attrs, null);
|
|
}
|
|
|
|
public static Drawable createFromXmlInner(Resources resources, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
|
|
if ("selector".equals(parser.getName())) {
|
|
StateListDrawable drawable = new StateListDrawable();
|
|
drawable.inflate(resources, parser, attrs, null);
|
|
return drawable;
|
|
} else if ("shape".equals(parser.getName())) {
|
|
GradientDrawable drawable = new GradientDrawable();
|
|
drawable.inflate(resources, parser, attrs);
|
|
return drawable;
|
|
} else if ("bitmap".equals(parser.getName())) {
|
|
BitmapDrawable drawable = new BitmapDrawable();
|
|
drawable.inflate(resources, parser, attrs, null);
|
|
return drawable;
|
|
} else if ("transition".equals(parser.getName())) {
|
|
return new Drawable();
|
|
} else if ("ripple".equals(parser.getName())) {
|
|
// FIXME: the non-pressed state of RippleDrawable should be equivalent to this
|
|
return new ColorDrawable(0);
|
|
} else if ("vector".equals(parser.getName())) {
|
|
VectorDrawable drawable = new VectorDrawable();
|
|
drawable.inflate(resources, parser, attrs, null);
|
|
return drawable;
|
|
} else if ("layer-list".equals(parser.getName())) {
|
|
LayerDrawable drawable = new LayerDrawable();
|
|
drawable.inflate(resources, parser, attrs);
|
|
return drawable;
|
|
} else if ("nine-patch".equals(parser.getName())) {
|
|
return new NinePatchDrawable(resources, null, null, null, null);
|
|
} else if ("animation-list".equals(parser.getName())) {
|
|
return new AnimationDrawable();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Drawable createFromResourceStream(Resources resources, TypedValue value, InputStream is, String file,
|
|
Object object) {
|
|
if (!file.endsWith(".9.png")) {
|
|
return new BitmapDrawable(resources, BitmapFactory.decodeStream(is));
|
|
}
|
|
Path path = Paths.get(android.os.Environment.getExternalStorageDirectory().getPath(), file);
|
|
if (!Files.exists(path)) {
|
|
try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(file)) {
|
|
if (inputStream != null) {
|
|
Files.createDirectories(path.getParent());
|
|
Files.copy(inputStream, path);
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
long paintable = native_paintable_from_path(path.toString());
|
|
return new Drawable(paintable);
|
|
}
|
|
|
|
public static Drawable createFromPath(String path) {
|
|
if (path == null)
|
|
return null;
|
|
|
|
long paintable = native_paintable_from_path(path);
|
|
return new Drawable(paintable);
|
|
}
|
|
|
|
protected boolean onStateChange(int[] stateSet) {
|
|
return false;
|
|
}
|
|
|
|
public void setAlpha(int alpha) {}
|
|
|
|
public boolean getPadding(Rect padding) {
|
|
return false;
|
|
}
|
|
|
|
public void copyBounds(Rect bounds) {
|
|
bounds.set(mBounds);
|
|
}
|
|
|
|
public int getMinimumWidth() {
|
|
return 10; // FIXME
|
|
}
|
|
public int getMinimumHeight() {
|
|
return 10; // FIXME
|
|
}
|
|
|
|
protected void onBoundsChange(Rect bounds) {}
|
|
|
|
public void setDither(boolean dither) {}
|
|
|
|
public void setAutoMirrored(boolean mirrored) {}
|
|
|
|
public void jumpToCurrentState() {}
|
|
|
|
public boolean setLayoutDirection(int layoutDirection) {
|
|
return false;
|
|
}
|
|
|
|
public void setHotspot(float x, float y) {}
|
|
|
|
protected static native long native_paintable_from_path(String path);
|
|
protected native long native_constructor();
|
|
protected native void native_invalidate(long paintable);
|
|
protected native void native_draw(long paintable, long snapshot, int width, int height);
|
|
}
|