1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.widget;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.app.Activity;
24 import android.text.DynamicLayout;
25 import android.text.FontFallbackSetup;
26 import android.text.Layout;
27 import android.text.StaticLayout;
28 import android.util.TypedValue;
29 import android.view.View;
30 import android.widget.TextView.BufferType;
31 
32 import androidx.test.filters.MediumTest;
33 import androidx.test.rule.ActivityTestRule;
34 
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.Parameterized;
39 
40 import java.util.Arrays;
41 import java.util.Collection;
42 
43 /**
44  * Parametrized test for TextView#setFallbackLineSpacing.
45  */
46 @MediumTest
47 @RunWith(Parameterized.class)
48 public class TextViewFallbackLineSpacingTest {
49 
50     @Parameterized.Parameters(name = "{0}")
layouts()51     public static Collection layouts() {
52         return Arrays.asList(new Object[][] {
53                 // name, enabled, BufferType
54                 { "Enabled - StaticLayout", true, BufferType.NORMAL},
55                 { "Disabled - StaticLayout", false, BufferType.NORMAL},
56                 { "Enabled - DynamicLayout", true, BufferType.EDITABLE},
57                 { "Disabled - DynamicLayout", false, BufferType.EDITABLE},
58         });
59     }
60 
61     @Rule
62     public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
63             TextViewActivity.class);
64 
65     private final boolean mEnabled;
66     private final BufferType mBufferType;
67 
TextViewFallbackLineSpacingTest(String testName, boolean enabled, BufferType bufferType)68     public TextViewFallbackLineSpacingTest(String testName, boolean enabled,
69             BufferType bufferType) {
70         mEnabled = enabled;
71         mBufferType = bufferType;
72     }
73 
74     @Test
testFallbackLineSpacing()75     public void testFallbackLineSpacing() {
76         // All glyphs in the fonts are 1em wide.
77         final String[] testFontFiles = {
78                 // ascent == 1em, descent == 2em, only supports 'a' and space
79                 "ascent1em-descent2em.ttf",
80                 // ascent == 3em, descent == 4em, only supports 'b'
81                 "ascent3em-descent4em.ttf"
82         };
83         final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
84                 + "<familyset>"
85                 + "  <family name='sans-serif'>"
86                 + "    <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>"
87                 + "  </family>"
88                 + "  <family>"
89                 + "    <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>"
90                 + "  </family>"
91                 + "</familyset>";
92 
93         try (FontFallbackSetup setup =
94                      new FontFallbackSetup("DynamicLayout", testFontFiles, xml)) {
95             final Activity activity = mActivityRule.getActivity();
96             final TextView textView = new TextView(activity);
97             textView.setTypeface(setup.getTypefaceFor("sans-serif"));
98             textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 100);
99             // This should result in three lines.
100             textView.setText("aaaaa aabaa aaaaa", mBufferType);
101             textView.setPadding(0, 0, 0, 0);
102             textView.setIncludeFontPadding(false);
103             textView.setFallbackLineSpacing(mEnabled);
104 
105             final int em = (int) Math.ceil(textView.getPaint().measureText("a"));
106             final int width = 5 * em;
107             final int height = 30 * em; // tall enough to not affect our other measurements
108             textView.measure(
109                     View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
110                     View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
111             textView.layout(0, 0, width, height);
112 
113             final Layout layout = textView.getLayout();
114             assertNotNull(layout);
115             if (mBufferType == BufferType.NORMAL) {
116                 assertTrue(layout instanceof StaticLayout);
117             } else {
118                 assertTrue(layout instanceof DynamicLayout);
119             }
120             assertEquals(3, layout.getLineCount());
121 
122             assertEquals(-em, layout.getLineAscent(0));
123             assertEquals(2 * em, layout.getLineDescent(0));
124 
125             if (mEnabled) {
126                 // The second line has a 'b', so it needs more ascent and descent.
127                 assertEquals(-3 * em, layout.getLineAscent(1));
128                 assertEquals(4 * em, layout.getLineDescent(1));
129             } else {
130                 // old behavior
131                 assertEquals(-em, layout.getLineAscent(1));
132                 assertEquals(2 * em, layout.getLineDescent(1));
133             }
134 
135             assertEquals(-em, layout.getLineAscent(2));
136             assertEquals(2 * em, layout.getLineDescent(2));
137         }
138     }
139 }
140