From a2b37432f75144488d48f627ae7635497a42ef60 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Thu, 7 Nov 2024 11:29:30 +0100 Subject: [PATCH 1/2] Fix `adjustsFontSizeToFit` for strings with a single character --- .../Libraries/Text/Text/NSTextStorage+FontScaling.m | 9 +++++++++ .../com/facebook/react/views/text/TextLayoutManager.java | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Text/Text/NSTextStorage+FontScaling.m b/packages/react-native/Libraries/Text/Text/NSTextStorage+FontScaling.m index fa86a458970a95..c92b2e94c6a1b5 100644 --- a/packages/react-native/Libraries/Text/Text/NSTextStorage+FontScaling.m +++ b/packages/react-native/Libraries/Text/Text/NSTextStorage+FontScaling.m @@ -66,6 +66,15 @@ - (RCTTextSizeComparisonOptions)compareToSize:(CGSize)size thresholdRatio:(CGFlo NSLayoutManager *layoutManager = self.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; + // A workaround for truncatedGlyphRangeInLineFragmentForGlyphAtIndex returning NSNotFound when text has only + // one character and it gets truncated + if ([self length] == 1) { + CGSize characterSize = [[self string] sizeWithAttributes:[self attributesAtIndex:0 effectiveRange:nil]]; + if (characterSize.width > size.width) { + return RCTTextSizeComparisonLarger; + } + } + [layoutManager ensureLayoutForTextContainer:textContainer]; // Does it fit the text container? diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 3d420f8b9eac51..18b32b3d9de7ca 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -630,7 +630,8 @@ private static Layout createLayout( && maximumNumberOfLines != 0 && layout.getLineCount() > maximumNumberOfLines) || (heightYogaMeasureMode != YogaMeasureMode.UNDEFINED - && layout.getHeight() > height))) { + && layout.getHeight() > height) + || (text.length() == 1 && layout.getPaint().measureText(text.toString()) > width))) { // TODO: We could probably use a smarter algorithm here. This will require 0(n) // measurements based on the number of points the font size needs to be reduced by. currentFontSize -= Math.max(1, (int) PixelUtil.toPixelFromDIP(1)); @@ -648,6 +649,7 @@ private static Layout createLayout( text.getSpanFlags(span)); text.removeSpan(span); } + boring = BoringLayout.isBoring(text, paint); layout = createLayout( text, From fb3f1f0ac755007fcddf805a03cea02d878df2f2 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Thu, 5 Dec 2024 10:15:26 +0100 Subject: [PATCH 2/2] Use `getLineWidth` instead of `measureText` --- .../com/facebook/react/views/text/TextLayoutManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 18b32b3d9de7ca..f537eab744e6c3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -631,7 +631,7 @@ private static Layout createLayout( && layout.getLineCount() > maximumNumberOfLines) || (heightYogaMeasureMode != YogaMeasureMode.UNDEFINED && layout.getHeight() > height) - || (text.length() == 1 && layout.getPaint().measureText(text.toString()) > width))) { + || (text.length() == 1 && layout.getLineWidth(0) > width))) { // TODO: We could probably use a smarter algorithm here. This will require 0(n) // measurements based on the number of points the font size needs to be reduced by. currentFontSize -= Math.max(1, (int) PixelUtil.toPixelFromDIP(1)); @@ -649,7 +649,9 @@ private static Layout createLayout( text.getSpanFlags(span)); text.removeSpan(span); } - boring = BoringLayout.isBoring(text, paint); + if (boring != null) { + boring = BoringLayout.isBoring(text, paint); + } layout = createLayout( text,