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

Commit 0e7248d

Browse files
Fix a bug in the HTML render's getClosestGlyphInfo implementation (#48774)
`closestFragmentAtOffset` takes a horizontal offset from the start of the line, not the start of the paragraph. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 0ca2f38 commit 0e7248d

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,11 @@ class TextLayoutService {
420420
}
421421

422422
ui.GlyphInfo? getClosestGlyphInfo(ui.Offset offset) {
423-
final LayoutFragment? fragment = _findLineForY(offset.dy)
424-
?.closestFragmentAtOffset(offset.dx);
423+
final ParagraphLine? line = _findLineForY(offset.dy);
424+
if (line == null) {
425+
return null;
426+
}
427+
final LayoutFragment? fragment = line.closestFragmentAtOffset(offset.dx - line.left);
425428
if (fragment == null) {
426429
return null;
427430
}
@@ -431,8 +434,8 @@ class TextLayoutService {
431434
|| fragment.line.left + fragment.line.width <= dx
432435
|| switch (fragment.textDirection!) {
433436
// If dx is closer to the trailing edge, no need to check other fragments.
434-
ui.TextDirection.ltr => dx >= (fragment.left + fragment.right) / 2,
435-
ui.TextDirection.rtl => dx <= (fragment.left + fragment.right) / 2,
437+
ui.TextDirection.ltr => dx >= line.left + (fragment.left + fragment.right) / 2,
438+
ui.TextDirection.rtl => dx <= line.left + (fragment.left + fragment.right) / 2,
436439
};
437440
final ui.GlyphInfo candidate1 = fragment.getClosestCharacterBox(dx);
438441
if (closestGraphemeStartInFragment) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ class ParagraphLine {
380380

381381
final double? minDistance = closestFragment?.distance;
382382
if (minDistance == null || minDistance > distance) {
383-
closestFragment = (fragment: fragment, distance: distance);
383+
closestFragment = (fragment: fragment, distance: distance);
384384
}
385385
}
386386
return closestFragment?.fragment;

lib/web_ui/test/html/text_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,29 @@ Future<void> testMain() async {
155155
expect(bottomRight?.writingDirection, TextDirection.ltr);
156156
});
157157

158+
test('Basic glyph metrics - hit test - center aligned text in separate fragments', () {
159+
const double fontSize = 10.0;
160+
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
161+
fontSize: fontSize,
162+
textAlign: TextAlign.center,
163+
fontFamily: 'FlutterTest',
164+
))..addText('12345\n')
165+
..addText('1')
166+
..addText('2')
167+
..addText('3');
168+
final Paragraph paragraph = builder.build();
169+
paragraph.layout(const ParagraphConstraints(width: 50));
170+
171+
final GlyphInfo? bottomCenter = paragraph.getClosestGlyphInfoForOffset(const Offset(25.0, 99.0));
172+
final GlyphInfo? expected = paragraph.getGlyphInfoAt(7);
173+
expect(bottomCenter, equals(expected));
174+
expect(bottomCenter, isNot(paragraph.getGlyphInfoAt(8)));
175+
176+
expect(bottomCenter?.graphemeClusterLayoutBounds, const Rect.fromLTWH(20, 10, 10, 10));
177+
expect(bottomCenter?.graphemeClusterCodeUnitRange, const TextRange(start: 7, end: 8));
178+
expect(bottomCenter?.writingDirection, TextDirection.ltr);
179+
});
180+
158181
test('Glyph metrics with grapheme split into different runs', () {
159182
const double fontSize = 10;
160183
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(

0 commit comments

Comments
 (0)