diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index 097379f19ea..18a8b6110f8 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -1468,10 +1468,15 @@ class TextPainter { final _LineCaretMetrics metrics; final List boxes = cachedLayout.paragraph .getBoxesForRange(graphemeRange.start, graphemeRange.end, boxHeightStyle: ui.BoxHeightStyle.strut); + if (boxes.isNotEmpty) { - final TextBox box = boxes.single; + final bool ahchorToLeft = switch (glyphInfo.writingDirection) { + TextDirection.ltr => anchorToLeadingEdge, + TextDirection.rtl => !anchorToLeadingEdge, + }; + final TextBox box = ahchorToLeft ? boxes.first : boxes.last; metrics = _LineCaretMetrics( - offset: Offset(anchorToLeadingEdge ? box.start : box.end, box.top), + offset: Offset(ahchorToLeft ? box.left : box.right, box.top), writingDirection: box.direction, ); } else { diff --git a/packages/flutter/test/painting/text_painter_test.dart b/packages/flutter/test/painting/text_painter_test.dart index f8feb2afd8b..47f4f18f870 100644 --- a/packages/flutter/test/painting/text_painter_test.dart +++ b/packages/flutter/test/painting/text_painter_test.dart @@ -1682,6 +1682,20 @@ void main() { }); }, skip: kIsWeb && !isSkiaWeb); // [intended] strut spport for HTML renderer https://github.com/flutter/flutter/issues/32243. + test('getOffsetForCaret does not crash on decomposed characters', () { + final TextPainter painter = TextPainter( + textDirection: TextDirection.ltr, + text: const TextSpan( + text: '각', + style: TextStyle(fontSize: 10), + ), + )..layout(maxWidth: 1); // Force the jamo characters to soft wrap. + expect( + () => painter.getOffsetForCaret(const TextPosition(offset: 0), Rect.zero), + returnsNormally, + ); + }); + test('TextPainter dispatches memory events', () async { await expectLater( await memoryEvents(() => TextPainter().dispose(), TextPainter),