/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package android.text;

import static android.text.Layout.Alignment.ALIGN_NORMAL;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.FontFamily;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Typeface;
import android.os.LocaleList;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.Layout.Alignment;
import android.text.method.EditorState;
import android.text.style.LocaleSpan;
import android.util.ArrayMap;
import android.util.Log;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * Tests StaticLayout vertical metrics behavior.
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StaticLayoutTest {
    private static final float SPACE_MULTI = 1.0f;
    private static final float SPACE_ADD = 0.0f;
    private static final int DEFAULT_OUTER_WIDTH = 150;

    private static final CharSequence LAYOUT_TEXT = "CharSe\tq\nChar"
            + "Sequence\nCharSequence\nHelllo\n, world\nLongLongLong";
    private static final CharSequence LAYOUT_TEXT_SINGLE_LINE = "CharSequence";

    private static final Alignment DEFAULT_ALIGN = Alignment.ALIGN_CENTER;
    private static final int ELLIPSIZE_WIDTH = 8;

    private StaticLayout mDefaultLayout;
    private TextPaint mDefaultPaint;

    @Before
    public void setup() {
        mDefaultPaint = new TextPaint();
        mDefaultLayout = createDefaultStaticLayout();
    }

    private StaticLayout createDefaultStaticLayout() {
        return new StaticLayout(LAYOUT_TEXT, mDefaultPaint,
                DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
    }

    @Test
    public void testBuilder() {
        {
            // Obtain.
            final StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0,
                    LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH);
            final StaticLayout layout = builder.build();
            // Check default value.
            assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
                    layout.getTextDirectionHeuristic());
        }
        {
            // setTextDirection.
            final StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0,
                    LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH);
            builder.setTextDirection(TextDirectionHeuristics.RTL);
            final StaticLayout layout = builder.build();
            // Always returns TextDirectionHeuristics.FIRSTSTRONG_LTR.
            assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
                    layout.getTextDirectionHeuristic());
        }
    }

    /**
     * Basic test showing expected behavior and relationship between font
     * metrics and line metrics.
     */
    @Test
    public void testGetters1() {
        LayoutBuilder b = builder();
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        // check default paint
        Log.i("TG1:paint", fmi.toString());

        Layout l = b.build();
        assertVertMetrics(l, 0, 0,
                new int[][]{{fmi.ascent, fmi.descent, 0}});

        // other quick metrics
        assertEquals(0, l.getLineStart(0));
        assertEquals(Layout.DIR_LEFT_TO_RIGHT, l.getParagraphDirection(0));
        assertEquals(false, l.getLineContainsTab(0));
        assertEquals(Layout.DIRS_ALL_LEFT_TO_RIGHT, l.getLineDirections(0));
        assertEquals(0, l.getEllipsisCount(0));
        assertEquals(0, l.getEllipsisStart(0));
        assertEquals(b.width, l.getEllipsizedWidth());
    }

    /**
     * Basic test showing effect of includePad = true with 1 line.
     * Top and bottom padding are affected, as is the line descent and height.
     */
    @Test
    public void testLineMetrics_withPadding() {
        LayoutBuilder b = builder()
            .setIncludePad(true);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{{fmi.top, fmi.bottom, 0}});
    }

    /**
     * Basic test showing effect of includePad = true wrapping to 2 lines.
     * Ascent of top line and descent of bottom line are affected.
     */
    @Test
    public void testLineMetrics_withPaddingAndWidth() {
        LayoutBuilder b = builder()
            .setIncludePad(true)
            .setWidth(50);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent, 0},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    /**
     * Basic test showing effect of includePad = true wrapping to 3 lines.
     * First line ascent is top, bottom line descent is bottom.
     */
    @Test
    public void testLineMetrics_withThreeLines() {
        LayoutBuilder b = builder()
            .setText("This is a longer test")
            .setIncludePad(true)
            .setWidth(50);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent, 0},
                        {fmi.ascent, fmi.descent, 0},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    /**
     * Basic test showing effect of includePad = true wrapping to 3 lines and
     * large text. See effect of leading. Currently, we don't expect there to
     * even be non-zero leading.
     */
    @Test
    public void testLineMetrics_withLargeText() {
        LayoutBuilder b = builder()
            .setText("This is a longer test")
            .setIncludePad(true)
            .setWidth(150);
        b.paint.setTextSize(36);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        if (fmi.leading == 0) { // nothing to test
            Log.i("TG5", "leading is 0, skipping test");
            return;
        }

        // So far, leading is not used, so this is the same as TG4.  If we start
        // using leading, this will fail.
        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent, 0},
                        {fmi.ascent, fmi.descent, 0},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 2, wrapping
     * to 3 lines.
     */
    @Test
    public void testLineMetrics_withSpacingAdd() {
        int spacingAdd = 2; // int so expressions return int
        LayoutBuilder b = builder()
            .setText("This is a longer test")
            .setIncludePad(true)
            .setWidth(50)
            .setSpacingAdd(spacingAdd);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent + spacingAdd, spacingAdd},
                        {fmi.ascent, fmi.descent + spacingAdd, spacingAdd},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 2,
     * spacingMult = 1.5, wrapping to 3 lines.
     */
    @Test
    public void testLineMetrics_withSpacingMult() {
        LayoutBuilder b = builder()
            .setText("This is a longer test")
            .setIncludePad(true)
            .setWidth(50)
            .setSpacingAdd(2)
            .setSpacingMult(1.5f);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();
        Scaler s = new Scaler(b.spacingMult, b.spacingAdd);

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent + s.scale(fmi.descent - fmi.top),
                                s.scale(fmi.descent - fmi.top)},
                        {fmi.ascent, fmi.descent + s.scale(fmi.descent - fmi.ascent),
                                s.scale(fmi.descent - fmi.ascent)},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 0,
     * spacingMult = 0.8 when wrapping to 3 lines.
     */
    @Test
    public void testLineMetrics_withUnitIntervalSpacingMult() {
        LayoutBuilder b = builder()
            .setText("This is a longer test")
            .setIncludePad(true)
            .setWidth(50)
            .setSpacingAdd(2)
            .setSpacingMult(.8f);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();
        Scaler s = new Scaler(b.spacingMult, b.spacingAdd);

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                new int[][]{
                        {fmi.top, fmi.descent + s.scale(fmi.descent - fmi.top),
                                s.scale(fmi.descent - fmi.top)},
                        {fmi.ascent, fmi.descent + s.scale(fmi.descent - fmi.ascent),
                                s.scale(fmi.descent - fmi.ascent)},
                        {fmi.ascent, fmi.bottom, 0}
                });
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testGetLineExtra_withNegativeValue() {
        final Layout layout = builder().build();
        layout.getLineExtra(-1);
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testGetLineExtra_withParamGreaterThanLineCount() {
        final Layout layout = builder().build();
        layout.getLineExtra(100);
    }

    // ----- test utility classes and methods -----

    // Models the effect of the scale and add parameters.  I think the current
    // implementation misbehaves.
    private static class Scaler {
        private final float sMult;
        private final float sAdd;

        Scaler(float sMult, float sAdd) {
            this.sMult = sMult - 1;
            this.sAdd = sAdd;
        }

        public int scale(float height) {
            int altVal = (int)(height * sMult + sAdd + 0.5);
            int rndVal = Math.round(height * sMult + sAdd);
            if (altVal != rndVal) {
                Log.i("Scale", "expected scale: " + rndVal +
                        " != returned scale: " + altVal);
            }
            return rndVal;
        }
    }

    /* package */ static LayoutBuilder builder() {
        return new LayoutBuilder();
    }

    /* package */ static class LayoutBuilder {
        String text = "This is a test";
        TextPaint paint = new TextPaint(); // default
        int width = 100;
        Alignment align = ALIGN_NORMAL;
        float spacingMult = 1;
        float spacingAdd = 0;
        boolean includePad = false;

        LayoutBuilder setText(String text) {
            this.text = text;
            return this;
        }

        LayoutBuilder setPaint(TextPaint paint) {
            this.paint = paint;
            return this;
        }

        LayoutBuilder setWidth(int width) {
            this.width = width;
            return this;
        }

        LayoutBuilder setAlignment(Alignment align) {
            this.align = align;
            return this;
        }

        LayoutBuilder setSpacingMult(float spacingMult) {
            this.spacingMult = spacingMult;
            return this;
        }

        LayoutBuilder setSpacingAdd(float spacingAdd) {
            this.spacingAdd = spacingAdd;
            return this;
        }

        LayoutBuilder setIncludePad(boolean includePad) {
            this.includePad = includePad;
            return this;
        }

       Layout build() {
            return  new StaticLayout(text, paint, width, align, spacingMult,
                spacingAdd, includePad);
        }
    }

    /**
     * Assert vertical metrics such as top, bottom, ascent, descent.
     * @param l layout instance
     * @param topPad top padding
     * @param botPad bottom padding
     * @param values values for each line where first is ascent, second is descent, and last one is
     *               extra
     */
    private void assertVertMetrics(Layout l, int topPad, int botPad, int[][] values) {
        assertTopBotPadding(l, topPad, botPad);
        assertLinesMetrics(l, values);
    }

    /**
     * Check given expected values against the Layout values.
     * @param l layout instance
     * @param values values for each line where first is ascent, second is descent, and last one is
     *               extra
     */
    private void assertLinesMetrics(Layout l, int[][] values) {
        final int lines = values.length;
        assertEquals(lines, l.getLineCount());

        int t = 0;
        for (int i = 0, n = 0; i < lines; ++i, n += 3) {
            if (values[i].length != 3) {
                throw new IllegalArgumentException(String.valueOf(values.length));
            }
            int a = values[i][0];
            int d = values[i][1];
            int extra = values[i][2];
            int h = -a + d;
            assertLineMetrics(l, i, t, a, d, h, extra);
            t += h;
        }

        assertEquals(t, l.getHeight());
    }

    private void assertLineMetrics(Layout l, int line,
            int top, int ascent, int descent, int height, int extra) {
        String info = "line " + line;
        assertEquals(info, top, l.getLineTop(line));
        assertEquals(info, ascent, l.getLineAscent(line));
        assertEquals(info, descent, l.getLineDescent(line));
        assertEquals(info, height, l.getLineBottom(line) - top);
        assertEquals(info, extra, l.getLineExtra(line));
    }

    private void assertTopBotPadding(Layout l, int topPad, int botPad) {
        assertEquals(topPad, l.getTopPadding());
        assertEquals(botPad, l.getBottomPadding());
    }

    private void moveCursorToRightCursorableOffset(EditorState state, TextPaint paint) {
        assertEquals("The editor has selection", state.mSelectionStart, state.mSelectionEnd);
        final Layout layout = builder().setText(state.mText.toString()).setPaint(paint).build();
        final int newOffset = layout.getOffsetToRightOf(state.mSelectionStart);
        state.mSelectionStart = state.mSelectionEnd = newOffset;
    }

    private void moveCursorToLeftCursorableOffset(EditorState state, TextPaint paint) {
        assertEquals("The editor has selection", state.mSelectionStart, state.mSelectionEnd);
        final Layout layout = builder().setText(state.mText.toString()).setPaint(paint).build();
        final int newOffset = layout.getOffsetToLeftOf(state.mSelectionStart);
        state.mSelectionStart = state.mSelectionEnd = newOffset;
    }

    /**
     * Tests for keycap, variation selectors, flags are in CTS.
     * See {@link android.text.cts.StaticLayoutTest}.
     */
    @Test
    public void testEmojiOffset() {
        EditorState state = new EditorState();
        TextPaint paint = new TextPaint();

        // Odd numbered regional indicator symbols.
        // U+1F1E6 is REGIONAL INDICATOR SYMBOL LETTER A, U+1F1E8 is REGIONAL INDICATOR SYMBOL
        // LETTER C.
        state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 | U+1F1E6 U+1F1E8 U+1F1E6");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 | U+1F1E6");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6 |");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6 |");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 | U+1F1E6");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("U+1F1E6 U+1F1E8 | U+1F1E6 U+1F1E8 U+1F1E6");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
        moveCursorToLeftCursorableOffset(state, paint);

        // Zero width sequence
        final String zwjSequence = "U+1F468 U+200D U+2764 U+FE0F U+200D U+1F468";
        state.setByString("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
        moveCursorToRightCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " | " + zwjSequence + " " + zwjSequence);
        moveCursorToRightCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " " + zwjSequence + " | " + zwjSequence);
        moveCursorToRightCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " " + zwjSequence + " " + zwjSequence + " |");
        moveCursorToRightCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " " + zwjSequence + " " + zwjSequence + " |");
        moveCursorToLeftCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " " + zwjSequence + " | " + zwjSequence);
        moveCursorToLeftCursorableOffset(state, paint);
        state.assertEquals(zwjSequence + " | " + zwjSequence + " " + zwjSequence);
        moveCursorToLeftCursorableOffset(state, paint);
        state.assertEquals("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
        moveCursorToLeftCursorableOffset(state, paint);
        state.assertEquals("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
        moveCursorToLeftCursorableOffset(state, paint);

        // Emoji modifiers
        // U+261D is WHITE UP POINTING INDEX, U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
        state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB | U+261D U+1F3FB U+261D U+1F3FB");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB U+261D U+1F3FB | U+261D U+1F3FB");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB |");
        moveCursorToRightCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB |");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB U+261D U+1F3FB | U+261D U+1F3FB");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("U+261D U+1F3FB | U+261D U+1F3FB U+261D U+1F3FB");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
        moveCursorToLeftCursorableOffset(state, paint);
        state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
        moveCursorToLeftCursorableOffset(state, paint);
    }

    private StaticLayout createEllipsizeStaticLayout(CharSequence text,
            TextUtils.TruncateAt ellipsize, int maxLines) {
        return new StaticLayout(text, 0, text.length(),
                mDefaultPaint, DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN,
                TextDirectionHeuristics.FIRSTSTRONG_LTR,
                SPACE_MULTI, SPACE_ADD, true /* include pad */,
                ellipsize,
                ELLIPSIZE_WIDTH,
                maxLines);
    }

    @Test
    public void testEllipsis_singleLine() {
        {
            // Single line case and TruncateAt.END so that we have some ellipsis
            StaticLayout layout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
                    TextUtils.TruncateAt.END, 1);
            assertTrue(layout.getEllipsisCount(0) > 0);
        }
        {
            // Single line case and TruncateAt.MIDDLE so that we have some ellipsis
            StaticLayout layout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
                    TextUtils.TruncateAt.MIDDLE, 1);
            assertTrue(layout.getEllipsisCount(0) > 0);
        }
        {
            // Single line case and TruncateAt.END so that we have some ellipsis
            StaticLayout layout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
                    TextUtils.TruncateAt.END, 1);
            assertTrue(layout.getEllipsisCount(0) > 0);
        }
        {
            // Single line case and TruncateAt.MARQUEE so that we have NO ellipsis
            StaticLayout layout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
                    TextUtils.TruncateAt.MARQUEE, 1);
            assertTrue(layout.getEllipsisCount(0) == 0);
        }
        {
            final String text = "\u3042" // HIRAGANA LETTER A
                    + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
            final float textWidth = mDefaultPaint.measureText(text);
            final int halfWidth = (int) (textWidth / 2.0f);
            {
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
                assertTrue(layout.getEllipsisCount(0) > 0);
                assertTrue(layout.getEllipsisStart(0) > 0);
            }
            {
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.START, halfWidth, 1);
                assertTrue(layout.getEllipsisCount(0) > 0);
                assertEquals(0, mDefaultLayout.getEllipsisStart(0));
            }
            {
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MIDDLE, halfWidth, 1);
                assertTrue(layout.getEllipsisCount(0) > 0);
                assertTrue(layout.getEllipsisStart(0) > 0);
            }
            {
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MARQUEE, halfWidth, 1);
                assertEquals(0, layout.getEllipsisCount(0));
            }
        }

        {
            // The white spaces in this text will be trailing if maxLines is larger than 1, but
            // width of the trailing white spaces must not be ignored if ellipsis is applied.
            final String text = "abc                                             def";
            final float textWidth = mDefaultPaint.measureText(text);
            final int halfWidth = (int) (textWidth / 2.0f);
            {
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
                assertTrue(layout.getEllipsisCount(0) > 0);
                assertTrue(layout.getEllipsisStart(0) > 0);
            }
        }

        {
            // 2 family emojis (11 code units + 11 code units).
            final String text = "\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66"
                    + "\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66";
            final float textWidth = mDefaultPaint.measureText(text);

            final TextUtils.TruncateAt[] kinds = {TextUtils.TruncateAt.START,
                    TextUtils.TruncateAt.MIDDLE, TextUtils.TruncateAt.END};
            for (final TextUtils.TruncateAt kind : kinds) {
                for (int i = 0; i <= 8; i++) {
                    int avail = (int) (textWidth * i / 7.0f);
                    StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
                            avail, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                            SPACE_MULTI, SPACE_ADD, false, kind, avail, 1);

                    assertTrue(layout.getEllipsisCount(0) == text.length()
                                    || layout.getEllipsisCount(0) == text.length() / 2
                                    || layout.getEllipsisCount(0) == 0);
                }
            }
        }
    }

    // String wrapper for testing not well known implementation of CharSequence.
    private class FakeCharSequence implements CharSequence {
        private String mStr;

        FakeCharSequence(String str) {
            mStr = str;
        }

        @Override
        public char charAt(int index) {
            return mStr.charAt(index);
        }

        @Override
        public int length() {
            return mStr.length();
        }

        @Override
        public CharSequence subSequence(int start, int end) {
            return mStr.subSequence(start, end);
        }

        @Override
        public String toString() {
            return mStr;
        }
    };

    private List<CharSequence> buildTestCharSequences(String testString, Normalizer.Form[] forms) {
        List<CharSequence> result = new ArrayList<>();

        List<String> normalizedStrings = new ArrayList<>();
        for (Normalizer.Form form: forms) {
            normalizedStrings.add(Normalizer.normalize(testString, form));
        }

        for (String str: normalizedStrings) {
            result.add(str);
            result.add(new SpannedString(str));
            result.add(new SpannableString(str));
            result.add(new SpannableStringBuilder(str));  // as a GraphicsOperations implementation.
            result.add(new FakeCharSequence(str));  // as a not well known implementation.
        }
        return result;
    }

    private String buildTestMessage(CharSequence seq) {
        String normalized;
        if (Normalizer.isNormalized(seq, Normalizer.Form.NFC)) {
            normalized = "NFC";
        } else if (Normalizer.isNormalized(seq, Normalizer.Form.NFD)) {
            normalized = "NFD";
        } else if (Normalizer.isNormalized(seq, Normalizer.Form.NFKC)) {
            normalized = "NFKC";
        } else if (Normalizer.isNormalized(seq, Normalizer.Form.NFKD)) {
            normalized = "NFKD";
        } else {
            throw new IllegalStateException("Normalized form is not NFC/NFD/NFKC/NFKD");
        }

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < seq.length(); ++i) {
            builder.append(String.format("0x%04X ", Integer.valueOf(seq.charAt(i))));
        }

        return "testString: \"" + seq.toString() + "\"[" + builder.toString() + "]"
                + ", class: " + seq.getClass().getName()
                + ", Normalization: " + normalized;
    }

    @Test
    public void testGetOffset_UNICODE_Hebrew() {
        String testString = "\u05DE\u05E1\u05E2\u05D3\u05D4"; // Hebrew Characters
        for (CharSequence seq: buildTestCharSequences(testString, Normalizer.Form.values())) {
            StaticLayout layout = new StaticLayout(seq, mDefaultPaint,
                    DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN,
                    TextDirectionHeuristics.RTL, SPACE_MULTI, SPACE_ADD, true);

            String testLabel = buildTestMessage(seq);

            assertEquals(testLabel, 1, layout.getOffsetToLeftOf(0));
            assertEquals(testLabel, 2, layout.getOffsetToLeftOf(1));
            assertEquals(testLabel, 3, layout.getOffsetToLeftOf(2));
            assertEquals(testLabel, 4, layout.getOffsetToLeftOf(3));
            assertEquals(testLabel, 5, layout.getOffsetToLeftOf(4));
            assertEquals(testLabel, 5, layout.getOffsetToLeftOf(5));

            assertEquals(testLabel, 0, layout.getOffsetToRightOf(0));
            assertEquals(testLabel, 0, layout.getOffsetToRightOf(1));
            assertEquals(testLabel, 1, layout.getOffsetToRightOf(2));
            assertEquals(testLabel, 2, layout.getOffsetToRightOf(3));
            assertEquals(testLabel, 3, layout.getOffsetToRightOf(4));
            assertEquals(testLabel, 4, layout.getOffsetToRightOf(5));
        }
    }

    @Test
    public void testLocaleSpanAffectsHyphenation() {
        TextPaint paint = new TextPaint();
        paint.setTextLocale(Locale.US);
        // Private use language, with no hyphenation rules.
        final Locale privateLocale = Locale.forLanguageTag("qaa");

        final String longWord = "philanthropic";
        final float wordWidth = paint.measureText(longWord);
        // Wide enough that words get hyphenated by default.
        final int paraWidth = Math.round(wordWidth * 1.8f);
        final String sentence = longWord + " " + longWord + " " + longWord + " " + longWord + " "
                + longWord + " " + longWord;

        final int numEnglishLines = StaticLayout.Builder
                .obtain(sentence, 0, sentence.length(), paint, paraWidth)
                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
                .build()
                .getLineCount();

        {
            final SpannableString text = new SpannableString(sentence);
            text.setSpan(new LocaleSpan(privateLocale), 0, text.length(),
                    Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            final int numPrivateLocaleLines = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
                    .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
                    .build()
                    .getLineCount();

            // Since the paragraph set to English gets hyphenated, the number of lines would be
            // smaller than the number of lines when there is a span setting a language that
            // doesn't get hyphenated.
            assertTrue(numEnglishLines < numPrivateLocaleLines);
        }
        {
            // Same as the above test, except that the locale span now uses a locale list starting
            // with the private non-hyphenating locale.
            final SpannableString text = new SpannableString(sentence);
            final LocaleList locales = new LocaleList(privateLocale, Locale.US);
            text.setSpan(new LocaleSpan(locales), 0, text.length(),
                    Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            final int numPrivateLocaleLines = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
                    .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
                    .build()
                    .getLineCount();

            assertTrue(numEnglishLines < numPrivateLocaleLines);
        }
        {
            final SpannableString text = new SpannableString(sentence);
            // Apply the private LocaleSpan only to the first word, which is not getting hyphenated
            // anyway.
            text.setSpan(new LocaleSpan(privateLocale), 0, longWord.length(),
                    Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            final int numPrivateLocaleLines = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
                    .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
                    .build()
                    .getLineCount();

            // Since the first word is not hyphenated anyway (there's enough width), the LocaleSpan
            // should not affect the layout.
            assertEquals(numEnglishLines, numPrivateLocaleLines);
        }
    }

    @Test
    public void testLayoutDoesntModifyPaint() {
        final TextPaint paint = new TextPaint();
        paint.setHyphenEdit(31);
        final StaticLayout layout = StaticLayout.Builder.obtain("", 0, 0, paint, 100).build();
        final Canvas canvas = new Canvas();
        layout.drawText(canvas, 0, 0);
        assertEquals(31, paint.getHyphenEdit());
    }

    private String getTestFontsDir() {
        final Context targetCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
        final File cacheDir = new File(targetCtx.getCacheDir(), "StaticLayoutTest");
        if (!cacheDir.isDirectory()) {
            final boolean dirsCreated = cacheDir.mkdirs();
            if (!dirsCreated) {
                throw new RuntimeException("Creating test directories for fonts failed.");
            }
        }
        return cacheDir.getAbsolutePath() + "/";
    }

    private TextPaint setupPaintForFallbackFonts(String[] fontFiles, String xml) {
        final String testFontsDir = getTestFontsDir();
        final String testFontsXml = new File(testFontsDir, "fonts.xml").getAbsolutePath();
        final AssetManager am =
                InstrumentationRegistry.getInstrumentation().getContext().getAssets();
        for (String fontFile : fontFiles) {
            final String sourceInAsset = "fonts/" + fontFile;
            final File outInCache = new File(testFontsDir, fontFile);
            try (InputStream is = am.open(sourceInAsset)) {
                Files.copy(is, outInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        try (FileOutputStream fos = new FileOutputStream(testFontsXml)) {
            fos.write(xml.getBytes(Charset.forName("UTF-8")));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
        Typeface.buildSystemFallback(testFontsXml, testFontsDir, fontMap, fallbackMap);

        final TextPaint paint = new TextPaint();
        final Typeface testTypeface = fontMap.get("sans-serif");
        paint.setTypeface(testTypeface);
        return paint;
    }

    void destroyFallbackFonts(String[] fontFiles) {
        final String testFontsDir = getTestFontsDir();
        for (String fontFile : fontFiles) {
            final File outInCache = new File(testFontsDir, fontFile);
            outInCache.delete();
        }
    }

    @Test
    public void testFallbackLineSpacing() {
        // All glyphs in the fonts are 1em wide.
        final String[] testFontFiles = {
            // ascent == 1em, descent == 2em, only supports 'a' and space
            "ascent1em-descent2em.ttf",
            // ascent == 3em, descent == 4em, only supports 'b'
            "ascent3em-descent4em.ttf"
        };
        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<familyset>"
                + "  <family name='sans-serif'>"
                + "    <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>"
                + "  </family>"
                + "</familyset>";

        try {
            final TextPaint paint = setupPaintForFallbackFonts(testFontFiles, xml);
            final int textSize = 100;
            paint.setTextSize(textSize);
            assertEquals(-textSize, paint.ascent(), 0.0f);
            assertEquals(2 * textSize, paint.descent(), 0.0f);

            final int paraWidth = 5 * textSize;
            final String text = "aaaaa aabaa aaaaa"; // This should result in three lines.

            // Old line spacing. All lines should get their ascent and descents from the first font.
            StaticLayout layout = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setIncludePad(false)
                    .setUseLineSpacingFromFallbacks(false)
                    .build();
            assertEquals(3, layout.getLineCount());
            assertEquals(-textSize, layout.getLineAscent(0));
            assertEquals(2 * textSize, layout.getLineDescent(0));
            assertEquals(-textSize, layout.getLineAscent(1));
            assertEquals(2 * textSize, layout.getLineDescent(1));
            assertEquals(-textSize, layout.getLineAscent(2));
            assertEquals(2 * textSize, layout.getLineDescent(2));

            // New line spacing. The second line has a 'b', so it needs more ascent and descent.
            layout = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setIncludePad(false)
                    .setUseLineSpacingFromFallbacks(true)
                    .build();
            assertEquals(3, layout.getLineCount());
            assertEquals(-textSize, layout.getLineAscent(0));
            assertEquals(2 * textSize, layout.getLineDescent(0));
            assertEquals(-3 * textSize, layout.getLineAscent(1));
            assertEquals(4 * textSize, layout.getLineDescent(1));
            assertEquals(-textSize, layout.getLineAscent(2));
            assertEquals(2 * textSize, layout.getLineDescent(2));

            // The default is the old line spacing, for backward compatibility.
            layout = StaticLayout.Builder
                    .obtain(text, 0, text.length(), paint, paraWidth)
                    .setIncludePad(false)
                    .build();
            assertEquals(3, layout.getLineCount());
            assertEquals(-textSize, layout.getLineAscent(0));
            assertEquals(2 * textSize, layout.getLineDescent(0));
            assertEquals(-textSize, layout.getLineAscent(1));
            assertEquals(2 * textSize, layout.getLineDescent(1));
            assertEquals(-textSize, layout.getLineAscent(2));
            assertEquals(2 * textSize, layout.getLineDescent(2));
        } finally {
            destroyFallbackFonts(testFontFiles);
        }
    }

    @Test
    public void testGetHeight_zeroMaxLines() {
        final String text = "a\nb";
        final TextPaint paint = new TextPaint();
        final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), paint,
                Integer.MAX_VALUE).setMaxLines(0).build();

        assertEquals(0, layout.getHeight(true));
        assertEquals(2, layout.getLineCount());
    }
}
