Add Dynamic Text support plus test page

This commit is contained in:
Adam Gleitman 2022-09-30 16:23:23 -07:00
Родитель ab720113d4
Коммит c56ccdfa90
9 изменённых файлов: 218 добавлений и 30 удалений

Просмотреть файл

@ -36,6 +36,7 @@ RCT_REMAP_SHADOW_PROPERTY(fontWeight, textAttributes.fontWeight, NSString)
RCT_REMAP_SHADOW_PROPERTY(fontStyle, textAttributes.fontStyle, NSString)
RCT_REMAP_SHADOW_PROPERTY(fontVariant, textAttributes.fontVariant, NSArray)
RCT_REMAP_SHADOW_PROPERTY(allowFontScaling, textAttributes.allowFontScaling, BOOL)
RCT_REMAP_SHADOW_PROPERTY(fontScaleRamp, textAttributes.fontScaleRamp, RCTFontScaleRamp)
RCT_REMAP_SHADOW_PROPERTY(maxFontSizeMultiplier, textAttributes.maxFontSizeMultiplier, CGFloat)
RCT_REMAP_SHADOW_PROPERTY(letterSpacing, textAttributes.letterSpacing, CGFloat)
RCT_REMAP_SHADOW_PROPERTY(apple_fontSmoothing, textAttributes.fontSmoothing, RCTFontSmoothing) // TODO(OSS Candidate ISS#2710739)

Просмотреть файл

@ -8,6 +8,7 @@
#import <React/RCTUIKit.h> // TODO(macOS GH#774)
#import <React/RCTTextDecorationLineType.h>
#import <React/RCTFontScaleRamp.h>
#import <React/RCTFontSmoothing.h> // TODO(OSS Candidate ISS#2710739)
#import "RCTTextTransform.h"
@ -38,6 +39,7 @@ extern NSString *const RCTTextAttributesTagAttributeName;
@property (nonatomic, copy, nullable) NSString *fontStyle;
@property (nonatomic, copy, nullable) NSArray<NSString *> *fontVariant;
@property (nonatomic, assign) BOOL allowFontScaling;
@property (nonatomic, assign) RCTFontScaleRamp fontScaleRamp;
@property (nonatomic, assign) CGFloat letterSpacing;
@property (nonatomic, assign) RCTFontSmoothing fontSmoothing; // TODO(OSS Candidate ISS#2710739)
@property (class, nonatomic, assign) RCTFontSmoothing fontSmoothingDefault; // TODO(OSS Candidate ISS#2710739)

Просмотреть файл

