Skip to content

Commit f01c4e2

Browse files
dulmandakhfacebook-github-bot
authored andcommitted
add support for native/downloadable fonts (#23865)
Summary: Android API 26 and Android Support Library 26 added support for font resource type and native/downloadable fonts. It allows apps to easily download fonts from online providers, but also use of various font weights other than normal and bold, like medium. So it deprecated APIs for asset fonts, and should be removed in the future. Advantages: - Just copy font files in res/font and use it specifying filename (without extension) in fontFamily - Define custom font-family using XML file (in res/font) and font files, it may have many weights and styles. See PR for example. - Define configuration to download fonts from online font providers, and use it. See https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml and https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts [Android] [Changed] - add support for custom/downloadable fonts Pull Request resolved: #23865 Differential Revision: D14506542 Pulled By: hramos fbshipit-source-id: 67ba3148fb4b548cdbc779213cf6c1b2c3baffd2
1 parent d338a60 commit f01c4e2

File tree

9 files changed

+60
-15
lines changed

9 files changed

+60
-15
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
3+
<font app:fontStyle="normal" app:fontWeight="400" app:font="@font/srisakdi_regular"/>
4+
<font app:fontStyle="normal" app:fontWeight="700" app:font="@font/srisakdi_bold" />
5+
</font-family>
Binary file not shown.
Binary file not shown.

RNTester/js/TextExample.android.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,14 @@ class TextExample extends React.Component<{}> {
182182
<Text style={{fontFamily: 'notoserif', fontStyle: 'italic'}}>
183183
NotoSerif Italic (Missing Font file)
184184
</Text>
185+
<Text style={{fontFamily: 'srisakdi'}}>Srisakdi Regular</Text>
186+
<Text
187+
style={{
188+
fontFamily: 'srisakdi',
189+
fontWeight: 'bold',
190+
}}>
191+
Srisakdi Bold
192+
</Text>
185193
</View>
186194
</View>
187195
</RNTesterBlock>

ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
package com.facebook.react.views.text;
99

10+
import javax.annotation.Nonnull;
1011
import javax.annotation.Nullable;
1112

13+
import android.content.Context;
1214
import android.content.res.AssetManager;
1315
import android.graphics.Paint;
1416
import android.graphics.Typeface;
@@ -29,31 +31,30 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
2931
* Fonts are retrieved and cached using the {@link ReactFontManager}
3032
*/
3133

32-
private final AssetManager mAssetManager;
33-
3434
private final int mStyle;
3535
private final int mWeight;
3636
private final @Nullable String mFontFamily;
37+
private final Context mContext;
3738

3839
public CustomStyleSpan(
3940
int fontStyle,
4041
int fontWeight,
4142
@Nullable String fontFamily,
42-
AssetManager assetManager) {
43+
@Nonnull Context context) {
4344
mStyle = fontStyle;
4445
mWeight = fontWeight;
4546
mFontFamily = fontFamily;
46-
mAssetManager = assetManager;
47+
mContext = context;
4748
}
4849

4950
@Override
5051
public void updateDrawState(TextPaint ds) {
51-
apply(ds, mStyle, mWeight, mFontFamily, mAssetManager);
52+
apply(ds, mStyle, mWeight, mFontFamily, mContext);
5253
}
5354

5455
@Override
55-
public void updateMeasureState(TextPaint paint) {
56-
apply(paint, mStyle, mWeight, mFontFamily, mAssetManager);
56+
public void updateMeasureState(@Nonnull TextPaint paint) {
57+
apply(paint, mStyle, mWeight, mFontFamily, mContext);
5758
}
5859

5960
/**
@@ -82,7 +83,7 @@ private static void apply(
8283
int style,
8384
int weight,
8485
@Nullable String family,
85-
AssetManager assetManager) {
86+
Context context) {
8687
int oldStyle;
8788
Typeface typeface = paint.getTypeface();
8889
if (typeface == null) {
@@ -103,7 +104,7 @@ private static void apply(
103104
}
104105

105106
if (family != null) {
106-
typeface = ReactFontManager.getInstance().getTypeface(family, want, assetManager);
107+
typeface = ReactFontManager.getInstance().getTypeface(family, want, context);
107108
} else if (typeface != null) {
108109
// TODO(t9055065): Fix custom fonts getting applied to text children with different style
109110
typeface = Typeface.create(typeface, want);
@@ -116,5 +117,4 @@ private static void apply(
116117
}
117118
paint.setSubpixelText(true);
118119
}
119-
120120
}

ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private static void buildSpannedFromShadowNode(
188188
textShadowNode.mFontStyle,
189189
textShadowNode.mFontWeight,
190190
textShadowNode.mFontFamily,
191-
textShadowNode.getThemedContext().getAssets())));
191+
textShadowNode.getThemedContext())));
192192
}
193193
if (textShadowNode.mIsUnderlineTextDecorationSet) {
194194
ops.add(new SetSpanOperation(start, end, new ReactUnderlineSpan()));

ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
import java.util.HashMap;
1313
import java.util.Map;
1414

15+
import android.content.Context;
1516
import android.content.res.AssetManager;
1617
import android.graphics.Typeface;
1718
import android.util.SparseArray;
1819

20+
import androidx.core.content.res.ResourcesCompat;
21+
22+
1923
/**
2024
* Class responsible to load and cache Typeface objects. It will first try to load typefaces inside
2125
* the assets/fonts folder and if it doesn't find the right Typeface in that folder will fall back
@@ -37,9 +41,11 @@ public class ReactFontManager {
3741
private static ReactFontManager sReactFontManagerInstance;
3842

3943
private Map<String, FontFamily> mFontCache;
44+
private Map<String, Typeface> mTypeCache;
4045

4146
private ReactFontManager() {
4247
mFontCache = new HashMap<>();
48+
mTypeCache = new HashMap<>();
4349
}
4450

4551
public static ReactFontManager getInstance() {
@@ -49,8 +55,7 @@ public static ReactFontManager getInstance() {
4955
return sReactFontManagerInstance;
5056
}
5157

52-
public
53-
@Nullable Typeface getTypeface(
58+
private @Nullable Typeface getTypeface(
5459
String fontFamilyName,
5560
int style,
5661
AssetManager assetManager) {
@@ -71,6 +76,33 @@ public static ReactFontManager getInstance() {
7176
return typeface;
7277
}
7378

79+
public @Nullable Typeface getTypeface(
80+
String fontFamilyName,
81+
int style,
82+
Context context) {
83+
Typeface font = mTypeCache.get(fontFamilyName);
84+
85+
if (font != null) {
86+
return Typeface.create(
87+
font,
88+
style
89+
);
90+
}
91+
92+
int fontId = context.getResources().getIdentifier(fontFamilyName, "font", context.getPackageName());
93+
if (fontId != 0) {
94+
font = ResourcesCompat.getFont(context, fontId);
95+
if (font != null) {
96+
mTypeCache.put(fontFamilyName, font);
97+
return Typeface.create(
98+
font,
99+
style
100+
);
101+
}
102+
}
103+
return getTypeface(fontFamilyName, style, context.getAssets());
104+
}
105+
74106
/**
75107
* Add additional font family, or replace the exist one in the font memory cache.
76108
* @param style

ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ private static void buildSpannableFromFragment(
9797
textAttributes.mFontStyle,
9898
textAttributes.mFontWeight,
9999
textAttributes.mFontFamily,
100-
context.getAssets())));
100+
context)));
101101
}
102102
if (textAttributes.mIsUnderlineTextDecorationSet) {
103103
ops.add(new SetSpanOperation(start, end, new ReactUnderlineSpan()));

ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public void setFontFamily(ReactEditText view, String fontFamily) {
221221
Typeface newTypeface = ReactFontManager.getInstance().getTypeface(
222222
fontFamily,
223223
style,
224-
view.getContext().getAssets());
224+
view.getContext());
225225
view.setTypeface(newTypeface);
226226
}
227227

0 commit comments

Comments
 (0)