1 /*
2  * Copyright (C) 2017 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;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.res.AssetManager;
22 import android.graphics.FontListParser;
23 import android.graphics.Typeface;
24 import android.graphics.fonts.FontFamily;
25 import android.graphics.fonts.SystemFonts;
26 
27 import androidx.test.InstrumentationRegistry;
28 
29 import org.xmlpull.v1.XmlPullParserException;
30 
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.nio.charset.Charset;
36 import java.nio.file.Files;
37 import java.nio.file.StandardCopyOption;
38 import java.util.Map;
39 
40 public class FontFallbackSetup implements AutoCloseable {
41     private final String[] mTestFontFiles;
42     private final String mXml;
43     private final String mTestFontsDir;
44     private final Map<String, Typeface> mFontMap;
45 
FontFallbackSetup(@onNull String testSubDir, @NonNull String[] testFontFiles, @NonNull String xml)46     public FontFallbackSetup(@NonNull String testSubDir, @NonNull String[] testFontFiles,
47             @NonNull String xml) {
48         mTestFontFiles = testFontFiles;
49         mXml = xml;
50 
51         final Context targetCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
52         final File cacheDir = new File(targetCtx.getCacheDir(), testSubDir);
53         if (!cacheDir.isDirectory()) {
54             final boolean dirsCreated = cacheDir.mkdirs();
55             if (!dirsCreated) {
56                 throw new RuntimeException("Creating test directories for fonts failed.");
57             }
58         }
59         mTestFontsDir = cacheDir.getAbsolutePath() + "/";
60 
61         final String testFontsXml = new File(mTestFontsDir, "fonts.xml").getAbsolutePath();
62         final AssetManager am =
63                 InstrumentationRegistry.getInstrumentation().getContext().getAssets();
64         for (String fontFile : mTestFontFiles) {
65             final String sourceInAsset = "fonts/" + fontFile;
66             final File outInCache = new File(mTestFontsDir, fontFile);
67             try (InputStream is = am.open(sourceInAsset)) {
68                 Files.copy(is, outInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
69             } catch (IOException e) {
70                 throw new RuntimeException(e);
71             }
72         }
73 
74         try (FileOutputStream fos = new FileOutputStream(testFontsXml)) {
75             fos.write(mXml.getBytes(Charset.forName("UTF-8")));
76         } catch (IOException e) {
77             throw new RuntimeException(e);
78         }
79 
80         FontConfig fontConfig;
81         try {
82             fontConfig = FontListParser.parse(testFontsXml, mTestFontsDir, null, null, null, 0, 0);
83         } catch (IOException | XmlPullParserException e) {
84             throw new RuntimeException(e);
85         }
86 
87         Map<String, FontFamily[]> fallbackMap = SystemFonts.buildSystemFallback(fontConfig);
88         mFontMap = SystemFonts.buildSystemTypefaces(fontConfig, fallbackMap);
89     }
90 
91     @NonNull
getTypefaceFor(@onNull String fontName)92     public Typeface getTypefaceFor(@NonNull String fontName) {
93         return mFontMap.get(fontName);
94     }
95 
96     @NonNull
getPaintFor(@onNull String fontName)97     public TextPaint getPaintFor(@NonNull String fontName) {
98         final TextPaint paint = new TextPaint();
99         paint.setTypeface(getTypefaceFor(fontName));
100         return paint;
101     }
102 
103     @Override
close()104     public void close() {
105         for (String fontFile : mTestFontFiles) {
106             final File outInCache = new File(mTestFontsDir, fontFile);
107             outInCache.delete();
108         }
109     }
110 }
111