/*
 * 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.graphics.Paint.FontMetricsInt;
import android.os.LocaleList;
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.Log;

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

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,
                fmi.ascent, fmi.descent);

        // 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 testGetters2() {
        LayoutBuilder b = builder()
            .setIncludePad(true);
        FontMetricsInt fmi = b.paint.getFontMetricsInt();

        Layout l = b.build();
        assertVertMetrics(l, fmi.top - fmi.ascent, fmi.bottom - fmi.descent,
                fmi.top, fmi.bottom);
    }

    /**
     * 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 testGetters3() {
        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,
            fmi.top, fmi.descent,
            fmi.ascent, fmi.bottom);
    }

    /**
     * Basic test showing effect of includePad = true wrapping to 3 lines.
     * First line ascent is top, bottom line descent is bottom.
     */
    @Test
    public void testGetters4() {
        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,
                fmi.top, fmi.descent,
                fmi.ascent, fmi.descent,
                fmi.ascent, fmi.bottom);
    }

    /**
     * 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 testGetters5() {
        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,
                fmi.top, fmi.descent,
                fmi.ascent, fmi.descent,
                fmi.ascent, fmi.bottom);
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 2, wrapping
     * to 3 lines.
     */
    @Test
    public void testGetters6() {
        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,
                fmi.top, fmi.descent + spacingAdd,
                fmi.ascent, fmi.descent + spacingAdd,
                fmi.ascent, fmi.bottom);
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 2,
     * spacingMult = 1.5, wrapping to 3 lines.
     */
    @Test
    public void testGetters7() {
        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,
                fmi.top, fmi.descent + s.scale(fmi.descent - fmi.top),
                fmi.ascent, fmi.descent + s.scale(fmi.descent - fmi.ascent),
                fmi.ascent, fmi.bottom);
    }

    /**
     * Basic test showing effect of includePad = true, spacingAdd = 0,
     * spacingMult = 0.8 when wrapping to 3 lines.
     */
    @Test
    public void testGetters8() {
        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,
                fmi.top, fmi.descent + s.scale(fmi.descent - fmi.top),
                fmi.ascent, fmi.descent + s.scale(fmi.descent - fmi.ascent),
                fmi.ascent, fmi.bottom);
    }

    // ----- 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);
        }
    }

    private void assertVertMetrics(Layout l, int topPad, int botPad, int... values) {
        assertTopBotPadding(l, topPad, botPad);
        assertLinesMetrics(l, values);
    }

    private void assertLinesMetrics(Layout l, int... values) {
        // sanity check
        if ((values.length & 0x1) != 0) {
            throw new IllegalArgumentException(String.valueOf(values.length));
        }

        int lines = values.length >> 1;
        assertEquals(lines, l.getLineCount());

        int t = 0;
        for (int i = 0, n = 0; i < lines; ++i, n += 2) {
            int a = values[n];
            int d = values[n+1];
            int h = -a + d;
            assertLineMetrics(l, i, t, a, d, h);
            t += h;
        }

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

    private void assertLineMetrics(Layout l, int line,
            int top, int ascent, int descent, int height) {
        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);
    }

    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);
        }
    }
}
