From 01f7ab814f847eb3038efa7120d81e92e3ff4187 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Tue, 18 Jun 2024 05:28:21 -0700 Subject: [PATCH] Fix text baseline being moved up on iOS (#44932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Fixes https://github.com/facebook/react-native/issues/44929 Moves calling `RCTApplyBaselineOffset` so it's called in similar way as on the old architecture: https://github.com/facebook/react-native/blob/726a4a1e5ef3bc8034a068145da2bb94ae3acfaa/packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm#L229 https://github.com/facebook/react-native/blob/726a4a1e5ef3bc8034a068145da2bb94ae3acfaa/packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm#L165-L167 I'm not exactly sure why (and Apple's docs aren't helping) but it looks like calling `NSTextStorage initWithAttributedString` results in an attributed string where emojis are separate fragments with Apple's emoji font set, which results in the correct baseline calculations. This is the way it happens on the old arch. The way it's currently implemented on the new architecture, `RCTApplyBaselineOffset` is called on ` newly created attributed string where emojis are in the same fragment as other parts of the text which alters the result of baseline calculations compared to what's later drawn on the screen. ## Changelog: [IOS] [FIXED] - Fixed text baseline being moved upwards in certain cases Pull Request resolved: https://github.com/facebook/react-native/pull/44932 Test Plan:
Check the following snipped ```jsx import React from 'react'; import { Text, View, } from 'react-native'; const App = () => { return ( A 😞😞😞 B ); }; export default App; ```
|Before|After| |-|-| |new-broken|new-fixed| Reviewed By: cipolleschi Differential Revision: D58589249 Pulled By: sammy-SC fbshipit-source-id: 1e0a730519a5c79ff8a35b0dfb16b68966a8dd9f --- .../react/renderer/textlayoutmanager/RCTAttributedTextUtils.h | 2 ++ .../react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm | 3 +-- .../react/renderer/textlayoutmanager/RCTTextLayoutManager.mm | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h index 49a4353c5f011c..c0158f3df61e7a 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h @@ -39,6 +39,8 @@ facebook::react::AttributedStringBox RCTAttributedStringBoxFromNSAttributedStrin NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook::react::TextTransform textTransform); +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText); + @interface RCTWeakEventEmitterWrapper : NSObject @property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter; @end diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index 74f5b65df1338d..5bdeac31b493c1 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -300,7 +300,7 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex return [attributes copy]; } -static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) { __block CGFloat maximumLineHeight = 0; @@ -411,7 +411,6 @@ static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) [nsAttributedString appendAttributedString:nsAttributedStringFragment]; } - RCTApplyBaselineOffset(nsAttributedString); [nsAttributedString endEditing]; return nsAttributedString; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index b17124642b5332..a50065a56cf416 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -185,6 +185,8 @@ - (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttribute NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; + RCTApplyBaselineOffset(textStorage); + [textStorage addLayoutManager:layoutManager]; if (paragraphAttributes.adjustsFontSizeToFit) {