• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.content.res.AssetManager;
21  import android.graphics.fonts.FontVariationAxis;
22  import android.text.TextUtils;
23  import android.util.Log;
24  
25  import dalvik.annotation.optimization.CriticalNative;
26  
27  import libcore.util.NativeAllocationRegistry;
28  
29  import java.io.FileInputStream;
30  import java.io.IOException;
31  import java.nio.ByteBuffer;
32  import java.nio.channels.FileChannel;
33  
34  /**
35   * A family of typefaces with different styles.
36   *
37   * @hide
38   */
39  public class FontFamily {
40  
41      private static String TAG = "FontFamily";
42  
43      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  
51      /**
52       * @hide
53       */
54      public long mNativePtr;
55  
56      // Points native font family builder. Must be zero after freezing this family.
57      private long mBuilderPtr;
58  
FontFamily()59      public FontFamily() {
60          mBuilderPtr = nInitBuilder(null, 0);
61          mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
62      }
63  
FontFamily(@ullable String[] langs, int variant)64      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);
74          mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
75      }
76  
77      /**
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       */
freeze()83      public boolean freeze() {
84          if (mBuilderPtr == 0) {
85              throw new IllegalStateException("This FontFamily is already frozen");
86          }
87          mNativePtr = nCreateFamily(mBuilderPtr);
88          mNativeBuilderCleaner.run();
89          mBuilderPtr = 0;
90          if (mNativePtr != 0) {
91              sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
92          }
93          return mNativePtr != 0;
94      }
95  
abortCreation()96      public void abortCreation() {
97          if (mBuilderPtr == 0) {
98              throw new IllegalStateException("This FontFamily is already frozen or abandoned");
99          }
100          mNativeBuilderCleaner.run();
101          mBuilderPtr = 0;
102      }
103  
addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight, int italic)104      public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
105              int italic) {
106          if (mBuilderPtr == 0) {
107              throw new IllegalStateException("Unable to call addFont after freezing.");
108          }
109          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);
113              if (axes != null) {
114                  for (FontVariationAxis axis : axes) {
115                      nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
116                  }
117              }
118              return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
119          } catch (IOException e) {
120              Log.e(TAG, "Error mapping font file " + path);
121              return false;
122          }
123      }
124  
addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes, int weight, int italic)125      public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
126              int weight, int italic) {
127          if (mBuilderPtr == 0) {
128              throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
129          }
130          if (axes != null) {
131              for (FontVariationAxis axis : axes) {
132                  nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
133              }
134          }
135          return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
136      }
137  
138      /**
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       */
addFontFromAssetManager(AssetManager mgr, String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic, FontVariationAxis[] axes)150      public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
151              boolean isAsset, int ttcIndex, int weight, int isItalic,
152              FontVariationAxis[] axes) {
153          if (mBuilderPtr == 0) {
154              throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
155          }
156          if (axes != null) {
157              for (FontVariationAxis axis : axes) {
158                  nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
159              }
160          }
161          return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
162                  isItalic);
163      }
164  
165      // TODO: Remove once internal user stop using private API.
nAddFont(long builderPtr, ByteBuffer font, int ttcIndex)166      private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
167          return nAddFont(builderPtr, font, ttcIndex, -1, -1);
168      }
169  
nInitBuilder(String langs, int variant)170      private static native long nInitBuilder(String langs, int variant);
171  
172      @CriticalNative
nCreateFamily(long mBuilderPtr)173      private static native long nCreateFamily(long mBuilderPtr);
174  
175      @CriticalNative
nGetBuilderReleaseFunc()176      private static native long nGetBuilderReleaseFunc();
177  
178      @CriticalNative
nGetFamilyReleaseFunc()179      private static native long nGetFamilyReleaseFunc();
180      // 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.
nAddFont(long builderPtr, ByteBuffer font, int ttcIndex, int weight, int isItalic)182      private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
183              int weight, int isItalic);
nAddFontWeightStyle(long builderPtr, ByteBuffer font, int ttcIndex, int weight, int isItalic)184      private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
185              int ttcIndex, int weight, int isItalic);
nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic)186      private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
187              String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
188  
189      // The added axis values are only valid for the next nAddFont* method call.
190      @CriticalNative
nAddAxisValue(long builderPtr, int tag, float value)191      private static native void nAddAxisValue(long builderPtr, int tag, float value);
192  }
193