@ -70,6 +70,7 @@ NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttrib
_fontStyle = textAttributes->_fontStyle ?: _fontStyle;
_fontVariant = textAttributes->_fontVariant ?: _fontVariant;
_allowFontScaling = textAttributes->_allowFontScaling || _allowFontScaling; // *
_fontScaleRamp = textAttributes->_fontScaleRamp != RCTFontScaleRampUndefined ? textAttributes->_fontScaleRamp : _fontScaleRamp;
_letterSpacing = !isnan(textAttributes->_letterSpacing) ? textAttributes->_letterSpacing : _letterSpacing;
_fontSmoothing = textAttributes->_fontSmoothing != RCTFontSmoothingAuto ? textAttributes->_fontSmoothing : _fontSmoothing; // TODO(OSS Candidate ISS#2710739)
@ -230,6 +231,13 @@ NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttrib
if (fontScalingEnabled) {
CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0;
#if !TARGET_OS_OSX // [TODO(macOS GH#774)
if (_fontScaleRamp != RCTFontScaleRampUndefined) {
UIFontMetrics *fontMetrics = RCTUIFontMetricsForFontScaleRamp(_fontScaleRamp);
CGFloat baseSize = RCTUIBaseSizeForFontScaleRamp(_fontScaleRamp);
fontSizeMultiplier = [fontMetrics scaledValueForValue:baseSize] / baseSize;
}
#endif // ]TODO(macOS GH#774)
CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0;
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
} else {
@ -328,6 +336,7 @@ static NSString *capitalizeText(NSString *text)
RCTTextAttributesCompareObjects(_fontStyle) &&
RCTTextAttributesCompareObjects(_fontVariant) &&
RCTTextAttributesCompareOthers(_allowFontScaling) &&
RCTTextAttributesCompareOthers(_fontScaleRamp) &&
RCTTextAttributesCompareFloats(_letterSpacing) &&
RCTTextAttributesCompareOthers(_fontSmoothing) && // TODO(OSS Candidate ISS#2710739)
// Paragraph Styles

Просмотреть файл

@ -0,0 +1,38 @@
/*
* 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.
*/
#import <Foundation/Foundation.h>
#import <React/RCTConvert.h>
typedef NS_ENUM(NSInteger, RCTFontScaleRamp) {
RCTFontScaleRampUndefined,
RCTFontScaleRampCaption2,
RCTFontScaleRampCaption1,
RCTFontScaleRampFootnote,
RCTFontScaleRampSubhead,
RCTFontScaleRampCallout,
RCTFontScaleRampBody,
RCTFontScaleRampHeadline,
RCTFontScaleRampTitle3,
RCTFontScaleRampTitle2,
RCTFontScaleRampTitle1,
RCTFontScaleRampLargeTitle
};
@interface RCTConvert (FontScaleRamp)
+ (RCTFontScaleRamp)RCTFontScaleRamp:(nullable id)json;
@end
#if !TARGET_OS_OSX // [TODO(macOS GH#774)
/// Generates a `UIFontMetrics` instance representing a particular font scale ramp.
UIFontMetrics * _Nonnull RCTUIFontMetricsForFontScaleRamp(RCTFontScaleRamp fontScaleRamp);
/// The "reference" size for a particular font scale ramp, equal to a text element's size under default text size settings.
CGFloat RCTUIBaseSizeForFontScaleRamp(RCTFontScaleRamp fontScaleRamp);
#endif // ]TODO(macOS GH#774)

Просмотреть файл

@ -0,0 +1,75 @@
/*
* 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.
*/
#import <React/RCTFontScaleRamp.h>
@implementation RCTConvert (FontScaleRamp)
RCT_ENUM_CONVERTER(RCTFontScaleRamp, (@{
@"caption2": @(RCTFontScaleRampCaption2),
@"caption1": @(RCTFontScaleRampCaption1),
@"footnote": @(RCTFontScaleRampFootnote),
@"subhead": @(RCTFontScaleRampSubhead),
@"callout": @(RCTFontScaleRampCallout),
@"body": @(RCTFontScaleRampBody),
@"headline": @(RCTFontScaleRampHeadline),
@"title3": @(RCTFontScaleRampTitle3),
@"title2": @(RCTFontScaleRampTitle2),
@"title1": @(RCTFontScaleRampTitle1),
@"largeTitle": @(RCTFontScaleRampLargeTitle),
}), RCTFontScaleRampUndefined, integerValue)
@end
#if !TARGET_OS_OSX // [TODO(macOS GH#774)
UIFontMetrics *RCTUIFontMetricsForFontScaleRamp(RCTFontScaleRamp fontScaleRamp) {
static NSDictionary<NSNumber *, UIFontTextStyle> *mapping;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mapping = @{
@(RCTFontScaleRampCaption2): UIFontTextStyleCaption2,
@(RCTFontScaleRampCaption1): UIFontTextStyleCaption1,
@(RCTFontScaleRampFootnote): UIFontTextStyleFootnote,
@(RCTFontScaleRampSubhead): UIFontTextStyleSubheadline,
@(RCTFontScaleRampCallout): UIFontTextStyleCallout,
@(RCTFontScaleRampBody): UIFontTextStyleBody,
@(RCTFontScaleRampHeadline): UIFontTextStyleHeadline,
@(RCTFontScaleRampTitle3): UIFontTextStyleTitle3,
@(RCTFontScaleRampTitle2): UIFontTextStyleTitle2,
@(RCTFontScaleRampTitle1): UIFontTextStyleTitle1,
@(RCTFontScaleRampLargeTitle): UIFontTextStyleLargeTitle,
};
});
id textStyle = mapping[@(fontScaleRamp)] ?: UIFontTextStyleBody; // Default to body if we don't recognize the specified ramp
return [UIFontMetrics metricsForTextStyle:textStyle];
}
CGFloat RCTUIBaseSizeForFontScaleRamp(RCTFontScaleRamp fontScaleRamp) {
static NSDictionary<NSNumber *, NSNumber *> *mapping;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Values taken from https://developer.apple.com/design/human-interface-guidelines/foundations/typography/
mapping = @{
@(RCTFontScaleRampCaption2): @11,
@(RCTFontScaleRampCaption1): @12,
@(RCTFontScaleRampFootnote): @13,
@(RCTFontScaleRampSubhead): @15,
@(RCTFontScaleRampCallout): @16,
@(RCTFontScaleRampBody): @17,
@(RCTFontScaleRampHeadline): @17,
@(RCTFontScaleRampTitle3): @20,
@(RCTFontScaleRampTitle2): @22,
@(RCTFontScaleRampTitle1): @28,
@(RCTFontScaleRampLargeTitle): @34,
};
});
NSNumber *baseSize = mapping[@(fontScaleRamp)] ?: @17; // Default to body size if we don't recognize the specified ramp
return CGFLOAT_IS_DOUBLE ? [baseSize doubleValue] : [baseSize floatValue];
}
#endif // ]TODO(macOS GH#774)

