Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ public class com/facebook/react/bridge/ColorPropConverter {
public fun <init> ()V
public static fun getColor (Ljava/lang/Object;Landroid/content/Context;)Ljava/lang/Integer;
public static fun getColor (Ljava/lang/Object;Landroid/content/Context;I)Ljava/lang/Integer;
public static fun getColorInstance (Ljava/lang/Object;Landroid/content/Context;)Landroid/graphics/Color;
public static fun resolveResourcePath (Landroid/content/Context;Ljava/lang/String;)Ljava/lang/Integer;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.ColorSpace;
import android.os.Build;
import android.util.TypedValue;
import androidx.annotation.ColorLong;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import com.facebook.common.logging.FLog;
import com.facebook.react.common.ReactConstants;

public class ColorPropConverter {

private static boolean supportWideGamut() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}

private static final String JSON_KEY = "resource_paths";
private static final String PREFIX_RESOURCE = "@";
private static final String PREFIX_ATTR = "?";
Expand All @@ -24,7 +33,8 @@ public class ColorPropConverter {
private static final String ATTR = "attr";
private static final String ATTR_SEGMENT = "attr/";

public static Integer getColor(Object value, Context context) {
@Nullable
private static Integer getColorInteger(Object value, Context context) {
if (value == null) {
return null;
}
Expand All @@ -39,6 +49,16 @@ public static Integer getColor(Object value, Context context) {

if (value instanceof ReadableMap) {
ReadableMap map = (ReadableMap) value;

if (map.hasKey("space")) {
int r = (int) ((float) map.getDouble("r") * 255);
int g = (int) ((float) map.getDouble("g") * 255);
int b = (int) ((float) map.getDouble("b") * 255);
int a = (int) ((float) map.getDouble("a") * 255);

return Color.argb(a, r, g, b);
}

ReadableArray resourcePaths = map.getArray(JSON_KEY);

if (resourcePaths == null) {
Expand All @@ -63,6 +83,73 @@ public static Integer getColor(Object value, Context context) {
"ColorValue: the value must be a number or Object.");
}

@Nullable
public static Color getColorInstance(Object value, Context context) {
if (value == null) {
return null;
}

if (supportWideGamut() && value instanceof Double) {
return Color.valueOf(((Double) value).intValue());
}

if (context == null) {
throw new RuntimeException("Context may not be null.");
}

if (value instanceof ReadableMap) {
ReadableMap map = (ReadableMap) value;

if (supportWideGamut() && map.hasKey("space")) {
String rawColorSpace = map.getString("space");
boolean isDisplayP3 = rawColorSpace != null && rawColorSpace.equals("display-p3");
ColorSpace space =
ColorSpace.get(isDisplayP3 ? ColorSpace.Named.DISPLAY_P3 : ColorSpace.Named.SRGB);
float r = (float) map.getDouble("r");
float g = (float) map.getDouble("g");
float b = (float) map.getDouble("b");
float a = (float) map.getDouble("a");

@ColorLong long color = Color.pack(r, g, b, a, space);
return Color.valueOf(color);
}

ReadableArray resourcePaths = map.getArray(JSON_KEY);
if (resourcePaths == null) {
throw new JSApplicationCausedNativeException(
"ColorValue: The `" + JSON_KEY + "` must be an array of color resource path strings.");
}

for (int i = 0; i < resourcePaths.size(); i++) {
Integer result = resolveResourcePath(context, resourcePaths.getString(i));
if (supportWideGamut() && result != null) {
return Color.valueOf(result);
}
}

throw new JSApplicationCausedNativeException(
"ColorValue: None of the paths in the `"
+ JSON_KEY
+ "` array resolved to a color resource.");
}
throw new JSApplicationCausedNativeException(
"ColorValue: the value must be a number or Object.");
}

public static Integer getColor(Object value, Context context) {
try {
if (supportWideGamut()) {
Color color = getColorInstance(value, context);
if (color != null) {
return color.toArgb();
}
}
} catch (JSApplicationCausedNativeException ex) {
FLog.w(ReactConstants.TAG, ex, "Error extracting color from WideGamut");
}
return getColorInteger(value, context);
}

public static Integer getColor(Object value, Context context, int defaultInt) {
try {
return getColor(value, context);
Expand Down