From 9d2fedc6e22ca1b45fbc2059971cd194de5d0170 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 12 Jul 2021 22:16:00 -0700 Subject: [PATCH] RN: Unify Typeface Logic (Android) Summary: Refactors how `Typeface` style and weight are applied in React Native on Android. - Unifies all style and weight normalization logic into a new `TypefaceStyle` class. - Fixes font weight support for the Fabric renderer. - De-duplicates code with `TextAttributeProps`. - Simplified normalization logic. - Fixes a rare crash due to `Typeface.sDefaultTypeface` (Android SDK) being `null`. - Adds a new example to test font weights in `TextInput`. - Adds missing `Nullsafe` and `Nullable` annotations. - Clean up a bunch of obsolete inline comments. Changelog: [Android][Fixed] - Fixed a rare crash due to `Typeface.sDefaultTypeface` (Android SDK) being `null`. [Android][Fixed] - Fixed font weight support for the Fabric renderer. [Android][Added] - Added a new example to test font weights in `TextInput`. Reviewed By: JoshuaGross Differential Revision: D29631134 fbshipit-source-id: 3f227d84253104fa828a5561b77ba7a9cbc030c4 --- .../react/views/text/CustomStyleSpan.java | 14 +-- .../react/views/text/ReactFontManager.java | 103 ++++++++------- .../react/views/text/ReactTypefaceUtils.java | 119 ++++++------------ .../react/views/text/TextAttributeProps.java | 54 +------- .../react/views/text/TypefaceStyle.java | 72 +++++++++++ .../react/views/textinput/ReactEditText.java | 4 +- .../TextInput/TextInputExample.android.js | 32 +++++ 7 files changed, 214 insertions(+), 184 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/text/TypefaceStyle.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java index cf0c8b141b0..61900f19f6f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java @@ -12,9 +12,10 @@ import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextPaint; import android.text.style.MetricAffectingSpan; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Nullsafe; +@Nullsafe(Nullsafe.Mode.LOCAL) public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan { /** @@ -40,7 +41,7 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan { int fontWeight, @Nullable String fontFeatureSettings, @Nullable String fontFamily, - @NonNull AssetManager assetManager) { + AssetManager assetManager) { mStyle = fontStyle; mWeight = fontWeight; mFeatureSettings = fontFeatureSettings; @@ -54,21 +55,18 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan { } @Override - public void updateMeasureState(@NonNull TextPaint paint) { + public void updateMeasureState(TextPaint paint) { apply(paint, mStyle, mWeight, mFeatureSettings, mFontFamily, mAssetManager); } - /** Returns {@link Typeface#NORMAL} or {@link Typeface#ITALIC}. */ public int getStyle() { - return (mStyle == ReactTextShadowNode.UNSET ? 0 : mStyle); + return mStyle == ReactBaseTextShadowNode.UNSET ? Typeface.NORMAL : mStyle; } - /** Returns {@link Typeface#NORMAL} or {@link Typeface#BOLD}. */ public int getWeight() { - return (mWeight == ReactTextShadowNode.UNSET ? 0 : mWeight); + return mWeight == ReactBaseTextShadowNode.UNSET ? TypefaceStyle.NORMAL : mWeight; } - /** Returns the font family set for this StyleSpan. */ public @Nullable String getFontFamily() { return mFontFamily; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.java index 32f0219db87..077f6006887 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.java @@ -10,31 +10,39 @@ package com.facebook.react.views.text; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Typeface; -import android.os.Build; import android.util.SparseArray; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.res.ResourcesCompat; +import com.facebook.infer.annotation.Nullsafe; import java.util.HashMap; import java.util.Map; /** - * Class responsible to load and cache Typeface objects. It will first try to load typefaces inside - * the assets/fonts folder and if it doesn't find the right Typeface in that folder will fall back - * on the best matching system Typeface The supported custom fonts extensions are .ttf and .otf. For - * each font family the bold, italic and bold_italic variants are supported. Given a "family" font - * family the files in the assets/fonts folder need to be family.ttf(.otf) family_bold.ttf(.otf) - * family_italic.ttf(.otf) and family_bold_italic.ttf(.otf) + * Responsible for loading and caching Typeface objects. + * + *

This will first try to load a typeface from the assets/fonts folder. If one is not found in + * that folder, this will fallback to the best matching system typeface. + * + *

Custom fonts support the extensions `.ttf` and `.otf` and the variants `bold`, `italic`, and + * `bold_italic`. For example, given a font named "ExampleFontFamily", the following are supported: + * + *