Skip to content

Commit 305f256

Browse files
ryanlntnfacebook-github-bot
authored andcommitted
Update ColorPropConverterto support color function values (facebook#44237)
Summary: Pull Request resolved: facebook#44237 This adds support for color function values to ColorPropConverter per the wide gamut color [RFC](react-native-community/discussions-and-proposals#738). It updates the color conversion code so that it returns a Color instance before ultimately being converted to an Integer in preparation for returning long values as needed. ## Changelog: [ANDROID] [ADDED] - Update ColorPropConverter to support color function values Pull Request resolved: facebook#43031 Test Plan: Colors should work exactly the same as before. Follow test steps from facebook#42831 to test support for color() function syntax. While colors specified with color() function syntax will not yet render in DisplayP3 color space they will not be misrecognized as resource path colors but will instead fallback to their sRGB color space values. --- After the failure with the tests, I reapplied the changes and test some Jest e2e tests that were failing yesterday: {F1495277376} Differential Revision: D56517579 Pulled By: cipolleschi
1 parent c3a1ae3 commit 305f256

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ public class com/facebook/react/bridge/ColorPropConverter {
649649
public fun <init> ()V
650650
public static fun getColor (Ljava/lang/Object;Landroid/content/Context;)Ljava/lang/Integer;
651651
public static fun getColor (Ljava/lang/Object;Landroid/content/Context;I)Ljava/lang/Integer;
652+
public static fun getColorInstance (Ljava/lang/Object;Landroid/content/Context;)Landroid/graphics/Color;
652653
public static fun resolveResourcePath (Landroid/content/Context;Ljava/lang/String;)Ljava/lang/Integer;
653654
}
654655

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.java

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@
99

1010
import android.content.Context;
1111
import android.content.res.Resources;
12+
import android.graphics.Color;
13+
import android.graphics.ColorSpace;
14+
import android.os.Build;
1215
import android.util.TypedValue;
16+
import androidx.annotation.ColorLong;
1317
import androidx.annotation.Nullable;
1418
import androidx.core.content.res.ResourcesCompat;
1519
import com.facebook.common.logging.FLog;
1620
import com.facebook.react.common.ReactConstants;
1721

1822
public class ColorPropConverter {
23+
24+
private static boolean supportWideGamut() {
25+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
26+
}
27+
1928
private static final String JSON_KEY = "resource_paths";
2029
private static final String PREFIX_RESOURCE = "@";
2130
private static final String PREFIX_ATTR = "?";
@@ -24,7 +33,8 @@ public class ColorPropConverter {
2433
private static final String ATTR = "attr";
2534
private static final String ATTR_SEGMENT = "attr/";
2635

27-
public static Integer getColor(Object value, Context context) {
36+
@Nullable
37+
private static Integer getColorInteger(Object value, Context context) {
2838
if (value == null) {
2939
return null;
3040
}
@@ -39,6 +49,16 @@ public static Integer getColor(Object value, Context context) {
3949

4050
if (value instanceof ReadableMap) {
4151
ReadableMap map = (ReadableMap) value;
52+
53+
if (map.hasKey("space")) {
54+
int r = (int) ((float) map.getDouble("r") * 255);
55+
int g = (int) ((float) map.getDouble("g") * 255);
56+
int b = (int) ((float) map.getDouble("b") * 255);
57+
int a = (int) ((float) map.getDouble("a") * 255);
58+
59+
return Color.argb(a, r, g, b);
60+
}
61+
4262
ReadableArray resourcePaths = map.getArray(JSON_KEY);
4363

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

86+
@Nullable
87+
public static Color getColorInstance(Object value, Context context) {
88+
if (value == null) {
89+
return null;
90+
}
91+
92+
if (supportWideGamut() && value instanceof Double) {
93+
return Color.valueOf(((Double) value).intValue());
94+
}
95+
96+
if (context == null) {
97+
throw new RuntimeException("Context may not be null.");
98+
}
99+
100+
if (value instanceof ReadableMap) {
101+
ReadableMap map = (ReadableMap) value;
102+
103+
if (supportWideGamut() && map.hasKey("space")) {
104+
String rawColorSpace = map.getString("space");
105+
boolean isDisplayP3 = rawColorSpace != null && rawColorSpace.equals("display-p3");
106+
ColorSpace space =
107+
ColorSpace.get(isDisplayP3 ? ColorSpace.Named.DISPLAY_P3 : ColorSpace.Named.SRGB);
108+
float r = (float) map.getDouble("r");
109+
float g = (float) map.getDouble("g");
110+
float b = (float) map.getDouble("b");
111+
float a = (float) map.getDouble("a");
112+
113+
@ColorLong long color = Color.pack(r, g, b, a, space);
114+
return Color.valueOf(color);
115+
}
116+
117+
ReadableArray resourcePaths = map.getArray(JSON_KEY);
118+
if (resourcePaths == null) {
119+
throw new JSApplicationCausedNativeException(
120+
"ColorValue: The `" + JSON_KEY + "` must be an array of color resource path strings.");
121+
}
122+
123+
for (int i = 0; i < resourcePaths.size(); i++) {
124+
Integer result = resolveResourcePath(context, resourcePaths.getString(i));
125+
if (supportWideGamut() && result != null) {
126+
return Color.valueOf(result);
127+
}
128+
}
129+
130+
throw new JSApplicationCausedNativeException(
131+
"ColorValue: None of the paths in the `"
132+
+ JSON_KEY
133+
+ "` array resolved to a color resource.");
134+
}
135+
throw new JSApplicationCausedNativeException(
136+
"ColorValue: the value must be a number or Object.");
137+
}
138+
139+
public static Integer getColor(Object value, Context context) {
140+
try {
141+
if (supportWideGamut()) {
142+
Color color = getColorInstance(value, context);
143+
if (color != null) {
144+
return color.toArgb();
145+
}
146+
}
147+
} catch (JSApplicationCausedNativeException ex) {
148+
FLog.w(ReactConstants.TAG, ex, "Error extracting color from WideGamut");
149+
}
150+
return getColorInteger(value, context);
151+
}
152+
66153
public static Integer getColor(Object value, Context context, int defaultInt) {
67154
try {
68155
return getColor(value, context);

0 commit comments

Comments
 (0)