1 /* 2 * Copyright (C) 2014 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.text.cts; 18 19 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assume.assumeTrue; 21 22 import android.content.Context; 23 import android.content.res.Resources; 24 import android.graphics.Bitmap; 25 import android.graphics.Paint; 26 import android.graphics.fonts.Font; 27 import android.graphics.fonts.SystemFonts; 28 import android.icu.util.ULocale; 29 import android.os.LocaleList; 30 import android.util.TypedValue; 31 import android.widget.TextView; 32 33 import androidx.test.InstrumentationRegistry; 34 import androidx.test.filters.SmallTest; 35 import androidx.test.runner.AndroidJUnit4; 36 37 import org.junit.Before; 38 import org.junit.BeforeClass; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 import java.util.Locale; 45 import java.util.Set; 46 47 @SmallTest 48 @RunWith(AndroidJUnit4.class) 49 public class MyanmarTest { 50 51 private static final String SCRIPT_QAAG = "Qaag"; 52 private static final String SCRIPT_MYMR = "Mymr"; 53 54 /** 55 * The following will be rendered correctly as a single cluster for both Unicode and Zawgyi. 56 */ 57 private static final String UNICODE_CORRECT_ORDER = "\u1019\u102d\u102f"; 58 59 /** 60 * The following will not be rendered correctly as a single cluster in Unicode. However it will 61 * render correctly with Zawgyi. 62 */ 63 private static final String UNICODE_WRONG_ORDER = "\u1019\u102f\u102d"; 64 65 private static boolean sHasBurmeseLocale; 66 private static List<Locale> sZawgyiLocales = new ArrayList<>(); 67 private static List<Locale> sMymrLocales = new ArrayList<>(); 68 private Context mContext; 69 70 @BeforeClass setupLocales()71 public static void setupLocales() { 72 final String[] supportedLocaleNames = getSupportedLocales(); 73 for (String localeName : supportedLocaleNames) { 74 final Locale locale = Locale.forLanguageTag(localeName); 75 final String script = ULocale.addLikelySubtags(ULocale.forLocale(locale)).getScript(); 76 77 if (SCRIPT_QAAG.equals(script)) { 78 sZawgyiLocales.add(locale); 79 } else if (SCRIPT_MYMR.equals(script)) { 80 sMymrLocales.add(locale); 81 } 82 83 sHasBurmeseLocale = (sMymrLocales.size() + sZawgyiLocales.size()) > 0; 84 } 85 } 86 87 @Before setupTest()88 public void setupTest() { 89 mContext = InstrumentationRegistry.getTargetContext(); 90 } 91 92 @Test testIfZawgyiExistsThenUnicodeExists()93 public void testIfZawgyiExistsThenUnicodeExists() { 94 assumeTrue(sHasBurmeseLocale); 95 assumeTrue(!sZawgyiLocales.isEmpty()); 96 97 assertTrue("If the system supports Zawgyi, it should also support Unicode Myanmar", 98 sMymrLocales.size() > 0); 99 } 100 101 @Test testShouldHaveGlyphs()102 public void testShouldHaveGlyphs() { 103 assumeTrue(sHasBurmeseLocale); 104 105 final Paint paint = new Paint(); 106 int index = 0; 107 while (index < UNICODE_CORRECT_ORDER.length()) { 108 int codepoint = UNICODE_CORRECT_ORDER.codePointAt(index); 109 110 assertTrue("Should have glyph for " + Integer.toHexString(codepoint), 111 paint.hasGlyph(new String(Character.toChars(codepoint)))); 112 113 index += Character.charCount(codepoint); 114 } 115 } 116 117 @Test testMyanmarUnicodeRenders()118 public void testMyanmarUnicodeRenders() { 119 assumeTrue(sHasBurmeseLocale); 120 assumeTrue(!sMymrLocales.isEmpty()); 121 122 assertTrue("Should render Unicode text correctly in Myanmar Unicode locale", 123 isUnicodeRendersCorrectly(mContext, new LocaleList(sMymrLocales.get(0)))); 124 } 125 126 @Test testUnicodeRenders_withValidLocaleList()127 public void testUnicodeRenders_withValidLocaleList() { 128 assumeTrue(sHasBurmeseLocale); 129 assumeTrue(!sMymrLocales.isEmpty()); 130 131 final LocaleList[] testLocales = new LocaleList[]{ 132 LocaleList.forLanguageTags("en-Latn-US"), 133 LocaleList.forLanguageTags("en-Latn"), 134 LocaleList.forLanguageTags("my-Mymr"), 135 LocaleList.forLanguageTags("my-Mymr,my-Qaag"), 136 LocaleList.forLanguageTags("my-Mymr-MM,my-Qaag-MM"), 137 LocaleList.forLanguageTags("en-Latn,my-Mymr"), 138 LocaleList.forLanguageTags("en-Latn-US,my-Mymr-MM"), 139 LocaleList.forLanguageTags("en-Mymr,my-Qaag"), 140 LocaleList.forLanguageTags("en-Mymr-MM,my-Qaag-MM"), 141 }; 142 143 for (LocaleList localeList : testLocales) { 144 assertTrue("Should render Unicode text correctly in locale " + localeList.toString(), 145 isUnicodeRendersCorrectly(mContext, localeList)); 146 } 147 148 } 149 150 @Test testZawgyiRenders()151 public void testZawgyiRenders() { 152 assumeTrue(sHasBurmeseLocale); 153 assumeTrue(!sZawgyiLocales.isEmpty()); 154 155 assertTrue("Should render Zawgyi text correctly with Zawgyi system locale", 156 isZawgyiRendersCorrectly(mContext, new LocaleList(sZawgyiLocales.get(0)))); 157 } 158 159 @Test testZawgyiRenders_withValidLocaleList()160 public void testZawgyiRenders_withValidLocaleList() { 161 assumeTrue(sHasBurmeseLocale); 162 assumeTrue(!sZawgyiLocales.isEmpty()); 163 164 final LocaleList[] testLocales = new LocaleList[]{ 165 LocaleList.forLanguageTags("my-Qaag"), 166 LocaleList.forLanguageTags("my-Qaag,my-Mymr"), 167 LocaleList.forLanguageTags("my-Qaag-MM,my-Mymr-MM"), 168 LocaleList.forLanguageTags("en-Latn,my-Qaag"), 169 LocaleList.forLanguageTags("en-Latn-US,my-Qaag-MM"), 170 LocaleList.forLanguageTags("en-Qaag,my-Mymr"), 171 LocaleList.forLanguageTags("en-Qaag-MM,my-Mymr-MM"), 172 }; 173 174 for (LocaleList localeList : testLocales) { 175 assertTrue("Should render Zawgyi text correctly in locale " + localeList.toString(), 176 isZawgyiRendersCorrectly(mContext, localeList)); 177 } 178 } 179 180 @Test testIfZawgyiLocaleIsSupported_fontWithQaagShouldExists()181 public void testIfZawgyiLocaleIsSupported_fontWithQaagShouldExists() { 182 assumeTrue(sHasBurmeseLocale); 183 assumeTrue(!sZawgyiLocales.isEmpty()); 184 185 boolean qaagFontExists = false; 186 final Set<Font> availableFonts = SystemFonts.getAvailableFonts(); 187 for (Font font : availableFonts) { 188 final LocaleList localeList = font.getLocaleList(); 189 for (int index = 0; index < localeList.size(); index++) { 190 final Locale fontLocale = localeList.get(index); 191 final ULocale uLocale = ULocale.addLikelySubtags(ULocale.forLocale(fontLocale)); 192 final String script = uLocale.getScript(); 193 if (SCRIPT_QAAG.equals(script)) { 194 qaagFontExists = true; 195 break; 196 } 197 } 198 } 199 200 assertTrue(qaagFontExists); 201 } 202 isUnicodeRendersCorrectly(Context context, LocaleList localeList)203 private static boolean isUnicodeRendersCorrectly(Context context, LocaleList localeList) { 204 final Bitmap bitmapCorrect = CaptureTextView.capture(context, localeList, 205 UNICODE_CORRECT_ORDER); 206 final Bitmap bitmapWrong = CaptureTextView.capture(context, localeList, 207 UNICODE_WRONG_ORDER); 208 209 return !bitmapCorrect.sameAs(bitmapWrong); 210 } 211 isZawgyiRendersCorrectly(Context context, LocaleList localeList)212 private static boolean isZawgyiRendersCorrectly(Context context, LocaleList localeList) { 213 final Bitmap bitmapCorrect = CaptureTextView.capture(context, localeList, 214 UNICODE_CORRECT_ORDER); 215 final Bitmap bitmapWrong = CaptureTextView.capture(context, localeList, 216 UNICODE_WRONG_ORDER); 217 218 return bitmapCorrect.sameAs(bitmapWrong); 219 } 220 getSupportedLocales()221 private static String[] getSupportedLocales() { 222 return Resources.getSystem().getStringArray( 223 Resources.getSystem().getIdentifier("supported_locales", "array", "android")); 224 } 225 226 private static class CaptureTextView extends TextView { 227 CaptureTextView(Context context)228 CaptureTextView(Context context) { 229 super(context); 230 final float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 8, 231 context.getResources().getDisplayMetrics()); 232 setTextSize(textSize); 233 } 234 capture(String text)235 private Bitmap capture(String text) { 236 setText(text); 237 238 invalidate(); 239 240 setDrawingCacheEnabled(true); 241 measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 242 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 243 layout(0, 0, 200, 200); 244 245 Bitmap bitmap = Bitmap.createBitmap(getDrawingCache()); 246 setDrawingCacheEnabled(false); 247 return bitmap; 248 } 249 capture(Context context, LocaleList localeList, String string)250 static Bitmap capture(Context context, LocaleList localeList, String string) { 251 final CaptureTextView textView = new CaptureTextView(context); 252 if (localeList != null) textView.setTextLocales(localeList); 253 return textView.capture(string); 254 } 255 } 256 257 } 258