blob: c69eb32148c07d34d3ebfa14ed7a251001384d60 [file] [log] [blame]
Raph Levien1a73f7322014-01-30 16:06:28 -08001/*
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
17package android.graphics;
18
Roozbeh Pournader99975a32017-08-09 09:42:20 -070019import android.annotation.Nullable;
Raph Leviend5737942014-06-01 22:52:12 -070020import android.content.res.AssetManager;
Seigo Nonakaff551152017-03-28 16:16:41 -070021import android.graphics.fonts.FontVariationAxis;
Roozbeh Pournader99975a32017-08-09 09:42:20 -070022import android.text.TextUtils;
Raph Levien296bf8c2016-04-06 15:23:57 -070023import android.util.Log;
Siyamed Sinir46dd24a2018-02-09 12:10:34 -080024
Seigo Nonaka8b48e622017-01-07 15:33:38 +090025import dalvik.annotation.optimization.CriticalNative;
Raph Leviend5737942014-06-01 22:52:12 -070026
Seigo Nonakaabe50312018-02-20 14:49:59 -080027import libcore.util.NativeAllocationRegistry;
28
Raph Levien296bf8c2016-04-06 15:23:57 -070029import java.io.FileInputStream;
30import java.io.IOException;
Ben Wagnerfb956992016-01-28 16:05:33 -050031import java.nio.ByteBuffer;
Raph Levien296bf8c2016-04-06 15:23:57 -070032import java.nio.channels.FileChannel;
Ben Wagnera87b07d2015-11-06 11:57:09 -050033
Raph Levien1a73f7322014-01-30 16:06:28 -080034/**
35 * A family of typefaces with different styles.
36 *
37 * @hide
38 */
39public class FontFamily {
Raph Levien296bf8c2016-04-06 15:23:57 -070040
41 private static String TAG = "FontFamily";
42
Seigo Nonakaabe50312018-02-20 14:49:59 -080043 private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
44 FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
45
46 private @Nullable Runnable mNativeBuilderCleaner;
47
48 private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
49 FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
50
Raph Levien9a5b61c2014-04-29 18:26:48 -070051 /**
52 * @hide
53 */
Raph Levien1a73f7322014-01-30 16:06:28 -080054 public long mNativePtr;
Raph Levien9a5b61c2014-04-29 18:26:48 -070055
Seigo Nonaka8b48e622017-01-07 15:33:38 +090056 // Points native font family builder. Must be zero after freezing this family.
57 private long mBuilderPtr;
58
Raph Levien1a73f7322014-01-30 16:06:28 -080059 public FontFamily() {
Seigo Nonaka8b48e622017-01-07 15:33:38 +090060 mBuilderPtr = nInitBuilder(null, 0);
Seigo Nonakaabe50312018-02-20 14:49:59 -080061 mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
Raph Levienf9e3d312014-05-27 16:33:11 -070062 }
63
Roozbeh Pournader99975a32017-08-09 09:42:20 -070064 public FontFamily(@Nullable String[] langs, int variant) {
65 final String langsString;
66 if (langs == null || langs.length == 0) {
67 langsString = null;
68 } else if (langs.length == 1) {
69 langsString = langs[0];
70 } else {
71 langsString = TextUtils.join(",", langs);
72 }
73 mBuilderPtr = nInitBuilder(langsString, variant);
Seigo Nonakaabe50312018-02-20 14:49:59 -080074 mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
Seigo Nonaka8b48e622017-01-07 15:33:38 +090075 }
76
Seigo Nonaka5b6347a2017-03-31 14:30:05 -070077 /**
78 * Finalize the FontFamily creation.
79 *
80 * @return boolean returns false if some error happens in native code, e.g. broken font file is
81 * passed, etc.
82 */
83 public boolean freeze() {
Seigo Nonaka8b48e622017-01-07 15:33:38 +090084 if (mBuilderPtr == 0) {
85 throw new IllegalStateException("This FontFamily is already frozen");
Raph Levien9a5b61c2014-04-29 18:26:48 -070086 }
Seigo Nonaka8b48e622017-01-07 15:33:38 +090087 mNativePtr = nCreateFamily(mBuilderPtr);
Seigo Nonakaabe50312018-02-20 14:49:59 -080088 mNativeBuilderCleaner.run();
Seigo Nonaka8b48e622017-01-07 15:33:38 +090089 mBuilderPtr = 0;
Seigo Nonakaabe50312018-02-20 14:49:59 -080090 if (mNativePtr != 0) {
91 sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
92 }
Seigo Nonaka5b6347a2017-03-31 14:30:05 -070093 return mNativePtr != 0;
Seigo Nonaka8b48e622017-01-07 15:33:38 +090094 }
95
96 public void abortCreation() {
97 if (mBuilderPtr == 0) {
98 throw new IllegalStateException("This FontFamily is already frozen or abandoned");
99 }
Seigo Nonakaabe50312018-02-20 14:49:59 -0800100 mNativeBuilderCleaner.run();
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900101 mBuilderPtr = 0;
Raph Levien1a73f7322014-01-30 16:06:28 -0800102 }
Raph Levien15cf4752014-05-05 16:08:07 -0700103
Seigo Nonakaff551152017-03-28 16:16:41 -0700104 public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900105 int italic) {
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900106 if (mBuilderPtr == 0) {
107 throw new IllegalStateException("Unable to call addFont after freezing.");
108 }
Raph Levien296bf8c2016-04-06 15:23:57 -0700109 try (FileInputStream file = new FileInputStream(path)) {
110 FileChannel fileChannel = file.getChannel();
111 long fontSize = fileChannel.size();
112 ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900113 if (axes != null) {
Seigo Nonakaff551152017-03-28 16:16:41 -0700114 for (FontVariationAxis axis : axes) {
115 nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900116 }
117 }
118 return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
Raph Levien296bf8c2016-04-06 15:23:57 -0700119 } catch (IOException e) {
120 Log.e(TAG, "Error mapping font file " + path);
121 return false;
122 }
Raph Levien1a73f7322014-01-30 16:06:28 -0800123 }
124
Seigo Nonakaff551152017-03-28 16:16:41 -0700125 public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900126 int weight, int italic) {
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900127 if (mBuilderPtr == 0) {
128 throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
129 }
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900130 if (axes != null) {
Seigo Nonakaff551152017-03-28 16:16:41 -0700131 for (FontVariationAxis axis : axes) {
132 nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900133 }
Seigo Nonakaac873c92017-03-07 15:34:53 -0800134 }
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900135 return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
Raph Levien117cbeb2014-08-25 13:47:16 -0700136 }
137
Clara Bayarrib44abf22017-02-16 14:19:19 +0000138 /**
139 * @param mgr The AssetManager to use for this context.
140 * @param path The path to the font file to load.
141 * @param cookie If available, the resource cookie given by Resources.
142 * @param isAsset {@code true} if this is from the assets/ folder, {@code false} if from
143 * resources
144 * @param weight The weight of the font. If 0 is given, the weight and italic will be resolved
145 * using the OS/2 table in the font.
146 * @param isItalic Whether this font is italic. If the weight is set to 0, this will be resolved
147 * using the OS/2 table in the font.
148 * @return
149 */
Clara Bayarri18e9f9f2016-12-19 16:20:29 +0000150 public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900151 boolean isAsset, int ttcIndex, int weight, int isItalic,
Seigo Nonakaff551152017-03-28 16:16:41 -0700152 FontVariationAxis[] axes) {
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900153 if (mBuilderPtr == 0) {
154 throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
155 }
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900156 if (axes != null) {
Seigo Nonakaff551152017-03-28 16:16:41 -0700157 for (FontVariationAxis axis : axes) {
158 nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900159 }
160 }
161 return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
162 isItalic);
Raph Leviend5737942014-06-01 22:52:12 -0700163 }
164
Seigo Nonaka2660aca2017-03-22 09:14:33 -0700165 // TODO: Remove once internal user stop using private API.
166 private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
167 return nAddFont(builderPtr, font, ttcIndex, -1, -1);
168 }
169
Roozbeh Pournader99975a32017-08-09 09:42:20 -0700170 private static native long nInitBuilder(String langs, int variant);
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900171
172 @CriticalNative
173 private static native long nCreateFamily(long mBuilderPtr);
174
175 @CriticalNative
Seigo Nonakaabe50312018-02-20 14:49:59 -0800176 private static native long nGetBuilderReleaseFunc();
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900177
178 @CriticalNative
Seigo Nonakaabe50312018-02-20 14:49:59 -0800179 private static native long nGetFamilyReleaseFunc();
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900180 // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
181 // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
182 private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
183 int weight, int isItalic);
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900184 private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900185 int ttcIndex, int weight, int isItalic);
Seigo Nonaka8b48e622017-01-07 15:33:38 +0900186 private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
Seigo Nonaka20e5d912017-01-18 20:31:27 +0900187 String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
Seigo Nonakaac873c92017-03-07 15:34:53 -0800188
189 // The added axis values are only valid for the next nAddFont* method call.
190 @CriticalNative
191 private static native void nAddAxisValue(long builderPtr, int tag, float value);
Raph Levien1a73f7322014-01-30 16:06:28 -0800192}