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.cts; 18 19 import android.content.Context; 20 import android.graphics.Typeface; 21 import android.support.test.InstrumentationRegistry; 22 import android.support.test.filters.SmallTest; 23 import android.text.Layout; 24 import android.text.PrecomputedText; 25 import android.text.PrecomputedText.Params; 26 import android.text.PrecomputedText.Params.Builder; 27 import android.text.TextDirectionHeuristic; 28 import android.text.TextDirectionHeuristics; 29 import android.text.TextPaint; 30 import android.text.TextUtils; 31 import android.util.Pair; 32 import android.widget.TextView; 33 34 import static org.junit.Assert.fail; 35 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 import org.junit.runners.Parameterized; 39 40 import java.util.ArrayList; 41 import java.util.Collection; 42 import java.util.Locale; 43 44 /** 45 * Tests for TextView with precomputed text. 46 */ 47 @RunWith(Parameterized.class) 48 public class TextViewPrecomputedTextTest { 49 private static final String TEXT = "Hello, World!"; 50 51 @Parameterized.Parameter(0) 52 public boolean differentTextSize; 53 @Parameterized.Parameter(1) 54 public boolean differentScaleX; 55 @Parameterized.Parameter(2) 56 public boolean differentSkewX; 57 @Parameterized.Parameter(3) 58 public boolean differentLetterSpacing; 59 @Parameterized.Parameter(4) 60 public boolean differentTextLocale; 61 @Parameterized.Parameter(5) 62 public boolean differentTypeface; 63 @Parameterized.Parameter(6) 64 public boolean differentElegantTextHeight; 65 @Parameterized.Parameter(7) 66 public boolean differentBreakStrategy; 67 @Parameterized.Parameter(8) 68 public boolean differentHyphenationFrequency; 69 @Parameterized.Parameter(9) 70 public boolean differentTextDir; 71 @Parameterized.Parameter(10) 72 public boolean differentFontVariationSettings; 73 74 // text size from the default value. 75 private Pair<Params, String[]> makeDifferentParams(Params params) { 76 final TextPaint paint = new TextPaint(params.getTextPaint()); 77 ArrayList<String> differenceList = new ArrayList(); 78 79 if (differentTextSize) { 80 paint.setTextSize(paint.getTextSize() * 2.0f + 1.0f); 81 differenceList.add("Text Size"); 82 } 83 if (differentScaleX) { 84 paint.setTextScaleX(paint.getTextScaleX() * 2.0f + 1.0f); 85 differenceList.add("Text Scale X"); 86 } 87 if (differentSkewX) { 88 paint.setTextSkewX(paint.getTextSkewX() * 2.0f + 1.0f); 89 differenceList.add("Text Skew X"); 90 } 91 if (differentLetterSpacing) { 92 paint.setLetterSpacing(paint.getLetterSpacing() * 2.0f + 1.0f); 93 differenceList.add("Letter Spacing"); 94 } 95 if (differentTextLocale) { 96 paint.setTextLocale(Locale.US.equals(paint.getTextLocale()) ? Locale.JAPAN : Locale.US); 97 } 98 if (differentTypeface) { 99 final Typeface tf = paint.getTypeface(); 100 if (tf == null || tf == Typeface.DEFAULT) { 101 paint.setTypeface(Typeface.SERIF); 102 } else { 103 paint.setTypeface(Typeface.DEFAULT); 104 } 105 differenceList.add("Typeface"); 106 } 107 if (differentFontVariationSettings) { 108 final String wght = "'wght' 700"; 109 final String wdth = "'wdth' 100"; 110 111 final String varSettings = paint.getFontVariationSettings(); 112 if (varSettings == null || varSettings.equals(wght)) { 113 paint.setFontVariationSettings(wdth); 114 } else { 115 paint.setFontVariationSettings(wght); 116 } 117 differenceList.add("Font variation settings"); 118 } 119 if (differentElegantTextHeight) { 120 paint.setElegantTextHeight(!paint.isElegantTextHeight()); 121 differenceList.add("Elegant Text Height"); 122 } 123 124 int strategy = params.getBreakStrategy(); 125 if (differentBreakStrategy) { 126 strategy = strategy == Layout.BREAK_STRATEGY_SIMPLE 127 ? Layout.BREAK_STRATEGY_HIGH_QUALITY : Layout.BREAK_STRATEGY_SIMPLE; 128 differenceList.add("Break strategy"); 129 } 130 131 int hyFreq = params.getHyphenationFrequency(); 132 if (differentHyphenationFrequency) { 133 hyFreq = hyFreq == Layout.HYPHENATION_FREQUENCY_NONE 134 ? Layout.HYPHENATION_FREQUENCY_FULL : Layout.HYPHENATION_FREQUENCY_NONE; 135 differenceList.add("Hyphenation Frequency"); 136 } 137 138 TextDirectionHeuristic dir = params.getTextDirection(); 139 if (differentTextDir) { 140 dir = dir == TextDirectionHeuristics.LTR 141 ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR; 142 differenceList.add("Text Direction"); 143 } 144 145 final Params outParams = new Builder(paint).setBreakStrategy(strategy) 146 .setHyphenationFrequency(hyFreq).setTextDirection(dir).build(); 147 return new Pair(outParams, differenceList.toArray(new String[differenceList.size()])); 148 } 149 150 private static Context getContext() { 151 return InstrumentationRegistry.getInstrumentation().getTargetContext(); 152 } 153 154 @Parameterized.Parameters 155 public static Collection<Object[]> getParameters() { 156 ArrayList<Object[]> allParams = new ArrayList<>(); 157 158 // Compute the powerset except for all false case. 159 final int allParameterCount = 11; 160 // The 11-th bit is for font variation settings. Don't add test case if the system don't 161 // have variable fonts. 162 final int fullBits = hasVarFont() 163 ? (1 << allParameterCount) - 1 : (1 << (allParameterCount - 1)) - 1; 164 for (int bits = 1; bits <= fullBits; ++bits) { 165 Object[] param = new Object[allParameterCount]; 166 for (int j = 0; j < allParameterCount; ++j) { 167 param[j] = new Boolean((bits & (1 << j)) != 0); 168 } 169 allParams.add(param); 170 } 171 return allParams; 172 } 173 174 private static boolean hasVarFont() { 175 final TextPaint copied = new TextPaint((new TextView(getContext())).getPaint()); 176 return copied.setFontVariationSettings("'wght' 400") 177 && copied.setFontVariationSettings("'wdth' 100"); 178 } 179 180 @SmallTest 181 @Test 182 public void setText() { 183 final TextView tv = new TextView(getContext()); 184 final Params tvParams = tv.getTextMetricsParams(); 185 final Pair<Params, String[]> testConfig = makeDifferentParams(tvParams); 186 final Params pctParams = testConfig.first; 187 188 final PrecomputedText pct = PrecomputedText.create(TEXT, pctParams); 189 try { 190 tv.setText(pct); 191 fail("Test Case: {" + TextUtils.join(",", testConfig.second) + "}, " 192 + tvParams.toString() + " vs " + pctParams.toString()); 193 } catch (IllegalArgumentException e) { 194 // pass 195 } 196 197 tv.setTextMetricsParams(pctParams); 198 tv.setText(pct); 199 } 200 } 201