Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix maxFontSizeMultiplier prop on Text and TextInput components in new architecture #47614

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class TextAttributeProps {
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;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I've skipped 28 here. It's reserved by TA_KEY_ALIGNMENT_VERTICAL in attributedstring/conversions.h, but is missing its equivalent in this file. Might be another bug.


public static final int UNSET = -1;

Expand All @@ -81,6 +82,7 @@ public class TextAttributeProps {
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;
Expand Down Expand Up @@ -227,6 +229,9 @@ public static TextAttributeProps fromMapBuffer(MapBuffer props) {
case TA_KEY_TEXT_TRANSFORM:
result.setTextTransform(entry.getStringValue());
break;
case TA_KEY_MAX_FONT_SIZE_MULTIPLIER:
result.setMaxFontSizeMultiplier((float) entry.getDoubleValue());
break;
}
}

Expand All @@ -243,6 +248,7 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) {
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(
Expand Down Expand Up @@ -411,7 +417,14 @@ private void setAllowFontScaling(boolean allowFontScaling) {
mAllowFontScaling = allowFontScaling;
setFontSize(mFontSizeInput);
setLineHeight(mLineHeightInput);
setLetterSpacing(mLetterSpacingInput);
}
}

private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) {
mMaxFontSizeMultiplier = maxFontSizeMultiplier;
setFontSize(mFontSizeInput);
setLineHeight(mLineHeightInput);
}
}

