From 1209c0ac48b17074e3d37ede55f13c58f8c87aad Mon Sep 17 00:00:00 2001 From: delekta Date: Wed, 11 Feb 2026 10:32:26 +0100 Subject: [PATCH 1/2] Fix: [iOS] Correctly mark inline attachments as clipped when in truncated text range --- .../textlayoutmanager/RCTTextLayoutManager.mm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 ef50487f91200e..285b46c33993ed 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 @@ -391,6 +391,8 @@ - (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage size = (CGSize){ceil(size.width * layoutContext.pointScaleFactor) / layoutContext.pointScaleFactor, ceil(size.height * layoutContext.pointScaleFactor) / layoutContext.pointScaleFactor}; + NSRange visibleGlyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; + __block auto attachments = TextMeasurement::Attachments{}; [textStorage @@ -406,7 +408,14 @@ - (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage actualCharacterRange:NULL]; NSRange truncatedRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:attachmentGlyphRange.location]; - if (truncatedRange.location != NSNotFound && attachmentGlyphRange.location >= truncatedRange.location) { + + // Mark attachment as clipped if it falls outside the laid-out glyph range + // or if it lies in a truncated portion of the last visible line. + BOOL isOutsideVisibleRange = !NSLocationInRange(attachmentGlyphRange.location, visibleGlyphRange); + BOOL isInTruncatedRange = truncatedRange.location != NSNotFound && + attachmentGlyphRange.location >= truncatedRange.location; + + if (isOutsideVisibleRange || isInTruncatedRange) { attachments.push_back(TextMeasurement::Attachment{.isClipped = true}); } else { CGSize attachmentSize = attachment.bounds.size; From 3ea2906028b0cb9ada143e1517b30ab756ef45a5 Mon Sep 17 00:00:00 2001 From: delekta Date: Wed, 11 Feb 2026 12:05:46 +0100 Subject: [PATCH 2/2] Updating comments --- .../react/renderer/textlayoutmanager/RCTTextLayoutManager.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 285b46c33993ed..dda3a283939f7a 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 @@ -409,9 +409,9 @@ - (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage NSRange truncatedRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:attachmentGlyphRange.location]; - // Mark attachment as clipped if it falls outside the laid-out glyph range - // or if it lies in a truncated portion of the last visible line. + // Attachment on a line that did not fit (e.g. on the 4th line when the container is limited to 3 lines) BOOL isOutsideVisibleRange = !NSLocationInRange(attachmentGlyphRange.location, visibleGlyphRange); + // Attachment in the ellipsis range of the last visible line (line truncated with "..." and the attachment falls in that portion) BOOL isInTruncatedRange = truncatedRange.location != NSNotFound && attachmentGlyphRange.location >= truncatedRange.location;