Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 59ef058

Browse files
authored
[web] Implement CanvasParagraph.getLineBoundary (#24037)
1 parent 009a47c commit 59ef058

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

lib/web_ui/lib/src/engine/text/canvas_paragraph.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,19 @@ class CanvasParagraph implements EngineParagraph {
242242

243243
@override
244244
ui.TextRange getLineBoundary(ui.TextPosition position) {
245-
// TODO(mdebbar): After layout, line metrics should be available and can be
246-
// used to determine the line boundary of the given `position`.
247-
return ui.TextRange.empty;
245+
final int index = position.offset;
246+
final List<EngineLineMetrics> lines = computeLineMetrics();
247+
248+
int i;
249+
for (i = 0; i < lines.length - 1; i++) {
250+
final EngineLineMetrics line = lines[i];
251+
if (index >= line.startIndex && index < line.endIndex) {
252+
break;
253+
}
254+
}
255+
256+
final EngineLineMetrics line = lines[i];
257+
return ui.TextRange(start: line.startIndex, end: line.endIndex);
248258
}
249259

250260
@override

lib/web_ui/test/text/canvas_paragraph_test.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,60 @@ void testMain() async {
547547
);
548548
});
549549
});
550+
551+
group('$CanvasParagraph.getLineBoundary', () {
552+
test('single-line', () {
553+
final CanvasParagraph paragraph = rich(ahemStyle, (builder) {
554+
builder.addText('One single line');
555+
})
556+
..layout(constrain(400.0));
557+
558+
// "One single line".length == 15
559+
for (int i = 0; i < 15; i++) {
560+
expect(
561+
paragraph.getLineBoundary(ui.TextPosition(offset: i)),
562+
ui.TextRange(start: 0, end: 15),
563+
reason: 'failed at offset $i',
564+
);
565+
}
566+
});
567+
568+
test('multi-line', () {
569+
final CanvasParagraph paragraph = rich(ahemStyle, (builder) {
570+
builder.addText('First line\n');
571+
builder.addText('Second line\n');
572+
builder.addText('Third line');
573+
})
574+
..layout(constrain(400.0));
575+
576+
// "First line\n".length == 11
577+
for (int i = 0; i < 11; i++) {
578+
expect(
579+
paragraph.getLineBoundary(ui.TextPosition(offset: i)),
580+
ui.TextRange(start: 0, end: 11),
581+
reason: 'failed at offset $i',
582+
);
583+
}
584+
585+
// "Second line\n".length == 12
586+
for (int i = 11; i < 23; i++) {
587+
expect(
588+
paragraph.getLineBoundary(ui.TextPosition(offset: i)),
589+
ui.TextRange(start: 11, end: 23),
590+
reason: 'failed at offset $i',
591+
);
592+
}
593+
594+
// "Third line".length == 10
595+
for (int i = 23; i < 33; i++) {
596+
expect(
597+
paragraph.getLineBoundary(ui.TextPosition(offset: i)),
598+
ui.TextRange(start: 23, end: 33),
599+
reason: 'failed at offset $i',
600+
);
601+
}
602+
});
603+
});
550604
}
551605

552606
/// Shortcut to create a [ui.TextBox] with an optional [ui.TextDirection].

0 commit comments

Comments
 (0)