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.graphics;
18 
19 import android.annotation.Nullable;
20 import android.annotation.UnsupportedAppUsage;
21 import android.content.res.AssetManager;
22 import android.graphics.fonts.FontVariationAxis;
23 import android.text.TextUtils;
24 import android.util.Log;
25 
26 import dalvik.annotation.optimization.CriticalNative;
27 
28 import libcore.util.NativeAllocationRegistry;
29 
30 import java.io.FileInputStream;
31 import java.io.IOException;
32 import java.nio.ByteBuffer;
33 import java.nio.channels.FileChannel;
34 
35 /**
36  * A family of typefaces with different styles.
37  *
38  * @hide
39  *
40  * @deprecated Use {@link android.graphics.fonts.FontFamily} instead.
41  */
42 @Deprecated
43 public class FontFamily {
44 
45     private static String TAG = "FontFamily";
46 
47     private static final NativeAllocationRegistry sBuilderRegistry =
48             NativeAllocationRegistry.createMalloced(
49             FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc());
50 
51     private @Nullable Runnable mNativeBuilderCleaner;
52 
53     private static final NativeAllocationRegistry sFamilyRegistry =
54             NativeAllocationRegistry.createMalloced(
55             FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc());
56 
57     /**
58      * @hide
59      *
60      * This cannot be deleted because it's in use by AndroidX.
61      */
62     @UnsupportedAppUsage(trackingBug = 123768928)
63     public long mNativePtr;
64 
65     // Points native font family builder. Must be zero after freezing this family.
66     private long mBuilderPtr;
67 
68     /**
69      * This cannot be deleted because it's in use by AndroidX.
70      */
71     @UnsupportedAppUsage(trackingBug = 123768928)
FontFamily()72     public FontFamily() {
73         mBuilderPtr = nInitBuilder(null, 0);
74         mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
75     }
76 
77     /**
78      * This cannot be deleted because it's in use by AndroidX.
79      */
80     @UnsupportedAppUsage(trackingBug = 123768928)
FontFamily(@ullable String[] langs, int variant)81     public FontFamily(@Nullable String[] langs, int variant) {
82         final String langsString;
83         if (langs == null || langs.length == 0) {
84             langsString = null;
85         } else if (langs.length == 1) {
86             langsString = langs[0];
87         } else {
88             langsString = TextUtils.join(",", langs);
89         }
90         mBuilderPtr = nInitBuilder(langsString, variant);
91         mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
92     }
93 
94     /**
95      * Finalize the FontFamily creation.
96      *
97      * @return boolean returns false if some error happens in native code, e.g. broken font file is
98      *                 passed, etc.
99      *
100      * This cannot be deleted because it's in use by AndroidX.
101      */
102     @UnsupportedAppUsage(trackingBug = 123768928)
freeze()103     public boolean freeze() {
104         if (mBuilderPtr == 0) {
105             throw new IllegalStateException("This FontFamily is already frozen");
106         }
107         mNativePtr = nCreateFamily(mBuilderPtr);
108         mNativeBuilderCleaner.run();
109         mBuilderPtr = 0;
110         if (mNativePtr != 0) {
111             sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
112         }
113         return mNativePtr != 0;
114     }
115 
116     /**
117      * This cannot be deleted because it's in use by AndroidX.
118      */
119     @UnsupportedAppUsage(trackingBug = 123768928)
abortCreation()120     public void abortCreation() {
121         if (mBuilderPtr == 0) {
122             throw new IllegalStateException("This FontFamily is already frozen or abandoned");
123         }
124         mNativeBuilderCleaner.run();
125         mBuilderPtr = 0;
126     }
127 
128     /**
129      * This cannot be deleted because it's in use by AndroidX.
130      */
131     @UnsupportedAppUsage(trackingBug = 123768928)
addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight, int italic)132     public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
133             int italic) {
134         if (mBuilderPtr == 0) {
135             throw new IllegalStateException("Unable to call addFont after freezing.");
136         }
137         try (FileInputStream file = new FileInputStream(path)) {
138             FileChannel fileChannel = file.getChannel();
139             long fontSize = fileChannel.size();
140             ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
141             if (axes != null) {
142                 for (FontVariationAxis axis : axes) {
143                     nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
144                 }
145             }
146             return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
147         } catch (IOException e) {
148             Log.e(TAG, "Error mapping font file " + path);
149             return false;
150         }
151     }
152 
153     /**
154      * This cannot be deleted because it's in use by AndroidX.
155      */
156     @UnsupportedAppUsage(trackingBug = 123768928)
addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes, int weight, int italic)157     public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
158             int weight, int italic) {
159         if (mBuilderPtr == 0) {
160             throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
161         }
162         if (axes != null) {
163             for (FontVariationAxis axis : axes) {
164                 nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
165             }
166         }
167         return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
168     }
169 
170     /**
171      * @param mgr The AssetManager to use for this context.
172      * @param path The path to the font file to load.
173      * @param cookie If available, the resource cookie given by Resources.
174      * @param isAsset {@code true} if this is from the assets/ folder, {@code false} if from
175      *            resources
176      * @param weight The weight of the font. If 0 is given, the weight and italic will be resolved
177      *            using the OS/2 table in the font.
178      * @param isItalic Whether this font is italic. If the weight is set to 0, this will be resolved
179      *            using the OS/2 table in the font.
180      * @return
181      *
182      * This cannot be deleted because it's in use by AndroidX.
183      */
184     @UnsupportedAppUsage(trackingBug = 123768928)
addFontFromAssetManager(AssetManager mgr, String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic, FontVariationAxis[] axes)185     public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
186             boolean isAsset, int ttcIndex, int weight, int isItalic,
187             FontVariationAxis[] axes) {
188         if (mBuilderPtr == 0) {
189             throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
190         }
191         if (axes != null) {
192             for (FontVariationAxis axis : axes) {
193                 nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
194             }
195         }
196         return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
197                 isItalic);
198     }
199 
200     // TODO: Remove once internal user stop using private API.
nAddFont(long builderPtr, ByteBuffer font, int ttcIndex)201     private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
202         return nAddFont(builderPtr, font, ttcIndex, -1, -1);
203     }
204 
nInitBuilder(String langs, int variant)205     private static native long nInitBuilder(String langs, int variant);
206 
207     @CriticalNative
nCreateFamily(long mBuilderPtr)208     private static native long nCreateFamily(long mBuilderPtr);
209 
210     @CriticalNative
nGetBuilderReleaseFunc()211     private static native long nGetBuilderReleaseFunc();
212 
213     @CriticalNative
nGetFamilyReleaseFunc()214     private static native long nGetFamilyReleaseFunc();
215     // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
216     // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
nAddFont(long builderPtr, ByteBuffer font, int ttcIndex, int weight, int isItalic)217     private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
218             int weight, int isItalic);
nAddFontWeightStyle(long builderPtr, ByteBuffer font, int ttcIndex, int weight, int isItalic)219     private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
220             int ttcIndex, int weight, int isItalic);
nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic)221     private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
222             String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
223 
224     // The added axis values are only valid for the next nAddFont* method call.
225     @CriticalNative
nAddAxisValue(long builderPtr, int tag, float value)226     private static native void nAddAxisValue(long builderPtr, int tag, float value);
227 }
228