From 61774088d79ac3ab730fa55d175d681b10ae50f3 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Wed, 7 Feb 2024 07:25:30 -0800 Subject: [PATCH] Make font styling work when using specific font name on the new architecture (#37109) Summary: Currently, when `fontFamily` style is set to a specific font instead of a font family, [that specific font is used](https://github.com/facebook/react-native/blob/2058da8f2012578c3e82f1af19c3248346655f9a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm#L126) to display the text on iOS when using the new architecture. This is different behavior to the old architecture, where the font family and [font properties were extracted from the specified](https://github.com/facebook/react-native/blob/2058da8f2012578c3e82f1af19c3248346655f9a/packages/react-native/React/Views/RCTFont.mm#L450-L457) font and overridden if not provided by the user. ## Changelog: [IOS] [FIXED] - Make font resolution work when using specific font name on the new architecture Pull Request resolved: https://github.com/facebook/react-native/pull/37109 Test Plan: You can verify the problem on a simple snippet: ```jsx import React from 'react'; import {SafeAreaView, Text} from 'react-native'; function App() { return ( Some random text ); } export default App; ```
Here's before & after Without changes from this PR: With changes from this PR:
Reviewed By: NickGerleman Differential Revision: D45351185 Pulled By: sammy-SC fbshipit-source-id: 1f0a6a52a714ca4989775817d1fb53ae593143f8 --- .../textlayoutmanager/RCTFontUtils.mm | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm index 4f8d5aa0703293..dd5900b41ce399 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm @@ -35,9 +35,6 @@ static RCTFontProperties RCTResolveFontProperties( { fontProperties.family = fontProperties.family.length ? fontProperties.family : baseFontProperties.family; fontProperties.size = !isnan(fontProperties.size) ? fontProperties.size : baseFontProperties.size; - fontProperties.weight = !isnan(fontProperties.weight) ? fontProperties.weight : baseFontProperties.weight; - fontProperties.style = - fontProperties.style != RCTFontStyleUndefined ? fontProperties.style : baseFontProperties.style; fontProperties.variant = fontProperties.variant != RCTFontVariantUndefined ? fontProperties.variant : baseFontProperties.variant; return fontProperties; @@ -116,9 +113,15 @@ static RCTFontStyle RCTGetFontStyle(UIFont *font) if ([fontProperties.family isEqualToString:defaultFontProperties.family]) { // Handle system font as special case. This ensures that we preserve // the specific metrics of the standard system font as closely as possible. + fontProperties.weight = !isnan(fontProperties.weight) ? fontProperties.weight : defaultFontProperties.weight; + fontProperties.style = + fontProperties.style != RCTFontStyleUndefined ? fontProperties.style : defaultFontProperties.style; + font = RCTDefaultFontWithFontProperties(fontProperties); } else { NSArray *fontNames = [UIFont fontNamesForFamilyName:fontProperties.family]; + UIFontWeight fontWeight = fontProperties.weight; + RCTFontStyle fontStyle = fontProperties.style; if (fontNames.count == 0) { // Gracefully handle being given a font name rather than font family, for @@ -129,18 +132,24 @@ static RCTFontStyle RCTGetFontStyle(UIFont *font) // Failback to system font. font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight]; } - } else { + + fontNames = [UIFont fontNamesForFamilyName:font.familyName]; + fontWeight = isnan(fontWeight) ? RCTGetFontWeight(font) : fontWeight; + fontStyle = fontStyle == RCTFontStyleUndefined ? RCTGetFontStyle(font) : fontStyle; + } + + if (fontNames.count != 0) { // Get the closest font that matches the given weight for the fontFamily CGFloat closestWeight = INFINITY; for (NSString *name in fontNames) { UIFont *fontMatch = [UIFont fontWithName:name size:effectiveFontSize]; - if (RCTGetFontStyle(fontMatch) != fontProperties.style) { + if (RCTGetFontStyle(fontMatch) != fontStyle) { continue; } CGFloat testWeight = RCTGetFontWeight(fontMatch); - if (ABS(testWeight - fontProperties.weight) < ABS(closestWeight - fontProperties.weight)) { + if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) { font = fontMatch; closestWeight = testWeight; }