1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics.text.cts;
18 
19 import static android.graphics.text.LineBreaker.BREAK_STRATEGY_BALANCED;
20 import static android.graphics.text.LineBreaker.BREAK_STRATEGY_HIGH_QUALITY;
21 import static android.graphics.text.LineBreaker.BREAK_STRATEGY_SIMPLE;
22 import static android.graphics.text.LineBreaker.HYPHENATION_FREQUENCY_FULL;
23 import static android.graphics.text.LineBreaker.HYPHENATION_FREQUENCY_NONE;
24 import static android.graphics.text.LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
25 import static android.graphics.text.LineBreaker.JUSTIFICATION_MODE_INTER_WORD;
26 import static android.graphics.text.LineBreaker.JUSTIFICATION_MODE_NONE;
27 import static android.graphics.text.LineBreaker.ParagraphConstraints;
28 import static android.graphics.text.LineBreaker.Result;
29 
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertFalse;
32 import static org.junit.Assert.assertNotNull;
33 import static org.junit.Assert.assertNull;
34 import static org.junit.Assert.assertTrue;
35 
36 import android.content.Context;
37 import android.content.res.AssetManager;
38 import android.graphics.Paint;
39 import android.graphics.Typeface;
40 import android.graphics.text.LineBreaker;
41 import android.graphics.text.MeasuredText;
42 
43 import androidx.test.InstrumentationRegistry;
44 import androidx.test.filters.SmallTest;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import org.junit.BeforeClass;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 @SmallTest
52 @RunWith(AndroidJUnit4.class)
53 public class LineBreakerTest {
54     private static final String TAG = "LineBreakerTest";
55 
56     private static Paint sPaint;
57     @BeforeClass
classSetUp()58     public static void classSetUp() {
59         sPaint = new Paint();
60         Context context = InstrumentationRegistry.getTargetContext();
61         AssetManager am = context.getAssets();
62         Typeface tf = new Typeface.Builder(am, "fonts/layout/linebreak.ttf").build();
63         sPaint.setTypeface(tf);
64         sPaint.setTextSize(10.0f);  // Make 1em = 10px
65     }
66 
67     @Test
testLineBreak_construct()68     public void testLineBreak_construct() {
69         assertNotNull(new LineBreaker.Builder().build());
70     }
71 
72     @Test
testSetBreakStrategy_shoulNotThrowExceptions()73     public void testSetBreakStrategy_shoulNotThrowExceptions() {
74         assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_SIMPLE).build());
75         assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_HIGH_QUALITY)
76                 .build());
77         assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_BALANCED).build());
78     }
79 
80     @Test
testSetHyphenationFrequency_shouldNotThrowExceptions()81     public void testSetHyphenationFrequency_shouldNotThrowExceptions() {
82         assertNotNull(new LineBreaker.Builder()
83                 .setHyphenationFrequency(HYPHENATION_FREQUENCY_NORMAL).build());
84         assertNotNull(new LineBreaker.Builder()
85                 .setHyphenationFrequency(HYPHENATION_FREQUENCY_FULL).build());
86         assertNotNull(new LineBreaker.Builder()
87                 .setHyphenationFrequency(HYPHENATION_FREQUENCY_NONE).build());
88     }
89 
90     @Test
testSetJustification_shouldNotThrowExceptions()91     public void testSetJustification_shouldNotThrowExceptions() {
92         assertNotNull(new LineBreaker.Builder()
93                 .setJustificationMode(JUSTIFICATION_MODE_NONE).build());
94         assertNotNull(new LineBreaker.Builder()
95                 .setJustificationMode(JUSTIFICATION_MODE_INTER_WORD).build());
96     }
97 
98     @Test
testSetIntent_shouldNotThrowExceptions()99     public void testSetIntent_shouldNotThrowExceptions() {
100         assertNotNull(new LineBreaker.Builder().setIndents(null).build());
101         assertNotNull(new LineBreaker.Builder().setIndents(new int[] {}).build());
102         assertNotNull(new LineBreaker.Builder().setIndents(new int[] { 100 }).build());
103     }
104 
105     @Test
testSetGetWidth()106     public void testSetGetWidth() {
107         ParagraphConstraints c = new ParagraphConstraints();
108         assertEquals(0, c.getWidth(), 0.0f);  // 0 by default
109         c.setWidth(100);
110         assertEquals(100, c.getWidth(), 0.0f);
111         c.setWidth(200);
112         assertEquals(200, c.getWidth(), 0.0f);
113     }
114 
115     @Test
testSetGetIndent()116     public void testSetGetIndent() {
117         ParagraphConstraints c = new ParagraphConstraints();
118         assertEquals(0.0f, c.getFirstWidth(), 0.0f);  // 0 by default
119         assertEquals(0, c.getFirstWidthLineCount());  // 0 by default
120         c.setIndent(100.0f, 1);
121         assertEquals(100.0f, c.getFirstWidth(), 0.0f);
122         assertEquals(1, c.getFirstWidthLineCount());
123         c.setIndent(200.0f, 5);
124         assertEquals(200.0f, c.getFirstWidth(), 0.0f);
125         assertEquals(5, c.getFirstWidthLineCount());
126     }
127 
128     @Test
testSetGetTabStops()129     public void testSetGetTabStops() {
130         ParagraphConstraints c = new ParagraphConstraints();
131         assertNull(c.getTabStops());  // null by default
132         assertEquals(0, c.getDefaultTabStop(), 0.0);  // 0 by default
133         c.setTabStops(new float[] { 120 }, 240);
134         assertEquals(1, c.getTabStops().length);
135         assertEquals(120, c.getTabStops()[0], 0.0);
136         assertEquals(240, c.getDefaultTabStop(), 0.0);
137     }
138 
139     @Test
testLineBreak_Simple()140     public void testLineBreak_Simple() {
141         final String text = "Hello, World.";
142         final LineBreaker lb = new LineBreaker.Builder()
143                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
144                 .build();
145         final ParagraphConstraints c = new ParagraphConstraints();
146         c.setWidth(Float.MAX_VALUE);
147         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
148                 .appendStyleRun(sPaint, text.length(), false).build(), c, 0);
149         assertEquals(1, r.getLineCount());
150         assertEquals(13, r.getLineBreakOffset(0));
151         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
152         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
153         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
154         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
155         assertFalse(r.hasLineTab(0));
156         assertEquals(130.0f, r.getLineWidth(0), 0.0f);
157     }
158 
159     @Test
testLineBreak_Simple2()160     public void testLineBreak_Simple2() {
161         // The visual line break output is like
162         // |abc defg|
163         // |hijkl   |
164         final String text = "abc defg hijkl";
165         final LineBreaker lb = new LineBreaker.Builder()
166                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
167                 .build();
168         final ParagraphConstraints c = new ParagraphConstraints();
169         c.setWidth(80.0f);
170         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
171                 .appendStyleRun(sPaint, text.length(), false).build(), c, 0);
172         assertEquals(2, r.getLineCount());
173         assertEquals(9, r.getLineBreakOffset(0));
174         assertEquals(14, r.getLineBreakOffset(1));
175         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
176         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
177         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
178         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
179         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
180         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
181         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
182         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
183         assertFalse(r.hasLineTab(0));
184         assertFalse(r.hasLineTab(1));
185         assertEquals(80.0f, r.getLineWidth(0), 0.0f);
186         assertEquals(50.0f, r.getLineWidth(1), 0.0f);
187     }
188 
189     @Test
testLineBreak_Simple3()190     public void testLineBreak_Simple3() {
191         // The visual line break output is like
192         // |abc |
193         // |defg|
194         // |hijk|
195         // |l   |
196         final String text = "abc defg hijkl";
197         final LineBreaker lb = new LineBreaker.Builder()
198                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
199                 .build();
200         final ParagraphConstraints c = new ParagraphConstraints();
201         c.setWidth(40.0f);
202         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
203                 .appendStyleRun(sPaint, text.length(), false).build(), c, 0);
204         assertEquals(4, r.getLineCount());
205         assertEquals(4, r.getLineBreakOffset(0));
206         assertEquals(9, r.getLineBreakOffset(1));
207         assertEquals(13, r.getLineBreakOffset(2));
208         assertEquals(14, r.getLineBreakOffset(3));
209         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
210         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
211         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
212         assertEquals(-10.0f, r.getLineAscent(3), 0.0f);
213         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
214         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
215         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
216         assertEquals(2.0f, r.getLineDescent(3), 0.0f);
217         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
218         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
219         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
220         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
221         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
222         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
223         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(3));
224         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(3));
225         assertFalse(r.hasLineTab(0));
226         assertFalse(r.hasLineTab(1));
227         assertFalse(r.hasLineTab(2));
228         assertFalse(r.hasLineTab(3));
229         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
230         assertEquals(40.0f, r.getLineWidth(1), 0.0f);
231         assertEquals(40.0f, r.getLineWidth(2), 0.0f);
232         assertEquals(10.0f, r.getLineWidth(3), 0.0f);
233     }
234 
235     @Test
testLineBreak_Simple_NotRectangle()236     public void testLineBreak_Simple_NotRectangle() {
237         // The visual line break output is like
238         // |abc  |
239         // |defg hijkl|
240         final String text = "abc defg hijkl";
241         final LineBreaker lb = new LineBreaker.Builder()
242                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
243                 .build();
244         final ParagraphConstraints c = new ParagraphConstraints();
245         c.setWidth(100.0f);
246         c.setIndent(50.0f, 1);  // Make the first line width 50 px.
247         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
248                 .appendStyleRun(sPaint, text.length(), false).build(), c, 0);
249         assertEquals(2, r.getLineCount());
250         assertEquals(4, r.getLineBreakOffset(0));
251         assertEquals(14, r.getLineBreakOffset(1));
252         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
253         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
254         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
255         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
256         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
257         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
258         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
259         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
260         assertFalse(r.hasLineTab(0));
261         assertFalse(r.hasLineTab(1));
262         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
263         assertEquals(100.0f, r.getLineWidth(1), 0.0f);
264     }
265 
266     @Test
testLineBreak_Simple_Hyphenation()267     public void testLineBreak_Simple_Hyphenation() {
268         // The visual line break output is like
269         // |abc |
270         // |defg|
271         // |hi- |
272         // |jkl |
273         final String text = "ab\u00ADc de\u00ADfg hi\u00ADjkl";
274         final LineBreaker lb = new LineBreaker.Builder()
275                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
276                 .setHyphenationFrequency(HYPHENATION_FREQUENCY_NORMAL)
277                 .build();
278         final ParagraphConstraints c = new ParagraphConstraints();
279         c.setWidth(40.0f);
280         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
281                 .appendStyleRun(sPaint, text.length(), false).build(), c, 0);
282         assertEquals(4, r.getLineCount());
283         assertEquals(5, r.getLineBreakOffset(0));
284         assertEquals(11, r.getLineBreakOffset(1));
285         assertEquals(14, r.getLineBreakOffset(2));
286         assertEquals(17, r.getLineBreakOffset(3));
287         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
288         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
289         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
290         assertEquals(-10.0f, r.getLineAscent(3), 0.0f);
291         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
292         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
293         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
294         assertEquals(2.0f, r.getLineDescent(3), 0.0f);
295         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
296         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
297         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
298         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
299         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
300         assertEquals(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN, r.getEndLineHyphenEdit(2));
301         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(3));
302         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(3));
303         assertFalse(r.hasLineTab(0));
304         assertFalse(r.hasLineTab(1));
305         assertFalse(r.hasLineTab(2));
306         assertFalse(r.hasLineTab(3));
307         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
308         assertEquals(40.0f, r.getLineWidth(1), 0.0f);
309         assertEquals(30.0f, r.getLineWidth(2), 0.0f);
310         assertEquals(30.0f, r.getLineWidth(3), 0.0f);
311     }
312 
313     @Test
testLineBreak_Simple_Styled()314     public void testLineBreak_Simple_Styled() {
315         // The visual line break output is like
316         // |abc      |
317         // |ddeeffgg | (Make text size of "defg" doubled)
318         // |hijkl    |
319         final String text = "abc defg hijkl";
320         final LineBreaker lb = new LineBreaker.Builder()
321                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
322                 .build();
323         final ParagraphConstraints c = new ParagraphConstraints();
324         c.setWidth(90.0f);
325         final Paint biggerPaint = new Paint(sPaint);
326         biggerPaint.setTextSize(sPaint.getTextSize() * 2.0f);
327         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
328                 .appendStyleRun(sPaint, 4, false)
329                 .appendStyleRun(biggerPaint, 5, false)
330                 .appendStyleRun(sPaint, 5, false).build(), c, 0);
331         assertEquals(3, r.getLineCount());
332         assertEquals(4, r.getLineBreakOffset(0));
333         assertEquals(9, r.getLineBreakOffset(1));
334         assertEquals(14, r.getLineBreakOffset(2));
335         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
336         assertEquals(-20.0f, r.getLineAscent(1), 0.0f);
337         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
338         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
339         assertEquals(4.0f, r.getLineDescent(1), 0.0f);
340         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
341         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
342         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
343         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
344         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
345         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
346         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
347         assertFalse(r.hasLineTab(0));
348         assertFalse(r.hasLineTab(1));
349         assertFalse(r.hasLineTab(2));
350         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
351         assertEquals(80.0f, r.getLineWidth(1), 0.0f);
352         assertEquals(50.0f, r.getLineWidth(2), 0.0f);
353     }
354 
355     @Test
testLineBreak_Simple_Styled2()356     public void testLineBreak_Simple_Styled2() {
357         // The visual line break output is like
358         // |abc deffg| (Make text size of "f" doubled)
359         // |hijkl    |
360         final String text = "abc defg hijkl";
361         final LineBreaker lb = new LineBreaker.Builder()
362                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
363                 .build();
364         final ParagraphConstraints c = new ParagraphConstraints();
365         c.setWidth(90.0f);
366         final Paint biggerPaint = new Paint(sPaint);
367         biggerPaint.setTextSize(sPaint.getTextSize() * 2.0f);
368         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
369                 .appendStyleRun(sPaint, 6, false)
370                 .appendStyleRun(biggerPaint, 1, false)
371                 .appendStyleRun(sPaint, 7, false)
372                 .build(), c, 0);
373         assertEquals(2, r.getLineCount());
374         assertEquals(9, r.getLineBreakOffset(0));
375         assertEquals(14, r.getLineBreakOffset(1));
376         assertEquals(-20.0f, r.getLineAscent(0), 0.0f);
377         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
378         assertEquals(4.0f, r.getLineDescent(0), 0.0f);
379         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
380         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
381         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
382         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
383         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
384         assertFalse(r.hasLineTab(0));
385         assertFalse(r.hasLineTab(1));
386         assertEquals(90.0f, r.getLineWidth(0), 0.0f);
387         assertEquals(50.0f, r.getLineWidth(1), 0.0f);
388     }
389 
390     @Test
testLineBreak_Simple_indents()391     public void testLineBreak_Simple_indents() {
392         // The visual line break output is like
393         // |abc  |
394         // |defg hijkl|
395         final String text = "abc defg hijkl";
396         final LineBreaker lb = new LineBreaker.Builder()
397                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
398                 .setIndents(new int[] { 50, 0 })  // The first line indent is 50 and 0 for others.
399                 .build();
400         final ParagraphConstraints c = new ParagraphConstraints();
401         c.setWidth(100.0f);
402         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
403                 .appendStyleRun(sPaint, text.length(), false)
404                 .build(), c, 0);
405         assertEquals(2, r.getLineCount());
406         assertEquals(4, r.getLineBreakOffset(0));
407         assertEquals(14, r.getLineBreakOffset(1));
408         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
409         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
410         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
411         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
412         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
413         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
414         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
415         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
416         assertFalse(r.hasLineTab(0));
417         assertFalse(r.hasLineTab(1));
418         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
419         assertEquals(100.0f, r.getLineWidth(1), 0.0f);
420     }
421 
422     @Test
testLineBreak_Simple_indents2()423     public void testLineBreak_Simple_indents2() {
424         // The visual line break output is like
425         // |abc |
426         // |defg|
427         // |hijkl     |
428         final String text = "abc defg hijkl";
429         final LineBreaker lb = new LineBreaker.Builder()
430                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
431                 .setIndents(new int[] { 60, 60, 0 })
432                 .build();
433         final ParagraphConstraints c = new ParagraphConstraints();
434         c.setWidth(100.0f);
435         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
436                 .appendStyleRun(sPaint, text.length(), false)
437                 .build(), c, 0);
438         assertEquals(3, r.getLineCount());
439         assertEquals(4, r.getLineBreakOffset(0));
440         assertEquals(9, r.getLineBreakOffset(1));
441         assertEquals(14, r.getLineBreakOffset(2));
442         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
443         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
444         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
445         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
446         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
447         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
448         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
449         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
450         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
451         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
452         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
453         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
454         assertFalse(r.hasLineTab(0));
455         assertFalse(r.hasLineTab(1));
456         assertFalse(r.hasLineTab(2));
457         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
458         assertEquals(40.0f, r.getLineWidth(1), 0.0f);
459         assertEquals(50.0f, r.getLineWidth(2), 0.0f);
460     }
461 
462     @Test
testLineBreak_Simple_tabStop()463     public void testLineBreak_Simple_tabStop() {
464         // The visual line break output is like
465         // |abc    |
466         // |de  fg |
467         // |hijkl  |
468         final String text = "abc de\tfg hijkl";
469         final LineBreaker lb = new LineBreaker.Builder()
470                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
471                 .build();
472         final ParagraphConstraints c = new ParagraphConstraints();
473         c.setWidth(70.0f);
474         c.setTabStops(null, 40);
475         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
476                 .appendStyleRun(sPaint, text.length(), false)
477                 .build(), c, 0);
478         assertEquals(3, r.getLineCount());
479         assertEquals(4, r.getLineBreakOffset(0));
480         assertEquals(10, r.getLineBreakOffset(1));
481         assertEquals(15, r.getLineBreakOffset(2));
482         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
483         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
484         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
485         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
486         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
487         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
488         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
489         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
490         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
491         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
492         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
493         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
494         assertFalse(r.hasLineTab(0));
495         assertTrue(r.hasLineTab(1));
496         assertFalse(r.hasLineTab(2));
497         assertEquals(30.0f, r.getLineWidth(0), 0.0f);
498         assertEquals(60.0f, r.getLineWidth(1), 0.0f);
499         assertEquals(50.0f, r.getLineWidth(2), 0.0f);
500     }
501 
502     @Test
testLineBreak_Simple_tabStop2()503     public void testLineBreak_Simple_tabStop2() {
504         // The visual line break output is like
505         // |a b  c |
506         // |defg   |
507         // |hijkl  |
508         final String text = "a\tb\tc defg hijkl";
509         final LineBreaker lb = new LineBreaker.Builder()
510                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
511                 .build();
512         final ParagraphConstraints c = new ParagraphConstraints();
513         c.setWidth(70.0f);
514         c.setTabStops(new float[] { 20 }, 50);
515         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
516                 .appendStyleRun(sPaint, text.length(), false)
517                 .build(), c, 0);
518         assertEquals(3, r.getLineCount());
519         assertEquals(6, r.getLineBreakOffset(0));
520         assertEquals(11, r.getLineBreakOffset(1));
521         assertEquals(16, r.getLineBreakOffset(2));
522         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
523         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
524         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
525         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
526         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
527         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
528         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
529         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
530         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
531         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
532         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
533         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
534         assertTrue(r.hasLineTab(0));
535         assertFalse(r.hasLineTab(1));
536         assertFalse(r.hasLineTab(2));
537         assertEquals(60.0f, r.getLineWidth(0), 0.0f);
538         assertEquals(40.0f, r.getLineWidth(1), 0.0f);
539         assertEquals(50.0f, r.getLineWidth(2), 0.0f);
540     }
541 
542     @Test
testLineBreak_Balanced()543     public void testLineBreak_Balanced() {
544         // The visual BALANCED line break output is like
545         // |This   |
546         // |is an  |
547         // |example|
548         //
549         // FYI, SIMPLE line breaker breaks this string to
550         // |This is|
551         // |an     |
552         // |example|
553         final String text = "This is an example";
554         final LineBreaker lb = new LineBreaker.Builder()
555                 .setBreakStrategy(BREAK_STRATEGY_BALANCED)
556                 .build();
557         final ParagraphConstraints c = new ParagraphConstraints();
558         c.setWidth(70.0f);
559         final Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
560                 .appendStyleRun(sPaint, text.length(), false)
561                 .build(), c, 0);
562         assertEquals(3, r.getLineCount());
563         assertEquals(5, r.getLineBreakOffset(0));
564         assertEquals(11, r.getLineBreakOffset(1));
565         assertEquals(18, r.getLineBreakOffset(2));
566         assertEquals(-10.0f, r.getLineAscent(0), 0.0f);
567         assertEquals(-10.0f, r.getLineAscent(1), 0.0f);
568         assertEquals(-10.0f, r.getLineAscent(2), 0.0f);
569         assertEquals(2.0f, r.getLineDescent(0), 0.0f);
570         assertEquals(2.0f, r.getLineDescent(1), 0.0f);
571         assertEquals(2.0f, r.getLineDescent(2), 0.0f);
572         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(0));
573         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(0));
574         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(1));
575         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(1));
576         assertEquals(Paint.START_HYPHEN_EDIT_NO_EDIT, r.getStartLineHyphenEdit(2));
577         assertEquals(Paint.END_HYPHEN_EDIT_NO_EDIT, r.getEndLineHyphenEdit(2));
578         assertFalse(r.hasLineTab(0));
579         assertFalse(r.hasLineTab(1));
580         assertFalse(r.hasLineTab(2));
581         assertEquals(40.0f, r.getLineWidth(0), 0.0f);
582         assertEquals(50.0f, r.getLineWidth(1), 0.0f);
583         assertEquals(70.0f, r.getLineWidth(2), 0.0f);
584     }
585 
586     @Test
testLineBreak_ZeroWidthTab()587     public void testLineBreak_ZeroWidthTab() {
588         final String text = "Hi, \tWorld.";
589         final LineBreaker lb = new LineBreaker.Builder()
590                 .setBreakStrategy(BREAK_STRATEGY_SIMPLE)
591                 .build();
592         final ParagraphConstraints c = new ParagraphConstraints();
593         c.setWidth(70.0f);
594         c.setTabStops(null, 0);
595         Result r = lb.computeLineBreaks(new MeasuredText.Builder(text.toCharArray())
596                 .appendStyleRun(sPaint, text.length(), false)
597                 .build(), c, 0);
598         float lw = r.getLineWidth(0);
599         assertFalse(Float.isNaN(lw));
600     }
601 }
602