102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader/*
202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * Copyright (C) 2008 The Android Open Source Project
302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader *
402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * Licensed under the Apache License, Version 2.0 (the "License");
502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * you may not use this file except in compliance with the License.
602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * You may obtain a copy of the License at
702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader *
802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader *      http://www.apache.org/licenses/LICENSE-2.0
902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader *
1002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * Unless required by applicable law or agreed to in writing, software
1102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * distributed under the License is distributed on an "AS IS" BASIS,
1202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * See the License for the specific language governing permissions and
1402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader * limitations under the License.
1502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader */
1602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
1702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderpackage android.text;
1802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
1902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.assertEquals;
2002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.assertFalse;
2102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.assertNull;
2202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.assertSame;
2302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.assertTrue;
2402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport static org.junit.Assert.fail;
2502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
2602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.Bitmap;
2702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.Canvas;
2802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.Paint;
2902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.Path;
3002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.Rect;
3102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.graphics.RectF;
32a6b12de7dfaccd61e904d9cb69d9e07d6a9ce377Siyamed Sinirimport android.platform.test.annotations.Presubmit;
3302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.support.test.filters.SmallTest;
3402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.support.test.runner.AndroidJUnit4;
3502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.text.Layout.Alignment;
3602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport android.text.style.StrikethroughSpan;
3702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
3802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport org.junit.Before;
3902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport org.junit.Test;
4002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport org.junit.runner.RunWith;
4102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
4202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport java.util.ArrayList;
4302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderimport java.util.List;
44c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å eginaimport java.util.Locale;
4502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
46a6b12de7dfaccd61e904d9cb69d9e07d6a9ce377Siyamed Sinir@Presubmit
4702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader@SmallTest
4802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader@RunWith(AndroidJUnit4.class)
4902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournaderpublic class LayoutTest {
5002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private static final int LINE_COUNT = 5;
5102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private static final int LINE_HEIGHT = 12;
5202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private static final int LINE_DESCENT = 4;
5302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private static final CharSequence LAYOUT_TEXT = "alwei\t;sdfs\ndf @";
5402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
5502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private SpannableString mSpannedText;
5602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
5702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private int mWidth;
5802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private Layout.Alignment mAlign;
5902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private float mSpacingMult;
6002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private float mSpacingAdd;
6102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private TextPaint mTextPaint;
6202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
6302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Before
6402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void setup() {
6502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mTextPaint = new TextPaint();
6602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mSpannedText = new SpannableString(LAYOUT_TEXT);
6702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mSpannedText.setSpan(new StrikethroughSpan(), 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
6802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mWidth = 11;
6902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mAlign = Alignment.ALIGN_CENTER;
7002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mSpacingMult = 1;
7102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        mSpacingAdd = 2;
7202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
7302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
7402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
7502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testConstructor() {
7602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, mSpacingMult, mSpacingAdd);
7702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
7802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
7902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test(expected = IllegalArgumentException.class)
8002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testConstructorNull() {
8102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        new MockLayout(null, null, -1, null, 0, 0);
8202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
8302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
8402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
8502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetText() {
8602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        CharSequence text = "test case 1";
8702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(text, mTextPaint, mWidth,
8802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
8902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(text, layout.getText());
9002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
9102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(null, mTextPaint, mWidth, mAlign, mSpacingMult, mSpacingAdd);
9202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertNull(layout.getText());
9302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
9402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
9502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
9602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetPaint() {
9702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
9802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
9902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
10002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertSame(mTextPaint, layout.getPaint());
10102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
10202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, null, mWidth, mAlign, mSpacingMult, mSpacingAdd);
10302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertNull(layout.getPaint());
10402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
10502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
10602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
10702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetWidth() {
10802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, 10,
10902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
11002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(10,  layout.getWidth());
11102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
11202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, mTextPaint, 0, mAlign, mSpacingMult, mSpacingAdd);
11302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0,  layout.getWidth());
11402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
11502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
11602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
11702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetEllipsizedWidth() {
11802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, 15,
11902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
12002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(15, layout.getEllipsizedWidth());
12102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
12202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, mTextPaint, 0, mAlign, mSpacingMult, mSpacingAdd);
12302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0,  layout.getEllipsizedWidth());
12402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
12502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
12602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
12702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testIncreaseWidthTo() {
12802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
12902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
13002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        int oldWidth = layout.getWidth();
13102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
13202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout.increaseWidthTo(oldWidth);
13302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(oldWidth, layout.getWidth());
13402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
13502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        try {
13602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            layout.increaseWidthTo(oldWidth - 1);
13702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            fail("should throw runtime exception attempted to reduce Layout width");
13802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        } catch (RuntimeException e) {
13902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
14002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
14102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout.increaseWidthTo(oldWidth + 1);
14202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(oldWidth + 1, layout.getWidth());
14302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
14402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
14502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
14602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetHeight() {
14702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
14802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
14902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(60, layout.getHeight());
15002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
15102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
15202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
15302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetAlignment() {
15402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
15502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
15602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertSame(mAlign, layout.getAlignment());
15702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
15802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, null, mSpacingMult, mSpacingAdd);
15902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertNull(layout.getAlignment());
16002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
16102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
16202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
16302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetSpacingMultiplier() {
16402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, -1, mSpacingAdd);
16502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(-1.0f, layout.getSpacingMultiplier(), 0.0f);
16602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
16702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, 5, mSpacingAdd);
16802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(5.0f, layout.getSpacingMultiplier(), 0.0f);
16902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
17002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
17102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
17202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetSpacingAdd() {
17302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, mSpacingMult, -1);
17402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(-1.0f, layout.getSpacingAdd(), 0.0f);
17502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
17602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, mSpacingMult, 20);
17702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(20.0f, layout.getSpacingAdd(), 0.0f);
17802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
17902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
18002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
18102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineBounds() {
18202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
18302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
18402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Rect bounds = new Rect();
18502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
18602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(32, layout.getLineBounds(2, bounds));
18702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, bounds.left);
18802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(mWidth, bounds.right);
18902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(24, bounds.top);
19002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(36, bounds.bottom);
19102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
19202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
19302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
19402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineForVertical() {
19502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
19602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
19702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, layout.getLineForVertical(-1));
19802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, layout.getLineForVertical(0));
19902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, layout.getLineForVertical(LINE_COUNT));
20002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_COUNT - 1, layout.getLineForVertical(1000));
20102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
20202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
20302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
20402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineForOffset() {
20502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
20602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
20702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, layout.getLineForOffset(-1));
20802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(1, layout.getLineForOffset(1));
20902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_COUNT - 1, layout.getLineForOffset(LINE_COUNT - 1));
21002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_COUNT - 1, layout.getLineForOffset(1000));
21102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
21202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
21302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
21402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineEnd() {
21502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
21602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
21702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(2, layout.getLineEnd(1));
21802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
21902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
22002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
2210fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir    public void testGetLineExtra_returnsZeroByDefault() {
2220fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir        final String text = "a\nb\nc\n";
2230fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir        final Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
2240fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir                mAlign, 100 /* spacingMult*/, 100 /*spacingAdd*/);
2250fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir        final int lineCount = text.split("\n").length;
2260fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir        for (int i = 0; i < lineCount; i++) {
2270fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir            assertEquals(0, layout.getLineExtra(i));
2280fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir        }
2290fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir    }
2300fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir
2310fa89d6f62c31a033a9dece9c7cfee2d50dc063dSiyamed Sinir    @Test
23202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineVisibleEnd() {
23302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
23402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
23502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
23602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(2, layout.getLineVisibleEnd(1));
23702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_COUNT, layout.getLineVisibleEnd(LINE_COUNT - 1));
23802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LAYOUT_TEXT.length(), layout.getLineVisibleEnd(LAYOUT_TEXT.length() - 1));
23902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        try {
24002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            layout.getLineVisibleEnd(LAYOUT_TEXT.length());
24102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            fail("should throw .StringIndexOutOfBoundsException here");
24202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        } catch (StringIndexOutOfBoundsException e) {
24302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
24402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
24502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
24602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
24702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineBottom() {
24802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
24902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
25002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_HEIGHT, layout.getLineBottom(0));
25102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
25202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
25302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
25402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineBaseline() {
25502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
25602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
25702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(8, layout.getLineBaseline(0));
25802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
25902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
26002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
26102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineAscent() {
26202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
26302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
26402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(-8, layout.getLineAscent(0));
26502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
26602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
26702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
26802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetParagraphAlignment() {
26902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
27002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
27102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertSame(mAlign, layout.getParagraphAlignment(0));
27202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
27302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(mSpannedText, mTextPaint, mWidth,
27402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
27502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertSame(mAlign, layout.getParagraphAlignment(0));
27602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertSame(mAlign, layout.getParagraphAlignment(1));
27702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
27802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
27902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
28002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetParagraphLeft() {
28102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
28202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
28302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(0, layout.getParagraphLeft(0));
28402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
28502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
28602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
28702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetParagraphRight() {
28802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
28902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
29002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(mWidth, layout.getParagraphRight(0));
29102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
29202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
29302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
294c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    public void testGetSelectionWithEmptySelection() {
295c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
296c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                mAlign, mSpacingMult, mSpacingAdd);
297c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
298c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        /*
299c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * When the selection is empty (i.e. the start and the end index are the same), we do not
300c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * expect any rectangles to be generated.
301c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         */
302c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
303c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelection(5 /* startIndex */, 5 /* endIndex */,
304b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> fail(
305b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        String.format(Locale.getDefault(),
306c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                        "Did not expect any rectangles, got a rectangle with (left: %f,"
307c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                                + " top: %f), (right: %f, bottom: %f)",
308c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                        left, top, right, bottom)));
309c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    }
310c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
311c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    @Test
312c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    public void testGetSelectionWithASingleLineSelection() {
313c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Layout layout = new StaticLayout("abc", mTextPaint, Integer.MAX_VALUE,
314c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
315c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
316c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final List<RectF> rectangles = new ArrayList<>();
317c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
318c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelection(0 /* startIndex */, 1 /* endIndex */,
319b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> rectangles.add(
320b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        new RectF(left, top, right, bottom)));
321c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
322c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        /*
323c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * The selection we expect will only cover the letter "a". Hence, we expect one rectangle
324c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * to be generated and this rectangle should start at the top left of the canvas and should
325c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * end somewhere to the right and down.
326c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
327c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * | a | b c
328c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
329c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         */
330c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
331c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(1, rectangles.size());
332c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
333c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF rectangle = rectangles.get(0);
334c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
335c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, rectangle.left, 0.0f);
336c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, rectangle.top, 0.0f);
337c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(rectangle.right > 0);
338c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(rectangle.bottom > 0);
339c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    }
340c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
341c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    @Test
342c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    public void
343c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina            testGetSelectionWithMultilineSelection_secondLineSelectionEndsBeforeFirstCharacter() {
344c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Layout layout = new StaticLayout("a\nb\nc", mTextPaint, Integer.MAX_VALUE,
345c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
346c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
347c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final List<RectF> rectangles = new ArrayList<>();
348c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
349c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelection(0 /* startIndex */, 2 /* endIndex */,
350b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> rectangles.add(
351b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        new RectF(left, top, right, bottom)));
352c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
353c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        /*
354c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * The selection that will be selected is "a\n" - the selection starts at the beginning
355c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * of the first line and ends at the start of the second line. This means the selection
356c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * highlight will span from the beginning of the first line to the end of the first line
357c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * and will appear as a zero width line at the beginning of the second line.
358c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
359c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * Hence, we expect three rectangles - one that will select the "a" on the first line,
360c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * one that will extend the selection from the "a" to the end of the first line and one
361c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * that will prepare the selection for the second line.
362c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
363c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * | a | *topToEndOfLineRectangle* |
364c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * | b
365c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *   c
366c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         */
367c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
368c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(3, rectangles.size());
369c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
370c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF topRectangle = rectangles.get(0);
371c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF topToEndOfLineRectangle = rectangles.get(1);
372c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF bottomLineStartRectangle = rectangles.get(2);
373c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
374c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertFalse(topRectangle.intersect(bottomLineStartRectangle));
375c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.top < bottomLineStartRectangle.top);
376c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.left == bottomLineStartRectangle.left);
377c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
378c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertFalse(topRectangle.intersect(topToEndOfLineRectangle));
379c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(Integer.MAX_VALUE, topToEndOfLineRectangle.right, 1);
380c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.top == topToEndOfLineRectangle.top);
381c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.right == topToEndOfLineRectangle.left);
382c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.bottom == topToEndOfLineRectangle.bottom);
383c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
384c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, bottomLineStartRectangle.left, 0.0f);
385c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, bottomLineStartRectangle.right, 0.0f);
386c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    }
387c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
388c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    @Test
389c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    public void testGetSelectionWithMultilineSelection_secondLineSelectionEndsAfterACharacter() {
390c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Layout layout = new StaticLayout("a\nb\nc", mTextPaint, Integer.MAX_VALUE,
391c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
392c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
393c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final List<RectF> rectangles = new ArrayList<>();
394c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
395c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelection(0 /* startIndex */, 3 /* endIndex */,
396b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> rectangles.add(
397b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        new RectF(left, top, right, bottom)));
398c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
399c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        /*
400c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * The selection that will be selected is "a\nb" - the selection starts at the beginning
401c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * of the first line and ends at the end of the letter "b". This means the selection
402c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * highlight will span from the beginning of the first line to the end of the first line
403c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * and will also cover the letter "b" on the second line.
404c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
405c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * We expect four rectangles - one that will select the "a" on the first line,
406c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * one that will extend the selection from the "a" to the end of the first line the one
407c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * from the previous case that will prepare the selection for the second line and finally
408c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * one that will select the letter b.
409c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
410c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *  | a | *topToEndOfLineRectangle* |
411c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * || b |
412c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *    c
413c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         */
414c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
415c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(4, rectangles.size());
416c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
417c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF topRectangle = rectangles.get(0);
418c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF topToEndOfLineRectangle = rectangles.get(1);
419c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF bottomRectangle = rectangles.get(2);
420c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF bottomLineStartRectangle = rectangles.get(3);
421c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
422c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(topRectangle.top == topToEndOfLineRectangle.top);
423c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(bottomLineStartRectangle.top == bottomRectangle.top);
424c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(bottomLineStartRectangle.bottom == bottomRectangle.bottom);
425c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, bottomLineStartRectangle.left, 0.0f);
426c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, bottomLineStartRectangle.right, 0.0f);
427c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(0, bottomRectangle.left, 0.0f);
428c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(bottomRectangle.right > 0);
429c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    }
430c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
431c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    @Test
432c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    public void testGetSelectionPathWithASingleLineSelection() {
433c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Layout layout = new StaticLayout("abc", mTextPaint, Integer.MAX_VALUE,
434c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
435c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
436c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final List<RectF> rectangles = new ArrayList<>();
437c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
438c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelection(0 /* startIndex */, 1 /* endIndex */,
439b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> rectangles.add(
440b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        new RectF(left, top, right, bottom)));
441c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
442c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        /*
443c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * In the single line selection case, we expect that only one rectangle covering the letter
444c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * "a" will be generated. Hence, we expect that the generated path will only consist of
445c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * that rectangle as well.
446c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
447c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         * | a | b c
448c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         *
449c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina         */
450c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
451c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(1, rectangles.size());
452c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
453c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF rectangle = rectangles.get(0);
454c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
455c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final Path generatedPath = new Path();
456c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        layout.getSelectionPath(0 /* startIndex */, 1 /* endIndex */, generatedPath);
457c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
458c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        final RectF pathRectangle = new RectF();
459c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
460c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertTrue(generatedPath.isRect(pathRectangle));
461c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina        assertEquals(rectangle, pathRectangle);
462c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    }
463c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina
464c7f89450a6cea6ad70e69e21f56404c6dc36eaf1Petar Å egina    @Test
465b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    public void testGetSelection_latinTextDirection() {
466b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        final Layout layout = new StaticLayout("abc", mTextPaint, Integer.MAX_VALUE,
467b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
468b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
469b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        layout.getSelection(0 /* startIndex */, 2 /* endIndex */,
470b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) ->
4713a92fb632b6509610c5c3bf2a117631816a56899Petar Å egina                        assertEquals(Layout.TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT,
472b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                                textSelectionLayout));
473b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    }
474b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
475b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    @Test
476b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    public void testGetSelection_arabicTextDirection() {
477b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        final Layout layout = new StaticLayout("غينيا", mTextPaint, Integer.MAX_VALUE,
478b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
479b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
480b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        layout.getSelection(0 /* startIndex */, 2 /* endIndex */,
481b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) ->
4823a92fb632b6509610c5c3bf2a117631816a56899Petar Å egina                        assertEquals(Layout.TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT,
483b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                                textSelectionLayout));
484b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    }
485b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
486b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    @Test
487b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    public void testGetSelection_mixedLatinAndArabicTextDirection() {
488b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        final Layout layout = new StaticLayout("abcغينيا", mTextPaint, Integer.MAX_VALUE,
489b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false);
490b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
491b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        final List<Integer> layouts = new ArrayList<>(2);
492b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
493b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        layout.getSelection(0 /* startIndex */, 6 /* endIndex */,
494b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                (left, top, right, bottom, textSelectionLayout) -> layouts.add(
495b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina                        textSelectionLayout));
496b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
497b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina        assertEquals(2, layouts.size());
4983a92fb632b6509610c5c3bf2a117631816a56899Petar Å egina        assertEquals(Layout.TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT, (long) layouts.get(0));
4993a92fb632b6509610c5c3bf2a117631816a56899Petar Å egina        assertEquals(Layout.TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT, (long) layouts.get(1));
500b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    }
501b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina
502b92c539232900537d5005bcf7cbc8950ff7f42d9Petar Å egina    @Test
50302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testIsSpanned() {
50402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        MockLayout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
50502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
50602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        // default is not spanned text
50702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertFalse(layout.mockIsSpanned());
50802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
50902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        // try to create a spanned text
51002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout = new MockLayout(mSpannedText, mTextPaint, mWidth,
51102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
51202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertTrue(layout.mockIsSpanned());
51302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
51402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
51502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private static final class MockLayout extends Layout {
51602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        MockLayout(CharSequence text, TextPaint paint, int width,
51702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                Alignment align, float spacingmult, float spacingadd) {
51802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            super(text, paint, width, align, spacingmult, spacingadd);
51902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
52002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
52102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        protected boolean mockIsSpanned() {
52202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return super.isSpanned();
52302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
52402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
52502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
52602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getBottomPadding() {
52702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return 0;
52802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
52902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
53002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
53102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getEllipsisCount(int line) {
53202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return 0;
53302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
53402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
53502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
53602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getEllipsisStart(int line) {
53702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return 0;
53802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
53902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
54002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
54102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public boolean getLineContainsTab(int line) {
54202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return false;
54302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
54402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
54502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
54602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getLineCount() {
54702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return LINE_COUNT;
54802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
54902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
55002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
55102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getLineDescent(int line) {
55202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return LINE_DESCENT;
55302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
55402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
55502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
55602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public Directions getLineDirections(int line) {
55702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return Layout.DIRS_ALL_LEFT_TO_RIGHT;
55802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
55902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
56002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
56102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getLineStart(int line) {
56202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            if (line < 0) {
56302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                return 0;
56402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            }
56502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return line;
56602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
56702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
56802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
56902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getLineTop(int line) {
57002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            if (line < 0) {
57102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                return 0;
57202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            }
57302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return LINE_HEIGHT * (line);
57402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
57502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
57602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
57702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getParagraphDirection(int line) {
57802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return 0;
57902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
58002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
58102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
58202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public int getTopPadding() {
58302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return 0;
58402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
58502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
58602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
58702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
58802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetLineWidth() {
58902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
59002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
59102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        for (int i = 0; i < LINE_COUNT; i++) {
59202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            int start = layout.getLineStart(i);
59302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            int end = layout.getLineEnd(i);
59402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            String text = LAYOUT_TEXT.toString().substring(start, end);
59502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            assertEquals(mTextPaint.measureText(text), layout.getLineWidth(i), 1.0f);
59602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
59702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
59802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
59902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
60002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testGetCursorPath() {
60102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
60202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
60302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Path path = new Path();
60402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        final float epsilon = 1.0f;
60502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        for (int i = 0; i < LINE_COUNT; i++) {
60602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            layout.getCursorPath(i, path, LAYOUT_TEXT);
60702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            RectF bounds = new RectF();
60802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            path.computeBounds(bounds, false);
60902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            assertTrue(bounds.top >= layout.getLineTop(i) - epsilon);
61002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            assertTrue(bounds.bottom <= layout.getLineBottom(i) + epsilon);
61102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
61202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
61302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
61402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    @Test
61502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    public void testDraw() {
61602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
61702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                mAlign, mSpacingMult, mSpacingAdd);
61802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        final int width = 256;
61902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        final int height = 256;
62002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        MockCanvas c = new MockCanvas(width, height);
62102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        layout.draw(c);
62202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
62302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        assertEquals(LINE_COUNT, drawCommands.size());
62402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        for (int i = 0; i < LINE_COUNT; i++) {
62502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
62602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            int start = layout.getLineStart(i);
62702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            int end = layout.getLineEnd(i);
62802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text);
62902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            float expected_y = (i + 1) * LINE_HEIGHT - LINE_DESCENT;
63002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            assertEquals(expected_y, drawCommand.y, 0.0f);
63102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
63202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
63302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
63402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    private final class MockCanvas extends Canvas {
63502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
63602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        class DrawCommand {
63702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            public final String text;
63802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            public final float x;
63902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            public final float y;
64002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
64102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            DrawCommand(String text, float x, float y) {
64202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                this.text = text;
64302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                this.x = x;
64402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                this.y = y;
64502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            }
64602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
64702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
64802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        List<DrawCommand> mDrawCommands;
64902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
65002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        MockCanvas(int width, int height) {
65102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            super();
65202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            mDrawCommands = new ArrayList<>();
65302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
65402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            setBitmap(bitmap);
65502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
65602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
65702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        // Drawing text with either drawText or drawTextRun is valid; we don't care which.
65802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        // We also don't care which of the string representations is used.
65902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
66002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
66102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public void drawText(String text, int start, int end, float x, float y, Paint p) {
66202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            mDrawCommands.add(new DrawCommand(text.substring(start, end), x, y));
66302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
66402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
66502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
66602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public void drawText(CharSequence text, int start, int end, float x, float y, Paint p) {
66702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            drawText(text.toString(), start, end, x, y, p);
66802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
66902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
67002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
67102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public void drawText(char[] text, int index, int count, float x, float y, Paint p) {
67202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            mDrawCommands.add(new DrawCommand(new String(text, index, count), x, y));
67302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
67402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
67502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
67602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public void drawTextRun(CharSequence text, int start, int end, int contextStart,
67702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                int contextEnd, float x, float y, boolean isRtl, Paint paint) {
67802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            drawText(text, start, end, x, y, paint);
67902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
68002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
68102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        @Override
68202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        public void drawTextRun(char[] text, int index, int count, int contextIndex,
68302f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader                int contextCount, float x, float y, boolean isRtl, Paint paint) {
68402f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            drawText(text, index, count, x, y, paint);
68502f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
68602f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
68702f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        List<DrawCommand> getDrawCommands() {
68802f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader            return mDrawCommands;
68902f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader        }
69002f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader    }
69102f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader}
69202f167c35ad81fce82c0ebc14a15892fb6981866Roozbeh Pournader
693