1/*
2 * Copyright (C) 2008 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
17package android.graphics;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertTrue;
21
22import android.content.Context;
23import android.content.res.AssetManager;
24import android.content.res.Resources;
25import android.graphics.Paint;
26import android.graphics.Typeface;
27import android.support.test.InstrumentationRegistry;
28import android.support.test.runner.AndroidJUnit4;
29import android.test.suitebuilder.annotation.LargeTest;
30import android.test.suitebuilder.annotation.MediumTest;
31import android.test.suitebuilder.annotation.SmallTest;
32
33import com.android.frameworks.coretests.R;
34
35import org.junit.Test;
36import org.junit.runner.RunWith;
37
38import java.util.Random;
39
40@RunWith(AndroidJUnit4.class)
41public class TypefaceTest {
42
43    // create array of all std faces
44    private final Typeface[] mFaces = new Typeface[] {
45        Typeface.create(Typeface.SANS_SERIF, 0),
46        Typeface.create(Typeface.SANS_SERIF, 1),
47        Typeface.create(Typeface.SERIF, 0),
48        Typeface.create(Typeface.SERIF, 1),
49        Typeface.create(Typeface.SERIF, 2),
50        Typeface.create(Typeface.SERIF, 3),
51        Typeface.create(Typeface.MONOSPACE, 0)
52    };
53
54    @SmallTest
55    @Test
56    public void testBasic() throws Exception {
57        assertTrue("basic", Typeface.DEFAULT != null);
58        assertTrue("basic", Typeface.DEFAULT_BOLD != null);
59        assertTrue("basic", Typeface.SANS_SERIF != null);
60        assertTrue("basic", Typeface.SERIF != null);
61        assertTrue("basic", Typeface.MONOSPACE != null);
62    }
63
64    @SmallTest
65    @Test
66    public void testUnique() throws Exception {
67        final int n = mFaces.length;
68        for (int i = 0; i < n; i++) {
69            for (int j = i + 1; j < n; j++) {
70                assertTrue("unique", mFaces[i] != mFaces[j]);
71            }
72        }
73    }
74
75    @SmallTest
76    @Test
77    public void testStyles() throws Exception {
78        assertTrue("style", mFaces[0].getStyle() == Typeface.NORMAL);
79        assertTrue("style", mFaces[1].getStyle() == Typeface.BOLD);
80        assertTrue("style", mFaces[2].getStyle() == Typeface.NORMAL);
81        assertTrue("style", mFaces[3].getStyle() == Typeface.BOLD);
82        assertTrue("style", mFaces[4].getStyle() == Typeface.ITALIC);
83        assertTrue("style", mFaces[5].getStyle() == Typeface.BOLD_ITALIC);
84        assertTrue("style", mFaces[6].getStyle() == Typeface.NORMAL);
85    }
86
87    @MediumTest
88    @Test
89    public void testUniformY() throws Exception {
90        Paint p = new Paint();
91        final int n = mFaces.length;
92        for (int i = 1; i <= 36; i++) {
93            p.setTextSize(i);
94            float ascent = 0;
95            float descent = 0;
96            for (int j = 0; j < n; j++) {
97                p.setTypeface(mFaces[j]);
98                Paint.FontMetrics fm = p.getFontMetrics();
99                if (j == 0) {
100                    ascent = fm.ascent;
101                    descent = fm.descent;
102                } else {
103                    assertTrue("fontMetrics", fm.ascent == ascent);
104                    assertTrue("fontMetrics", fm.descent == descent);
105                }
106            }
107        }
108    }
109
110    @LargeTest
111    @Test
112    public void testMultithreadCacheStressTest() {
113        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
114        final Resources res = context.getResources();
115        final AssetManager assets = res.getAssets();
116        final Typeface[] baseTypefaces = {
117            null,
118            Typeface.SANS_SERIF,
119            Typeface.SERIF,
120            Typeface.MONOSPACE,
121            res.getFont(R.font.samplefont),
122            res.getFont(R.font.samplefont2),
123            res.getFont(R.font.samplefont3),
124            res.getFont(R.font.samplefont4),
125            res.getFont(R.font.samplexmlfont),
126            Typeface.createFromAsset(assets, "fonts/a3em.ttf"),
127            Typeface.createFromAsset(assets, "fonts/b3em.ttf"),
128            Typeface.createFromAsset(assets, "fonts/c3em.ttf"),
129            Typeface.createFromAsset(assets, "fonts/all2em.ttf"),
130            Typeface.createFromAsset(assets, "fonts/hasGlyphTestFont.ttf"),
131            Typeface.createFromAsset(assets, "fonts/samplefont1.ttf"),
132            Typeface.createFromAsset(assets, "fonts/no_coverage.ttf"),
133        };
134
135        final int loopCount = 10000;
136
137        final Runnable threadedCreater = () -> {
138            final Random random = new Random();
139            for (int i = 0; i < loopCount; ++i) {
140                final Typeface base = baseTypefaces[random.nextInt(baseTypefaces.length)];
141                if (random.nextBoolean()) {
142                    final int style = random.nextInt(3);
143                    final Typeface result = Typeface.create(base, style);
144                    assertEquals(style, result.getStyle());
145                } else {
146                    final int weight = 100 * (random.nextInt(10) + 1);  // [100, 1000]
147                    final boolean italic = random.nextBoolean();
148                    final Typeface result = Typeface.create(base, weight, italic);
149                    assertEquals(italic, result.isItalic());
150                    assertEquals(weight, result.getWeight());
151                }
152            }
153        };
154
155        final int threadCount = 4;
156        final Thread[] threads = new Thread[threadCount];
157        for (int i = 0; i < threadCount; ++i) {
158            threads[i] = new Thread(threadedCreater);
159        }
160
161        for (int i = 0; i < threadCount; ++i) {
162            threads[i].start();
163        }
164
165        for (int i = 0; i < threadCount; ++i) {
166            try {
167                threads[i].join();
168            } catch (InterruptedException e) {
169                // ignore
170            }
171        }
172
173    }
174
175}
176