Add a few simple tests of StaticLayout.
This commit is contained in:
319
core/tests/coretests/src/android/text/StaticLayoutTest.java
Normal file
319
core/tests/coretests/src/android/text/StaticLayoutTest.java
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* 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 android.graphics.Paint.FontMetricsInt;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.text.Layout.Alignment;
|
||||
import static android.text.Layout.Alignment.*;
|
||||
import android.util.Log;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests StaticLayout vertical metrics behavior.
|
||||
*/
|
||||
public class StaticLayoutTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Basic test showing expected behavior and relationship between font
|
||||
* metrics and line metrics.
|
||||
*/
|
||||
@SmallTest
|
||||
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.
|
||||
*/
|
||||
@SmallTest
|
||||
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.
|
||||
*/
|
||||
@SmallTest
|
||||
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.
|
||||
*/
|
||||
@SmallTest
|
||||
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.
|
||||
*/
|
||||
@SmallTest
|
||||
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.
|
||||
*/
|
||||
@SmallTest
|
||||
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 + spacingAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test showing effect of includePad = true, spacingAdd = 2,
|
||||
* spacingMult = 1.5, wrapping to 3 lines.
|
||||
*/
|
||||
@SmallTest
|
||||
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 + s.scale(fmi.bottom - fmi.ascent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test showing effect of includePad = true, spacingAdd = 0,
|
||||
* spacingMult = 0.8 when wrapping to 3 lines.
|
||||
*/
|
||||
@SmallTest
|
||||
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 + s.scale(fmi.bottom - fmi.ascent));
|
||||
}
|
||||
|
||||
// ----- 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); // existing impl
|
||||
int rndVal = Math.round(height * sMult + sAdd);
|
||||
if (altVal != rndVal) {
|
||||
Log.i("Scale", "expected scale: " + rndVal +
|
||||
" != returned scale: " + altVal);
|
||||
}
|
||||
return altVal; // existing implementation
|
||||
}
|
||||
}
|
||||
|
||||
private static LayoutBuilder builder() {
|
||||
return new LayoutBuilder();
|
||||
}
|
||||
|
||||
private 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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user