@@ -8,6 +8,8 @@ import 'package:test/test.dart';
88import 'package:ui/src/engine.dart' ;
99import 'package:ui/ui.dart' ;
1010
11+ import '../html/paragraph/helper.dart' ;
12+
1113// Two RTL strings, 5 characters each, to match the length of "$rtl1" and "$rtl2".
1214const String rtl1 = 'واحدة' ;
1315const String rtl2 = 'ثنتان' ;
@@ -17,110 +19,70 @@ void main() {
1719}
1820
1921Future <void > testMain () async {
20- group ('$getDirectionalBlockEnd ' , () {
22+ group ('$BidiFragmenter ' , () {
2123
2224 test ('basic cases' , () {
23- const String text = 'Lorem 12 $rtl1 ipsum34' ;
24- const LineBreakResult start = LineBreakResult .sameIndex (0 , LineBreakType .prohibited);
25- const LineBreakResult end = LineBreakResult .sameIndex (text.length, LineBreakType .endOfText);
26- const LineBreakResult loremMiddle = LineBreakResult .sameIndex (3 , LineBreakType .prohibited);
27- const LineBreakResult loremEnd = LineBreakResult .sameIndex (5 , LineBreakType .prohibited);
28- const LineBreakResult twelveStart = LineBreakResult (6 , 6 , 5 , LineBreakType .opportunity);
29- const LineBreakResult twelveEnd = LineBreakResult .sameIndex (8 , LineBreakType .prohibited);
30- const LineBreakResult rtl1Start = LineBreakResult (9 , 9 , 8 , LineBreakType .opportunity);
31- const LineBreakResult rtl1End = LineBreakResult .sameIndex (14 , LineBreakType .prohibited);
32- const LineBreakResult ipsumStart = LineBreakResult (17 , 17 , 15 , LineBreakType .opportunity);
33- const LineBreakResult ipsumEnd = LineBreakResult .sameIndex (22 , LineBreakType .prohibited);
34-
35- DirectionalPosition blockEnd;
36-
37- blockEnd = getDirectionalBlockEnd (text, start, end);
38- expect (blockEnd.isSpaceOnly, isFalse);
39- expect (blockEnd.textDirection, TextDirection .ltr);
40- expect (blockEnd.lineBreak, loremEnd);
41-
42- blockEnd = getDirectionalBlockEnd (text, start, loremMiddle);
43- expect (blockEnd.isSpaceOnly, isFalse);
44- expect (blockEnd.textDirection, TextDirection .ltr);
45- expect (blockEnd.lineBreak, loremMiddle);
46-
47- blockEnd = getDirectionalBlockEnd (text, loremMiddle, loremEnd);
48- expect (blockEnd.isSpaceOnly, isFalse);
49- expect (blockEnd.textDirection, TextDirection .ltr);
50- expect (blockEnd.lineBreak, loremEnd);
51-
52- blockEnd = getDirectionalBlockEnd (text, loremEnd, twelveStart);
53- expect (blockEnd.isSpaceOnly, isTrue);
54- expect (blockEnd.textDirection, isNull);
55- expect (blockEnd.lineBreak, twelveStart);
56-
57- blockEnd = getDirectionalBlockEnd (text, twelveStart, rtl1Start);
58- expect (blockEnd.isSpaceOnly, isFalse);
59- expect (blockEnd.textDirection, isNull);
60- expect (blockEnd.lineBreak, twelveEnd);
61-
62- blockEnd = getDirectionalBlockEnd (text, rtl1Start, end);
63- expect (blockEnd.isSpaceOnly, isFalse);
64- expect (blockEnd.textDirection, TextDirection .rtl);
65- expect (blockEnd.lineBreak, rtl1End);
66-
67- blockEnd = getDirectionalBlockEnd (text, ipsumStart, end);
68- expect (blockEnd.isSpaceOnly, isFalse);
69- expect (blockEnd.textDirection, TextDirection .ltr);
70- expect (blockEnd.lineBreak, ipsumEnd);
71-
72- blockEnd = getDirectionalBlockEnd (text, ipsumEnd, end);
73- expect (blockEnd.isSpaceOnly, isFalse);
74- expect (blockEnd.textDirection, isNull);
75- expect (blockEnd.lineBreak, end);
25+ expect (split ('Lorem 12 $rtl1 ipsum34' ), < _Bidi > [
26+ _Bidi ('Lorem 12 ' , TextDirection .ltr),
27+ _Bidi ('$rtl1 ' , TextDirection .rtl),
28+ _Bidi ('ipsum34' , TextDirection .ltr),
29+ ]);
30+ });
31+
32+ test ('symbols' , () {
33+ expect (split ('Calculate 2.2 + 4.5 and write the result' ), < _Bidi > [
34+ _Bidi ('Calculate 2.2 + 4.5 and write the result' , TextDirection .ltr),
35+ ]);
36+
37+ expect (split ('Calculate $rtl1 2.2 + 4.5 and write the result' ), < _Bidi > [
38+ _Bidi ('Calculate ' , TextDirection .ltr),
39+ _Bidi ('$rtl1 2.2 + 4.5 ' , TextDirection .rtl),
40+ _Bidi ('and write the result' , TextDirection .ltr),
41+ ]);
7642 });
7743
7844 test ('handles new lines' , () {
79- const String text = 'Lorem\n 12\n ipsum \n ' ;
80- const LineBreakResult start = LineBreakResult .sameIndex (0 , LineBreakType .prohibited);
81- const LineBreakResult end = LineBreakResult (
82- text.length,
83- text.length - 1 ,
84- text.length - 3 ,
85- LineBreakType .mandatory,
86- );
87- const LineBreakResult loremEnd = LineBreakResult .sameIndex (5 , LineBreakType .prohibited);
88- const LineBreakResult twelveStart = LineBreakResult (6 , 5 , 5 , LineBreakType .mandatory);
89- const LineBreakResult twelveEnd = LineBreakResult .sameIndex (8 , LineBreakType .prohibited);
90- const LineBreakResult ipsumStart = LineBreakResult (9 , 8 , 8 , LineBreakType .mandatory);
91- const LineBreakResult ipsumEnd = LineBreakResult .sameIndex (14 , LineBreakType .prohibited);
92-
93- DirectionalPosition blockEnd;
94-
95- blockEnd = getDirectionalBlockEnd (text, start, twelveStart);
96- expect (blockEnd.isSpaceOnly, isFalse);
97- expect (blockEnd.textDirection, TextDirection .ltr);
98- expect (blockEnd.lineBreak, twelveStart);
99-
100- blockEnd = getDirectionalBlockEnd (text, loremEnd, twelveStart);
101- expect (blockEnd.isSpaceOnly, isTrue);
102- expect (blockEnd.textDirection, isNull);
103- expect (blockEnd.lineBreak, twelveStart);
104-
105- blockEnd = getDirectionalBlockEnd (text, twelveStart, ipsumStart);
106- expect (blockEnd.isSpaceOnly, isFalse);
107- expect (blockEnd.textDirection, isNull);
108- expect (blockEnd.lineBreak, ipsumStart);
109-
110- blockEnd = getDirectionalBlockEnd (text, twelveEnd, ipsumStart);
111- expect (blockEnd.isSpaceOnly, isTrue);
112- expect (blockEnd.textDirection, isNull);
113- expect (blockEnd.lineBreak, ipsumStart);
114-
115- blockEnd = getDirectionalBlockEnd (text, ipsumStart, end);
116- expect (blockEnd.isSpaceOnly, isFalse);
117- expect (blockEnd.textDirection, TextDirection .ltr);
118- expect (blockEnd.lineBreak, ipsumEnd);
119-
120- blockEnd = getDirectionalBlockEnd (text, ipsumEnd, end);
121- expect (blockEnd.isSpaceOnly, isTrue);
122- expect (blockEnd.textDirection, isNull);
123- expect (blockEnd.lineBreak, end);
45+ expect (split ('Lorem\n 12\n ipsum \n ' ), < _Bidi > [
46+ _Bidi ('Lorem\n 12\n ipsum \n ' , TextDirection .ltr),
47+ ]);
48+
49+ expect (split ('$rtl1 \n $rtl2 \n ' ), < _Bidi > [
50+ _Bidi ('$rtl1 \n $rtl2 \n ' , TextDirection .rtl),
51+ ]);
12452 });
12553 });
12654}
55+
56+ /// Holds information about how a bidi region was split from a string.
57+ class _Bidi {
58+ _Bidi (this .text, this .textDirection);
59+
60+ final String text;
61+ final TextDirection textDirection;
62+
63+ @override
64+ int get hashCode => Object .hash (text, textDirection);
65+
66+ @override
67+ bool operator == (Object other) {
68+ return other is _Bidi && other.text == text && other.textDirection == textDirection;
69+ }
70+
71+ @override
72+ String toString () {
73+ return '"$text " ($textDirection )' ;
74+ }
75+ }
76+
77+ List <_Bidi > split (String text) {
78+ return < _Bidi > [
79+ for (final BidiFragment fragment in computeBidiFragments (text))
80+ _Bidi (text.substring (fragment.start, fragment.end), fragment.textDirection)
81+ ];
82+ }
83+
84+ List <BidiFragment > computeBidiFragments (String text) {
85+ final CanvasParagraph paragraph = plain (EngineParagraphStyle (), text);
86+ final BidiFragmenter fragmenter = BidiFragmenter (paragraph);
87+ return fragmenter.fragment ();
88+ }
0 commit comments