diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api
index 6d8d60cec62..3bda89c153e 100644
--- a/packages/react-native/ReactAndroid/api/ReactAndroid.api
+++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api
@@ -6213,97 +6213,74 @@ public final class com/facebook/react/views/text/ReactTypefaceUtils {
public static final fun parseFontWeight (Ljava/lang/String;)I
}
-public class com/facebook/react/views/text/TextAttributeProps {
- public static final field TA_KEY_ACCESSIBILITY_ROLE S
- public static final field TA_KEY_ALIGNMENT S
- public static final field TA_KEY_ALLOW_FONT_SCALING S
- public static final field TA_KEY_BACKGROUND_COLOR S
- public static final field TA_KEY_BEST_WRITING_DIRECTION S
- public static final field TA_KEY_FONT_FAMILY S
- public static final field TA_KEY_FONT_SIZE S
- public static final field TA_KEY_FONT_SIZE_MULTIPLIER S
- public static final field TA_KEY_FONT_STYLE S
- public static final field TA_KEY_FONT_VARIANT S
- public static final field TA_KEY_FONT_WEIGHT S
- public static final field TA_KEY_FOREGROUND_COLOR S
- public static final field TA_KEY_IS_HIGHLIGHTED S
- public static final field TA_KEY_LAYOUT_DIRECTION S
- public static final field TA_KEY_LETTER_SPACING S
- public static final field TA_KEY_LINE_BREAK_STRATEGY S
- public static final field TA_KEY_LINE_HEIGHT S
- public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S
- public static final field TA_KEY_OPACITY S
- public static final field TA_KEY_ROLE S
- public static final field TA_KEY_TEXT_DECORATION_COLOR S
- public static final field TA_KEY_TEXT_DECORATION_LINE S
- public static final field TA_KEY_TEXT_DECORATION_STYLE S
- public static final field TA_KEY_TEXT_SHADOW_COLOR S
- public static final field TA_KEY_TEXT_SHADOW_OFFSET_DX S
- public static final field TA_KEY_TEXT_SHADOW_OFFSET_DY S
- public static final field TA_KEY_TEXT_SHADOW_RADIUS S
- public static final field TA_KEY_TEXT_TRANSFORM S
+public final class com/facebook/react/views/text/TextAttributeProps {
+ public static final field Companion Lcom/facebook/react/views/text/TextAttributeProps$Companion;
+ public static final field TA_KEY_ACCESSIBILITY_ROLE I
+ public static final field TA_KEY_ALIGNMENT I
+ public static final field TA_KEY_ALLOW_FONT_SCALING I
+ public static final field TA_KEY_BACKGROUND_COLOR I
+ public static final field TA_KEY_BEST_WRITING_DIRECTION I
+ public static final field TA_KEY_FONT_FAMILY I
+ public static final field TA_KEY_FONT_SIZE I
+ public static final field TA_KEY_FONT_SIZE_MULTIPLIER I
+ public static final field TA_KEY_FONT_STYLE I
+ public static final field TA_KEY_FONT_VARIANT I
+ public static final field TA_KEY_FONT_WEIGHT I
+ public static final field TA_KEY_FOREGROUND_COLOR I
+ public static final field TA_KEY_IS_HIGHLIGHTED I
+ public static final field TA_KEY_LAYOUT_DIRECTION I
+ public static final field TA_KEY_LETTER_SPACING I
+ public static final field TA_KEY_LINE_BREAK_STRATEGY I
+ public static final field TA_KEY_LINE_HEIGHT I
+ public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER I
+ public static final field TA_KEY_OPACITY I
+ public static final field TA_KEY_ROLE I
+ public static final field TA_KEY_TEXT_DECORATION_COLOR I
+ public static final field TA_KEY_TEXT_DECORATION_LINE I
+ public static final field TA_KEY_TEXT_DECORATION_STYLE I
+ public static final field TA_KEY_TEXT_SHADOW_COLOR I
+ public static final field TA_KEY_TEXT_SHADOW_OFFSET_DX I
+ public static final field TA_KEY_TEXT_SHADOW_OFFSET_DY I
+ public static final field TA_KEY_TEXT_SHADOW_RADIUS I
+ public static final field TA_KEY_TEXT_TRANSFORM I
public static final field UNSET I
- protected field mAccessibilityRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
- protected field mAllowFontScaling Z
- protected field mBackgroundColor I
- protected field mColor I
- protected field mContainsImages Z
- protected field mFontFamily Ljava/lang/String;
- protected field mFontFeatureSettings Ljava/lang/String;
- protected field mFontSize I
- protected field mFontSizeInput F
- protected field mFontStyle I
- protected field mFontWeight I
- protected field mHeightOfTallestInlineImage F
- protected field mIncludeFontPadding Z
- protected field mIsBackgroundColorSet Z
- protected field mIsColorSet Z
- protected field mIsLineThroughTextDecorationSet Z
- protected field mIsUnderlineTextDecorationSet Z
- protected field mLayoutDirection I
- protected field mLetterSpacingInput F
- protected field mLineHeight F
- protected field mLineHeightInput F
- protected field mMaxFontSizeMultiplier F
- protected field mNumberOfLines I
- protected field mOpacity F
- protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
- protected field mTextAlign I
- protected field mTextShadowColor I
- protected field mTextShadowOffsetDx F
- protected field mTextShadowOffsetDy F
- protected field mTextShadowRadius F
- protected field mTextTransform Lcom/facebook/react/views/text/TextTransform;
- public static fun fromMapBuffer (Lcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/views/text/TextAttributeProps;
- public static fun fromReadableMap (Lcom/facebook/react/uimanager/ReactStylesDiffMap;)Lcom/facebook/react/views/text/TextAttributeProps;
- public fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
- public fun getBackgroundColor ()I
- public fun getColor ()I
- public fun getEffectiveFontSize ()I
- public fun getEffectiveLetterSpacing ()F
- public fun getEffectiveLineHeight ()F
- public static fun getEllipsizeMode (Ljava/lang/String;)Landroid/text/TextUtils$TruncateAt;
- public fun getFontFamily ()Ljava/lang/String;
- public fun getFontFeatureSettings ()Ljava/lang/String;
- public fun getFontStyle ()I
- public fun getFontWeight ()I
- public static fun getHyphenationFrequency (Ljava/lang/String;)I
- public static fun getJustificationMode (Lcom/facebook/react/uimanager/ReactStylesDiffMap;I)I
- public static fun getLayoutDirection (Ljava/lang/String;)I
- public fun getLetterSpacing ()F
- public fun getOpacity ()F
- public fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
- public static fun getTextAlignment (Lcom/facebook/react/uimanager/ReactStylesDiffMap;ZI)I
- public static fun getTextBreakStrategy (Ljava/lang/String;)I
- public fun getTextShadowColor ()I
- public fun getTextShadowOffsetDx ()F
- public fun getTextShadowOffsetDy ()F
- public fun getTextShadowRadius ()F
- public fun getTextTransform ()Lcom/facebook/react/views/text/TextTransform;
- public fun isBackgroundColorSet ()Z
- public fun isColorSet ()Z
- public fun isLineThroughTextDecorationSet ()Z
- public fun isUnderlineTextDecorationSet ()Z
+ public final fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
+ public final fun getAllowFontScaling ()Z
+ public final fun getBackgroundColor ()Ljava/lang/Integer;
+ public final fun getColor ()Ljava/lang/Integer;
+ public final fun getEffectiveLetterSpacing ()F
+ public final fun getEffectiveLineHeight ()F
+ public final fun getFontFamily ()Ljava/lang/String;
+ public final fun getFontFeatureSettings ()Ljava/lang/String;
+ public final fun getFontSize ()I
+ public final fun getFontStyle ()I
+ public final fun getFontWeight ()I
+ public final fun getLayoutDirection ()I
+ public final fun getLetterSpacing ()F
+ public final fun getLineHeight ()F
+ public final fun getMaxFontSizeMultiplier ()F
+ public final fun getNumberOfLines ()I
+ public final fun getOpacity ()F
+ public final fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
+ public final fun getTextShadowColor ()I
+ public final fun getTextShadowOffsetDx ()F
+ public final fun getTextShadowOffsetDy ()F
+ public final fun getTextShadowRadius ()F
+ public final fun isBackgroundColorSet ()Z
+ public final fun isColorSet ()Z
+ public final fun isLineThroughTextDecorationSet ()Z
+ public final fun isUnderlineTextDecorationSet ()Z
+}
+
+public final class com/facebook/react/views/text/TextAttributeProps$Companion {
+ public final fun fromMapBuffer (Lcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/views/text/TextAttributeProps;
+ public final fun fromReadableMap (Lcom/facebook/react/uimanager/ReactStylesDiffMap;)Lcom/facebook/react/views/text/TextAttributeProps;
+ public final fun getEllipsizeMode (Ljava/lang/String;)Landroid/text/TextUtils$TruncateAt;
+ public final fun getHyphenationFrequency (Ljava/lang/String;)I
+ public final fun getJustificationMode (Lcom/facebook/react/uimanager/ReactStylesDiffMap;I)I
+ public final fun getLayoutDirection (Ljava/lang/String;)I
+ public final fun getTextAlignment (Lcom/facebook/react/uimanager/ReactStylesDiffMap;ZI)I
+ public final fun getTextBreakStrategy (Ljava/lang/String;)I
}
public final class com/facebook/react/views/text/TextAttributes {
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
deleted file mode 100644
index 67baca4e116..00000000000
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
+++ /dev/null
@@ -1,811 +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.views.text;
-
-import android.os.Build;
-import android.text.Layout;
-import android.text.TextUtils;
-import android.util.LayoutDirection;
-import android.view.Gravity;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import com.facebook.common.logging.FLog;
-import com.facebook.infer.annotation.Nullsafe;
-import com.facebook.react.bridge.ReadableArray;
-import com.facebook.react.bridge.ReadableMap;
-import com.facebook.react.common.ReactConstants;
-import com.facebook.react.common.mapbuffer.MapBuffer;
-import com.facebook.react.uimanager.PixelUtil;
-import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole;
-import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role;
-import com.facebook.react.uimanager.ReactStylesDiffMap;
-import com.facebook.react.uimanager.ViewProps;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-// TODO: T63643819 refactor naming of TextAttributeProps to make explicit that this represents
-// TextAttributes and not TextProps. As part of this refactor extract methods that don't belong to
-// TextAttributeProps (e.g. TextAlign)
-@Nullsafe(Nullsafe.Mode.LOCAL)
-public class TextAttributeProps {
-
- // constants for Text Attributes serialization
- public static final short TA_KEY_FOREGROUND_COLOR = 0;
- public static final short TA_KEY_BACKGROUND_COLOR = 1;
- public static final short TA_KEY_OPACITY = 2;
- public static final short TA_KEY_FONT_FAMILY = 3;
- public static final short TA_KEY_FONT_SIZE = 4;
- public static final short TA_KEY_FONT_SIZE_MULTIPLIER = 5;
- public static final short TA_KEY_FONT_WEIGHT = 6;
- public static final short TA_KEY_FONT_STYLE = 7;
- public static final short TA_KEY_FONT_VARIANT = 8;
- public static final short TA_KEY_ALLOW_FONT_SCALING = 9;
- public static final short TA_KEY_LETTER_SPACING = 10;
- public static final short TA_KEY_LINE_HEIGHT = 11;
- public static final short TA_KEY_ALIGNMENT = 12;
- public static final short TA_KEY_BEST_WRITING_DIRECTION = 13;
- public static final short TA_KEY_TEXT_DECORATION_COLOR = 14;
- public static final short TA_KEY_TEXT_DECORATION_LINE = 15;
- public static final short TA_KEY_TEXT_DECORATION_STYLE = 16;
- public static final short TA_KEY_TEXT_SHADOW_RADIUS = 18;
- public static final short TA_KEY_TEXT_SHADOW_COLOR = 19;
- public static final short TA_KEY_TEXT_SHADOW_OFFSET_DX = 20;
- public static final short TA_KEY_TEXT_SHADOW_OFFSET_DY = 21;
- public static final short TA_KEY_IS_HIGHLIGHTED = 22;
- public static final short TA_KEY_LAYOUT_DIRECTION = 23;
- public static final short TA_KEY_ACCESSIBILITY_ROLE = 24;
- public static final short TA_KEY_LINE_BREAK_STRATEGY = 25;
- public static final short TA_KEY_ROLE = 26;
- public static final short TA_KEY_TEXT_TRANSFORM = 27;
- public static final short TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
-
- public static final int UNSET = -1;
-
- private static final String PROP_SHADOW_OFFSET = "textShadowOffset";
- private static final String PROP_SHADOW_OFFSET_WIDTH = "width";
- private static final String PROP_SHADOW_OFFSET_HEIGHT = "height";
- private static final String PROP_SHADOW_RADIUS = "textShadowRadius";
- private static final String PROP_SHADOW_COLOR = "textShadowColor";
-
- private static final String PROP_TEXT_TRANSFORM = "textTransform";
-
- private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;
- private static final int DEFAULT_JUSTIFICATION_MODE =
- (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? 0 : Layout.JUSTIFICATION_MODE_NONE;
- private static final int DEFAULT_BREAK_STRATEGY = Layout.BREAK_STRATEGY_HIGH_QUALITY;
- private static final int DEFAULT_HYPHENATION_FREQUENCY = Layout.HYPHENATION_FREQUENCY_NONE;
-
- protected float mLineHeight = Float.NaN;
- protected boolean mIsColorSet = false;
- protected boolean mAllowFontScaling = true;
- protected float mMaxFontSizeMultiplier = Float.NaN;
- protected int mColor;
- protected boolean mIsBackgroundColorSet = false;
- protected int mBackgroundColor;
- protected float mOpacity = Float.NaN;
-
- protected int mNumberOfLines = ReactConstants.UNSET;
- protected int mFontSize = ReactConstants.UNSET;
- protected float mFontSizeInput = ReactConstants.UNSET;
- protected float mLineHeightInput = ReactConstants.UNSET;
- protected float mLetterSpacingInput = Float.NaN;
- protected int mTextAlign = Gravity.NO_GRAVITY;
-
- // `ReactConstants.UNSET` is -1, same as `LayoutDirection.UNDEFINED` (which is a hidden symbol)
- protected int mLayoutDirection = ReactConstants.UNSET;
-
- @NonNull protected TextTransform mTextTransform = TextTransform.NONE;
-
- protected float mTextShadowOffsetDx = 0;
- protected float mTextShadowOffsetDy = 0;
- protected float mTextShadowRadius = 0;
- protected int mTextShadowColor = DEFAULT_TEXT_SHADOW_COLOR;
-
- protected boolean mIsUnderlineTextDecorationSet = false;
- protected boolean mIsLineThroughTextDecorationSet = false;
- protected boolean mIncludeFontPadding = true;
-
- protected @Nullable AccessibilityRole mAccessibilityRole = null;
- protected @Nullable Role mRole = null;
-
- protected int mFontStyle = ReactConstants.UNSET;
- protected int mFontWeight = ReactConstants.UNSET;
-
- /**
- * NB: If a font family is used that does not have a style in a certain Android version (ie.
- * monospace bold pre Android 5.0), that style (ie. bold) will not be inherited by nested Text
- * nodes. To retain that style, you have to add it to those nodes explicitly.
- *
- *
Example, Android 4.4:
- *
- *
- * Bold Text
- * Bold Text
- * Bold Text
- *
- * Not Bold Text
- * Not Bold Text
- * Not Bold Text
- *
- * Not Bold Text
- * Bold Text
- * Bold Text
- *
- */
- protected @Nullable String mFontFamily = null;
-
- /**
- * @see android.graphics.Paint#setFontFeatureSettings
- */
- protected @Nullable String mFontFeatureSettings = null;
-
- protected boolean mContainsImages = false;
- protected float mHeightOfTallestInlineImage = Float.NaN;
-
- private TextAttributeProps() {}
-
- /** Build a TextAttributeProps using data from the {@link MapBuffer} received as a parameter. */
- public static TextAttributeProps fromMapBuffer(MapBuffer props) {
- TextAttributeProps result = new TextAttributeProps();
-
- // TODO T83483191: Review constants that are not being set!
- Iterator iterator = props.iterator();
- while (iterator.hasNext()) {
- MapBuffer.Entry entry = iterator.next();
- switch (entry.getKey()) {
- case TA_KEY_FOREGROUND_COLOR:
- result.setColor(entry.getIntValue());
- break;
- case TA_KEY_BACKGROUND_COLOR:
- result.setBackgroundColor(entry.getIntValue());
- break;
- case TA_KEY_OPACITY:
- result.setOpacity((float) entry.getDoubleValue());
- break;
- case TA_KEY_FONT_FAMILY:
- result.setFontFamily(entry.getStringValue());
- break;
- case TA_KEY_FONT_SIZE:
- result.setFontSize((float) entry.getDoubleValue());
- break;
- case TA_KEY_FONT_SIZE_MULTIPLIER:
- break;
- case TA_KEY_FONT_WEIGHT:
- result.setFontWeight(entry.getStringValue());
- break;
- case TA_KEY_FONT_STYLE:
- result.setFontStyle(entry.getStringValue());
- break;
- case TA_KEY_FONT_VARIANT:
- result.setFontVariant(entry.getMapBufferValue());
- break;
- case TA_KEY_ALLOW_FONT_SCALING:
- result.setAllowFontScaling(entry.getBooleanValue());
- break;
- case TA_KEY_LETTER_SPACING:
- result.setLetterSpacing((float) entry.getDoubleValue());
- break;
- case TA_KEY_LINE_HEIGHT:
- result.setLineHeight((float) entry.getDoubleValue());
- break;
- case TA_KEY_ALIGNMENT:
- break;
- case TA_KEY_BEST_WRITING_DIRECTION:
- break;
- case TA_KEY_TEXT_DECORATION_COLOR:
- break;
- case TA_KEY_TEXT_DECORATION_LINE:
- result.setTextDecorationLine(entry.getStringValue());
- break;
- case TA_KEY_TEXT_DECORATION_STYLE:
- break;
- case TA_KEY_TEXT_SHADOW_RADIUS:
- result.setTextShadowRadius((float) entry.getDoubleValue());
- break;
- case TA_KEY_TEXT_SHADOW_COLOR:
- result.setTextShadowColor(entry.getIntValue());
- break;
- case TA_KEY_TEXT_SHADOW_OFFSET_DX:
- result.setTextShadowOffsetDx((float) entry.getDoubleValue());
- break;
- case TA_KEY_TEXT_SHADOW_OFFSET_DY:
- result.setTextShadowOffsetDy((float) entry.getDoubleValue());
- break;
- case TA_KEY_IS_HIGHLIGHTED:
- break;
- case TA_KEY_LAYOUT_DIRECTION:
- result.setLayoutDirection(entry.getStringValue());
- break;
- case TA_KEY_ACCESSIBILITY_ROLE:
- result.setAccessibilityRole(entry.getStringValue());
- break;
- case TA_KEY_ROLE:
- result.setRole(Role.values()[entry.getIntValue()]);
- break;
- case TA_KEY_TEXT_TRANSFORM:
- result.setTextTransform(entry.getStringValue());
- break;
- case TA_KEY_MAX_FONT_SIZE_MULTIPLIER:
- result.setMaxFontSizeMultiplier((float) entry.getDoubleValue());
- break;
- }
- }
-
- // TODO T83483191: Review why the following props are not serialized:
- // setNumberOfLines
- // setColor
- // setIncludeFontPadding
- return result;
- }
-
- public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) {
- TextAttributeProps result = new TextAttributeProps();
- result.setNumberOfLines(getIntProp(props, ViewProps.NUMBER_OF_LINES, ReactConstants.UNSET));
- result.setLineHeight(getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET));
- result.setLetterSpacing(getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN));
- result.setAllowFontScaling(getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true));
- result.setMaxFontSizeMultiplier(
- getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN));
- result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET));
- result.setColor(props.hasKey(ViewProps.COLOR) ? props.getInt(ViewProps.COLOR, 0) : null);
- result.setColor(
- props.hasKey(ViewProps.FOREGROUND_COLOR)
- ? props.getInt(ViewProps.FOREGROUND_COLOR, 0)
- : null);
- result.setBackgroundColor(
- props.hasKey(ViewProps.BACKGROUND_COLOR)
- ? props.getInt(ViewProps.BACKGROUND_COLOR, 0)
- : null);
- result.setOpacity(getFloatProp(props, ViewProps.OPACITY, Float.NaN));
- result.setFontFamily(getStringProp(props, ViewProps.FONT_FAMILY));
- result.setFontWeight(getStringProp(props, ViewProps.FONT_WEIGHT));
- result.setFontStyle(getStringProp(props, ViewProps.FONT_STYLE));
- result.setFontVariant(getArrayProp(props, ViewProps.FONT_VARIANT));
- result.setIncludeFontPadding(getBooleanProp(props, ViewProps.INCLUDE_FONT_PADDING, true));
- result.setTextDecorationLine(getStringProp(props, ViewProps.TEXT_DECORATION_LINE));
- result.setTextShadowOffset(
- props.hasKey(PROP_SHADOW_OFFSET) ? props.getMap(PROP_SHADOW_OFFSET) : null);
- result.setTextShadowRadius(getFloatProp(props, PROP_SHADOW_RADIUS, 1));
- result.setTextShadowColor(getIntProp(props, PROP_SHADOW_COLOR, DEFAULT_TEXT_SHADOW_COLOR));
- result.setTextTransform(getStringProp(props, PROP_TEXT_TRANSFORM));
- result.setLayoutDirection(getStringProp(props, ViewProps.LAYOUT_DIRECTION));
- result.setAccessibilityRole(getStringProp(props, ViewProps.ACCESSIBILITY_ROLE));
- result.setRole(getStringProp(props, ViewProps.ROLE));
- return result;
- }
-
- public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL, int defaultValue) {
- if (!props.hasKey(ViewProps.TEXT_ALIGN)) {
- return defaultValue;
- }
-
- String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN);
- if ("justify".equals(textAlignPropValue)) {
- return Gravity.LEFT;
- } else {
- if (textAlignPropValue == null || "auto".equals(textAlignPropValue)) {
- return Gravity.NO_GRAVITY;
- } else if ("left".equals(textAlignPropValue)) {
- return isRTL ? Gravity.RIGHT : Gravity.LEFT;
- } else if ("right".equals(textAlignPropValue)) {
- return isRTL ? Gravity.LEFT : Gravity.RIGHT;
- } else if ("center".equals(textAlignPropValue)) {
- return Gravity.CENTER_HORIZONTAL;
- } else {
- FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlignPropValue);
- return Gravity.NO_GRAVITY;
- }
- }
- }
-
- public static int getJustificationMode(ReactStylesDiffMap props, int defaultValue) {
- if (!props.hasKey(ViewProps.TEXT_ALIGN)) {
- return defaultValue;
- }
-
- String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN);
- if ("justify".equals(textAlignPropValue) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- return Layout.JUSTIFICATION_MODE_INTER_WORD;
- }
- return DEFAULT_JUSTIFICATION_MODE;
- }
-
- private static boolean getBooleanProp(
- ReactStylesDiffMap mProps, String name, boolean defaultValue) {
- if (mProps.hasKey(name)) {
- return mProps.getBoolean(name, defaultValue);
- } else {
- return defaultValue;
- }
- }
-
- private static @Nullable String getStringProp(ReactStylesDiffMap mProps, String name) {
- if (mProps.hasKey(name)) {
- return mProps.getString(name);
- } else {
- return null;
- }
- }
-
- private static int getIntProp(ReactStylesDiffMap mProps, String name, int defaultvalue) {
- if (mProps.hasKey(name)) {
- return mProps.getInt(name, defaultvalue);
- } else {
- return defaultvalue;
- }
- }
-
- private static float getFloatProp(ReactStylesDiffMap mProps, String name, float defaultvalue) {
- if (mProps.hasKey(name)) {
- return mProps.getFloat(name, defaultvalue);
- } else {
- return defaultvalue;
- }
- }
-
- private static @Nullable ReadableArray getArrayProp(ReactStylesDiffMap mProps, String name) {
- if (mProps.hasKey(name)) {
- return mProps.getArray(name);
- } else {
- return null;
- }
- }
-
- // Returns a line height which takes into account the requested line height
- // and the height of the inline images.
- public float getEffectiveLineHeight() {
- boolean useInlineViewHeight =
- !Float.isNaN(mLineHeight)
- && !Float.isNaN(mHeightOfTallestInlineImage)
- && mHeightOfTallestInlineImage > mLineHeight;
- return useInlineViewHeight ? mHeightOfTallestInlineImage : mLineHeight;
- }
-
- private void setNumberOfLines(int numberOfLines) {
- mNumberOfLines = numberOfLines == 0 ? ReactConstants.UNSET : numberOfLines;
- }
-
- private void setLineHeight(float lineHeight) {
- mLineHeightInput = lineHeight;
- if (lineHeight == ReactConstants.UNSET) {
- mLineHeight = Float.NaN;
- } else {
- mLineHeight =
- mAllowFontScaling
- ? PixelUtil.toPixelFromSP(lineHeight)
- : PixelUtil.toPixelFromDIP(lineHeight);
- }
- }
-
- private void setLetterSpacing(float letterSpacing) {
- mLetterSpacingInput = letterSpacing;
- }
-
- @NonNull
- public TextTransform getTextTransform() {
- return mTextTransform;
- }
-
- public float getLetterSpacing() {
- float letterSpacingPixels =
- mAllowFontScaling
- ? PixelUtil.toPixelFromSP(mLetterSpacingInput)
- : PixelUtil.toPixelFromDIP(mLetterSpacingInput);
-
- if (mFontSize <= 0) {
- throw new IllegalArgumentException(
- "FontSize should be a positive value. Current value: " + mFontSize);
- }
- // `letterSpacingPixels` and `mFontSize` are both in pixels,
- // yielding an accurate em value.
- return letterSpacingPixels / mFontSize;
- }
-
- public float getEffectiveLetterSpacing() {
- return getLetterSpacing();
- }
-
- public int getEffectiveFontSize() {
- return mFontSize;
- }
-
- private void setAllowFontScaling(boolean allowFontScaling) {
- if (allowFontScaling != mAllowFontScaling) {
- mAllowFontScaling = allowFontScaling;
- setFontSize(mFontSizeInput);
- setLineHeight(mLineHeightInput);
- }
- }
-
- private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
- if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) {
- mMaxFontSizeMultiplier = maxFontSizeMultiplier;
- setFontSize(mFontSizeInput);
- setLineHeight(mLineHeightInput);
- }
- }
-
- private void setFontSize(float fontSize) {
- mFontSizeInput = fontSize;
- if (fontSize != ReactConstants.UNSET) {
- fontSize =
- mAllowFontScaling
- ? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier))
- : (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));
- }
- mFontSize = (int) fontSize;
- }
-
- public int getColor() {
- return mColor;
- }
-
- private void setColor(@Nullable Integer color) {
- mIsColorSet = (color != null);
- if (color != null) {
- mColor = color;
- }
- }
-
- public boolean isColorSet() {
- return mIsColorSet;
- }
-
- public int getBackgroundColor() {
- return mBackgroundColor;
- }
-
- private void setBackgroundColor(@Nullable Integer color) {
- // TODO: Don't apply background color to anchor TextView since it will be applied on the View
- // directly
- // if (!isVirtualAnchor()) {
- mIsBackgroundColorSet = (color != null);
- if (color != null) {
- mBackgroundColor = color;
- }
- // }
- }
-
- public float getOpacity() {
- return mOpacity;
- }
-
- private void setOpacity(float opacity) {
- mOpacity = opacity;
- }
-
- public boolean isBackgroundColorSet() {
- return mIsBackgroundColorSet;
- }
-
- public int getFontStyle() {
- return mFontStyle;
- }
-
- public @Nullable String getFontFamily() {
- return mFontFamily;
- }
-
- private void setFontFamily(@Nullable String fontFamily) {
- mFontFamily = fontFamily;
- }
-
- private void setFontVariant(@Nullable ReadableArray fontVariant) {
- mFontFeatureSettings = ReactTypefaceUtils.parseFontVariant(fontVariant);
- }
-
- private void setFontVariant(@Nullable MapBuffer fontVariant) {
- if (fontVariant == null || fontVariant.getCount() == 0) {
- mFontFeatureSettings = null;
- return;
- }
-
- List features = new ArrayList<>();
- Iterator iterator = fontVariant.iterator();
- while (iterator.hasNext()) {
- MapBuffer.Entry entry = iterator.next();
- String value = entry.getStringValue();
- if (value != null) {
- switch (value) {
- case "small-caps":
- features.add("'smcp'");
- break;
- case "oldstyle-nums":
- features.add("'onum'");
- break;
- case "lining-nums":
- features.add("'lnum'");
- break;
- case "tabular-nums":
- features.add("'tnum'");
- break;
- case "proportional-nums":
- features.add("'pnum'");
- break;
- case "stylistic-one":
- features.add("'ss01'");
- break;
- case "stylistic-two":
- features.add("'ss02'");
- break;
- case "stylistic-three":
- features.add("'ss03'");
- break;
- case "stylistic-four":
- features.add("'ss04'");
- break;
- case "stylistic-five":
- features.add("'ss05'");
- break;
- case "stylistic-six":
- features.add("'ss06'");
- break;
- case "stylistic-seven":
- features.add("'ss07'");
- break;
- case "stylistic-eight":
- features.add("'ss08'");
- break;
- case "stylistic-nine":
- features.add("'ss09'");
- break;
- case "stylistic-ten":
- features.add("'ss10'");
- break;
- case "stylistic-eleven":
- features.add("'ss11'");
- break;
- case "stylistic-twelve":
- features.add("'ss12'");
- break;
- case "stylistic-thirteen":
- features.add("'ss13'");
- break;
- case "stylistic-fourteen":
- features.add("'ss14'");
- break;
- case "stylistic-fifteen":
- features.add("'ss15'");
- break;
- case "stylistic-sixteen":
- features.add("'ss16'");
- break;
- case "stylistic-seventeen":
- features.add("'ss17'");
- break;
- case "stylistic-eighteen":
- features.add("'ss18'");
- break;
- case "stylistic-nineteen":
- features.add("'ss19'");
- break;
- case "stylistic-twenty":
- features.add("'ss20'");
- break;
- }
- }
- }
- mFontFeatureSettings = TextUtils.join(", ", features);
- }
-
- public @Nullable String getFontFeatureSettings() {
- return mFontFeatureSettings;
- }
-
- public int getFontWeight() {
- return mFontWeight;
- }
-
- private void setFontWeight(@Nullable String fontWeightString) {
- mFontWeight = ReactTypefaceUtils.parseFontWeight(fontWeightString);
- }
-
- private void setFontStyle(@Nullable String fontStyleString) {
- mFontStyle = ReactTypefaceUtils.parseFontStyle(fontStyleString);
- }
-
- private void setIncludeFontPadding(boolean includepad) {
- mIncludeFontPadding = includepad;
- }
-
- private void setTextDecorationLine(@Nullable String textDecorationLineString) {
- mIsUnderlineTextDecorationSet = false;
- mIsLineThroughTextDecorationSet = false;
- if (textDecorationLineString != null) {
- for (String textDecorationLineSubString : textDecorationLineString.split("-")) {
- if ("underline".equals(textDecorationLineSubString)) {
- mIsUnderlineTextDecorationSet = true;
- } else if ("strikethrough".equals(textDecorationLineSubString)) {
- mIsLineThroughTextDecorationSet = true;
- }
- }
- }
- }
-
- public boolean isUnderlineTextDecorationSet() {
- return mIsUnderlineTextDecorationSet;
- }
-
- public boolean isLineThroughTextDecorationSet() {
- return mIsLineThroughTextDecorationSet;
- }
-
- private void setTextShadowOffset(@Nullable ReadableMap offsetMap) {
- mTextShadowOffsetDx = 0;
- mTextShadowOffsetDy = 0;
-
- if (offsetMap != null) {
- if (offsetMap.hasKey(PROP_SHADOW_OFFSET_WIDTH)
- && !offsetMap.isNull(PROP_SHADOW_OFFSET_WIDTH)) {
- mTextShadowOffsetDx =
- PixelUtil.toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_WIDTH));
- }
- if (offsetMap.hasKey(PROP_SHADOW_OFFSET_HEIGHT)
- && !offsetMap.isNull(PROP_SHADOW_OFFSET_HEIGHT)) {
- mTextShadowOffsetDy =
- PixelUtil.toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_HEIGHT));
- }
- }
- }
-
- public float getTextShadowOffsetDx() {
- return mTextShadowOffsetDx;
- }
-
- private void setTextShadowOffsetDx(float dx) {
- mTextShadowOffsetDx = PixelUtil.toPixelFromDIP(dx);
- }
-
- public float getTextShadowOffsetDy() {
- return mTextShadowOffsetDy;
- }
-
- private void setTextShadowOffsetDy(float dy) {
- mTextShadowOffsetDy = PixelUtil.toPixelFromDIP(dy);
- }
-
- public static int getLayoutDirection(@Nullable String layoutDirection) {
- int androidLayoutDirection;
- if (layoutDirection == null || "undefined".equals(layoutDirection)) {
- androidLayoutDirection = ReactConstants.UNSET;
- } else if ("rtl".equals(layoutDirection)) {
- androidLayoutDirection = LayoutDirection.RTL;
- } else if ("ltr".equals(layoutDirection)) {
- androidLayoutDirection = LayoutDirection.LTR;
- } else {
- FLog.w(ReactConstants.TAG, "Invalid layoutDirection: " + layoutDirection);
- androidLayoutDirection = ReactConstants.UNSET;
- }
- return androidLayoutDirection;
- }
-
- private void setLayoutDirection(@Nullable String layoutDirection) {
- mLayoutDirection = getLayoutDirection(layoutDirection);
- }
-
- public float getTextShadowRadius() {
- return mTextShadowRadius;
- }
-
- private void setTextShadowRadius(float textShadowRadius) {
- if (textShadowRadius != mTextShadowRadius) {
- mTextShadowRadius = textShadowRadius;
- }
- }
-
- public int getTextShadowColor() {
- return mTextShadowColor;
- }
-
- private void setTextShadowColor(int textShadowColor) {
- if (textShadowColor != mTextShadowColor) {
- mTextShadowColor = textShadowColor;
- }
- }
-
- private void setTextTransform(@Nullable String textTransform) {
- if (textTransform == null || "none".equals(textTransform)) {
- mTextTransform = TextTransform.NONE;
- } else if ("uppercase".equals(textTransform)) {
- mTextTransform = TextTransform.UPPERCASE;
- } else if ("lowercase".equals(textTransform)) {
- mTextTransform = TextTransform.LOWERCASE;
- } else if ("capitalize".equals(textTransform)) {
- mTextTransform = TextTransform.CAPITALIZE;
- } else {
- FLog.w(ReactConstants.TAG, "Invalid textTransform: " + textTransform);
- mTextTransform = TextTransform.NONE;
- }
- }
-
- public @Nullable AccessibilityRole getAccessibilityRole() {
- return mAccessibilityRole;
- }
-
- private void setAccessibilityRole(@Nullable String accessibilityRole) {
- if (accessibilityRole == null) {
- mAccessibilityRole = null;
- } else {
- mAccessibilityRole = AccessibilityRole.fromValue(accessibilityRole);
- }
- }
-
- @Nullable
- public Role getRole() {
- return mRole;
- }
-
- private void setRole(@Nullable String role) {
- if (role == null) {
- mRole = null;
- } else {
- mRole = Role.fromValue(role);
- }
- }
-
- private void setRole(Role role) {
- mRole = role;
- }
-
- public static int getTextBreakStrategy(@Nullable String textBreakStrategy) {
- int androidTextBreakStrategy = DEFAULT_BREAK_STRATEGY;
- if (textBreakStrategy != null) {
- switch (textBreakStrategy) {
- case "simple":
- androidTextBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
- break;
- case "balanced":
- androidTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED;
- break;
- default:
- androidTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
- break;
- }
- }
- return androidTextBreakStrategy;
- }
-
- public static int getHyphenationFrequency(@Nullable String hyphenationFrequency) {
- int androidHyphenationFrequency = DEFAULT_HYPHENATION_FREQUENCY;
- if (hyphenationFrequency != null) {
- switch (hyphenationFrequency) {
- case "none":
- androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
- break;
- case "normal":
- androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NORMAL;
- break;
- default:
- androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_FULL;
- break;
- }
- }
- return androidHyphenationFrequency;
- }
-
- public static @Nullable TextUtils.TruncateAt getEllipsizeMode(@Nullable String ellipsizeMode) {
- @Nullable TextUtils.TruncateAt truncateAt = null;
- if (ellipsizeMode != null) {
- switch (ellipsizeMode) {
- case "head":
- truncateAt = TextUtils.TruncateAt.START;
- break;
- case "middle":
- truncateAt = TextUtils.TruncateAt.MIDDLE;
- break;
- case "tail":
- truncateAt = TextUtils.TruncateAt.END;
- break;
- case "clip":
- truncateAt = null;
- }
- }
- return truncateAt;
- }
-}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt
new file mode 100644
index 00000000000..4d6e8665be1
--- /dev/null
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt
@@ -0,0 +1,569 @@
+/*
+ * 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.views.text
+
+import android.os.Build
+import android.text.Layout
+import android.text.TextUtils
+import android.text.TextUtils.TruncateAt
+import android.util.LayoutDirection
+import android.view.Gravity
+import com.facebook.common.logging.FLog
+import com.facebook.react.bridge.ReadableArray
+import com.facebook.react.bridge.ReadableMap
+import com.facebook.react.common.ReactConstants
+import com.facebook.react.common.mapbuffer.MapBuffer
+import com.facebook.react.uimanager.PixelUtil.toPixelFromDIP
+import com.facebook.react.uimanager.PixelUtil.toPixelFromSP
+import com.facebook.react.uimanager.ReactAccessibilityDelegate
+import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole
+import com.facebook.react.uimanager.ReactStylesDiffMap
+import com.facebook.react.uimanager.ViewProps
+import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
+import com.facebook.react.views.text.ReactTypefaceUtils.parseFontVariant
+import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
+import kotlin.math.ceil
+
+// TODO: T63643819 refactor naming of TextAttributeProps to make explicit that this represents
+// TextAttributes and not TextProps. As part of this refactor extract methods that don't belong to
+// TextAttributeProps (e.g. TextAlign)
+public class TextAttributeProps private constructor() {
+ public var lineHeight: Float = Float.NaN
+ private set(value) {
+ lineHeightInput = value
+ field =
+ if (value == ReactConstants.UNSET.toFloat()) {
+ Float.NaN
+ } else {
+ if (allowFontScaling) toPixelFromSP(value) else toPixelFromDIP(value)
+ }
+ }
+
+ public var isColorSet: Boolean = false
+ private set
+
+ public var allowFontScaling: Boolean = true
+ private set(value) {
+ if (value != field) {
+ field = value
+ setFontSize(fontSizeInput)
+ lineHeight = lineHeightInput
+ }
+ }
+
+ public var maxFontSizeMultiplier: Float = Float.NaN
+ private set(value) {
+ if (value != field) {
+ field = value
+ setFontSize(fontSizeInput)
+ lineHeight = lineHeightInput
+ }
+ }
+
+ public var isBackgroundColorSet: Boolean = false
+ private set
+
+ public var opacity: Float = Float.NaN
+ private set
+
+ public var numberOfLines: Int = ReactConstants.UNSET
+ private set
+
+ public var fontSize: Int = ReactConstants.UNSET
+ private set
+
+ private var fontSizeInput: Float = ReactConstants.UNSET.toFloat()
+ private var lineHeightInput: Float = ReactConstants.UNSET.toFloat()
+ private var letterSpacingInput: Float = Float.NaN
+
+ // `ReactConstants.UNSET` is -1, same as `LayoutDirection.UNDEFINED` (which is a hidden symbol)
+ public var layoutDirection: Int = ReactConstants.UNSET
+ private set
+
+ internal var textTransform: TextTransform = TextTransform.NONE
+
+ public var isUnderlineTextDecorationSet: Boolean = false
+ private set
+
+ public var isLineThroughTextDecorationSet: Boolean = false
+ private set
+
+ private var includeFontPadding: Boolean = true
+
+ public var accessibilityRole: AccessibilityRole? = null
+ private set
+
+ public var role: ReactAccessibilityDelegate.Role? = null
+ private set
+
+ public var fontStyle: Int = ReactConstants.UNSET
+ private set
+
+ public var fontWeight: Int = ReactConstants.UNSET
+ private set
+
+ /**
+ * NB: If a font family is used that does not have a style in a certain Android version (ie.
+ * monospace bold pre Android 5.0), that style (ie. bold) will not be inherited by nested Text
+ * nodes. To retain that style, you have to add it to those nodes explicitly.
+ *
+ * Example, Android 4.4:
+ *
+ * Bold Text
+ * Bold Text
+ * Bold Text
+ *
+ * Not Bold Text
+ * Not Bold Text
+ * Not Bold Text
+ *
+ * Not Bold Text
+ * Bold Text
+ * Bold Text
+ *
*
+ */
+ public var fontFamily: String? = null
+ private set
+
+ /** @see android.graphics.Paint.setFontFeatureSettings */
+ public var fontFeatureSettings: String? = null
+ private set
+
+ private var heightOfTallestInlineImage: Float = Float.NaN
+
+ public val effectiveLineHeight: Float
+ // Returns a line height which takes into account the requested line height
+ get() {
+ val useInlineViewHeight =
+ !lineHeight.isNaN() &&
+ !heightOfTallestInlineImage.isNaN() &&
+ heightOfTallestInlineImage > lineHeight
+ return if (useInlineViewHeight) heightOfTallestInlineImage else lineHeight
+ }
+
+ private fun setNumberOfLines(numberOfLines: Int) {
+ this.numberOfLines = if (numberOfLines == 0) ReactConstants.UNSET else numberOfLines
+ }
+
+ public var letterSpacing: Float
+ get() {
+ val letterSpacingPixels =
+ if (allowFontScaling) toPixelFromSP(letterSpacingInput)
+ else toPixelFromDIP(letterSpacingInput)
+
+ require(fontSize > 0) { "FontSize should be a positive value. Current value: $fontSize" }
+ // `letterSpacingPixels` and `fontSize` are both in pixels,
+ // yielding an accurate em value.
+ return letterSpacingPixels / fontSize
+ }
+ private set(letterSpacing) {
+ letterSpacingInput = letterSpacing
+ }
+
+ public val effectiveLetterSpacing: Float
+ get() = letterSpacing
+
+ private fun setFontSize(fontSize: Float) {
+ var fontSizeLocal = fontSize
+ fontSizeInput = fontSizeLocal
+ if (fontSizeLocal != ReactConstants.UNSET.toFloat()) {
+ fontSizeLocal =
+ if (allowFontScaling)
+ ceil(toPixelFromSP(fontSize, maxFontSizeMultiplier).toDouble()).toFloat()
+ else ceil(toPixelFromDIP(fontSize).toDouble()).toFloat()
+ }
+ this.fontSize = fontSizeLocal.toInt()
+ }
+
+ public var color: Int? = null
+ private set(value) {
+ isColorSet = (value != null)
+ if (value != null) {
+ field = value
+ }
+ }
+
+ public var backgroundColor: Int? = 0
+ private set(color) {
+ // TODO: Don't apply background color to anchor TextView since it will be applied on the
+ // View directly
+ // if (!isVirtualAnchor()) {
+ isBackgroundColorSet = (color != null)
+ if (color != null) {
+ field = color
+ }
+ // }
+ }
+
+ private fun setFontVariant(fontVariant: ReadableArray?) {
+ fontFeatureSettings = parseFontVariant(fontVariant)
+ }
+
+ private fun setFontVariant(fontVariant: MapBuffer?) {
+ if (fontVariant == null || fontVariant.count == 0) {
+ fontFeatureSettings = null
+ return
+ }
+
+ val features: MutableList = ArrayList()
+ val iterator = fontVariant.iterator()
+ while (iterator.hasNext()) {
+ val entry = iterator.next()
+ val value = entry.stringValue
+ @Suppress("SENSELESS_COMPARISON")
+ if (value != null) {
+ when (value) {
+ "small-caps" -> features.add("'smcp'")
+ "oldstyle-nums" -> features.add("'onum'")
+ "lining-nums" -> features.add("'lnum'")
+ "tabular-nums" -> features.add("'tnum'")
+ "proportional-nums" -> features.add("'pnum'")
+ "stylistic-one" -> features.add("'ss01'")
+ "stylistic-two" -> features.add("'ss02'")
+ "stylistic-three" -> features.add("'ss03'")
+ "stylistic-four" -> features.add("'ss04'")
+ "stylistic-five" -> features.add("'ss05'")
+ "stylistic-six" -> features.add("'ss06'")
+ "stylistic-seven" -> features.add("'ss07'")
+ "stylistic-eight" -> features.add("'ss08'")
+ "stylistic-nine" -> features.add("'ss09'")
+ "stylistic-ten" -> features.add("'ss10'")
+ "stylistic-eleven" -> features.add("'ss11'")
+ "stylistic-twelve" -> features.add("'ss12'")
+ "stylistic-thirteen" -> features.add("'ss13'")
+ "stylistic-fourteen" -> features.add("'ss14'")
+ "stylistic-fifteen" -> features.add("'ss15'")
+ "stylistic-sixteen" -> features.add("'ss16'")
+ "stylistic-seventeen" -> features.add("'ss17'")
+ "stylistic-eighteen" -> features.add("'ss18'")
+ "stylistic-nineteen" -> features.add("'ss19'")
+ "stylistic-twenty" -> features.add("'ss20'")
+ }
+ }
+ }
+ fontFeatureSettings = TextUtils.join(", ", features)
+ }
+
+ private fun setFontWeight(fontWeightString: String?) {
+ fontWeight = parseFontWeight(fontWeightString)
+ }
+
+ private fun setFontStyle(fontStyleString: String?) {
+ fontStyle = parseFontStyle(fontStyleString)
+ }
+
+ private fun setTextDecorationLine(textDecorationLineString: String?) {
+ isUnderlineTextDecorationSet = false
+ isLineThroughTextDecorationSet = false
+ if (textDecorationLineString != null) {
+ for (textDecorationLineSubString in
+ textDecorationLineString
+ .split("-".toRegex())
+ .dropLastWhile { it.isEmpty() }
+ .toTypedArray()) {
+ if ("underline" == textDecorationLineSubString) {
+ isUnderlineTextDecorationSet = true
+ } else if ("strikethrough" == textDecorationLineSubString) {
+ isLineThroughTextDecorationSet = true
+ }
+ }
+ }
+ }
+
+ private fun setTextShadowOffset(offsetMap: ReadableMap?) {
+ textShadowOffsetDx = 0f
+ textShadowOffsetDy = 0f
+
+ if (offsetMap != null) {
+ if (offsetMap.hasKey(PROP_SHADOW_OFFSET_WIDTH) &&
+ !offsetMap.isNull(PROP_SHADOW_OFFSET_WIDTH)) {
+ textShadowOffsetDx = toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_WIDTH))
+ }
+ if (offsetMap.hasKey(PROP_SHADOW_OFFSET_HEIGHT) &&
+ !offsetMap.isNull(PROP_SHADOW_OFFSET_HEIGHT)) {
+ textShadowOffsetDy = toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_HEIGHT))
+ }
+ }
+ }
+
+ public var textShadowOffsetDx: Float = 0f
+ private set(value) {
+ field = toPixelFromDIP(value)
+ }
+
+ public var textShadowOffsetDy: Float = 0f
+ private set(value) {
+ field = toPixelFromDIP(value)
+ }
+
+ private fun setLayoutDirection(layoutDirection: String?) {
+ this.layoutDirection = getLayoutDirection(layoutDirection)
+ }
+
+ public var textShadowRadius: Float = 0f
+ private set(value) {
+ if (value != field) {
+ field = value
+ }
+ }
+
+ public var textShadowColor: Int = DEFAULT_TEXT_SHADOW_COLOR
+ private set(value) {
+ if (value != field) {
+ field = value
+ }
+ }
+
+ private fun setTextTransform(textTransform: String?) {
+ this.textTransform =
+ when (textTransform) {
+ null,
+ "none" -> TextTransform.NONE
+ "uppercase" -> TextTransform.UPPERCASE
+ "lowercase" -> TextTransform.LOWERCASE
+ "capitalize" -> TextTransform.CAPITALIZE
+ else -> {
+ FLog.w(ReactConstants.TAG, "Invalid textTransform: $textTransform")
+ TextTransform.NONE
+ }
+ }
+ }
+
+ private fun setAccessibilityRole(accessibilityRole: String?) {
+ this.accessibilityRole =
+ if (accessibilityRole == null) null else AccessibilityRole.fromValue(accessibilityRole)
+ }
+
+ private fun setRole(role: String?) {
+ if (role == null) {
+ this.role = null
+ } else {
+ this.role = ReactAccessibilityDelegate.Role.fromValue(role)
+ }
+ }
+
+ private fun setRole(role: ReactAccessibilityDelegate.Role) {
+ this.role = role
+ }
+
+ public companion object {
+ // constants for Text Attributes serialization
+ public const val TA_KEY_FOREGROUND_COLOR: Int = 0
+ public const val TA_KEY_BACKGROUND_COLOR: Int = 1
+ public const val TA_KEY_OPACITY: Int = 2
+ public const val TA_KEY_FONT_FAMILY: Int = 3
+ public const val TA_KEY_FONT_SIZE: Int = 4
+ public const val TA_KEY_FONT_SIZE_MULTIPLIER: Int = 5
+ public const val TA_KEY_FONT_WEIGHT: Int = 6
+ public const val TA_KEY_FONT_STYLE: Int = 7
+ public const val TA_KEY_FONT_VARIANT: Int = 8
+ public const val TA_KEY_ALLOW_FONT_SCALING: Int = 9
+ public const val TA_KEY_LETTER_SPACING: Int = 10
+ public const val TA_KEY_LINE_HEIGHT: Int = 11
+ public const val TA_KEY_ALIGNMENT: Int = 12
+ public const val TA_KEY_BEST_WRITING_DIRECTION: Int = 13
+ public const val TA_KEY_TEXT_DECORATION_COLOR: Int = 14
+ public const val TA_KEY_TEXT_DECORATION_LINE: Int = 15
+ public const val TA_KEY_TEXT_DECORATION_STYLE: Int = 16
+ public const val TA_KEY_TEXT_SHADOW_RADIUS: Int = 18
+ public const val TA_KEY_TEXT_SHADOW_COLOR: Int = 19
+ public const val TA_KEY_TEXT_SHADOW_OFFSET_DX: Int = 20
+ public const val TA_KEY_TEXT_SHADOW_OFFSET_DY: Int = 21
+ public const val TA_KEY_IS_HIGHLIGHTED: Int = 22
+ public const val TA_KEY_LAYOUT_DIRECTION: Int = 23
+ public const val TA_KEY_ACCESSIBILITY_ROLE: Int = 24
+ public const val TA_KEY_LINE_BREAK_STRATEGY: Int = 25
+ public const val TA_KEY_ROLE: Int = 26
+ public const val TA_KEY_TEXT_TRANSFORM: Int = 27
+ public const val TA_KEY_MAX_FONT_SIZE_MULTIPLIER: Int = 29
+
+ public const val UNSET: Int = -1
+
+ private const val PROP_SHADOW_OFFSET = "textShadowOffset"
+ private const val PROP_SHADOW_OFFSET_WIDTH = "width"
+ private const val PROP_SHADOW_OFFSET_HEIGHT = "height"
+ private const val PROP_SHADOW_RADIUS = "textShadowRadius"
+ private const val PROP_SHADOW_COLOR = "textShadowColor"
+
+ private const val PROP_TEXT_TRANSFORM = "textTransform"
+
+ private const val DEFAULT_TEXT_SHADOW_COLOR = 0x55000000
+ private val DEFAULT_JUSTIFICATION_MODE =
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) 0 else Layout.JUSTIFICATION_MODE_NONE
+ private const val DEFAULT_BREAK_STRATEGY = Layout.BREAK_STRATEGY_HIGH_QUALITY
+ private const val DEFAULT_HYPHENATION_FREQUENCY = Layout.HYPHENATION_FREQUENCY_NONE
+
+ /** Build a TextAttributeProps using data from the [MapBuffer] received as a parameter. */
+ public fun fromMapBuffer(props: MapBuffer): TextAttributeProps {
+ val result = TextAttributeProps()
+
+ // TODO T83483191: Review constants that are not being set!
+ val iterator = props.iterator()
+ while (iterator.hasNext()) {
+ val entry = iterator.next()
+ when (entry.key) {
+ TA_KEY_FOREGROUND_COLOR -> result.color = entry.intValue
+ TA_KEY_BACKGROUND_COLOR -> result.backgroundColor = entry.intValue
+ TA_KEY_OPACITY -> result.opacity = entry.doubleValue.toFloat()
+ TA_KEY_FONT_FAMILY -> result.fontFamily = entry.stringValue
+ TA_KEY_FONT_SIZE -> result.setFontSize(entry.doubleValue.toFloat())
+ TA_KEY_FONT_SIZE_MULTIPLIER -> {}
+ TA_KEY_FONT_WEIGHT -> result.setFontWeight(entry.stringValue)
+ TA_KEY_FONT_STYLE -> result.setFontStyle(entry.stringValue)
+ TA_KEY_FONT_VARIANT -> result.setFontVariant(entry.mapBufferValue)
+ TA_KEY_ALLOW_FONT_SCALING -> result.allowFontScaling = entry.booleanValue
+ TA_KEY_LETTER_SPACING -> result.letterSpacing = entry.doubleValue.toFloat()
+ TA_KEY_LINE_HEIGHT -> result.lineHeight = entry.doubleValue.toFloat()
+ TA_KEY_ALIGNMENT -> {}
+ TA_KEY_BEST_WRITING_DIRECTION -> {}
+ TA_KEY_TEXT_DECORATION_COLOR -> {}
+ TA_KEY_TEXT_DECORATION_LINE -> result.setTextDecorationLine(entry.stringValue)
+ TA_KEY_TEXT_DECORATION_STYLE -> {}
+ TA_KEY_TEXT_SHADOW_RADIUS -> result.textShadowRadius = entry.doubleValue.toFloat()
+ TA_KEY_TEXT_SHADOW_COLOR -> result.textShadowColor = entry.intValue
+ TA_KEY_TEXT_SHADOW_OFFSET_DX -> result.textShadowOffsetDx = entry.doubleValue.toFloat()
+ TA_KEY_TEXT_SHADOW_OFFSET_DY -> result.textShadowOffsetDy = entry.doubleValue.toFloat()
+ TA_KEY_IS_HIGHLIGHTED -> {}
+ TA_KEY_LAYOUT_DIRECTION -> result.setLayoutDirection(entry.stringValue)
+ TA_KEY_ACCESSIBILITY_ROLE -> result.setAccessibilityRole(entry.stringValue)
+ TA_KEY_ROLE -> result.setRole(ReactAccessibilityDelegate.Role.entries[entry.intValue])
+ TA_KEY_TEXT_TRANSFORM -> result.setTextTransform(entry.stringValue)
+ TA_KEY_MAX_FONT_SIZE_MULTIPLIER ->
+ result.maxFontSizeMultiplier = entry.doubleValue.toFloat()
+ }
+ }
+
+ // TODO T83483191: Review why the following props are not serialized:
+ // setNumberOfLines
+ // setColor
+ // setIncludeFontPadding
+ return result
+ }
+
+ public fun fromReadableMap(props: ReactStylesDiffMap): TextAttributeProps {
+ val result = TextAttributeProps()
+ result.setNumberOfLines(getIntProp(props, ViewProps.NUMBER_OF_LINES, ReactConstants.UNSET))
+ result.lineHeight = getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET.toFloat())
+ result.letterSpacing = getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN)
+ result.allowFontScaling = getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true)
+ result.maxFontSizeMultiplier =
+ getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN)
+ result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET.toFloat()))
+ result.color = if (props.hasKey(ViewProps.COLOR)) props.getInt(ViewProps.COLOR, 0) else null
+ result.color =
+ if (props.hasKey(ViewProps.FOREGROUND_COLOR)) props.getInt(ViewProps.FOREGROUND_COLOR, 0)
+ else null
+ result.backgroundColor =
+ if (props.hasKey(ViewProps.BACKGROUND_COLOR)) props.getInt(ViewProps.BACKGROUND_COLOR, 0)
+ else null
+ result.opacity = getFloatProp(props, ViewProps.OPACITY, Float.NaN)
+ result.fontFamily = getStringProp(props, ViewProps.FONT_FAMILY)
+ result.setFontWeight(getStringProp(props, ViewProps.FONT_WEIGHT))
+ result.setFontStyle(getStringProp(props, ViewProps.FONT_STYLE))
+ result.setFontVariant(getArrayProp(props, ViewProps.FONT_VARIANT))
+ result.includeFontPadding = getBooleanProp(props, ViewProps.INCLUDE_FONT_PADDING, true)
+ result.setTextDecorationLine(getStringProp(props, ViewProps.TEXT_DECORATION_LINE))
+ result.setTextShadowOffset(
+ if (props.hasKey(PROP_SHADOW_OFFSET)) props.getMap(PROP_SHADOW_OFFSET) else null)
+ result.textShadowRadius = getFloatProp(props, PROP_SHADOW_RADIUS, 1f)
+ result.textShadowColor = getIntProp(props, PROP_SHADOW_COLOR, DEFAULT_TEXT_SHADOW_COLOR)
+ result.setTextTransform(getStringProp(props, PROP_TEXT_TRANSFORM))
+ result.setLayoutDirection(getStringProp(props, ViewProps.LAYOUT_DIRECTION))
+ result.setAccessibilityRole(getStringProp(props, ViewProps.ACCESSIBILITY_ROLE))
+ result.setRole(getStringProp(props, ViewProps.ROLE))
+ return result
+ }
+
+ public fun getTextAlignment(props: ReactStylesDiffMap, isRTL: Boolean, defaultValue: Int): Int {
+ if (!props.hasKey(ViewProps.TEXT_ALIGN)) {
+ return defaultValue
+ }
+
+ return when (val textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN)) {
+ "justify" -> Gravity.LEFT
+ null,
+ "auto" -> Gravity.NO_GRAVITY
+ "left" -> if (isRTL) Gravity.RIGHT else Gravity.LEFT
+ "right" -> if (isRTL) Gravity.LEFT else Gravity.RIGHT
+ "center" -> Gravity.CENTER_HORIZONTAL
+ else -> {
+ FLog.w(ReactConstants.TAG, "Invalid textAlign: $textAlignPropValue")
+ Gravity.NO_GRAVITY
+ }
+ }
+ }
+
+ public fun getJustificationMode(props: ReactStylesDiffMap, defaultValue: Int): Int {
+ if (!props.hasKey(ViewProps.TEXT_ALIGN)) {
+ return defaultValue
+ }
+
+ val textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN)
+ if ("justify" == textAlignPropValue && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ return Layout.JUSTIFICATION_MODE_INTER_WORD
+ }
+ return DEFAULT_JUSTIFICATION_MODE
+ }
+
+ private fun getBooleanProp(
+ props: ReactStylesDiffMap,
+ name: String,
+ defaultValue: Boolean
+ ): Boolean = if (props.hasKey(name)) props.getBoolean(name, defaultValue) else defaultValue
+
+ private fun getStringProp(props: ReactStylesDiffMap, name: String): String? =
+ if (props.hasKey(name)) props.getString(name) else null
+
+ private fun getIntProp(props: ReactStylesDiffMap, name: String, defaultValue: Int): Int =
+ if (props.hasKey(name)) props.getInt(name, defaultValue) else defaultValue
+
+ private fun getFloatProp(props: ReactStylesDiffMap, name: String, defaultValue: Float): Float =
+ if (props.hasKey(name)) props.getFloat(name, defaultValue) else defaultValue
+
+ private fun getArrayProp(props: ReactStylesDiffMap, name: String): ReadableArray? =
+ if (props.hasKey(name)) props.getArray(name) else null
+
+ public fun getLayoutDirection(layoutDirection: String?): Int {
+ return when (layoutDirection) {
+ null,
+ "undefined" -> ReactConstants.UNSET
+ "rtl" -> LayoutDirection.RTL
+ "ltr" -> LayoutDirection.LTR
+ else -> {
+ FLog.w(ReactConstants.TAG, "Invalid layoutDirection: $layoutDirection")
+ ReactConstants.UNSET
+ }
+ }
+ }
+
+ public fun getTextBreakStrategy(textBreakStrategy: String?): Int =
+ when (textBreakStrategy) {
+ null -> DEFAULT_BREAK_STRATEGY
+ "simple" -> Layout.BREAK_STRATEGY_SIMPLE
+ "balanced" -> Layout.BREAK_STRATEGY_BALANCED
+ else -> Layout.BREAK_STRATEGY_HIGH_QUALITY
+ }
+
+ public fun getHyphenationFrequency(hyphenationFrequency: String?): Int =
+ when (hyphenationFrequency) {
+ null -> DEFAULT_HYPHENATION_FREQUENCY
+ "none" -> Layout.HYPHENATION_FREQUENCY_NONE
+ "normal" -> Layout.HYPHENATION_FREQUENCY_NORMAL
+ else -> Layout.HYPHENATION_FREQUENCY_FULL
+ }
+
+ public fun getEllipsizeMode(ellipsizeMode: String?): TruncateAt? =
+ when (ellipsizeMode) {
+ "head" -> TruncateAt.START
+ "middle" -> TruncateAt.MIDDLE
+ "tail" -> TruncateAt.END
+ "clip" -> null
+ else -> null
+ }
+ }
+}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt
index 7f66d6b0123..2a9ec5cb045 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt
@@ -231,7 +231,7 @@ internal object TextLayoutManager {
TextAttributeProps.fromMapBuffer(fragment.getMapBuffer(FR_KEY_TEXT_ATTRIBUTES))
sb.append(
- TextTransform.apply(fragment.getString(FR_KEY_STRING), textAttributes.mTextTransform))
+ TextTransform.apply(fragment.getString(FR_KEY_STRING), textAttributes.textTransform))
val end = sb.length
val reactTag =
@@ -246,10 +246,10 @@ internal object TextLayoutManager {
TextInlineViewPlaceholderSpan(reactTag, width.toInt(), height.toInt())))
} else if (end >= start) {
val roleIsLink =
- if (textAttributes.mRole != null)
- (textAttributes.mRole == ReactAccessibilityDelegate.Role.LINK)
+ if (textAttributes.role != null)
+ (textAttributes.role == ReactAccessibilityDelegate.Role.LINK)
else
- (textAttributes.mAccessibilityRole ==
+ (textAttributes.accessibilityRole ==
ReactAccessibilityDelegate.AccessibilityRole.LINK)
if (roleIsLink) {
if (ReactNativeFeatureFlags.enablePreparedTextLayout()) {
@@ -258,13 +258,17 @@ internal object TextLayoutManager {
ops.add(SetSpanOperation(start, end, ReactClickableSpan(reactTag)))
}
}
- if (textAttributes.mIsColorSet) {
- ops.add(SetSpanOperation(start, end, ReactForegroundColorSpan(textAttributes.mColor)))
+ if (textAttributes.isColorSet) {
+ textAttributes.color
+ ?.let { ReactForegroundColorSpan(it) }
+ ?.let { SetSpanOperation(start, end, it) }
+ ?.let { ops.add(it) }
}
- if (textAttributes.mIsBackgroundColorSet) {
- ops.add(
- SetSpanOperation(
- start, end, ReactBackgroundColorSpan(textAttributes.mBackgroundColor)))
+ if (textAttributes.isBackgroundColorSet) {
+ textAttributes.backgroundColor
+ ?.let { ReactBackgroundColorSpan(it) }
+ ?.let { SetSpanOperation(start, end, it) }
+ ?.let { ops.add(it) }
}
if (!textAttributes.opacity.isNaN()) {
ops.add(SetSpanOperation(start, end, ReactOpacitySpan(textAttributes.opacity)))
@@ -273,40 +277,40 @@ internal object TextLayoutManager {
ops.add(
SetSpanOperation(start, end, CustomLetterSpacingSpan(textAttributes.letterSpacing)))
}
- ops.add(SetSpanOperation(start, end, ReactAbsoluteSizeSpan(textAttributes.mFontSize)))
- if (textAttributes.mFontStyle != ReactConstants.UNSET ||
- textAttributes.mFontWeight != ReactConstants.UNSET ||
- textAttributes.mFontFamily != null) {
+ ops.add(SetSpanOperation(start, end, ReactAbsoluteSizeSpan(textAttributes.fontSize)))
+ if (textAttributes.fontStyle != ReactConstants.UNSET ||
+ textAttributes.fontWeight != ReactConstants.UNSET ||
+ textAttributes.fontFamily != null) {
ops.add(
SetSpanOperation(
start,
end,
CustomStyleSpan(
- textAttributes.mFontStyle,
- textAttributes.mFontWeight,
- textAttributes.mFontFeatureSettings,
- textAttributes.mFontFamily,
+ textAttributes.fontStyle,
+ textAttributes.fontWeight,
+ textAttributes.fontFeatureSettings,
+ textAttributes.fontFamily,
context.assets)))
}
- if (textAttributes.mIsUnderlineTextDecorationSet) {
+ if (textAttributes.isUnderlineTextDecorationSet) {
ops.add(SetSpanOperation(start, end, ReactUnderlineSpan()))
}
- if (textAttributes.mIsLineThroughTextDecorationSet) {
+ if (textAttributes.isLineThroughTextDecorationSet) {
ops.add(SetSpanOperation(start, end, ReactStrikethroughSpan()))
}
- if ((textAttributes.mTextShadowOffsetDx != 0f ||
- textAttributes.mTextShadowOffsetDy != 0f ||
- textAttributes.mTextShadowRadius != 0f) &&
- Color.alpha(textAttributes.mTextShadowColor) != 0) {
+ if ((textAttributes.textShadowOffsetDx != 0f ||
+ textAttributes.textShadowOffsetDy != 0f ||
+ textAttributes.textShadowRadius != 0f) &&
+ Color.alpha(textAttributes.textShadowColor) != 0) {
ops.add(
SetSpanOperation(
start,
end,
ShadowStyleSpan(
- textAttributes.mTextShadowOffsetDx,
- textAttributes.mTextShadowOffsetDy,
- textAttributes.mTextShadowRadius,
- textAttributes.mTextShadowColor)))
+ textAttributes.textShadowOffsetDx,
+ textAttributes.textShadowOffsetDy,
+ textAttributes.textShadowRadius,
+ textAttributes.textShadowColor)))
}
if (!textAttributes.effectiveLineHeight.isNaN()) {
ops.add(
@@ -409,12 +413,16 @@ internal object TextLayoutManager {
}
if (fragment.props.isColorSet) {
- spannable.setSpan(ReactForegroundColorSpan(fragment.props.color), start, end, spanFlags)
+ spannable.setSpan(
+ fragment.props.color?.let { ReactForegroundColorSpan(it) }, start, end, spanFlags)
}
if (fragment.props.isBackgroundColorSet) {
spannable.setSpan(
- ReactBackgroundColorSpan(fragment.props.backgroundColor), start, end, spanFlags)
+ fragment.props.backgroundColor?.let { ReactBackgroundColorSpan(it) },
+ start,
+ end,
+ spanFlags)
}
if (!fragment.props.opacity.isNaN()) {
@@ -426,8 +434,7 @@ internal object TextLayoutManager {
CustomLetterSpacingSpan(fragment.props.letterSpacing), start, end, spanFlags)
}
- // TODO: Should this be using effectiveFontSize instead of fontSize?
- spannable.setSpan(ReactAbsoluteSizeSpan(fragment.props.mFontSize), start, end, spanFlags)
+ spannable.setSpan(ReactAbsoluteSizeSpan(fragment.props.fontSize), start, end, spanFlags)
if (fragment.props.fontStyle != ReactConstants.UNSET ||
fragment.props.fontWeight != ReactConstants.UNSET ||
@@ -611,8 +618,8 @@ internal object TextLayoutManager {
baseTextAttributes: TextAttributeProps,
context: Context
) {
- if (baseTextAttributes.effectiveFontSize != ReactConstants.UNSET) {
- paint.textSize = baseTextAttributes.effectiveFontSize.toFloat()
+ if (baseTextAttributes.fontSize != ReactConstants.UNSET) {
+ paint.textSize = baseTextAttributes.fontSize.toFloat()
}
if (baseTextAttributes.fontStyle != ReactConstants.UNSET ||