@@ -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