Expand All @@ -420,7 +433,7 @@ private void setFontSize(float fontSize) {
if (fontSize != ReactConstants.UNSET) {
fontSize =
mAllowFontScaling
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize))
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier))
: (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));
}
mFontSize = (int) fontSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) {
allowFontScaling = textAttributes.allowFontScaling.has_value()
? textAttributes.allowFontScaling
: allowFontScaling;
maxFontSizeMultiplier = !std::isnan(textAttributes.maxFontSizeMultiplier)
? textAttributes.maxFontSizeMultiplier
: maxFontSizeMultiplier;
dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value()
? textAttributes.dynamicTypeRamp
: dynamicTypeRamp;
Expand Down Expand Up @@ -168,6 +171,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
rhs.accessibilityRole,
rhs.role,
rhs.textTransform) &&
floatEquality(maxFontSizeMultiplier, rhs.maxFontSizeMultiplier) &&
floatEquality(opacity, rhs.opacity) &&
floatEquality(fontSize, rhs.fontSize) &&
floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) &&
Expand Down Expand Up @@ -211,6 +215,7 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const {
debugStringConvertibleItem("fontStyle", fontStyle),
debugStringConvertibleItem("fontVariant", fontVariant),
debugStringConvertibleItem("allowFontScaling", allowFontScaling),
debugStringConvertibleItem("maxFontSizeMultiplier", maxFontSizeMultiplier),
debugStringConvertibleItem("dynamicTypeRamp", dynamicTypeRamp),
debugStringConvertibleItem("letterSpacing", letterSpacing),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible {
std::optional<FontStyle> fontStyle{};
std::optional<FontVariant> fontVariant{};
std::optional<bool> allowFontScaling{};
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
std::optional<TextTransform> textTransform{};
Expand Down Expand Up @@ -117,6 +118,7 @@ struct hash<facebook::react::TextAttributes> {
textAttributes.opacity,
textAttributes.fontFamily,
textAttributes.fontSize,
textAttributes.maxFontSizeMultiplier,
textAttributes.fontSizeMultiplier,
textAttributes.fontWeight,
textAttributes.fontStyle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25;
constexpr static MapBuffer::Key TA_KEY_ROLE = 26;
constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27;
constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28;
constexpr static MapBuffer::Key TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;

// constants for ParagraphAttributes serialization
constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0;
Expand Down Expand Up @@ -1004,6 +1005,9 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) {
builder.putBool(
TA_KEY_ALLOW_FONT_SCALING, *textAttributes.allowFontScaling);
}
if (!std::isnan(textAttributes.maxFontSizeMultiplier)) {
builder.putDouble(TA_KEY_MAX_FONT_SIZE_MULTIPLIER, textAttributes.maxFontSizeMultiplier);
}
if (!std::isnan(textAttributes.letterSpacing)) {
builder.putDouble(TA_KEY_LETTER_SPACING, textAttributes.letterSpacing);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ static TextAttributes convertRawProp(
"allowFontScaling",
sourceTextAttributes.allowFontScaling,
defaultTextAttributes.allowFontScaling);
textAttributes.maxFontSizeMultiplier = convertRawProp(
context,
rawProps,
"maxFontSizeMultiplier",
sourceTextAttributes.maxFontSizeMultiplier,
defaultTextAttributes.maxFontSizeMultiplier);
textAttributes.dynamicTypeRamp = convertRawProp(
context,
rawProps,
Expand Down Expand Up @@ -266,6 +272,8 @@ void BaseTextProps::setProp(
defaults, value, textAttributes, fontVariant, "fontVariant");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, allowFontScaling, "allowFontScaling");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, maxFontSizeMultiplier, "maxFontSizeMultiplier");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, letterSpacing, "letterSpacing");
REBUILD_FIELD_SWITCH_CASE(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex
isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize;
return [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
} else {
return textAttributes.fontSizeMultiplier;
Float fontSizeMultiplier = textAttributes.fontSizeMultiplier;
Float maxFontSizeMultiplier =
isnan(textAttributes.maxFontSizeMultiplier) ? 0.0 : textAttributes.maxFontSizeMultiplier;
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
}
} else {
return 1.0;
Expand Down
38 changes: 38 additions & 0 deletions packages/rn-tester/js/examples/Text/TextExample.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,37 @@ function AllowFontScalingExample(props: {}): React.Node {
);
}

function MaxFontSizeMultiplierExample(props: {}): React.Node {
return (
<>
<Text>
When allowFontScaling is enabled, you can use the maxFontSizeMultiplier
prop to set an upper limit on how much the font size will be scaled.
</Text>
<Text
allowFontScaling={true}
maxFontSizeMultiplier={1}
style={{marginTop: 10}}>
This text will not scale up (max 1x)
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
This text will scale up (max 1.5x)
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text>Inherit max (max 1x)</Text>
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text maxFontSizeMultiplier={1.5}>
Override inherited max (max 1.5x)
</Text>
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
</Text>
</>
);
}

function NumberOfLinesExample(props: {}): React.Node {
return (
<>
Expand Down Expand Up @@ -1370,6 +1401,13 @@ const examples = [
return <AllowFontScalingExample />;
},
},
{
title: 'maxFontSizeMultiplier attribute',
name: 'maxFontSizeMultiplier',
render(): React.Node {
return <MaxFontSizeMultiplierExample />;
},
},
{
title: 'selectable attribute',
name: 'selectable',
Expand Down
35 changes: 35 additions & 0 deletions packages/rn-tester/js/examples/Text/TextExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,41 @@ const examples = [
);
},
},
{
title: 'maxFontSizeMultiplier attribute',
name: 'maxFontSizeMultiplier',
render(): React.Node {
return (
<>
<Text>
When allowFontScaling is enabled, you can use the
maxFontSizeMultiplier prop to set an upper limit on how much the
font size will be scaled.
</Text>
<Text
allowFontScaling={true}
maxFontSizeMultiplier={1}
style={{marginTop: 10}}>
This text will not scale up (max 1x)
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
This text will scale up (max 1.5x)
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text>Inherit max (max 1x)</Text>
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text maxFontSizeMultiplier={1.5}>
Override inherited max (max 1.5x)
</Text>
</Text>
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
</Text>
</>
);
},
},
{
title: 'Inline views',
render: (): React.Node => <TextInlineView.Basic />,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,57 @@ const examples: Array<RNTesterModuleExample> = [
);
},
},
{
title: 'allowFontScaling attribute',
render: function (): React.Node {
return (
<View>
<Text>
By default, text will respect Text Size accessibility setting on
Android. It means that all font sizes will be increased or decreased
depending on the value of the Text Size setting in the OS's Settings
app.
</Text>
<ExampleTextInput
placeholder="allowFontScaling = false"
allowFontScaling={false}
/>
<ExampleTextInput
style={{marginTop: 10}}
placeholder="allowFontScaling = false"
allowFontScaling={true}
/>
</View>
);
},
},
{
title: 'maxFontSizeMultiplier attribute',
name: 'maxFontSizeMultiplier',
render(): React.Node {
return (
<View>
<Text>
When allowFontScaling is enabled, you can use the
maxFontSizeMultiplier prop to set an upper limit on how much the
font size will be scaled.
</Text>
<ExampleTextInput
allowFontScaling={true}
maxFontSizeMultiplier={1}
placeholder="This text will not scale up (max 1x)"
style={{marginTop: 10}}
/>
<ExampleTextInput
allowFontScaling={true}
maxFontSizeMultiplier={1.5}
placeholder="This text will scale up (max 1.5x)"
style={{marginTop: 10}}
/>
</View>
);
},
},
{
title: 'Auto-expanding',
render: function (): React.Node {
Expand Down
54 changes: 54 additions & 0 deletions packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import type {KeyboardType} from 'react-native/Libraries/Components/TextInput/TextInput';

import ExampleTextInput from './ExampleTextInput';
import {TextInput} from 'react-native';

Check warning on line 20 in packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js

View workflow job for this annotation

GitHub Actions / test_js (20)

'TextInput' is defined but never used

Check warning on line 20 in packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js

View workflow job for this annotation

GitHub Actions / test_js (18)

'TextInput' is defined but never used

const TextInputSharedExamples = require('./TextInputSharedExamples.js');
const React = require('react');
Expand Down Expand Up @@ -691,6 +692,59 @@
);
},
},
{
title: 'allowFontScaling attribute',
render: function (): React.Node {
return (
<View>
<Text>
By default, text will respect Text Size accessibility setting on
iOS. It means that all font sizes will be increased or decreased
depending on the value of Text Size setting in{' '}
<Text style={{fontWeight: 'bold'}}>
Settings.app - Display & Brightness - Text Size
</Text>
</Text>
<ExampleTextInput
placeholder="allowFontScaling = false"
allowFontScaling={false}
/>
<ExampleTextInput
style={{marginTop: 10}}
placeholder="allowFontScaling = false"
allowFontScaling={true}
/>
</View>
);
},
},
{
title: 'maxFontSizeMultiplier attribute',
name: 'maxFontSizeMultiplier',
render(): React.Node {
return (
<View>
<Text>
When allowFontScaling is enabled, you can use the
maxFontSizeMultiplier prop to set an upper limit on how much the
font size will be scaled.
</Text>
<ExampleTextInput
allowFontScaling={true}
maxFontSizeMultiplier={1}
placeholder="This text will not scale up (max 1x)"
style={{marginTop: 10}}
/>
<ExampleTextInput
allowFontScaling={true}
maxFontSizeMultiplier={1.5}
placeholder="This text will scale up (max 1.5x)"
style={{marginTop: 10}}
/>
</View>
);
},
},
{
title: 'Auto-expanding',
render: function (): React.Node {
Expand Down
Loading