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

Commit 58df5d4

Browse files
committed
[web] Handle alignment correctly in Paragraph.getPositionForOffset
1 parent 22d08d1 commit 58df5d4

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ class EngineParagraph implements ui.Paragraph {
434434
// code below will do a binary search to find where exactly the [offset]
435435
// falls within the line.
436436

437-
final double dx = offset.dx - _alignOffset;
437+
final double dx = offset.dx - lineMetrics.left;
438438
final TextMeasurementService instance = _measurementService;
439439

440440
int low = lineMetrics.startIndex;

lib/web_ui/test/paragraph_test.dart

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,115 @@ void main() async {
284284
TextMeasurementService.enableExperimentalCanvasImplementation = false;
285285
});
286286

287+
test('getPositionForOffset multi-line centered', () {
288+
TextMeasurementService.enableExperimentalCanvasImplementation = true;
289+
TextMeasurementService.initialize(rulerCacheCapacity: 2);
290+
291+
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
292+
fontFamily: 'Ahem',
293+
fontStyle: FontStyle.normal,
294+
fontWeight: FontWeight.normal,
295+
fontSize: 10,
296+
textDirection: TextDirection.ltr,
297+
textAlign: TextAlign.center,
298+
));
299+
builder.addText('abcd\n');
300+
builder.addText('abcdefg\n');
301+
builder.addText('ab');
302+
final Paragraph paragraph = builder.build();
303+
paragraph.layout(const ParagraphConstraints(width: 100));
304+
305+
// First line: "abcd\n"
306+
307+
// At the beginning of the first line.
308+
expect(
309+
paragraph.getPositionForOffset(Offset(0, 5)),
310+
TextPosition(offset: 0, affinity: TextAffinity.downstream),
311+
);
312+
// Above the first line.
313+
expect(
314+
paragraph.getPositionForOffset(Offset(0, -15)),
315+
TextPosition(offset: 0, affinity: TextAffinity.downstream),
316+
);
317+
// At the end of the first line.
318+
expect(
319+
paragraph.getPositionForOffset(Offset(100, 5)),
320+
TextPosition(offset: 4, affinity: TextAffinity.upstream),
321+
);
322+
// On the left side of "b" in the first line.
323+
expect(
324+
// The line is centered so it's shifted to the right by "30.0px".
325+
paragraph.getPositionForOffset(Offset(30.0 + 14, 5)),
326+
TextPosition(offset: 1, affinity: TextAffinity.downstream),
327+
);
328+
// On the right side of "b" in the first line.
329+
expect(
330+
// The line is centered so it's shifted to the right by "30.0px".
331+
paragraph.getPositionForOffset(Offset(30.0 + 16, 5)),
332+
TextPosition(offset: 2, affinity: TextAffinity.upstream),
333+
);
334+
335+
336+
// Second line: "abcdefg\n"
337+
338+
// At the beginning of the second line.
339+
expect(
340+
paragraph.getPositionForOffset(Offset(0, 15)),
341+
TextPosition(offset: 5, affinity: TextAffinity.downstream),
342+
);
343+
// At the end of the second line.
344+
expect(
345+
paragraph.getPositionForOffset(Offset(100, 15)),
346+
TextPosition(offset: 12, affinity: TextAffinity.upstream),
347+
);
348+
// On the left side of "e" in the second line.
349+
expect(
350+
// The line is centered so it's shifted to the right by "15.0px".
351+
paragraph.getPositionForOffset(Offset(15.0 + 44, 15)),
352+
TextPosition(offset: 9, affinity: TextAffinity.downstream),
353+
);
354+
// On the right side of "e" in the second line.
355+
expect(
356+
// The line is centered so it's shifted to the right by "15.0px".
357+
paragraph.getPositionForOffset(Offset(15.0 + 46, 15)),
358+
TextPosition(offset: 10, affinity: TextAffinity.upstream),
359+
);
360+
361+
362+
// Last (third) line: "ab"
363+
364+
// At the beginning of the last line.
365+
expect(
366+
paragraph.getPositionForOffset(Offset(0, 25)),
367+
TextPosition(offset: 13, affinity: TextAffinity.downstream),
368+
);
369+
// At the end of the last line.
370+
expect(
371+
paragraph.getPositionForOffset(Offset(100, 25)),
372+
TextPosition(offset: 15, affinity: TextAffinity.upstream),
373+
);
374+
// Below the last line.
375+
expect(
376+
paragraph.getPositionForOffset(Offset(0, 32)),
377+
TextPosition(offset: 15, affinity: TextAffinity.upstream),
378+
);
379+
// On the left side of "b" in the last line.
380+
expect(
381+
// The line is centered so it's shifted to the right by "40.0px".
382+
paragraph.getPositionForOffset(Offset(40.0 + 12, 25)),
383+
TextPosition(offset: 14, affinity: TextAffinity.downstream),
384+
);
385+
// On the right side of "a" in the last line.
386+
expect(
387+
// The line is centered so it's shifted to the right by "40.0px".
388+
paragraph.getPositionForOffset(Offset(40.0 + 9, 25)),
389+
TextPosition(offset: 14, affinity: TextAffinity.upstream),
390+
);
391+
392+
TextMeasurementService.clearCache();
393+
TextMeasurementService.enableExperimentalCanvasImplementation = false;
394+
});
395+
287396
testEachMeasurement('getBoxesForRange returns a box', () {
288397
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
289398
fontFamily: 'Ahem',

0 commit comments

Comments
 (0)