• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.graphics.fonts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotEquals;
21 
22 import android.graphics.Typeface;
23 import android.graphics.cts.R;
24 import android.platform.test.ravenwood.RavenwoodRule;
25 import android.text.TextPaint;
26 import android.util.Pair;
27 
28 import com.android.ravenwood.common.RavenwoodCommonUtils;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.Map;
36 
37 /**
38  * Provides a utility for testing fonts
39  *
40  * For the purpose of testing font selection of families or fallbacks, this class provies following
41  * regular font files.
42  *
43  * - ascii_a3em_weight100_upright.ttf
44  *   'a' has 3em width and others have 1em width. The metadata has weight=100, non-italic value.
45  * - ascii_b3em_weight100_italic.ttf
46  *   'b' has 3em width and others have 1em width. The metadata has weight=100, italic value.
47  * - ascii_c3em_weight200_upright.ttf
48  *   'c' has 3em width and others have 1em width. The metadata has weight=200, non-italic value.
49  * - ascii_d3em_weight200_italic.ttf
50  *   'd' has 3em width and others have 1em width. The metadata has weight=200, italic value.
51  * - ascii_e3em_weight300_upright.ttf
52  *   'e' has 3em width and others have 1em width. The metadata has weight=300, non-italic value.
53  * - ascii_f3em_weight300_italic.ttf
54  *   'f' has 3em width and others have 1em width. The metadata has weight=300, italic value.
55  * - ascii_g3em_weight400_upright.ttf
56  *   'g' has 3em width and others have 1em width. The metadata has weight=400, non-italic value.
57  * - ascii_h3em_weight400_italic.ttf
58  *   'h' has 3em width and others have 1em width. The metadata has weight=400, italic value.
59  * - ascii_i3em_weight500_upright.ttf
60  *   'i' has 3em width and others have 1em width. The metadata has weight=500, non-italic value.
61  * - ascii_j3em_weight500_italic.ttf
62  *   'j' has 3em width and others have 1em width. The metadata has weight=500, italic value.
63  * - ascii_k3em_weight600_upright.ttf
64  *   'k' has 3em width and others have 1em width. The metadata has weight=600, non-italic value.
65  * - ascii_l3em_weight600_italic.ttf
66  *   'l' has 3em width and others have 1em width. The metadata has weight=600, italic value.
67  * - ascii_m3em_weight700_upright.ttf
68  *   'm' has 3em width and others have 1em width. The metadata has weight=700, non-italic value.
69  * - ascii_n3em_weight700_italic.ttf
70  *   'n' has 3em width and others have 1em width. The metadata has weight=700, italic value.
71  * - ascii_o3em_weight800_upright.ttf
72  *   'o' has 3em width and others have 1em width. The metadata has weight=800, non-italic value.
73  * - ascii_p3em_weight800_italic.ttf
74  *   'p' has 3em width and others have 1em width. The metadata has weight=800, italic value.
75  * - ascii_q3em_weight900_upright.ttf
76  *   'q' has 3em width and others have 1em width. The metadata has weight=900, non-italic value.
77  * - ascii_r3em_weight900_italic.ttf
78  *   'r' has 3em width and others have 1em width. The metadata has weight=900, italic value.
79  *
80  * In addition to above font files, this class provides a font collection file and a variable font
81  * file.
82  * - ascii.ttc
83  *   The collection of above 18 fonts with above order.
84  * - ascii_vf.ttf
85  *   This font supports a-z characters and all characters has 1em width. This font supports 'wght',
86  *   'ital' axes but no effect for the glyph width. This font also supports 'Asc[a-z]' 26 axes which
87  *   makes glyph width 3em. For example, 'Asca 1.0' makes a glyph width of 'a' 3em, 'Ascb 1.0' makes
88  *   a glyph width of 'b' 3em. With these axes, above font can be replicated like
89  *   - 'Asca' 1.0, 'wght' 100.0' is equivalent with ascii_a3em_width100_upright.ttf
90  *   - 'Ascb' 1.0, 'wght' 100.0, 'ital' 1.0' is equivalent with ascii_b3em_width100_italic.ttf
91  */
92 public class FontTestUtil {
93     private static final String FAMILY_SELECTION_FONT_PATH_IN_ASSET = "fonts/family_selection";
94     private static final List<Pair<Integer, Boolean>> sStyleList;
95     private static final Map<Pair<Integer, Boolean>, String> sFontMap;
96     private static final Map<Pair<Integer, Boolean>, Integer> sTtcMap;
97     private static final Map<Pair<Integer, Boolean>, String> sVariationSettingsMap;
98     private static final Map<Pair<Integer, Boolean>, Integer> sResourceMap;
99     private static final String[] sFontList = {  // Same order of ascii.ttc
100             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_a3em_weight100_upright.ttf",
101             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_b3em_weight100_italic.ttf",
102             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_c3em_weight200_upright.ttf",
103             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_d3em_weight200_italic.ttf",
104             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_e3em_weight300_upright.ttf",
105             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_f3em_weight300_italic.ttf",
106             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_g3em_weight400_upright.ttf",
107             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_h3em_weight400_italic.ttf",
108             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_i3em_weight500_upright.ttf",
109             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_j3em_weight500_italic.ttf",
110             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_k3em_weight600_upright.ttf",
111             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_l3em_weight600_italic.ttf",
112             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_m3em_weight700_upright.ttf",
113             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_n3em_weight700_italic.ttf",
114             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_o3em_weight800_upright.ttf",
115             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_p3em_weight800_italic.ttf",
116             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_q3em_weight900_upright.ttf",
117             FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ttf/ascii_r3em_weight900_italic.ttf",
118     };
119 
120     private static final String[] FONT_VARIATION_SETTING_LIST = {
121             "'Asca' 1.0, 'wght' 100.0",
122             "'Ascb' 1.0, 'wght' 100.0, 'ital' 1.0",
123             "'Ascc' 1.0, 'wght' 200.0",
124             "'Ascd' 1.0, 'wght' 200.0, 'ital' 1.0",
125             "'Asce' 1.0, 'wght' 300.0",
126             "'Ascf' 1.0, 'wght' 300.0, 'ital' 1.0",
127             "'Ascg' 1.0, 'wght' 400.0",
128             "'Asch' 1.0, 'wght' 400.0, 'ital' 1.0",
129             "'Asci' 1.0, 'wght' 500.0",
130             "'Ascj' 1.0, 'wght' 500.0, 'ital' 1.0",
131             "'Asck' 1.0, 'wght' 600.0",
132             "'Ascl' 1.0, 'wght' 600.0, 'ital' 1.0",
133             "'Ascm' 1.0, 'wght' 700.0",
134             "'Ascn' 1.0, 'wght' 700.0, 'ital' 1.0",
135             "'Asco' 1.0, 'wght' 800.0",
136             "'Ascp' 1.0, 'wght' 800.0, 'ital' 1.0",
137             "'Ascq' 1.0, 'wght' 900.0",
138             "'Ascr' 1.0, 'wght' 900.0, 'ital' 1.0",
139     };
140 
141     private static final int[] FONT_RESOURCE_ID_LIST = {
142             R.font.ascii_a3em_weight100_upright,
143             R.font.ascii_b3em_weight100_italic,
144             R.font.ascii_c3em_weight200_upright,
145             R.font.ascii_d3em_weight200_italic,
146             R.font.ascii_e3em_weight300_upright,
147             R.font.ascii_f3em_weight300_italic,
148             R.font.ascii_g3em_weight400_upright,
149             R.font.ascii_h3em_weight400_italic,
150             R.font.ascii_i3em_weight500_upright,
151             R.font.ascii_j3em_weight500_italic,
152             R.font.ascii_k3em_weight600_upright,
153             R.font.ascii_l3em_weight600_italic,
154             R.font.ascii_m3em_weight700_upright,
155             R.font.ascii_n3em_weight700_italic,
156             R.font.ascii_o3em_weight800_upright,
157             R.font.ascii_p3em_weight800_italic,
158             R.font.ascii_q3em_weight900_upright,
159             R.font.ascii_r3em_weight900_italic,
160     };
161 
162     private static final char[] CHAR_3EM_WIDTH = {
163             'a',
164             'b',
165             'c',
166             'd',
167             'e',
168             'f',
169             'g',
170             'h',
171             'i',
172             'j',
173             'k',
174             'l',
175             'm',
176             'n',
177             'o',
178             'p',
179             'q',
180             'r',
181     };
182 
183     static {
184         // Style list with the same order of sFontList.
185         ArrayList<Pair<Integer, Boolean>> styles = new ArrayList<>();
styles.add(new Pair<>(100, false))186         styles.add(new Pair<>(100, false));
styles.add(new Pair<>(100, true))187         styles.add(new Pair<>(100, true));
styles.add(new Pair<>(200, false))188         styles.add(new Pair<>(200, false));
styles.add(new Pair<>(200, true))189         styles.add(new Pair<>(200, true));
styles.add(new Pair<>(300, false))190         styles.add(new Pair<>(300, false));
styles.add(new Pair<>(300, true))191         styles.add(new Pair<>(300, true));
styles.add(new Pair<>(400, false))192         styles.add(new Pair<>(400, false));
styles.add(new Pair<>(400, true))193         styles.add(new Pair<>(400, true));
styles.add(new Pair<>(500, false))194         styles.add(new Pair<>(500, false));
styles.add(new Pair<>(500, true))195         styles.add(new Pair<>(500, true));
styles.add(new Pair<>(600, false))196         styles.add(new Pair<>(600, false));
styles.add(new Pair<>(600, true))197         styles.add(new Pair<>(600, true));
styles.add(new Pair<>(700, false))198         styles.add(new Pair<>(700, false));
styles.add(new Pair<>(700, true))199         styles.add(new Pair<>(700, true));
styles.add(new Pair<>(800, false))200         styles.add(new Pair<>(800, false));
styles.add(new Pair<>(800, true))201         styles.add(new Pair<>(800, true));
styles.add(new Pair<>(900, false))202         styles.add(new Pair<>(900, false));
styles.add(new Pair<>(900, true))203         styles.add(new Pair<>(900, true));
204         sStyleList = Collections.unmodifiableList(styles);
205 
206         HashMap<Pair<Integer, Boolean>, String> map = new HashMap<>();
207         HashMap<Pair<Integer, Boolean>, Integer> ttcMap = new HashMap<>();
208         HashMap<Pair<Integer, Boolean>, String> variationMap = new HashMap<>();
209         HashMap<Pair<Integer, Boolean>, Integer> resourceMap = new HashMap<>();
210         HashMap<Character, Pair<Integer, Boolean>> reverseMap = new HashMap<>();
211         for (int i = 0; i < sFontList.length; ++i) {
sStyleList.get(i)212             map.put(sStyleList.get(i), sFontList[i]);
sStyleList.get(i)213             ttcMap.put(sStyleList.get(i), i);
sStyleList.get(i)214             variationMap.put(sStyleList.get(i), FONT_VARIATION_SETTING_LIST[i]);
sStyleList.get(i)215             resourceMap.put(sStyleList.get(i), FONT_RESOURCE_ID_LIST[i]);
216         }
217         sFontMap = Collections.unmodifiableMap(map);
218         sTtcMap = Collections.unmodifiableMap(ttcMap);
219         sVariationSettingsMap = Collections.unmodifiableMap(variationMap);
220         sResourceMap = Collections.unmodifiableMap(resourceMap);
221     }
222 
223     /**
224      * Measure a character with 100px text size
225      */
measureChar(Typeface typeface, char c)226     private static float measureChar(Typeface typeface, char c) {
227         final TextPaint tp = new TextPaint();
228         tp.setTextSize(100);
229         tp.setTypeface(typeface);
230         tp.setTextLocale(Locale.US);
231         return tp.measureText(new char[] { c }, 0, 1);
232     }
233 
234     /**
235      * Returns a path to the font collection file in asset directory.
236      */
getTtcFontFileInAsset()237     public static String getTtcFontFileInAsset() {
238         return FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ascii.ttc";
239     }
240 
241     /**
242      * Returns a resource id for the font collection file.
243      */
getTtcFontFileResourceId()244     public static int getTtcFontFileResourceId() {
245         return R.font.ascii;
246     }
247 
248     /**
249      * Returns a path to the variable font file in asset directory.
250      */
getVFFontInAsset()251     public static String getVFFontInAsset() {
252         return FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ascii_vf.ttf";
253     }
254 
255     /**
256      * Returns a resource id for the variable font.
257      */
getVFFontResourceId()258     public static int getVFFontResourceId() {
259         return R.font.ascii_vf;
260     }
261 
262     /**
263      * Returns a ttc index of the specified style.
264      */
getTtcIndexFromStyle(int weight, boolean italic)265     public static int getTtcIndexFromStyle(int weight, boolean italic) {
266         return sTtcMap.get(new Pair<>(weight, italic)).intValue();
267     }
268 
269     /**
270      * Returns a variation settings string of the specified style.
271      */
getVarSettingsFromStyle(int weight, boolean italic)272     public static String getVarSettingsFromStyle(int weight, boolean italic) {
273         return sVariationSettingsMap.get(new Pair<>(weight, italic));
274     }
275 
276     /**
277      * Returns a font resource ID of the specific style.
278      */
getFontResourceIdFromStyle(int weight, boolean italic)279     public static int getFontResourceIdFromStyle(int weight, boolean italic) {
280         return sResourceMap.get(new Pair<>(weight, italic));
281     }
282 
283     /**
284      * Returns a font path from the specified style.
285      */
getFontPathFromStyle(int weight, boolean italic)286     public static String getFontPathFromStyle(int weight, boolean italic) {
287         return sFontMap.get(new Pair<>(weight, italic));
288     }
289 
290     /**
291      * Returns all supported styles.
292      *
293      * @return a pair of weight and style(uplight/italic)
294      */
getAllStyles()295     public static List<Pair<Integer, Boolean>> getAllStyles() {
296         return sStyleList;
297     }
298 
299     /**
300      * Returns selected font index in the sStyleList array.
301      */
getSelectedFontStyle(Typeface typeface)302     private static int getSelectedFontStyle(Typeface typeface) {
303         int indexOf3Em = -1;
304         for (int i = 0; i < CHAR_3EM_WIDTH.length; ++i) {
305             if (measureChar(typeface, CHAR_3EM_WIDTH[i]) == 300.0f) {
306                 assertEquals("A font has two 3em width character. Likely the wrong test setup.",
307                         -1, indexOf3Em);
308                 indexOf3Em = i;
309             }
310         }
311         assertNotEquals("No font has 3em width character. Likely the wrong test setup.",
312                 -1, indexOf3Em);
313         return indexOf3Em;
314     }
315 
316     /**
317      * Returns selected font's style.
318      */
getSelectedStyle(Typeface typeface)319     public static Pair<Integer, Boolean> getSelectedStyle(Typeface typeface) {
320         return sStyleList.get(getSelectedFontStyle(typeface));
321     }
322 
323     /**
324      * Returns selected font's file path.
325      *
326      * Note that this is valid only if the all Font objects in the FontFamily is created with
327      * AssetManager.
328      */
getSelectedFontPathInAsset(Typeface typeface)329     public static String getSelectedFontPathInAsset(Typeface typeface) {
330         return sFontList[getSelectedFontStyle(typeface)];
331     }
332 
333     /**
334      * Returns selected font's ttc index.
335      *
336      * Note that this is valid only if the all Font objects in the FontFamily is created with
337      * TTC font with ttcIndex.
338      */
getSelectedTtcIndex(Typeface typeface)339     public static int getSelectedTtcIndex(Typeface typeface) {
340         return getSelectedFontStyle(typeface);
341     }
342 
343     /**
344      * Returns selected font's variation settings.
345      *
346      * Note that this is valid only if the all Font objects in the FontFamily is created with
347      * variable fonts with font variation settings.
348      */
getSelectedVariationSettings(Typeface typeface)349     public static String getSelectedVariationSettings(Typeface typeface) {
350         return FONT_VARIATION_SETTING_LIST[getSelectedFontStyle(typeface)];
351     }
352 
353     /** Returns the correct fonts directory, either on device or running in Ravenwood. */
getFontsDir()354     public static String getFontsDir() {
355         if (RavenwoodRule.isOnRavenwood()) {
356             return RavenwoodCommonUtils.getRavenwoodRuntimePath() + "/fonts/";
357         } else {
358             return "/system/fonts/";
359         }
360     }
361 }
362