@@ -630,6 +630,204 @@ void main() async {
630630 );
631631 });
632632
633+ testEachMeasurement ('getBoxesForRange with maxLines' , () {
634+ final ParagraphBuilder builder = ParagraphBuilder (ParagraphStyle (
635+ fontFamily: 'Ahem' ,
636+ fontStyle: FontStyle .normal,
637+ fontWeight: FontWeight .normal,
638+ fontSize: 10 ,
639+ textDirection: TextDirection .ltr,
640+ maxLines: 2 ,
641+ ));
642+ builder.addText ('abcd\n ' );
643+ builder.addText ('abcdefg\n ' );
644+ builder.addText ('ab' );
645+ final Paragraph paragraph = builder.build ();
646+ paragraph.layout (const ParagraphConstraints (width: 100 ));
647+
648+ // In the dom-based measurement (except Firefox), there will be some
649+ // discrepancies around line ends.
650+ final isDiscrepancyExpected =
651+ ! TextMeasurementService .enableExperimentalCanvasImplementation &&
652+ browserEngine != BrowserEngine .firefox;
653+
654+ // First line: "abcd\n"
655+
656+ // At the beginning of the first line.
657+ expect (
658+ paragraph.getBoxesForRange (0 , 0 ),
659+ < TextBox > [],
660+ );
661+ // At the end of the first line.
662+ expect (
663+ paragraph.getBoxesForRange (4 , 4 ),
664+ < TextBox > [],
665+ );
666+ // Between "b" and "c" in the first line.
667+ expect (
668+ paragraph.getBoxesForRange (2 , 2 ),
669+ < TextBox > [],
670+ );
671+ // The range "ab" in the first line.
672+ expect (
673+ paragraph.getBoxesForRange (0 , 2 ),
674+ < TextBox > [
675+ TextBox .fromLTRBD (0.0 , 0.0 , 20.0 , 10.0 , TextDirection .ltr),
676+ ],
677+ );
678+ // The range "bc" in the first line.
679+ expect (
680+ paragraph.getBoxesForRange (1 , 3 ),
681+ < TextBox > [
682+ TextBox .fromLTRBD (10.0 , 0.0 , 30.0 , 10.0 , TextDirection .ltr),
683+ ],
684+ );
685+ // The range "d" in the first line.
686+ expect (
687+ paragraph.getBoxesForRange (3 , 4 ),
688+ < TextBox > [
689+ TextBox .fromLTRBD (30.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
690+ ],
691+ );
692+ // The range "\n" in the first line.
693+ expect (
694+ paragraph.getBoxesForRange (4 , 5 ),
695+ < TextBox > [
696+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
697+ ],
698+ );
699+ // The range "cd\n" in the first line.
700+ expect (
701+ paragraph.getBoxesForRange (2 , 5 ),
702+ < TextBox > [
703+ TextBox .fromLTRBD (20.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
704+ if (isDiscrepancyExpected)
705+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
706+ ],
707+ );
708+
709+ // Second line: "abcdefg\n"
710+
711+ // At the beginning of the second line.
712+ expect (
713+ paragraph.getBoxesForRange (5 , 5 ),
714+ < TextBox > [],
715+ );
716+ // At the end of the second line.
717+ expect (
718+ paragraph.getBoxesForRange (12 , 12 ),
719+ < TextBox > [],
720+ );
721+ // The range "efg" in the second line.
722+ expect (
723+ paragraph.getBoxesForRange (9 , 12 ),
724+ < TextBox > [
725+ TextBox .fromLTRBD (40.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
726+ ],
727+ );
728+ // The range "bcde" in the second line.
729+ expect (
730+ paragraph.getBoxesForRange (6 , 10 ),
731+ < TextBox > [
732+ TextBox .fromLTRBD (10.0 , 10.0 , 50.0 , 20.0 , TextDirection .ltr),
733+ ],
734+ );
735+ // The range "fg\n" in the second line.
736+ expect (
737+ paragraph.getBoxesForRange (10 , 13 ),
738+ < TextBox > [
739+ TextBox .fromLTRBD (50.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
740+ if (isDiscrepancyExpected)
741+ TextBox .fromLTRBD (70.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
742+ ],
743+ );
744+
745+ // Last (third) line: "ab"
746+
747+ // At the beginning of the last line.
748+ expect (
749+ paragraph.getBoxesForRange (13 , 13 ),
750+ < TextBox > [],
751+ );
752+ // At the end of the last line.
753+ expect (
754+ paragraph.getBoxesForRange (15 , 15 ),
755+ < TextBox > [],
756+ );
757+ // The range "a" in the last line.
758+ expect (
759+ paragraph.getBoxesForRange (14 , 15 ),
760+ < TextBox > [],
761+ );
762+ // The range "ab" in the last line.
763+ expect (
764+ paragraph.getBoxesForRange (13 , 15 ),
765+ < TextBox > [],
766+ );
767+
768+
769+ // Combine multiple lines
770+
771+ // The range "cd\nabc".
772+ expect (
773+ paragraph.getBoxesForRange (2 , 8 ),
774+ < TextBox > [
775+ TextBox .fromLTRBD (20.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
776+ if (isDiscrepancyExpected)
777+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
778+ TextBox .fromLTRBD (0.0 , 10.0 , 30.0 , 20.0 , TextDirection .ltr),
779+ ],
780+ );
781+
782+ // The range "\nabcd".
783+ expect (
784+ paragraph.getBoxesForRange (4 , 9 ),
785+ < TextBox > [
786+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
787+ TextBox .fromLTRBD (0.0 , 10.0 , 40.0 , 20.0 , TextDirection .ltr),
788+ ],
789+ );
790+
791+ // The range "d\nabcdefg\na".
792+ expect (
793+ paragraph.getBoxesForRange (3 , 14 ),
794+ < TextBox > [
795+ TextBox .fromLTRBD (30.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
796+ if (isDiscrepancyExpected)
797+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
798+ TextBox .fromLTRBD (0.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
799+ if (isDiscrepancyExpected)
800+ TextBox .fromLTRBD (70.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
801+ ],
802+ );
803+
804+ // The range "abcd\nabcdefg\n".
805+ expect (
806+ paragraph.getBoxesForRange (0 , 13 ),
807+ < TextBox > [
808+ TextBox .fromLTRBD (0.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
809+ if (isDiscrepancyExpected)
810+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
811+ TextBox .fromLTRBD (0.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
812+ if (isDiscrepancyExpected)
813+ TextBox .fromLTRBD (70.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
814+ ],
815+ );
816+
817+ // The range "abcd\nabcdefg\nab".
818+ expect (
819+ paragraph.getBoxesForRange (0 , 15 ),
820+ < TextBox > [
821+ TextBox .fromLTRBD (0.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
822+ if (isDiscrepancyExpected)
823+ TextBox .fromLTRBD (40.0 , 0.0 , 40.0 , 10.0 , TextDirection .ltr),
824+ TextBox .fromLTRBD (0.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
825+ if (isDiscrepancyExpected)
826+ TextBox .fromLTRBD (70.0 , 10.0 , 70.0 , 20.0 , TextDirection .ltr),
827+ ],
828+ );
829+ });
830+
633831 test ('longestLine' , () {
634832 // [Paragraph.longestLine] is only supported by canvas-based measurement.
635833 TextMeasurementService .enableExperimentalCanvasImplementation = true ;
0 commit comments