From 61101b838f9daecda0d0cb31869b3ae755f81d70 Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Wed, 12 Oct 2022 16:30:20 -0700 Subject: [PATCH 1/8] Non-Fabric dynamic text support --- .../Text/BaseText/RCTBaseTextViewManager.m | 1 + Libraries/Text/RCTTextAttributes.h | 2 + Libraries/Text/RCTTextAttributes.m | 7 ++ Libraries/Text/Text.d.ts | 17 +++++ Libraries/Text/Text/RCTDynamicTypeRamp.h | 36 +++++++++ Libraries/Text/Text/RCTDynamicTypeRamp.m | 73 +++++++++++++++++++ Libraries/Text/TextNativeComponent.js | 1 + Libraries/Text/TextProps.js | 17 +++++ packages/rn-tester/Podfile.lock | 68 ++++++++--------- .../js/examples/Text/TextExample.ios.js | 45 ++++++++++++ 10 files changed, 233 insertions(+), 34 deletions(-) create mode 100644 Libraries/Text/Text/RCTDynamicTypeRamp.h create mode 100644 Libraries/Text/Text/RCTDynamicTypeRamp.m diff --git a/Libraries/Text/BaseText/RCTBaseTextViewManager.m b/Libraries/Text/BaseText/RCTBaseTextViewManager.m index fee8647bab155f..85bb23c5b700f2 100644 --- a/Libraries/Text/BaseText/RCTBaseTextViewManager.m +++ b/Libraries/Text/BaseText/RCTBaseTextViewManager.m @@ -36,6 +36,7 @@ - (RCTShadowView *)shadowView 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(dynamicTypeRamp, textAttributes.dynamicTypeRamp, RCTDynamicTypeRamp) RCT_REMAP_SHADOW_PROPERTY(maxFontSizeMultiplier, textAttributes.maxFontSizeMultiplier, CGFloat) RCT_REMAP_SHADOW_PROPERTY(letterSpacing, textAttributes.letterSpacing, CGFloat) // Paragraph Styles diff --git a/Libraries/Text/RCTTextAttributes.h b/Libraries/Text/RCTTextAttributes.h index a95536d1b671d7..b098273e05163f 100644 --- a/Libraries/Text/RCTTextAttributes.h +++ b/Libraries/Text/RCTTextAttributes.h @@ -7,6 +7,7 @@ #import +#import #import #import "RCTTextTransform.h" @@ -36,6 +37,7 @@ extern NSString *const RCTTextAttributesTagAttributeName; @property (nonatomic, copy, nullable) NSString *fontStyle; @property (nonatomic, copy, nullable) NSArray *fontVariant; @property (nonatomic, assign) BOOL allowFontScaling; +@property (nonatomic, assign) RCTDynamicTypeRamp dynamicTypeRamp; @property (nonatomic, assign) CGFloat letterSpacing; // Paragraph Styles @property (nonatomic, assign) CGFloat lineHeight; diff --git a/Libraries/Text/RCTTextAttributes.m b/Libraries/Text/RCTTextAttributes.m index 01131cfb20e2fb..372acbbbf8c49e 100644 --- a/Libraries/Text/RCTTextAttributes.m +++ b/Libraries/Text/RCTTextAttributes.m @@ -55,6 +55,7 @@ - (void)applyTextAttributes:(RCTTextAttributes *)textAttributes _fontStyle = textAttributes->_fontStyle ?: _fontStyle; _fontVariant = textAttributes->_fontVariant ?: _fontVariant; _allowFontScaling = textAttributes->_allowFontScaling || _allowFontScaling; // * + _dynamicTypeRamp = textAttributes->_dynamicTypeRamp != RCTDynamicTypeRampUndefined ? textAttributes->_dynamicTypeRamp : _dynamicTypeRamp; _letterSpacing = !isnan(textAttributes->_letterSpacing) ? textAttributes->_letterSpacing : _letterSpacing; // Paragraph Styles @@ -208,6 +209,11 @@ - (CGFloat)effectiveFontSizeMultiplier if (fontScalingEnabled) { CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0; + if (_dynamicTypeRamp != RCTDynamicTypeRampUndefined) { + UIFontMetrics *fontMetrics = RCTUIFontMetricsForDynamicTypeRamp(_dynamicTypeRamp); + CGFloat baseSize = RCTUIBaseSizeForDynamicTypeRamp(_dynamicTypeRamp); + fontSizeMultiplier = [fontMetrics scaledValueForValue:baseSize] / baseSize; + } CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0; return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier; } else { @@ -306,6 +312,7 @@ - (BOOL)isEqual:(RCTTextAttributes *)textAttributes RCTTextAttributesCompareObjects(_fontStyle) && RCTTextAttributesCompareObjects(_fontVariant) && RCTTextAttributesCompareOthers(_allowFontScaling) && + RCTTextAttributesCompareOthers(_dynamicTypeRamp) && RCTTextAttributesCompareFloats(_letterSpacing) && // Paragraph Styles RCTTextAttributesCompareFloats(_lineHeight) && diff --git a/Libraries/Text/Text.d.ts b/Libraries/Text/Text.d.ts index 715123576a12c1..7ea17984b0cbc8 100644 --- a/Libraries/Text/Text.d.ts +++ b/Libraries/Text/Text.d.ts @@ -26,6 +26,23 @@ export interface TextPropsIOS { */ adjustsFontSizeToFit?: boolean | undefined; + /** + * The Dynamic Text scale ramp to apply to this element on iOS. + */ + dynamicTypeRamp?: + | 'caption2' + | 'caption1' + | 'footnote' + | 'subhead' + | 'callout' + | 'body' + | 'headline' + | 'title3' + | 'title2' + | 'title1' + | 'largeTitle' + | undefined; + /** * Specifies smallest possible scale a font can reach when adjustsFontSizeToFit is enabled. (values 0.01-1.0). */ diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.h b/Libraries/Text/Text/RCTDynamicTypeRamp.h new file mode 100644 index 00000000000000..e64f9f3553f942 --- /dev/null +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.h @@ -0,0 +1,36 @@ +/* + * 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 + +#import + +typedef NS_ENUM(NSInteger, RCTDynamicTypeRamp) { + RCTDynamicTypeRampUndefined, + RCTDynamicTypeRampCaption2, + RCTDynamicTypeRampCaption1, + RCTDynamicTypeRampFootnote, + RCTDynamicTypeRampSubhead, + RCTDynamicTypeRampCallout, + RCTDynamicTypeRampBody, + RCTDynamicTypeRampHeadline, + RCTDynamicTypeRampTitle3, + RCTDynamicTypeRampTitle2, + RCTDynamicTypeRampTitle1, + RCTDynamicTypeRampLargeTitle +}; + +@interface RCTConvert (DynamicTypeRamp) + ++ (RCTDynamicTypeRamp)RCTDynamicTypeRamp:(nullable id)json; + +@end + +/// Generates a `UIFontMetrics` instance representing a particular Dynamic Type ramp. +UIFontMetrics * _Nonnull RCTUIFontMetricsForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp); +/// The "reference" size for a particular font scale ramp, equal to a text element's size under default text size settings. +CGFloat RCTUIBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp); diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.m b/Libraries/Text/Text/RCTDynamicTypeRamp.m new file mode 100644 index 00000000000000..d76b13b4644435 --- /dev/null +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.m @@ -0,0 +1,73 @@ +/* + * 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 + +@implementation RCTConvert (DynamicTypeRamp) + +RCT_ENUM_CONVERTER(RCTDynamicTypeRamp, (@{ + @"caption2": @(RCTDynamicTypeRampCaption2), + @"caption1": @(RCTDynamicTypeRampCaption1), + @"footnote": @(RCTDynamicTypeRampFootnote), + @"subhead": @(RCTDynamicTypeRampSubhead), + @"callout": @(RCTDynamicTypeRampCallout), + @"body": @(RCTDynamicTypeRampBody), + @"headline": @(RCTDynamicTypeRampHeadline), + @"title3": @(RCTDynamicTypeRampTitle3), + @"title2": @(RCTDynamicTypeRampTitle2), + @"title1": @(RCTDynamicTypeRampTitle1), + @"largeTitle": @(RCTDynamicTypeRampLargeTitle), +}), RCTDynamicTypeRampUndefined, integerValue) + +@end + +UIFontMetrics *RCTUIFontMetricsForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { + static NSDictionary *mapping; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + mapping = @{ + @(RCTDynamicTypeRampCaption2): UIFontTextStyleCaption2, + @(RCTDynamicTypeRampCaption1): UIFontTextStyleCaption1, + @(RCTDynamicTypeRampFootnote): UIFontTextStyleFootnote, + @(RCTDynamicTypeRampSubhead): UIFontTextStyleSubheadline, + @(RCTDynamicTypeRampCallout): UIFontTextStyleCallout, + @(RCTDynamicTypeRampBody): UIFontTextStyleBody, + @(RCTDynamicTypeRampHeadline): UIFontTextStyleHeadline, + @(RCTDynamicTypeRampTitle3): UIFontTextStyleTitle3, + @(RCTDynamicTypeRampTitle2): UIFontTextStyleTitle2, + @(RCTDynamicTypeRampTitle1): UIFontTextStyleTitle1, + @(RCTDynamicTypeRampLargeTitle): UIFontTextStyleLargeTitle, + }; + }); + + id textStyle = mapping[@(dynamicTypeRamp)] ?: UIFontTextStyleBody; // Default to body if we don't recognize the specified ramp + return [UIFontMetrics metricsForTextStyle:textStyle]; +} + +CGFloat RCTUIBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { + static NSDictionary *mapping; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Values taken from https://developer.apple.com/design/human-interface-guidelines/foundations/typography/ + mapping = @{ + @(RCTDynamicTypeRampCaption2): @11, + @(RCTDynamicTypeRampCaption1): @12, + @(RCTDynamicTypeRampFootnote): @13, + @(RCTDynamicTypeRampSubhead): @15, + @(RCTDynamicTypeRampCallout): @16, + @(RCTDynamicTypeRampBody): @17, + @(RCTDynamicTypeRampHeadline): @17, + @(RCTDynamicTypeRampTitle3): @20, + @(RCTDynamicTypeRampTitle2): @22, + @(RCTDynamicTypeRampTitle1): @28, + @(RCTDynamicTypeRampLargeTitle): @34, + }; + }); + + NSNumber *baseSize = mapping[@(dynamicTypeRamp)] ?: @17; // Default to body size if we don't recognize the specified ramp + return CGFLOAT_IS_DOUBLE ? [baseSize doubleValue] : [baseSize floatValue]; +} diff --git a/Libraries/Text/TextNativeComponent.js b/Libraries/Text/TextNativeComponent.js index 22b29bfbab1527..3f7f3cd4545019 100644 --- a/Libraries/Text/TextNativeComponent.js +++ b/Libraries/Text/TextNativeComponent.js @@ -34,6 +34,7 @@ const textViewConfig = { numberOfLines: true, ellipsizeMode: true, allowFontScaling: true, + dynamicTypeRamp: true, maxFontSizeMultiplier: true, disabled: true, selectable: true, diff --git a/Libraries/Text/TextProps.js b/Libraries/Text/TextProps.js index 16e4f87b25cc03..54579809c80b30 100644 --- a/Libraries/Text/TextProps.js +++ b/Libraries/Text/TextProps.js @@ -223,6 +223,23 @@ export type TextProps = $ReadOnly<{| */ adjustsFontSizeToFit?: ?boolean, + /** + * The Dynamic Text scale ramp to apply to this element on iOS. + */ + dynamicTypeRamp?: ?( + | 'caption2' + | 'caption1' + | 'footnote' + | 'subhead' + | 'callout' + | 'body' + | 'headline' + | 'title3' + | 'title2' + | 'title1' + | 'largeTitle' + ), + /** * Smallest possible scale a font can reach. * diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 57c109f6770222..7b90e300faece8 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -908,8 +908,8 @@ SPEC CHECKSUMS: boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 - FBLazyVector: 19e408e76fa9258dd32191a50d60c41444f52d29 - FBReactNativeSpec: 27a89a8eea1b441a73a78f420dd18dad3ed13723 + FBLazyVector: c50a257599cf9da24c1d2c21cc0e64a290a399f2 + FBReactNativeSpec: 58e448b97b57e7fac3578c15de86294f3ef48f3b Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -924,41 +924,41 @@ SPEC CHECKSUMS: libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda - RCTRequired: 1c8808cf84569265784a6c33984bbb506ada8c6e - RCTTypeSafety: b6dcb5036a808864ee8cad66ca15f263c24661cc - React: 8d809d414723bb5763093ddec7658066a21ccabc - React-bridging: c8806159f8ef90f27443857eed1efdb8c85940e1 - React-callinvoker: 5f16202ad4e45f0607b1fae0f6955a8f7c87eef1 + RCTRequired: 9f2b31454e8195e0c8413735235fe750277134f2 + RCTTypeSafety: 17199a76178ddb70422ea94a5c8a76c70c5cfac5 + React: be1aa9dcc92931fc476ed82ed6aefc92ce642060 + React-bridging: ce8ffc84c4f41799578090cf7532c71cbf91f46f + React-callinvoker: 244ae02050af427803b765ed884a8f9f30b24d53 React-Codegen: 5adf19af97eb37a7d441c040521191e446255086 - React-Core: ce4282fb714ffbe444b84d296d1728eaee4d0e9f - React-CoreModules: 675170bccf156da3a3348e04e2036ce401b2010d - React-cxxreact: 7276467c246302fedf598cc40d7003896ddb20ba - React-Fabric: a696c92be541f2015b9777956a3e7df8a8f34aed - React-graphics: 5ccc9cc0d91794fd42bc1c693e9aea207554bbef - React-jsi: a042596cb558abea721ab5e23cb175647610a73d - React-jsiexecutor: f7fbac5dff7e7ff110a66edf2626b4f4f4600ef5 - React-jsinspector: 7733dd522d044aef87caa39f3eda77593358a7eb - React-logger: c7960346b021767ed90971aff592a44e3d69f8bb - React-perflogger: c4fdd48988c2d3047186fc1bc1772d634cfca2ea - React-RCTActionSheet: 166fd1df85ac10219466b45d12a5884d3eaceac1 - React-RCTAnimation: d6127046c6bb44bd3e67b7503c4ad7f91131b58e - React-RCTAppDelegate: 475ca9b80e26c1c4aed93ce04363092fa78cf788 - React-RCTBlob: 68675c89ebe6edf310dddd0774ba07b685f090a9 - React-RCTFabric: a98a6effece6719669b8c6b4d2c33fb0edddc613 - React-RCTImage: 6de9f0f4402af859849e97cc73a56a52f400f4c9 - React-RCTLinking: 21bb4675c3ec8fe704672ea511e817aeb3bf8370 - React-RCTNetwork: a865deadacbf6b3d863f0496e7d2c2e81c269317 - React-RCTPushNotification: 7f678a88147254ede5d21a1e1e71e8a964dd0051 - React-RCTSettings: 23ce1aa52ddf5db44c973bb5cc93713e871e09b6 - React-RCTTest: 06c388632dc7b30df17af01c8f9e89e641b4d31c - React-RCTText: a861fbf2835299d3cc4189697cddd8bd8602afb9 - React-RCTVibration: 0386f50996a153b3f39cecbe7d139763ac9a9fdf - React-rncore: 665c70690f404bbfa3948148de72689672a906d2 - React-runtimeexecutor: 97dca9247f4d3cfe0733384b189c6930fbd402b7 - ReactCommon: 8e39c4b24da570ea2b631accbf779b5891befe0c + React-Core: ddecf8c67011fec7697da12c9a090e92e5b6a860 + React-CoreModules: c9a08d3428f0be36dada84707f8ef4292acb05ba + React-cxxreact: afe09d4f7d2754786fa6c5de79dd2e1cf7e7ac64 + React-Fabric: bc6469b342732a405ccac43bdfdbdb34d819cbef + React-graphics: e11b0d7457c1ab53f0073e537325cbad2de7bc98 + React-jsi: cc42f25cc4b0f8f51cfde249f531af2069012a4e + React-jsiexecutor: 604874b1e8e6bc22daf266b80a72dd49e6f82679 + React-jsinspector: 0663f98209948f169000c7022dc394c7e945d4f3 + React-logger: 8ed341fb3aff82f2ecc77e0eb574ffd60a87e802 + React-perflogger: 3928409bbe9f4b11cf1fd70a729184bc373ae6b5 + React-RCTActionSheet: fa01322d448fbd0cc7fe17eb7b1686da89facad6 + React-RCTAnimation: f0f540289f062b9c52f89184e5b157bfb40e908b + React-RCTAppDelegate: 4c447d7b77c5d375d7897f57cb3fa5a73b1cb5b7 + React-RCTBlob: 2bb1f1f50779639707d8b9a883930a86c9761934 + React-RCTFabric: 3bc0da24aa8947109d32632488a4ada44623312c + React-RCTImage: d35dd20b0ff246bc632482de05ef59eec66dd13d + React-RCTLinking: bf8fb7ce2e459b7ed33cf2024b414def310a6b49 + React-RCTNetwork: 1cd021f6b8a158e268501610c5e7f5b1e4fd9d33 + React-RCTPushNotification: e28a33c76cb2396e953939696e95ce0a19701e7a + React-RCTSettings: fc9ffc85741c176f3e96c6b9672f2145959c16e1 + React-RCTTest: ce80c003f358e350ff4dd30060a5ae877b0e8a8d + React-RCTText: f39916041c4a5646a46a4c077968e417bfbeddbd + React-RCTVibration: d869da327b3646b29afd820ed864e2a57390d9e2 + React-rncore: 108bbd7fc467cd7cc98a7859e31b08f0ab0f3d6d + React-runtimeexecutor: 9475e4eac1c2c89642f96dd8d5eb8a6461f12e1d + ReactCommon: 74d516ff962ad59019e7170270178c999b045b92 ScreenshotManager: 3fc534a218e7b8dde632158411d0f15b0ca8893c SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 - Yoga: 1b1a12ff3d86a10565ea7cbe057d42f5e5fb2a07 + Yoga: e93e9d984e1020010c2d69311e9e5152841b9c12 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 6e26aac84dafab208188a8c6e45de8b3cf2a9f62 diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 9f92af41c71252..b41ec723a7d1a5 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1246,4 +1246,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 ( + + + Adjust text size in Accessibility settings and watch how the font + sizes change relative to each other. + + + With `dynamicTypeRamp`: + + Large Title + + + Title + + + Title 2 + + + Title 3 + + + Body + + + + Without `dynamicTypeRamp`: + Large Title + Title + Title 2 + Title 3 + Body + + + ); + }, + }, ]; From 5483552bb3f6145a0660221078d1d9b63951e5a1 Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Fri, 14 Oct 2022 12:35:39 -0700 Subject: [PATCH 2/8] Dynamic type ramp: subhead -> subheadline --- Libraries/Text/Text.d.ts | 2 +- Libraries/Text/Text/RCTDynamicTypeRamp.h | 2 +- Libraries/Text/Text/RCTDynamicTypeRamp.m | 6 +++--- Libraries/Text/TextProps.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Libraries/Text/Text.d.ts b/Libraries/Text/Text.d.ts index 7ea17984b0cbc8..5ce6fecc5e72b2 100644 --- a/Libraries/Text/Text.d.ts +++ b/Libraries/Text/Text.d.ts @@ -33,7 +33,7 @@ export interface TextPropsIOS { | 'caption2' | 'caption1' | 'footnote' - | 'subhead' + | 'subheadline' | 'callout' | 'body' | 'headline' diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.h b/Libraries/Text/Text/RCTDynamicTypeRamp.h index e64f9f3553f942..8d6e59e04fd014 100644 --- a/Libraries/Text/Text/RCTDynamicTypeRamp.h +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.h @@ -14,7 +14,7 @@ typedef NS_ENUM(NSInteger, RCTDynamicTypeRamp) { RCTDynamicTypeRampCaption2, RCTDynamicTypeRampCaption1, RCTDynamicTypeRampFootnote, - RCTDynamicTypeRampSubhead, + RCTDynamicTypeRampSubheadline, RCTDynamicTypeRampCallout, RCTDynamicTypeRampBody, RCTDynamicTypeRampHeadline, diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.m b/Libraries/Text/Text/RCTDynamicTypeRamp.m index d76b13b4644435..1559203a34f977 100644 --- a/Libraries/Text/Text/RCTDynamicTypeRamp.m +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.m @@ -13,7 +13,7 @@ @implementation RCTConvert (DynamicTypeRamp) @"caption2": @(RCTDynamicTypeRampCaption2), @"caption1": @(RCTDynamicTypeRampCaption1), @"footnote": @(RCTDynamicTypeRampFootnote), - @"subhead": @(RCTDynamicTypeRampSubhead), + @"subheadline": @(RCTDynamicTypeRampSubheadline), @"callout": @(RCTDynamicTypeRampCallout), @"body": @(RCTDynamicTypeRampBody), @"headline": @(RCTDynamicTypeRampHeadline), @@ -33,7 +33,7 @@ @implementation RCTConvert (DynamicTypeRamp) @(RCTDynamicTypeRampCaption2): UIFontTextStyleCaption2, @(RCTDynamicTypeRampCaption1): UIFontTextStyleCaption1, @(RCTDynamicTypeRampFootnote): UIFontTextStyleFootnote, - @(RCTDynamicTypeRampSubhead): UIFontTextStyleSubheadline, + @(RCTDynamicTypeRampSubheadline): UIFontTextStyleSubheadline, @(RCTDynamicTypeRampCallout): UIFontTextStyleCallout, @(RCTDynamicTypeRampBody): UIFontTextStyleBody, @(RCTDynamicTypeRampHeadline): UIFontTextStyleHeadline, @@ -57,7 +57,7 @@ CGFloat RCTUIBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { @(RCTDynamicTypeRampCaption2): @11, @(RCTDynamicTypeRampCaption1): @12, @(RCTDynamicTypeRampFootnote): @13, - @(RCTDynamicTypeRampSubhead): @15, + @(RCTDynamicTypeRampSubheadline): @15, @(RCTDynamicTypeRampCallout): @16, @(RCTDynamicTypeRampBody): @17, @(RCTDynamicTypeRampHeadline): @17, diff --git a/Libraries/Text/TextProps.js b/Libraries/Text/TextProps.js index 54579809c80b30..967826dadb9714 100644 --- a/Libraries/Text/TextProps.js +++ b/Libraries/Text/TextProps.js @@ -230,7 +230,7 @@ export type TextProps = $ReadOnly<{| | 'caption2' | 'caption1' | 'footnote' - | 'subhead' + | 'subheadline' | 'callout' | 'body' | 'headline' From ddb70d292d5936c57c471a23e3b848035b2815ff Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Fri, 14 Oct 2022 12:56:21 -0700 Subject: [PATCH 3/8] RCTUIBaseSizeForDynamicTypeRamp -> RCTBaseSizeForDynamicTypeRamp --- Libraries/Text/RCTTextAttributes.m | 2 +- Libraries/Text/Text/RCTDynamicTypeRamp.h | 2 +- Libraries/Text/Text/RCTDynamicTypeRamp.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/Text/RCTTextAttributes.m b/Libraries/Text/RCTTextAttributes.m index 372acbbbf8c49e..6e2cfee99437f1 100644 --- a/Libraries/Text/RCTTextAttributes.m +++ b/Libraries/Text/RCTTextAttributes.m @@ -211,7 +211,7 @@ - (CGFloat)effectiveFontSizeMultiplier CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0; if (_dynamicTypeRamp != RCTDynamicTypeRampUndefined) { UIFontMetrics *fontMetrics = RCTUIFontMetricsForDynamicTypeRamp(_dynamicTypeRamp); - CGFloat baseSize = RCTUIBaseSizeForDynamicTypeRamp(_dynamicTypeRamp); + CGFloat baseSize = RCTBaseSizeForDynamicTypeRamp(_dynamicTypeRamp); fontSizeMultiplier = [fontMetrics scaledValueForValue:baseSize] / baseSize; } CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0; diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.h b/Libraries/Text/Text/RCTDynamicTypeRamp.h index 8d6e59e04fd014..49fee502671a46 100644 --- a/Libraries/Text/Text/RCTDynamicTypeRamp.h +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.h @@ -33,4 +33,4 @@ typedef NS_ENUM(NSInteger, RCTDynamicTypeRamp) { /// Generates a `UIFontMetrics` instance representing a particular Dynamic Type ramp. UIFontMetrics * _Nonnull RCTUIFontMetricsForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp); /// The "reference" size for a particular font scale ramp, equal to a text element's size under default text size settings. -CGFloat RCTUIBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp); +CGFloat RCTBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp); diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.m b/Libraries/Text/Text/RCTDynamicTypeRamp.m index 1559203a34f977..563fb18663cde3 100644 --- a/Libraries/Text/Text/RCTDynamicTypeRamp.m +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.m @@ -48,7 +48,7 @@ @implementation RCTConvert (DynamicTypeRamp) return [UIFontMetrics metricsForTextStyle:textStyle]; } -CGFloat RCTUIBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { +CGFloat RCTBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { static NSDictionary *mapping; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ From 6085f4412a8110ebdadb86ba09974ba9b5d1833a Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Wed, 26 Oct 2022 23:58:51 -0700 Subject: [PATCH 4/8] Fabric implementation of Dynamic Type --- .../attributedstring/TextAttributes.cpp | 6 ++ .../attributedstring/TextAttributes.h | 1 + .../renderer/attributedstring/conversions.h | 78 ++++++++++++++++++ .../renderer/attributedstring/primitives.h | 21 +++++ .../components/text/BaseTextProps.cpp | 6 ++ .../textlayoutmanager/TextMeasureCache.h | 3 + .../platform/ios/RCTAttributedTextUtils.mm | 80 ++++++++++++++++--- 7 files changed, 186 insertions(+), 9 deletions(-) diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 24f5bbd07b8072..63b5a4aab19fce 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) { allowFontScaling = textAttributes.allowFontScaling.has_value() ? textAttributes.allowFontScaling : allowFontScaling; + dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value() + ? textAttributes.dynamicTypeRamp + : dynamicTypeRamp; letterSpacing = !std::isnan(textAttributes.letterSpacing) ? textAttributes.letterSpacing : letterSpacing; @@ -111,6 +114,7 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { fontStyle, fontVariant, allowFontScaling, + dynamicTypeRamp, alignment, baseWritingDirection, lineBreakStrategy, @@ -131,6 +135,7 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { rhs.fontStyle, rhs.fontVariant, rhs.allowFontScaling, + rhs.dynamicTypeRamp, rhs.alignment, rhs.baseWritingDirection, rhs.lineBreakStrategy, @@ -186,6 +191,7 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const { debugStringConvertibleItem("fontStyle", fontStyle), debugStringConvertibleItem("fontVariant", fontVariant), debugStringConvertibleItem("allowFontScaling", allowFontScaling), + debugStringConvertibleItem("dynamicTypeRamp", dynamicTypeRamp), debugStringConvertibleItem("letterSpacing", letterSpacing), // Paragraph Styles diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 69400f2ed172f7..89a6ba36f247ec 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -50,6 +50,7 @@ class TextAttributes : public DebugStringConvertible { std::optional fontStyle{}; std::optional fontVariant{}; std::optional allowFontScaling{}; + std::optional dynamicTypeRamp{}; Float letterSpacing{std::numeric_limits::quiet_NaN()}; std::optional textTransform{}; diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index f854d6f53036ca..f768de8cd82d2f 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -34,6 +34,84 @@ namespace facebook { namespace react { +inline std::string toString(const DynamicTypeRamp &dynamicTypeRamp) { + switch (dynamicTypeRamp) { + case DynamicTypeRamp::Caption2: + return "caption2"; + case DynamicTypeRamp::Caption1: + return "caption1"; + case DynamicTypeRamp::Footnote: + return "footnote"; + case DynamicTypeRamp::Subheadline: + return "subheadline"; + case DynamicTypeRamp::Callout: + return "callout"; + case DynamicTypeRamp::Body: + return "body"; + case DynamicTypeRamp::Headline: + return "headline"; + case DynamicTypeRamp::Title3: + return "title3"; + case DynamicTypeRamp::Title2: + return "title2"; + case DynamicTypeRamp::Title1: + return "title1"; + case DynamicTypeRamp::LargeTitle: + return "largeTitle"; + } + + LOG(ERROR) << "Unsupported DynamicTypeRamp value"; + react_native_assert(false); + + // Sane default in case of parsing errors + return "body"; +} + +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + DynamicTypeRamp &result) { + react_native_assert(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "caption2") { + result = DynamicTypeRamp::Caption2; + } else if (string == "caption1") { + result = DynamicTypeRamp::Caption1; + } else if (string == "footnote") { + result = DynamicTypeRamp::Footnote; + } else if (string == "subheadline") { + result = DynamicTypeRamp::Subheadline; + } else if (string == "callout") { + result = DynamicTypeRamp::Callout; + } else if (string == "body") { + result = DynamicTypeRamp::Body; + } else if (string == "headline") { + result = DynamicTypeRamp::Headline; + } else if (string == "title3") { + result = DynamicTypeRamp::Title3; + } else if (string == "title2") { + result = DynamicTypeRamp::Title2; + } else if (string == "title1") { + result = DynamicTypeRamp::Title1; + } else if (string == "largeTitle") { + result = DynamicTypeRamp::LargeTitle; + } else { + // sane default + LOG(ERROR) << "Unsupported DynamicTypeRamp value: " << string; + react_native_assert(false); + result = DynamicTypeRamp::Body; + } + return; + } + + LOG(ERROR) << "Unsupported DynamicTypeRamp type"; + react_native_assert(false); + + // Sane default in case of parsing errors + result = DynamicTypeRamp::Body; +} + inline std::string toString(const EllipsizeMode &ellipsisMode) { switch (ellipsisMode) { case EllipsizeMode::Clip: diff --git a/ReactCommon/react/renderer/attributedstring/primitives.h b/ReactCommon/react/renderer/attributedstring/primitives.h index 3c6c7bda2654b6..f3ef237c9a829f 100644 --- a/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/ReactCommon/react/renderer/attributedstring/primitives.h @@ -46,6 +46,20 @@ enum class FontVariant : int { ProportionalNums = 1 << 5 }; +enum class DynamicTypeRamp { + Caption2, + Caption1, + Footnote, + Subheadline, + Callout, + Body, + Headline, + Title3, + Title2, + Title1, + LargeTitle +}; + enum class EllipsizeMode { Clip, // Do not add ellipsize, simply clip. Head, // Truncate at head of line: "...wxyz". @@ -190,6 +204,13 @@ struct hash { } }; +template <> +struct hash { + size_t operator()(const facebook::react::DynamicTypeRamp &v) const { + return hash()(static_cast(v)); + } +}; + template <> struct hash { size_t operator()(const facebook::react::EllipsizeMode &v) const { diff --git a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index 6f4741ba69c9ee..e098e7beab2404 100644 --- a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -73,6 +73,12 @@ static TextAttributes convertRawProp( "allowFontScaling", sourceTextAttributes.allowFontScaling, defaultTextAttributes.allowFontScaling); + textAttributes.dynamicTypeRamp = convertRawProp( + context, + rawProps, + "dynamicTypeRamp", + sourceTextAttributes.dynamicTypeRamp, + defaultTextAttributes.dynamicTypeRamp); textAttributes.letterSpacing = convertRawProp( context, rawProps, diff --git a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h index aee6ebdeceea73..23486173c68068 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h +++ b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h @@ -94,6 +94,7 @@ inline bool areTextAttributesEquivalentLayoutWise( lhs.fontStyle, lhs.fontVariant, lhs.allowFontScaling, + lhs.dynamicTypeRamp, lhs.alignment) == std::tie( rhs.fontFamily, @@ -101,6 +102,7 @@ inline bool areTextAttributesEquivalentLayoutWise( rhs.fontStyle, rhs.fontVariant, rhs.allowFontScaling, + rhs.dynamicTypeRamp, rhs.alignment) && floatEquality(lhs.fontSize, rhs.fontSize) && floatEquality(lhs.fontSizeMultiplier, rhs.fontSizeMultiplier) && @@ -121,6 +123,7 @@ inline size_t textAttributesHashLayoutWise( textAttributes.fontStyle, textAttributes.fontVariant, textAttributes.allowFontScaling, + textAttributes.dynamicTypeRamp, textAttributes.letterSpacing, textAttributes.lineHeight, textAttributes.alignment); diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index 7f5117040cc1a2..2405eabe04d79a 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -55,6 +55,76 @@ inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight) return weights[(fontWeight + 50) / 100 - 1]; } +inline static UIFontTextStyle RCTUIFontTextStyleForDynamicTypeRamp(const DynamicTypeRamp &dynamicTypeRamp) { + switch (dynamicTypeRamp) { + case DynamicTypeRamp::Caption2: + return UIFontTextStyleCaption2; + case DynamicTypeRamp::Caption1: + return UIFontTextStyleCaption1; + case DynamicTypeRamp::Footnote: + return UIFontTextStyleFootnote; + case DynamicTypeRamp::Subheadline: + return UIFontTextStyleSubheadline; + case DynamicTypeRamp::Callout: + return UIFontTextStyleCallout; + case DynamicTypeRamp::Body: + return UIFontTextStyleBody; + case DynamicTypeRamp::Headline: + return UIFontTextStyleHeadline; + case DynamicTypeRamp::Title3: + return UIFontTextStyleTitle3; + case DynamicTypeRamp::Title2: + return UIFontTextStyleTitle2; + case DynamicTypeRamp::Title1: + return UIFontTextStyleTitle1; + case DynamicTypeRamp::LargeTitle: + return UIFontTextStyleLargeTitle; + } +} + +inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynamicTypeRamp) { + switch (dynamicTypeRamp) { + case DynamicTypeRamp::Caption2: + return 11.0; + case DynamicTypeRamp::Caption1: + return 12.0; + case facebook::react::DynamicTypeRamp::Footnote: + return 13.0; + case facebook::react::DynamicTypeRamp::Subheadline: + return 15.0; + case facebook::react::DynamicTypeRamp::Callout: + return 16.0; + case facebook::react::DynamicTypeRamp::Body: + return 17.0; + case facebook::react::DynamicTypeRamp::Headline: + return 17.0; + case facebook::react::DynamicTypeRamp::Title3: + return 20.0; + case facebook::react::DynamicTypeRamp::Title2: + return 22.0; + case facebook::react::DynamicTypeRamp::Title1: + return 28.0; + case facebook::react::DynamicTypeRamp::LargeTitle: + return 34.0; + } +} + +inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes) +{ + if (textAttributes.allowFontScaling.value_or(true)) { + if (textAttributes.dynamicTypeRamp.has_value()) { + DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value(); + UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:RCTUIFontTextStyleForDynamicTypeRamp(dynamicTypeRamp)]; + CGFloat baseSize = RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp); + return [fontMetrics scaledValueForValue:baseSize] / baseSize; + } else { + return textAttributes.fontSizeMultiplier; + } + } else { + return 1.0; + } +} + inline static UIFont *RCTEffectiveFontFromTextAttributes(const TextAttributes &textAttributes) { NSString *fontFamily = [NSString stringWithCString:textAttributes.fontFamily.c_str() encoding:NSUTF8StringEncoding]; @@ -71,19 +141,11 @@ inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight) fontProperties.weight = textAttributes.fontWeight.has_value() ? RCTUIFontWeightFromInteger((NSInteger)textAttributes.fontWeight.value()) : NAN; - fontProperties.sizeMultiplier = - textAttributes.allowFontScaling.value_or(true) ? textAttributes.fontSizeMultiplier : 1; + fontProperties.sizeMultiplier = RCTEffectiveFontSizeMultiplierFromTextAttributes(textAttributes); return RCTFontWithFontProperties(fontProperties); } -inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes) -{ - return textAttributes.allowFontScaling.value_or(true) && !isnan(textAttributes.fontSizeMultiplier) - ? textAttributes.fontSizeMultiplier - : 1.0; -} - inline static UIColor *RCTEffectiveForegroundColorFromTextAttributes(const TextAttributes &textAttributes) { UIColor *effectiveForegroundColor = RCTUIColorFromSharedColor(textAttributes.foregroundColor) ?: [UIColor blackColor]; From fc4ab43c98a22c07dd02db08cb5d70bb17f56b23 Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Thu, 27 Oct 2022 15:32:08 -0700 Subject: [PATCH 5/8] More accurate scaling arithmetic --- Libraries/Text/RCTTextAttributes.m | 5 +++-- .../textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Libraries/Text/RCTTextAttributes.m b/Libraries/Text/RCTTextAttributes.m index 28e1a4647797a3..91fa354afaa7c8 100644 --- a/Libraries/Text/RCTTextAttributes.m +++ b/Libraries/Text/RCTTextAttributes.m @@ -233,8 +233,9 @@ - (CGFloat)effectiveFontSizeMultiplier CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0; if (_dynamicTypeRamp != RCTDynamicTypeRampUndefined) { UIFontMetrics *fontMetrics = RCTUIFontMetricsForDynamicTypeRamp(_dynamicTypeRamp); - CGFloat baseSize = RCTBaseSizeForDynamicTypeRamp(_dynamicTypeRamp); - fontSizeMultiplier = [fontMetrics scaledValueForValue:baseSize] / baseSize; + // Using a specific font size reduces rounding errors from -scaledValueForValue: + CGFloat requestedSize = isnan(_fontSize) ? RCTBaseSizeForDynamicTypeRamp(_dynamicTypeRamp) : _fontSize; + fontSizeMultiplier = [fontMetrics scaledValueForValue:requestedSize] / requestedSize; } CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0; return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier; diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index 2405eabe04d79a..6aa4f283abc20e 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -115,8 +115,9 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex if (textAttributes.dynamicTypeRamp.has_value()) { DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value(); UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:RCTUIFontTextStyleForDynamicTypeRamp(dynamicTypeRamp)]; - CGFloat baseSize = RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp); - return [fontMetrics scaledValueForValue:baseSize] / baseSize; + // Using a specific font size reduces rounding errors from -scaledValueForValue: + CGFloat requestedSize = isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize; + return [fontMetrics scaledValueForValue:requestedSize] / requestedSize; } else { return textAttributes.fontSizeMultiplier; } From 2393f0431316f5fd8fe9c1eaa9c3a92b838d0136 Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Thu, 27 Oct 2022 15:32:59 -0700 Subject: [PATCH 6/8] RNTester: Dynamic Text -> Dynamic Type --- packages/rn-tester/js/examples/Text/TextExample.ios.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 15954007bcc6d5..4a4edacc5c690f 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1284,7 +1284,7 @@ exports.examples = [ }, }, { - title: 'Dynamic Text sizing (iOS only)', + title: 'Dynamic Type (iOS only)', render: function (): React.Node { const boldStyle = {fontWeight: 'bold'}; const boxStyle = { From 98bd7b061776ca2f26a9c616a3cd56d1840a1fe1 Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Tue, 1 Nov 2022 17:01:50 -0700 Subject: [PATCH 7/8] Add better links to Apple typography page --- Libraries/Text/Text/RCTDynamicTypeRamp.m | 2 +- .../textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Libraries/Text/Text/RCTDynamicTypeRamp.m b/Libraries/Text/Text/RCTDynamicTypeRamp.m index 563fb18663cde3..248d8790c950dc 100644 --- a/Libraries/Text/Text/RCTDynamicTypeRamp.m +++ b/Libraries/Text/Text/RCTDynamicTypeRamp.m @@ -52,7 +52,7 @@ CGFloat RCTBaseSizeForDynamicTypeRamp(RCTDynamicTypeRamp dynamicTypeRamp) { static NSDictionary *mapping; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - // Values taken from https://developer.apple.com/design/human-interface-guidelines/foundations/typography/ + // Values taken from https://developer.apple.com/design/human-interface-guidelines/foundations/typography/#specifications mapping = @{ @(RCTDynamicTypeRampCaption2): @11, @(RCTDynamicTypeRampCaption1): @12, diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index 6aa4f283abc20e..2e5777353c3623 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -83,6 +83,7 @@ inline static UIFontTextStyle RCTUIFontTextStyleForDynamicTypeRamp(const Dynamic } inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynamicTypeRamp) { + // Values taken from https://developer.apple.com/design/human-interface-guidelines/foundations/typography/#specifications switch (dynamicTypeRamp) { case DynamicTypeRamp::Caption2: return 11.0; From 0254c3a23d761e512a781031a1afd88173486c3a Mon Sep 17 00:00:00 2001 From: Adam Gleitman Date: Tue, 1 Nov 2022 17:19:24 -0700 Subject: [PATCH 8/8] Add RCTDynamicTypeRamp.h to BUCK public headers --- BUCK | 1 + 1 file changed, 1 insertion(+) diff --git a/BUCK b/BUCK index f6992f1619298c..53fd7dade2fe9e 100644 --- a/BUCK +++ b/BUCK @@ -264,6 +264,7 @@ REACT_PUBLIC_HEADERS = { "React/RCTDevLoadingViewProtocol.h": RCTDEVSUPPORT_PATH + "RCTDevLoadingViewProtocol.h", "React/RCTDevLoadingViewSetEnabled.h": RCTDEVSUPPORT_PATH + "RCTDevLoadingViewSetEnabled.h", "React/RCTDisplayLink.h": RCTBASE_PATH + "RCTDisplayLink.h", + "React/RCTDynamicTypeRamp.h": RCTLIB_PATH + "Text/Text/RCTDynamicTypeRamp.h", "React/RCTErrorCustomizer.h": RCTBASE_PATH + "RCTErrorCustomizer.h", "React/RCTErrorInfo.h": RCTBASE_PATH + "RCTErrorInfo.h", # NOTE: RCTEventDispatcher.h is exported from CoreModules:CoreModulesApple