From 7db26b09bb5fdb020b1347dd5545d41bd4f5db90 Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Sat, 13 Apr 2024 04:58:02 +0800 Subject: [PATCH] Fix `getOffsetForCaret` crash (#146669) Fixes a crash in Google tests (b/333560406) related to a decomposed complex character. --- .../flutter/lib/src/painting/text_painter.dart | 9 +++++++-- .../flutter/test/painting/text_painter_test.dart | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) 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),