Add a few simple tests of StaticLayout.
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
new file mode 100644
index 0000000..1e4db3d
--- /dev/null
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -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());
+ }
+}