Просмотреть файл

@ -34,6 +34,7 @@ export const NativeText: HostComponent<NativeTextProps> =
numberOfLines: true,
ellipsizeMode: true,
allowFontScaling: true,
fontScaleRamp: true,
maxFontSizeMultiplier: true,
disabled: true,
selectable: true,

Просмотреть файл

@ -186,6 +186,23 @@ export type TextProps = $ReadOnly<{|
*/
adjustsFontSizeToFit?: ?boolean,
/**
* The Dynamic Text scale ramp to apply to this element on iOS.
*/
fontScaleRamp?: ?(
| 'caption2'
| 'caption1'
| 'footnote'
| 'subhead'
| 'callout'
| 'body'
| 'headline'
| 'title3'
| 'title2'
| 'title1'
| 'largeTitle'
),
/**
* Smallest possible scale a font can reach.
*

Просмотреть файл

@ -563,8 +563,8 @@ SPEC CHECKSUMS:
boost: 613e39eac4239cc72b15421247b5ab05361266a2
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: ed15e075aa758ac0e4c1f8b830bd4e4d40d669e8
FBLazyVector: 8c015ab0962fa7ca8b83a2f85486553ee12fa2c3
FBReactNativeSpec: d5e0e1eab0166d3998da480c3277a4fc9d5beef9
FBLazyVector: e80429cc05cff5705af0a97a22a0f1be1d87ebf3
FBReactNativeSpec: edc16f1d57552d580d21fe5a640c0ad76c6a1b91
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c
@ -580,37 +580,37 @@ SPEC CHECKSUMS:
OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
RCT-Folly: 24c6da766832002a4a2aac5f79ee0ca50fbe8507
RCTRequired: 1efc34e0e287a4e1b514fcc9e163651c44c3dd9d
RCTTypeSafety: 239fff897dcb1fe657556057955c7e571d201d94
React: 0bb0907e6c1cd7ab1d1944c513fb8a278724135d
React-callinvoker: d982ccf1b8ac51b93deee087cb8ca5af41269e70
RCTRequired: d464086ee8d610689a8968ebb940815916685a97
RCTTypeSafety: a25d8ad134c389a662ce207d09c33ae2e6f31f59
React: eee389898adae6450c1bb131b0bdd1a6fe5e596f
React-callinvoker: ef69b20aa08b4c7051a8a72b276954818145d491
React-Codegen: b3fbef96f960cb15fc61250078b0700cfd4cd8a1
React-Core: 7388e919ba68e29e2068bb2dc4c83ee0e176c277
React-CoreModules: 7424cb36a2e91d9af6b01d1b20c9701a2fcdc322
React-cxxreact: d7be72a8ac63c058dff0da14a2340e461dee5a06
React-jsi: 6679d5fd952443b2945ad502f8f592f5a61916db
React-jsiexecutor: 8a92c56f39dbbaaf23b834b78a4aa950ac61f1f3
React-jsinspector: f5d9b01ea66dd10e25ed711a73e7b370c5f6a00b
React-logger: a87dbd13ef3409c729c9900954d19b3f0af0c57d
React-perflogger: 63baa12c036f63a56a591806089cba2178bfa5ce
React-RCTActionSheet: 657e35f1549f792ff8cb2175165a2e34eacc405e
React-RCTAnimation: 661b7b7d6b9244103f34a691a2a17cf08b870cda
React-RCTBlob: d033f8473850f445c0043bd17a53ac768d8ae003
React-RCTImage: f0ec96d288e9a97bdad40a91aa9371e5859db561
React-RCTLinking: 245902d2b32f1934b776add9af6fa6d13418b036
React-RCTNetwork: 51aba5631b28b959225ff1cc7e270975e571f1c6
React-RCTPushNotification: 0ce584762d852b8e7fb4ab76d531e2ce13ff2ca3
React-RCTSettings: d2c584eedf27f3e127e7c4e4ab8628e58b615782
React-RCTTest: 8e9fdc24c24ece07e0e5b3c3e1424c160025d194
React-RCTText: 9f60e6cc120fff66ebed92077d076210d203ffb1
React-RCTVibration: cd53df9d069038a6caa7274481f9cd94d0ea53f3
React-runtimeexecutor: 792724a76f30693d1db43dd2f5e96d7858adbf36
React-Core: 2d3e7572b473f30852352af25b2fe1cc1373fab9
React-CoreModules: 7e96d2339cdc1222bb881b84f1cf11cc43d009fb
React-cxxreact: e281966e72e33658d0be065c6e853cd59a019913
React-jsi: 4d8dfc08118d65560e3996d7221bab7ecb3993b6
React-jsiexecutor: d85100b9a614856b90ab1c362fe3f33465c9cc7f
React-jsinspector: b529c56a8b51ad33c1397b12045f5d0a119ed1a6
React-logger: d30a666bca9e66b34d4d8716891b1e061601833a
React-perflogger: 92cee36035743d30b9e6d96fd86b94a2a0008bd2
React-RCTActionSheet: 9a910651201dd3fad1b151e152caf06467e132ba
React-RCTAnimation: 7f76001c7252d19ed71b7774a16517e5ea48db4e
React-RCTBlob: 20bba1a828491a4ee59e5e059ec4c8e788f54309
React-RCTImage: b5cd9667278a9ffd9f6c31eb52d62798a34367f9
React-RCTLinking: 55d89d2a268b5f84938738d69aa893e899ea2cf2
React-RCTNetwork: 264a2b8c75c35250757aa7da3bf4fc1827ca9b54
React-RCTPushNotification: 54964d39a88b62ae2ebc7aafb12b42871d956bee
React-RCTSettings: efcdbb2e10d28f960f6778c8d256aa13b5a07722
React-RCTTest: 1b7527ab6b372b88dbaac17b80e4d0555fca7c1f
React-RCTText: 06274ceb822c0650544ad15b136c446d5293371a
React-RCTVibration: 0c4b247824ccef25d8596bbf7d8d57a89ecba77a
React-runtimeexecutor: 32b822f26f10d85676b747f9ce62145c99ed82a5
React-TurboModuleCxx-RNW: 881411415eafe818f9cc3c4016167cc3d219402b
React-TurboModuleCxx-WinRTPort: 50cd9648f6b21aab53d1c62c466dc6567263a983
ReactCommon: cbfca257bdf2378d6036321c28ad21765b833f3a
ScreenshotManager: b378292226c78474e70b139ba2e19f584836c520
React-TurboModuleCxx-WinRTPort: d998841ac172264f9d54f8726546d4a72634dc78
ReactCommon: 68700e9db52849dc55ec5d379450c5518b0d4feb
ScreenshotManager: 1d5d672b71a31623453916311ff5656e0a6d4cfd
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: ddfd728ee27a2b67dfdd249da09a6393d6d5514d
Yoga: f3fcf7a3bf93229ebd30a0cfb19bf8caa088eb46
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: cbf4f9be33910397d5f84dd4fcbe56d3d61d42fa

Просмотреть файл

@ -1245,4 +1245,49 @@ exports.examples = [
);
},
},
{
title: 'Dynamic Text sizing (iOS only)',
render: function (): React.Node {
const boldStyle = {fontWeight: 'bold'};
const boxStyle = {
borderWidth: 1,
padding: 8,
margin: 8,
};
return (
<View style={{marginTop: 10, marginBottom: 10}}>
<Text>
Adjust text size in Accessibility settings and watch how the font
sizes change relative to each other.
</Text>
<View style={boxStyle}>
<Text style={boldStyle}>With `fontScaleRamp`:</Text>
<Text style={{fontSize: 34}} fontScaleRamp="largeTitle">
Large Title
</Text>
<Text style={{fontSize: 28}} fontScaleRamp="title1">
Title
</Text>
<Text style={{fontSize: 22}} fontScaleRamp="title2">
Title 2
</Text>
<Text style={{fontSize: 20}} fontScaleRamp="title3">
Title 3
</Text>
<Text style={{fontSize: 17}} fontScaleRamp="body">
Body
</Text>
</View>
<View style={boxStyle}>
<Text style={boldStyle}>Without `fontScaleRamp`:</Text>
<Text style={{fontSize: 34}}>Large Title</Text>
<Text style={{fontSize: 28}}>Title</Text>
<Text style={{fontSize: 22}}>Title 2</Text>
<Text style={{fontSize: 20}}>Title 3</Text>
<Text style={{fontSize: 17}}>Body</Text>
</View>
</View>
);
},
},
];