diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.java
index 237fc3ff7bb5c1..ccbf3af90bec71 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.java
@@ -9,13 +9,16 @@
import android.content.res.AssetManager;
import android.graphics.Typeface;
+import android.os.Build;
import android.text.TextUtils;
import androidx.annotation.Nullable;
+import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.ReadableArray;
import java.util.ArrayList;
import java.util.List;
public class ReactTypefaceUtils {
+ private static final String TAG = "ReactTypefaceUtils";
public static final int UNSET = -1;
public static int parseFontWeight(@Nullable String fontWeightString) {
@@ -23,8 +26,8 @@ public static int parseFontWeight(@Nullable String fontWeightString) {
fontWeightString != null ? parseNumericFontWeight(fontWeightString) : UNSET;
int fontWeight = fontWeightNumeric != UNSET ? fontWeightNumeric : Typeface.NORMAL;
- if (fontWeight == 700 || "bold".equals(fontWeightString)) fontWeight = Typeface.BOLD;
- else if (fontWeight == 400 || "normal".equals(fontWeightString)) fontWeight = Typeface.NORMAL;
+ if ("bold".equals(fontWeightString)) fontWeight = Typeface.BOLD;
+ else if ("normal".equals(fontWeightString)) fontWeight = Typeface.NORMAL;
return fontWeight;
}
@@ -81,34 +84,50 @@ public static Typeface applyStyles(
AssetManager assetManager) {
int oldStyle;
if (typeface == null) {
- oldStyle = 0;
+ oldStyle = Typeface.NORMAL;
} else {
oldStyle = typeface.getStyle();
}
- int want = 0;
- if ((weight == Typeface.BOLD)
- || ((oldStyle & Typeface.BOLD) != 0 && weight == ReactTextShadowNode.UNSET)) {
- want |= Typeface.BOLD;
+ int newStyle = oldStyle;
+ boolean italic = false;
+ if (weight == UNSET) weight = Typeface.NORMAL;
+ if (style == Typeface.ITALIC) italic = true;
+ boolean UNDER_SDK_28 = Build.VERSION.SDK_INT < Build.VERSION_CODES.P;
+ boolean applyNumericValues = !(weight < (Typeface.BOLD_ITALIC + 1) || family != null);
+ boolean numericBold = UNDER_SDK_28 && weight > 699 && applyNumericValues;
+ boolean numericNormal = UNDER_SDK_28 && weight < 700 && applyNumericValues;
+ if (weight == Typeface.BOLD) {
+ newStyle = (newStyle == Typeface.ITALIC) ? Typeface.BOLD_ITALIC : Typeface.BOLD;
+ typeface = Typeface.create(typeface, newStyle);
}
-
- if ((style == Typeface.ITALIC)
- || ((oldStyle & Typeface.ITALIC) != 0 && style == ReactTextShadowNode.UNSET)) {
- want |= Typeface.ITALIC;
+ if (weight == Typeface.NORMAL) {
+ typeface = Typeface.create(typeface, Typeface.NORMAL);
+ newStyle = Typeface.NORMAL;
+ }
+ if (style == Typeface.ITALIC) {
+ newStyle = (newStyle == Typeface.BOLD) ? Typeface.BOLD_ITALIC : Typeface.ITALIC;
+ typeface = Typeface.create(typeface, newStyle);
+ }
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1 && weight > Typeface.BOLD_ITALIC) {
+ typeface = Typeface.create(typeface, weight, italic);
+ }
+ if (family != null && UNDER_SDK_28 && weight > Typeface.BOLD_ITALIC) {
+ FLog.d(
+ TAG,
+ "Support for numeric font weight numeric values with custom fonts under Android API 28 Pie is not yet supported in ReactNative.");
}
-
if (family != null) {
- typeface = ReactFontManager.getInstance().getTypeface(family, want, weight, assetManager);
- } else if (typeface != null) {
- // TODO(t9055065): Fix custom fonts getting applied to text children with different style
- typeface = Typeface.create(typeface, want);
+ typeface = ReactFontManager.getInstance().getTypeface(family, newStyle, weight, assetManager);
}
-
- if (typeface != null) {
- return typeface;
- } else {
- return Typeface.defaultFromStyle(want);
+ if (numericBold || numericNormal) {
+ newStyle = numericBold ? Typeface.BOLD : Typeface.NORMAL;
+ typeface = Typeface.create(typeface, newStyle);
+ FLog.d(
+ TAG,
+ "Support for numeric font weight numeric values available only from Android API 28 Pie. Android device lower then API 28 will use normal or bold.");
}
+ return typeface;
}
/**
diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js
index 219f5d298549c4..e8a09fb5209c0e 100644
--- a/packages/rn-tester/js/examples/Text/TextExample.android.js
+++ b/packages/rn-tester/js/examples/Text/TextExample.android.js
@@ -388,6 +388,15 @@ class TextExample extends React.Component<{...}> {
Move fast and be bold
Move fast and be normal
+ FONT WEIGHT 900
+ FONT WEIGHT 800
+ FONT WEIGHT 700
+ FONT WEIGHT 600
+ FONT WEIGHT 500
+ FONT WEIGHT 400
+ FONT WEIGHT 300
+ FONT WEIGHT 200
+ FONT WEIGHT 100
Move fast and be italic
diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js
index 1acdfd2e3aa47f..8c94f7bc70e78b 100644
--- a/packages/rn-tester/js/examples/Text/TextExample.ios.js
+++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js
@@ -603,21 +603,17 @@ exports.examples = [
render: function(): React.Node {
return (
-
- Move fast and be ultralight
-
-
- Move fast and be light
-
-
- Move fast and be normal
-
-
- Move fast and be bold
-
-
- Move fast and be ultrabold
-
+ Move fast and be bold
+ Move fast and be normal
+ FONT WEIGHT 900
+ FONT WEIGHT 800
+ FONT WEIGHT 700
+ FONT WEIGHT 600
+ FONT WEIGHT 500
+ FONT WEIGHT 400
+ FONT WEIGHT 300
+ FONT WEIGHT 200
+ FONT WEIGHT 100
);
},