mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Convert common/assets/ReactFontManager.java (#45668)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45668 Changelog: [Internal] [Changed] - Convert com.facebook.react.common.assets.ReactFontManager to Kotlin Reviewed By: cortinico Differential Revision: D60188666 fbshipit-source-id: 17ca6f162545e9185e1e0a24d8ebacf6cb49a064
This commit is contained in:
committed by
Facebook GitHub Bot
parent
34e3a6cc88
commit
fbfb430b3b
@@ -1884,25 +1884,36 @@ public abstract interface annotation class com/facebook/react/common/annotations
|
||||
public abstract interface annotation class com/facebook/react/common/annotations/VisibleForTesting : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public class com/facebook/react/common/assets/ReactFontManager {
|
||||
public fun addCustomFont (Landroid/content/Context;Ljava/lang/String;I)V
|
||||
public fun addCustomFont (Ljava/lang/String;Landroid/graphics/Typeface;)V
|
||||
public static fun getInstance ()Lcom/facebook/react/common/assets/ReactFontManager;
|
||||
public fun getTypeface (Ljava/lang/String;IILandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public fun getTypeface (Ljava/lang/String;ILandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public fun getTypeface (Ljava/lang/String;IZLandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public fun getTypeface (Ljava/lang/String;Lcom/facebook/react/common/assets/ReactFontManager$TypefaceStyle;Landroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public fun setTypeface (Ljava/lang/String;ILandroid/graphics/Typeface;)V
|
||||
public final class com/facebook/react/common/assets/ReactFontManager {
|
||||
public static final field Companion Lcom/facebook/react/common/assets/ReactFontManager$Companion;
|
||||
public fun <init> ()V
|
||||
public final fun addCustomFont (Landroid/content/Context;Ljava/lang/String;I)V
|
||||
public final fun addCustomFont (Ljava/lang/String;Landroid/graphics/Typeface;)V
|
||||
public static final fun getInstance ()Lcom/facebook/react/common/assets/ReactFontManager;
|
||||
public final fun getTypeface (Ljava/lang/String;IILandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public final fun getTypeface (Ljava/lang/String;ILandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public final fun getTypeface (Ljava/lang/String;IZLandroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public final fun getTypeface (Ljava/lang/String;Lcom/facebook/react/common/assets/ReactFontManager$TypefaceStyle;Landroid/content/res/AssetManager;)Landroid/graphics/Typeface;
|
||||
public final fun setTypeface (Ljava/lang/String;ILandroid/graphics/Typeface;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/common/assets/ReactFontManager$TypefaceStyle {
|
||||
public final class com/facebook/react/common/assets/ReactFontManager$Companion {
|
||||
public final fun getInstance ()Lcom/facebook/react/common/assets/ReactFontManager;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/common/assets/ReactFontManager$TypefaceStyle {
|
||||
public static final field BOLD I
|
||||
public static final field Companion Lcom/facebook/react/common/assets/ReactFontManager$TypefaceStyle$Companion;
|
||||
public static final field NORMAL I
|
||||
public fun <init> (I)V
|
||||
public fun <init> (II)V
|
||||
public synthetic fun <init> (IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (IZ)V
|
||||
public fun apply (Landroid/graphics/Typeface;)Landroid/graphics/Typeface;
|
||||
public fun getNearestStyle ()I
|
||||
public final fun apply (Landroid/graphics/Typeface;)Landroid/graphics/Typeface;
|
||||
public final fun getNearestStyle ()I
|
||||
}
|
||||
|
||||
public final class com/facebook/react/common/assets/ReactFontManager$TypefaceStyle$Companion {
|
||||
}
|
||||
|
||||
public class com/facebook/react/common/build/ReactBuildConfig {
|
||||
|
||||
-239
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.common.assets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Responsible for loading and caching Typeface objects.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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:
|
||||
*
|
||||
* <ul>
|
||||
* <li>ExampleFontFamily.ttf (or .otf)
|
||||
* <li>ExampleFontFamily_bold.ttf (or .otf)
|
||||
* <li>ExampleFontFamily_italic.ttf (or .otf)
|
||||
* <li>ExampleFontFamily_bold_italic.ttf (or .otf)
|
||||
*/
|
||||
@Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
public class ReactFontManager {
|
||||
|
||||
// NOTE: Indices in `EXTENSIONS` correspond to the `TypeFace` style constants.
|
||||
private static final String[] EXTENSIONS = {"", "_bold", "_italic", "_bold_italic"};
|
||||
private static final String[] FILE_EXTENSIONS = {".ttf", ".otf"};
|
||||
private static final String FONTS_ASSET_PATH = "fonts/";
|
||||
|
||||
private static ReactFontManager sReactFontManagerInstance;
|
||||
|
||||
private final Map<String, AssetFontFamily> mFontCache;
|
||||
private final Map<String, Typeface> mCustomTypefaceCache;
|
||||
|
||||
private ReactFontManager() {
|
||||
mFontCache = new HashMap<>();
|
||||
mCustomTypefaceCache = new HashMap<>();
|
||||
}
|
||||
|
||||
public static ReactFontManager getInstance() {
|
||||
if (sReactFontManagerInstance == null) {
|
||||
sReactFontManagerInstance = new ReactFontManager();
|
||||
}
|
||||
return sReactFontManagerInstance;
|
||||
}
|
||||
|
||||
public Typeface getTypeface(String fontFamilyName, int style, AssetManager assetManager) {
|
||||
return getTypeface(fontFamilyName, new TypefaceStyle(style), assetManager);
|
||||
}
|
||||
|
||||
public Typeface getTypeface(
|
||||
String fontFamilyName, int weight, boolean italic, AssetManager assetManager) {
|
||||
return getTypeface(fontFamilyName, new TypefaceStyle(weight, italic), assetManager);
|
||||
}
|
||||
|
||||
public Typeface getTypeface(
|
||||
String fontFamilyName, int style, int weight, AssetManager assetManager) {
|
||||
return getTypeface(fontFamilyName, new TypefaceStyle(style, weight), assetManager);
|
||||
}
|
||||
|
||||
public Typeface getTypeface(
|
||||
String fontFamilyName, TypefaceStyle typefaceStyle, AssetManager assetManager) {
|
||||
if (mCustomTypefaceCache.containsKey(fontFamilyName)) {
|
||||
// Apply `typefaceStyle` because custom fonts configure variants using `app:fontStyle` and
|
||||
// `app:fontWeight` in their resource XML configuration file.
|
||||
return typefaceStyle.apply(mCustomTypefaceCache.get(fontFamilyName));
|
||||
}
|
||||
|
||||
AssetFontFamily assetFontFamily = mFontCache.get(fontFamilyName);
|
||||
if (assetFontFamily == null) {
|
||||
assetFontFamily = new AssetFontFamily();
|
||||
mFontCache.put(fontFamilyName, assetFontFamily);
|
||||
}
|
||||
|
||||
int style = typefaceStyle.getNearestStyle();
|
||||
|
||||
Typeface assetTypeface = assetFontFamily.getTypefaceForStyle(style);
|
||||
if (assetTypeface == null) {
|
||||
assetTypeface = createAssetTypeface(fontFamilyName, style, assetManager);
|
||||
assetFontFamily.setTypefaceForStyle(style, assetTypeface);
|
||||
}
|
||||
// Do not apply `typefaceStyle` because asset font files already incorporate the style.
|
||||
return assetTypeface;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method allows you to load custom fonts from res/font folder as provided font family name.
|
||||
* Fonts may be one of .ttf, .otf or XML (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml).
|
||||
* To support multiple font styles or weights, you must provide a font in XML format.
|
||||
*
|
||||
* ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi);
|
||||
*/
|
||||
public void addCustomFont(Context context, String fontFamily, int fontId) {
|
||||
Typeface font = ResourcesCompat.getFont(context, fontId);
|
||||
if (font != null) {
|
||||
mCustomTypefaceCache.put(fontFamily, font);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent method to {@see addCustomFont(Context, String, int)} which accepts a Typeface
|
||||
* object.
|
||||
*/
|
||||
public void addCustomFont(String fontFamily, @Nullable Typeface font) {
|
||||
if (font != null) {
|
||||
mCustomTypefaceCache.put(fontFamily, font);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional font family, or replace the exist one in the font memory cache.
|
||||
*
|
||||
* @param style
|
||||
* @see {@link Typeface#DEFAULT}
|
||||
* @see {@link Typeface#BOLD}
|
||||
* @see {@link Typeface#ITALIC}
|
||||
* @see {@link Typeface#BOLD_ITALIC}
|
||||
*/
|
||||
public void setTypeface(String fontFamilyName, int style, Typeface typeface) {
|
||||
if (typeface != null) {
|
||||
AssetFontFamily assetFontFamily = mFontCache.get(fontFamilyName);
|
||||
if (assetFontFamily == null) {
|
||||
assetFontFamily = new AssetFontFamily();
|
||||
mFontCache.put(fontFamilyName, assetFontFamily);
|
||||
}
|
||||
assetFontFamily.setTypefaceForStyle(style, typeface);
|
||||
}
|
||||
}
|
||||
|
||||
private static Typeface createAssetTypeface(
|
||||
String fontFamilyName, int style, AssetManager assetManager) {
|
||||
String extension = EXTENSIONS[style];
|
||||
for (String fileExtension : FILE_EXTENSIONS) {
|
||||
String fileName =
|
||||
new StringBuilder()
|
||||
.append(FONTS_ASSET_PATH)
|
||||
.append(fontFamilyName)
|
||||
.append(extension)
|
||||
.append(fileExtension)
|
||||
.toString();
|
||||
try {
|
||||
return Typeface.createFromAsset(assetManager, fileName);
|
||||
} catch (RuntimeException e) {
|
||||
// If the typeface asset does not exist, try another extension.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return Typeface.create(fontFamilyName, style);
|
||||
}
|
||||
|
||||
/** Responsible for normalizing style and numeric weight for backward compatibility. */
|
||||
public static class TypefaceStyle {
|
||||
|
||||
public static final int BOLD = 700;
|
||||
public static final int NORMAL = 400;
|
||||
private static final int MIN_WEIGHT = 1;
|
||||
private static final int MAX_WEIGHT = 1000;
|
||||
|
||||
private final boolean mItalic;
|
||||
private final int mWeight;
|
||||
|
||||
public TypefaceStyle(int weight, boolean italic) {
|
||||
mItalic = italic;
|
||||
mWeight = weight == ReactConstants.UNSET ? NORMAL : weight;
|
||||
}
|
||||
|
||||
public TypefaceStyle(int style) {
|
||||
if (style == ReactConstants.UNSET) {
|
||||
style = Typeface.NORMAL;
|
||||
}
|
||||
|
||||
mItalic = (style & Typeface.ITALIC) != 0;
|
||||
mWeight = (style & Typeface.BOLD) != 0 ? BOLD : NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* If `weight` is supplied, it will be combined with the italic bit from `style`. Otherwise, any
|
||||
* existing weight bit in `style` will be used.
|
||||
*/
|
||||
public TypefaceStyle(int style, int weight) {
|
||||
if (style == ReactConstants.UNSET) {
|
||||
style = Typeface.NORMAL;
|
||||
}
|
||||
|
||||
mItalic = (style & Typeface.ITALIC) != 0;
|
||||
mWeight =
|
||||
weight == ReactConstants.UNSET ? (style & Typeface.BOLD) != 0 ? BOLD : NORMAL : weight;
|
||||
}
|
||||
|
||||
public int getNearestStyle() {
|
||||
if (mWeight < BOLD) {
|
||||
return mItalic ? Typeface.ITALIC : Typeface.NORMAL;
|
||||
} else {
|
||||
return mItalic ? Typeface.BOLD_ITALIC : Typeface.BOLD;
|
||||
}
|
||||
}
|
||||
|
||||
public Typeface apply(Typeface typeface) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
return Typeface.create(typeface, getNearestStyle());
|
||||
} else {
|
||||
return Typeface.create(typeface, mWeight, mItalic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Responsible for caching typefaces for each custom font family. */
|
||||
private static class AssetFontFamily {
|
||||
|
||||
private SparseArray<Typeface> mTypefaceSparseArray;
|
||||
|
||||
private AssetFontFamily() {
|
||||
mTypefaceSparseArray = new SparseArray<>(4);
|
||||
}
|
||||
|
||||
public @Nullable Typeface getTypefaceForStyle(int style) {
|
||||
return mTypefaceSparseArray.get(style);
|
||||
}
|
||||
|
||||
public void setTypefaceForStyle(int style, Typeface typeface) {
|
||||
mTypefaceSparseArray.put(style, typeface);
|
||||
}
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.common.assets
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.util.SparseArray
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.facebook.react.common.ReactConstants
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* * ExampleFontFamily.ttf (or .otf)
|
||||
* * ExampleFontFamily_bold.ttf (or .otf)
|
||||
* * ExampleFontFamily_italic.ttf (or .otf)
|
||||
* * ExampleFontFamily_bold_italic.ttf (or .otf)
|
||||
*/
|
||||
public class ReactFontManager {
|
||||
|
||||
private val fontCache: MutableMap<String, AssetFontFamily> = mutableMapOf()
|
||||
private val customTypefaceCache: MutableMap<String, Typeface> = mutableMapOf()
|
||||
|
||||
public fun getTypeface(
|
||||
fontFamilyName: String,
|
||||
style: Int,
|
||||
assetManager: AssetManager?,
|
||||
): Typeface = getTypeface(fontFamilyName, TypefaceStyle(style), assetManager)
|
||||
|
||||
public fun getTypeface(
|
||||
fontFamilyName: String,
|
||||
weight: Int,
|
||||
italic: Boolean,
|
||||
assetManager: AssetManager?,
|
||||
): Typeface = getTypeface(fontFamilyName, TypefaceStyle(weight, italic), assetManager)
|
||||
|
||||
public fun getTypeface(
|
||||
fontFamilyName: String,
|
||||
style: Int,
|
||||
weight: Int,
|
||||
assetManager: AssetManager?,
|
||||
): Typeface = getTypeface(fontFamilyName, TypefaceStyle(style, weight), assetManager)
|
||||
|
||||
public fun getTypeface(
|
||||
fontFamilyName: String,
|
||||
typefaceStyle: TypefaceStyle,
|
||||
assetManager: AssetManager?,
|
||||
): Typeface {
|
||||
if (customTypefaceCache.containsKey(fontFamilyName)) {
|
||||
// Apply `typefaceStyle` because custom fonts configure variants using `app:fontStyle` and
|
||||
// `app:fontWeight` in their resource XML configuration file.
|
||||
return typefaceStyle.apply(customTypefaceCache[fontFamilyName])
|
||||
}
|
||||
|
||||
val assetFontFamily = fontCache.getOrPut(fontFamilyName) { AssetFontFamily() }
|
||||
val style = typefaceStyle.nearestStyle
|
||||
return assetFontFamily.getTypefaceForStyle(style)
|
||||
?: createAssetTypeface(fontFamilyName, style, assetManager).also {
|
||||
assetFontFamily.setTypefaceForStyle(style, it)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method allows you to load custom fonts from res/font folder as provided font family name.
|
||||
* Fonts may be one of .ttf, .otf or XML (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml).
|
||||
* To support multiple font styles or weights, you must provide a font in XML format.
|
||||
*
|
||||
* ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi);
|
||||
*/
|
||||
public fun addCustomFont(context: Context, fontFamily: String, fontId: Int): Unit {
|
||||
addCustomFont(fontFamily, ResourcesCompat.getFont(context, fontId))
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent method to {@see addCustomFont(Context, String, int)} which accepts a Typeface
|
||||
* object.
|
||||
*/
|
||||
public fun addCustomFont(fontFamily: String, font: Typeface?): Unit {
|
||||
if (font != null) {
|
||||
customTypefaceCache[fontFamily] = font
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional font family, or replace the exist one in the font memory cache.
|
||||
*
|
||||
* @see [Typeface.DEFAULT]
|
||||
* @see [Typeface.BOLD]
|
||||
* @see [Typeface.ITALIC]
|
||||
* @see [Typeface.BOLD_ITALIC]
|
||||
*/
|
||||
public fun setTypeface(fontFamilyName: String, style: Int, typeface: Typeface?): Unit {
|
||||
if (typeface != null) {
|
||||
fontCache.getOrPut(fontFamilyName) { AssetFontFamily() }.setTypefaceForStyle(style, typeface)
|
||||
}
|
||||
}
|
||||
|
||||
/** Responsible for normalizing style and numeric weight for backward compatibility. */
|
||||
public class TypefaceStyle {
|
||||
private val italic: Boolean
|
||||
private val weight: Int
|
||||
|
||||
public constructor(weight: Int, italic: Boolean) {
|
||||
this.italic = italic
|
||||
this.weight = if (weight == ReactConstants.UNSET) NORMAL else weight
|
||||
}
|
||||
|
||||
/**
|
||||
* If `weight` is supplied, it will be combined with the italic bit from `style`. Otherwise, any
|
||||
* existing weight bit in `style` will be used.
|
||||
*/
|
||||
@JvmOverloads
|
||||
public constructor(style: Int, weight: Int = ReactConstants.UNSET) {
|
||||
val fixedStyle = if (style == ReactConstants.UNSET) Typeface.NORMAL else style
|
||||
italic = (fixedStyle and Typeface.ITALIC) != 0
|
||||
this.weight =
|
||||
if (weight == ReactConstants.UNSET)
|
||||
(if ((fixedStyle and Typeface.BOLD) != 0) BOLD else NORMAL)
|
||||
else weight
|
||||
}
|
||||
|
||||
public val nearestStyle: Int
|
||||
get() =
|
||||
if (weight < BOLD) {
|
||||
if (italic) Typeface.ITALIC else Typeface.NORMAL
|
||||
} else {
|
||||
if (italic) Typeface.BOLD_ITALIC else Typeface.BOLD
|
||||
}
|
||||
|
||||
public fun apply(typeface: Typeface?): Typeface =
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
Typeface.create(typeface, nearestStyle)
|
||||
} else {
|
||||
Typeface.create(typeface, weight, italic)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val BOLD: Int = 700
|
||||
public const val NORMAL: Int = 400
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
|
||||
// NOTE: Indices in `EXTENSIONS` correspond to the `TypeFace` style constants.
|
||||
private val EXTENSIONS = arrayOf("", "_bold", "_italic", "_bold_italic")
|
||||
private val FILE_EXTENSIONS = arrayOf(".ttf", ".otf")
|
||||
private const val FONTS_ASSET_PATH = "fonts/"
|
||||
|
||||
private val _instance = ReactFontManager()
|
||||
|
||||
@JvmStatic public fun getInstance(): ReactFontManager = _instance
|
||||
|
||||
private fun createAssetTypeface(
|
||||
fontFamilyName: String,
|
||||
style: Int,
|
||||
assetManager: AssetManager?,
|
||||
): Typeface {
|
||||
if (assetManager != null) {
|
||||
val extension = EXTENSIONS[style]
|
||||
for (fileExtension in FILE_EXTENSIONS) {
|
||||
val fileName = "$FONTS_ASSET_PATH$fontFamilyName$extension$fileExtension"
|
||||
try {
|
||||
return Typeface.createFromAsset(assetManager, fileName)
|
||||
} catch (e: RuntimeException) {
|
||||
// If the typeface asset does not exist, try another extension.
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return Typeface.create(fontFamilyName, style)
|
||||
}
|
||||
}
|
||||
|
||||
/** Responsible for caching typefaces for each custom font family. */
|
||||
private class AssetFontFamily {
|
||||
private val typefaceSparseArray: SparseArray<Typeface?> = SparseArray(4)
|
||||
|
||||
fun getTypefaceForStyle(style: Int): Typeface? = typefaceSparseArray[style]
|
||||
|
||||
fun setTypefaceForStyle(style: Int, typeface: Typeface?) {
|
||||
typefaceSparseArray.put(style, typeface)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user