Skip to content

Commit

Permalink
Fix adjustsFontSizeToFit for strings with a single character
Browse files Browse the repository at this point in the history
  • Loading branch information
j-piasecki committed Oct 17, 2024
1 parent f673759 commit 3234b8e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public long measure(
"Spannable element has not been prepared in onBeforeLayout");

Layout layout = measureSpannedText(text, width, widthMode);
TextPaint paint = new TextPaint(sTextPaintInstance);

if (mAdjustsFontSizeToFit) {
int initialFontSize = mTextAttributes.getEffectiveFontSize();
Expand All @@ -83,8 +84,9 @@ public long measure(
int minimumFontSize =
(int) Math.max(mMinimumFontScale * initialFontSize, PixelUtil.toPixelFromDIP(4));
while (currentFontSize > minimumFontSize
&& (mNumberOfLines != ReactConstants.UNSET && layout.getLineCount() > mNumberOfLines
|| heightMode != YogaMeasureMode.UNDEFINED && layout.getHeight() > height)) {
&& ((mNumberOfLines != ReactConstants.UNSET && layout.getLineCount() > mNumberOfLines
|| heightMode != YogaMeasureMode.UNDEFINED && layout.getHeight() > height)
|| (text.length() == 1 && paint.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.
Expand All @@ -94,13 +96,15 @@ public long measure(
ReactAbsoluteSizeSpan[] sizeSpans =
text.getSpans(0, text.length(), ReactAbsoluteSizeSpan.class);
for (ReactAbsoluteSizeSpan span : sizeSpans) {
int newSize = (int) Math.max((span.getSize() * ratio), minimumFontSize);
text.setSpan(
new ReactAbsoluteSizeSpan(
(int) Math.max((span.getSize() * ratio), minimumFontSize)),
new ReactAbsoluteSizeSpan(newSize),
text.getSpanStart(span),
text.getSpanEnd(span),
text.getSpanFlags(span));
text.removeSpan(span);

paint.setTextSize(newSize);
}
layout = measureSpannedText(text, width, widthMode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,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));
Expand All @@ -600,6 +601,7 @@ private static Layout createLayout(
text.getSpanFlags(span));
text.removeSpan(span);
}
boring = BoringLayout.isBoring(text, paint);
layout =
createLayout(
text,
Expand Down

0 comments on commit 3234b8e

Please sign in to comment.