166 lines
6.3 KiB
Java
166 lines
6.3 KiB
Java
package androidx.appcompat.widget;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.graphics.Insets;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.graphics.drawable.DrawableContainer;
|
|
import android.graphics.drawable.ScaleDrawable;
|
|
import android.os.Build;
|
|
import android.util.Log;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.appcompat.graphics.drawable.DrawableWrapper;
|
|
import androidx.core.graphics.drawable.DrawableCompat;
|
|
import androidx.core.graphics.drawable.WrappedDrawable;
|
|
import java.lang.reflect.Field;
|
|
@SuppressLint({"RestrictedAPI"})
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public class DrawableUtils {
|
|
private static final int[] CHECKED_STATE_SET = {16842912};
|
|
private static final int[] EMPTY_STATE_SET = new int[0];
|
|
public static final Rect INSETS_NONE = new Rect();
|
|
private static final String TAG = "DrawableUtils";
|
|
private static final String VECTOR_DRAWABLE_CLAZZ_NAME = "android.graphics.drawable.VectorDrawable";
|
|
private static Class<?> sInsetsClazz;
|
|
|
|
static {
|
|
try {
|
|
sInsetsClazz = Class.forName("android.graphics.Insets");
|
|
} catch (ClassNotFoundException unused) {
|
|
}
|
|
}
|
|
|
|
private DrawableUtils() {
|
|
}
|
|
|
|
public static boolean canSafelyMutateDrawable(@NonNull Drawable drawable) {
|
|
if (drawable instanceof DrawableContainer) {
|
|
Drawable.ConstantState constantState = drawable.getConstantState();
|
|
if (!(constantState instanceof DrawableContainer.DrawableContainerState)) {
|
|
return true;
|
|
}
|
|
for (Drawable drawable2 : ((DrawableContainer.DrawableContainerState) constantState).getChildren()) {
|
|
if (!canSafelyMutateDrawable(drawable2)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
} else if (drawable instanceof WrappedDrawable) {
|
|
return canSafelyMutateDrawable(((WrappedDrawable) drawable).getWrappedDrawable());
|
|
} else {
|
|
if (drawable instanceof DrawableWrapper) {
|
|
return canSafelyMutateDrawable(((DrawableWrapper) drawable).getWrappedDrawable());
|
|
}
|
|
if (drawable instanceof ScaleDrawable) {
|
|
return canSafelyMutateDrawable(((ScaleDrawable) drawable).getDrawable());
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static void fixDrawable(@NonNull Drawable drawable) {
|
|
if (Build.VERSION.SDK_INT == 21 && VECTOR_DRAWABLE_CLAZZ_NAME.equals(drawable.getClass().getName())) {
|
|
fixVectorDrawableTinting(drawable);
|
|
}
|
|
}
|
|
|
|
private static void fixVectorDrawableTinting(Drawable drawable) {
|
|
int[] state = drawable.getState();
|
|
if (state == null || state.length == 0) {
|
|
drawable.setState(CHECKED_STATE_SET);
|
|
} else {
|
|
drawable.setState(EMPTY_STATE_SET);
|
|
}
|
|
drawable.setState(state);
|
|
}
|
|
|
|
public static Rect getOpticalBounds(Drawable drawable) {
|
|
if (Build.VERSION.SDK_INT >= 29) {
|
|
Insets opticalInsets = drawable.getOpticalInsets();
|
|
Rect rect = new Rect();
|
|
rect.left = opticalInsets.left;
|
|
rect.right = opticalInsets.right;
|
|
rect.top = opticalInsets.top;
|
|
rect.bottom = opticalInsets.bottom;
|
|
return rect;
|
|
}
|
|
if (sInsetsClazz != null) {
|
|
try {
|
|
Drawable unwrap = DrawableCompat.unwrap(drawable);
|
|
Object invoke = unwrap.getClass().getMethod("getOpticalInsets", new Class[0]).invoke(unwrap, new Object[0]);
|
|
if (invoke != null) {
|
|
Rect rect2 = new Rect();
|
|
Field[] fields = sInsetsClazz.getFields();
|
|
for (Field field : fields) {
|
|
String name = field.getName();
|
|
char c2 = 65535;
|
|
switch (name.hashCode()) {
|
|
case -1383228885:
|
|
if (name.equals("bottom")) {
|
|
c2 = 3;
|
|
break;
|
|
}
|
|
break;
|
|
case 115029:
|
|
if (name.equals("top")) {
|
|
c2 = 1;
|
|
break;
|
|
}
|
|
break;
|
|
case 3317767:
|
|
if (name.equals("left")) {
|
|
c2 = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case 108511772:
|
|
if (name.equals("right")) {
|
|
c2 = 2;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
if (c2 == 0) {
|
|
rect2.left = field.getInt(invoke);
|
|
} else if (c2 == 1) {
|
|
rect2.top = field.getInt(invoke);
|
|
} else if (c2 == 2) {
|
|
rect2.right = field.getInt(invoke);
|
|
} else if (c2 == 3) {
|
|
rect2.bottom = field.getInt(invoke);
|
|
}
|
|
}
|
|
return rect2;
|
|
}
|
|
} catch (Exception unused) {
|
|
Log.e(TAG, "Couldn't obtain the optical insets. Ignoring.");
|
|
}
|
|
}
|
|
return INSETS_NONE;
|
|
}
|
|
|
|
public static PorterDuff.Mode parseTintMode(int i, PorterDuff.Mode mode) {
|
|
if (i == 3) {
|
|
return PorterDuff.Mode.SRC_OVER;
|
|
}
|
|
if (i == 5) {
|
|
return PorterDuff.Mode.SRC_IN;
|
|
}
|
|
if (i == 9) {
|
|
return PorterDuff.Mode.SRC_ATOP;
|
|
}
|
|
switch (i) {
|
|
case 14:
|
|
return PorterDuff.Mode.MULTIPLY;
|
|
case 15:
|
|
return PorterDuff.Mode.SCREEN;
|
|
case 16:
|
|
return PorterDuff.Mode.ADD;
|
|
default:
|
|
return mode;
|
|
}
|
|
}
|
|
}
|