diff --git a/lib/web_ui/lib/src/engine/text/paragraph.dart b/lib/web_ui/lib/src/engine/text/paragraph.dart index 3dbc6fbecafe13ade666806918629984ecf5e1c9..6b28d0609feccbceac18823db6dfed8512906e5b 100644 --- a/lib/web_ui/lib/src/engine/text/paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/paragraph.dart @@ -359,13 +359,23 @@ class EngineParagraph implements ui.Paragraph { }) { assert(boxHeightStyle != null); assert(boxWidthStyle != null); - if (_plainText == null || start == end) { + // Zero-length ranges and invalid ranges return an empty list. + if (start == end || start < 0 || end < 0) { return []; } + // For rich text, we can't measure the boxes. So for now, we'll just return + // a placeholder box to stop exceptions from being thrown in the framework. + // https://github.com/flutter/flutter/issues/55587 + if (_plainText == null) { + return [ + ui.TextBox.fromLTRBD(0, 0, 0, _lineHeight, _textDirection) + ]; + } + final int length = _plainText.length; // Ranges that are out of bounds should return an empty list. - if (start < 0 || end < 0 || start > length || end > length) { + if (start > length || end > length) { return []; } diff --git a/lib/web_ui/test/paragraph_test.dart b/lib/web_ui/test/paragraph_test.dart index c3432a00bed1f02653585060ab14414ebe781216..cc3f16663b4d25a64041f209405de3eae481a89b 100644 --- a/lib/web_ui/test/paragraph_test.dart +++ b/lib/web_ui/test/paragraph_test.dart @@ -415,6 +415,25 @@ void main() async { ); }); + testEachMeasurement('getBoxesForRange returns a box for rich text', () { + final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle( + fontFamily: 'Ahem', + fontStyle: FontStyle.normal, + fontWeight: FontWeight.normal, + fontSize: 10, + textDirection: TextDirection.ltr, + )); + builder.addText('abcd'); + builder.pushStyle(TextStyle(fontWeight: FontWeight.bold)); + builder.addText('xyz'); + final Paragraph paragraph = builder.build(); + paragraph.layout(const ParagraphConstraints(width: 1000)); + expect( + paragraph.getBoxesForRange(1, 2).single, + const TextBox.fromLTRBD(0, 0, 0, 10, TextDirection.ltr), + ); + }); + testEachMeasurement( 'getBoxesForRange return empty list for zero-length range', () { final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(