diff --git a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart index 305ce52544fac..8ff98e0d211a1 100644 --- a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart @@ -242,9 +242,19 @@ class CanvasParagraph implements EngineParagraph { @override ui.TextRange getLineBoundary(ui.TextPosition position) { - // TODO(mdebbar): After layout, line metrics should be available and can be - // used to determine the line boundary of the given `position`. - return ui.TextRange.empty; + final int index = position.offset; + final List lines = computeLineMetrics(); + + int i; + for (i = 0; i < lines.length - 1; i++) { + final EngineLineMetrics line = lines[i]; + if (index >= line.startIndex && index < line.endIndex) { + break; + } + } + + final EngineLineMetrics line = lines[i]; + return ui.TextRange(start: line.startIndex, end: line.endIndex); } @override diff --git a/lib/web_ui/test/text/canvas_paragraph_test.dart b/lib/web_ui/test/text/canvas_paragraph_test.dart index 601003fe4b669..d1f5d2b0642e8 100644 --- a/lib/web_ui/test/text/canvas_paragraph_test.dart +++ b/lib/web_ui/test/text/canvas_paragraph_test.dart @@ -547,6 +547,60 @@ void testMain() async { ); }); }); + + group('$CanvasParagraph.getLineBoundary', () { + test('single-line', () { + final CanvasParagraph paragraph = rich(ahemStyle, (builder) { + builder.addText('One single line'); + }) + ..layout(constrain(400.0)); + + // "One single line".length == 15 + for (int i = 0; i < 15; i++) { + expect( + paragraph.getLineBoundary(ui.TextPosition(offset: i)), + ui.TextRange(start: 0, end: 15), + reason: 'failed at offset $i', + ); + } + }); + + test('multi-line', () { + final CanvasParagraph paragraph = rich(ahemStyle, (builder) { + builder.addText('First line\n'); + builder.addText('Second line\n'); + builder.addText('Third line'); + }) + ..layout(constrain(400.0)); + + // "First line\n".length == 11 + for (int i = 0; i < 11; i++) { + expect( + paragraph.getLineBoundary(ui.TextPosition(offset: i)), + ui.TextRange(start: 0, end: 11), + reason: 'failed at offset $i', + ); + } + + // "Second line\n".length == 12 + for (int i = 11; i < 23; i++) { + expect( + paragraph.getLineBoundary(ui.TextPosition(offset: i)), + ui.TextRange(start: 11, end: 23), + reason: 'failed at offset $i', + ); + } + + // "Third line".length == 10 + for (int i = 23; i < 33; i++) { + expect( + paragraph.getLineBoundary(ui.TextPosition(offset: i)), + ui.TextRange(start: 23, end: 33), + reason: 'failed at offset $i', + ); + } + }); + }); } /// Shortcut to create a [ui.TextBox] with an optional [ui.TextDirection].