blob: b4fb8ab6455df6099a720889059bd30bb3dd730e [file] [log] [blame]
/*
* Copyright (C) 2008 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.cts;
import android.test.AndroidTestCase;
import android.text.Editable;
import android.text.StaticLayout;
import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.Layout.Alignment;
public class StaticLayoutTest extends AndroidTestCase {
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 int LAST_LINE = 5;
private static final int LINE_COUNT = 6;
private static final int LARGER_THAN_LINE_COUNT = 50;
/* the first line must have one tab. the others not. totally 6 lines
*/
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 int VERTICAL_BELOW_TEXT = 1000;
private static final Alignment DEFAULT_ALIGN = Alignment.ALIGN_CENTER;
private static final int ELLIPSIZE_WIDTH = 8;
private StaticLayout mDefaultLayout;
private TextPaint mDefaultPaint;
@Override
protected void setUp() throws Exception {
super.setUp();
if (mDefaultPaint == null) {
mDefaultPaint = new TextPaint();
}
if (mDefaultLayout == null) {
mDefaultLayout = createDefaultStaticLayout();
}
}
private StaticLayout createDefaultStaticLayout() {
return new StaticLayout(LAYOUT_TEXT, mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
}
private StaticLayout createEllipsizeStaticLayout() {
return new StaticLayout(LAYOUT_TEXT, 0, LAYOUT_TEXT.length(), mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true,
TextUtils.TruncateAt.MIDDLE, ELLIPSIZE_WIDTH);
}
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);
}
/**
* Constructor test
*/
public void testConstructor() {
new StaticLayout(LAYOUT_TEXT, mDefaultPaint, DEFAULT_OUTER_WIDTH,
DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
new StaticLayout(LAYOUT_TEXT, 0, LAYOUT_TEXT.length(), mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
new StaticLayout(LAYOUT_TEXT, 0, LAYOUT_TEXT.length(), mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, false, null, 0);
try {
new StaticLayout(null, null, -1, null, 0, 0, true);
fail("should throw NullPointerException here");
} catch (NullPointerException e) {
}
}
/*
* Get the line number corresponding to the specified vertical position.
* If you ask for a position above 0, you get 0. above 0 means pixel above the fire line
* if you ask for a position in the range of the height, return the pixel in line
* if you ask for a position below the bottom of the text, you get the last line.
* Test 4 values containing -1, 0, normal number and > count
*/
public void testGetLineForVertical() {
assertEquals(0, mDefaultLayout.getLineForVertical(-1));
assertEquals(0, mDefaultLayout.getLineForVertical(0));
assertTrue(mDefaultLayout.getLineForVertical(50) > 0);
assertEquals(LAST_LINE, mDefaultLayout.getLineForVertical(VERTICAL_BELOW_TEXT));
}
/**
* Return the number of lines of text in this layout.
*/
public void testGetLineCount() {
assertEquals(LINE_COUNT, mDefaultLayout.getLineCount());
}
/*
* Return the vertical position of the top of the specified line.
* If the specified line is one beyond the last line, returns the bottom of the last line.
* A line of text contains top and bottom in height. this method just get the top of a line
* Test 4 values containing -1, 0, normal number and > count
*/
public void testGetLineTop() {
assertTrue(mDefaultLayout.getLineTop(0) >= 0);
assertTrue(mDefaultLayout.getLineTop(1) > mDefaultLayout.getLineTop(0));
try {
mDefaultLayout.getLineTop(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getLineTop(LARGER_THAN_LINE_COUNT );
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/**
* Return the descent of the specified line.
* This method just like getLineTop, descent means the bottom pixel of the line
* Test 4 values containing -1, 0, normal number and > count
*/
public void testGetLineDescent() {
assertTrue(mDefaultLayout.getLineDescent(0) > 0);
assertTrue(mDefaultLayout.getLineDescent(1) > 0);
try {
mDefaultLayout.getLineDescent(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getLineDescent(LARGER_THAN_LINE_COUNT );
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/**
* Returns the primary directionality of the paragraph containing the specified line.
* By default, each line should be same
*/
public void testGetParagraphDirection() {
assertEquals(mDefaultLayout.getParagraphDirection(0),
mDefaultLayout.getParagraphDirection(1));
try {
mDefaultLayout.getParagraphDirection(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getParagraphDirection(LARGER_THAN_LINE_COUNT);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/**
* Return the text offset of the beginning of the specified line.
* If the specified line is one beyond the last line, returns the end of the last line.
* Test 4 values containing -1, 0, normal number and > count
* Each line's offset must >= 0
*/
public void testGetLineStart() {
assertTrue(mDefaultLayout.getLineStart(0) >= 0);
assertTrue(mDefaultLayout.getLineStart(1) >= 0);
try {
mDefaultLayout.getLineStart(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getLineStart(LARGER_THAN_LINE_COUNT);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/*
* Returns whether the specified line contains one or more tabs.
*/
public void testGetContainsTab() {
assertTrue(mDefaultLayout.getLineContainsTab(0));
assertFalse(mDefaultLayout.getLineContainsTab(1));
try {
mDefaultLayout.getLineContainsTab(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getLineContainsTab(LARGER_THAN_LINE_COUNT );
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/**
* Returns an array of directionalities for the specified line.
* The array alternates counts of characters in left-to-right
* and right-to-left segments of the line.
* We can not check the return value, for Directions's field is package private
* So only check it not null
*/
public void testGetLineDirections() {
assertNotNull(mDefaultLayout.getLineDirections(0));
assertNotNull(mDefaultLayout.getLineDirections(1));
try {
mDefaultLayout.getLineDirections(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getLineDirections(LARGER_THAN_LINE_COUNT);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/**
* Returns the (negative) number of extra pixels of ascent padding
* in the top line of the Layout.
*/
public void testGetTopPadding() {
assertTrue(mDefaultLayout.getTopPadding() < 0);
}
/**
* Returns the number of extra pixels of descent padding in the bottom line of the Layout.
*/
public void testGetBottomPadding() {
assertTrue(mDefaultLayout.getBottomPadding() > 0);
}
/*
* Returns the number of characters to be ellipsized away, or 0 if no ellipsis is to take place.
* So each line must >= 0
*/
public void testGetEllipsisCount() {
// Multilines (6 lines) and TruncateAt.START so no ellipsis at all
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT,
TextUtils.TruncateAt.MIDDLE,
Integer.MAX_VALUE /* maxLines */);
assertTrue(mDefaultLayout.getEllipsisCount(0) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(1) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(2) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(3) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(4) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(5) == 0);
try {
mDefaultLayout.getEllipsisCount(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getEllipsisCount(LARGER_THAN_LINE_COUNT);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
// Multilines (6 lines) and TruncateAt.MIDDLE so no ellipsis at all
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT,
TextUtils.TruncateAt.MIDDLE,
Integer.MAX_VALUE /* maxLines */);
assertTrue(mDefaultLayout.getEllipsisCount(0) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(1) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(2) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(3) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(4) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(5) == 0);
// Multilines (6 lines) and TruncateAt.END so ellipsis only on the last line
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT,
TextUtils.TruncateAt.END,
Integer.MAX_VALUE /* maxLines */);
assertTrue(mDefaultLayout.getEllipsisCount(0) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(1) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(2) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(3) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(4) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(5) > 0);
// Multilines (6 lines) and TruncateAt.MARQUEE so ellipsis only on the last line
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT,
TextUtils.TruncateAt.END,
Integer.MAX_VALUE /* maxLines */);
assertTrue(mDefaultLayout.getEllipsisCount(0) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(1) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(2) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(3) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(4) == 0);
assertTrue(mDefaultLayout.getEllipsisCount(5) > 0);
// Single line case and TruncateAt.END so that we have some ellipsis
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
TextUtils.TruncateAt.END,
1);
assertTrue(mDefaultLayout.getEllipsisCount(0) > 0);
// Single line case and TruncateAt.MIDDLE so that we have some ellipsis
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
TextUtils.TruncateAt.MIDDLE,
1);
assertTrue(mDefaultLayout.getEllipsisCount(0) > 0);
// Single line case and TruncateAt.END so that we have some ellipsis
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
TextUtils.TruncateAt.END,
1);
assertTrue(mDefaultLayout.getEllipsisCount(0) > 0);
// Single line case and TruncateAt.MARQUEE so that we have NO ellipsis
mDefaultLayout = createEllipsizeStaticLayout(LAYOUT_TEXT_SINGLE_LINE,
TextUtils.TruncateAt.MARQUEE,
1);
assertTrue(mDefaultLayout.getEllipsisCount(0) == 0);
}
/*
* Return the offset of the first character to be ellipsized away
* relative to the start of the line.
* (So 0 if the beginning of the line is ellipsized, not getLineStart().)
*/
public void testGetEllipsisStart() {
mDefaultLayout = createEllipsizeStaticLayout();
assertTrue(mDefaultLayout.getEllipsisStart(0) >= 0);
assertTrue(mDefaultLayout.getEllipsisStart(1) >= 0);
try {
mDefaultLayout.getEllipsisStart(-1);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
try {
mDefaultLayout.getEllipsisStart(LARGER_THAN_LINE_COUNT);
fail("should throw ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) {
}
}
/*
* Return the width to which this Layout is ellipsizing
* or getWidth() if it is not doing anything special.
* The constructor's Argument TextUtils.TruncateAt defines which EllipsizedWidth to use
* ellipsizedWidth if argument is not null
* outerWidth if argument is null
*/
public void testGetEllipsizedWidth() {
int ellipsizedWidth = 60;
int outerWidth = 100;
StaticLayout layout = new StaticLayout(LAYOUT_TEXT, 0, LAYOUT_TEXT.length(),
mDefaultPaint, outerWidth, DEFAULT_ALIGN, SPACE_MULTI,
SPACE_ADD, false, TextUtils.TruncateAt.END, ellipsizedWidth);
assertEquals(ellipsizedWidth, layout.getEllipsizedWidth());
layout = new StaticLayout(LAYOUT_TEXT, 0, LAYOUT_TEXT.length(),
mDefaultPaint, outerWidth, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD,
false, null, ellipsizedWidth);
assertEquals(outerWidth, layout.getEllipsizedWidth());
}
/**
* scenario description:
* 1. set the text.
* 2. change the text
* 3. Check the text won't change to the StaticLayout
*/
public void testImmutableStaticLayout() {
Editable editable = Editable.Factory.getInstance().newEditable("123\t\n555");
StaticLayout layout = new StaticLayout(editable, mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
assertEquals(2, layout.getLineCount());
assertTrue(mDefaultLayout.getLineContainsTab(0));
// change the text
editable.delete(0, editable.length() - 1);
assertEquals(2, layout.getLineCount());
assertTrue(layout.getLineContainsTab(0));
}
}