FontFamily.java revision 2660aca4912b4bd890c5c76688f67f1898dc7b97
11a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien/*
21a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Copyright (C) 2014 The Android Open Source Project
31a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
41a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Licensed under the Apache License, Version 2.0 (the "License");
51a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * you may not use this file except in compliance with the License.
61a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * You may obtain a copy of the License at
71a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
81a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *      http://www.apache.org/licenses/LICENSE-2.0
91a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
101a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Unless required by applicable law or agreed to in writing, software
111a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * distributed under the License is distributed on an "AS IS" BASIS,
121a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * See the License for the specific language governing permissions and
141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * limitations under the License.
151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */
161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
171a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienpackage android.graphics;
181a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
19d573794d83a049fe59e289944f0cd77406dd776aRaph Levienimport android.content.res.AssetManager;
2004d72abde1efc963ebb2f145f859552e83b92d13Clara Bayarriimport android.text.FontConfig;
21296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienimport android.util.Log;
228b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonakaimport dalvik.annotation.optimization.CriticalNative;
23d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
24296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienimport java.io.FileInputStream;
25296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienimport java.io.IOException;
26fb95699364e555148b437cfa1e5c69384f843845Ben Wagnerimport java.nio.ByteBuffer;
27296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienimport java.nio.channels.FileChannel;
28a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner
291a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien/**
301a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * A family of typefaces with different styles.
311a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
321a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * @hide
331a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */
341a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienpublic class FontFamily {
35296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien
36296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    private static String TAG = "FontFamily";
37296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien
389a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    /**
399a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien     * @hide
409a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien     */
411a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    public long mNativePtr;
429a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
438b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    // Points native font family builder. Must be zero after freezing this family.
448b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private long mBuilderPtr;
458b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
461a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    public FontFamily() {
478b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        mBuilderPtr = nInitBuilder(null, 0);
48f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    }
49f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien
50ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka    public FontFamily(String lang, int variant) {
51ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka        mBuilderPtr = nInitBuilder(lang, variant);
528b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    }
538b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
548b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    public void freeze() {
558b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        if (mBuilderPtr == 0) {
568b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            throw new IllegalStateException("This FontFamily is already frozen");
578b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        }
588b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        mNativePtr = nCreateFamily(mBuilderPtr);
598b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        mBuilderPtr = 0;
608b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    }
618b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
628b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    public void abortCreation() {
638b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        if (mBuilderPtr == 0) {
648b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            throw new IllegalStateException("This FontFamily is already frozen or abandoned");
659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
668b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        nAbort(mBuilderPtr);
678b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        mBuilderPtr = 0;
681a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    }
6915cf4757dc0099301662f8a26da561434cc07cfaRaph Levien
7015cf4757dc0099301662f8a26da561434cc07cfaRaph Levien    @Override
7115cf4757dc0099301662f8a26da561434cc07cfaRaph Levien    protected void finalize() throws Throwable {
7215cf4757dc0099301662f8a26da561434cc07cfaRaph Levien        try {
738b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            if (mNativePtr != 0) {
748b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka                nUnrefFamily(mNativePtr);
758b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            }
768b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            if (mBuilderPtr != 0) {
778b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka                nAbort(mBuilderPtr);
788b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            }
7915cf4757dc0099301662f8a26da561434cc07cfaRaph Levien        } finally {
8015cf4757dc0099301662f8a26da561434cc07cfaRaph Levien            super.finalize();
8115cf4757dc0099301662f8a26da561434cc07cfaRaph Levien        }
8215cf4757dc0099301662f8a26da561434cc07cfaRaph Levien    }
831a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
8420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    public boolean addFont(String path, int ttcIndex, FontConfig.Axis[] axes, int weight,
8520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            int italic) {
868b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        if (mBuilderPtr == 0) {
878b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            throw new IllegalStateException("Unable to call addFont after freezing.");
888b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        }
89296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        try (FileInputStream file = new FileInputStream(path)) {
90296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien            FileChannel fileChannel = file.getChannel();
91296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien            long fontSize = fileChannel.size();
92296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien            ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
9320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            if (axes != null) {
9420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                for (FontConfig.Axis axis : axes) {
9520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
9620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                }
9720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
9820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
99296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        } catch (IOException e) {
100296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien            Log.e(TAG, "Error mapping font file " + path);
101296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien            return false;
102296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        }
103d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    }
104d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
10520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontConfig.Axis[] axes,
10620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            int weight, int italic) {
1078b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        if (mBuilderPtr == 0) {
1088b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
1098b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        }
11020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        if (axes != null) {
11120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            for (FontConfig.Axis axis : axes) {
11220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
11320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
114ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka        }
11520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
116117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    }
117117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien
118b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri    /**
119b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param mgr The AssetManager to use for this context.
120b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param path The path to the font file to load.
121b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param cookie If available, the resource cookie given by Resources.
122b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param isAsset {@code true} if this is from the assets/ folder, {@code false} if from
123b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     *            resources
124b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param weight The weight of the font. If 0 is given, the weight and italic will be resolved
125b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     *            using the OS/2 table in the font.
126b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @param isItalic Whether this font is italic. If the weight is set to 0, this will be resolved
127b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     *            using the OS/2 table in the font.
128b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     * @return
129b44abf290190ceee037f24c47493a34de45fa3f4Clara Bayarri     */
13018e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
13120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            boolean isAsset, int ttcIndex, int weight, int isItalic,
13220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            FontConfig.Axis[] axes) {
1338b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        if (mBuilderPtr == 0) {
1348b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka            throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
1358b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka        }
13620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        if (axes != null) {
13720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            for (FontConfig.Axis axis : axes) {
13820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
13920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
14020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
14120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
14220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                isItalic);
1431a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    }
1441a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
1452660aca4912b4bd890c5c76688f67f1898dc7b97Seigo Nonaka    // TODO: Remove once internal user stop using private API.
1462660aca4912b4bd890c5c76688f67f1898dc7b97Seigo Nonaka    private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
1472660aca4912b4bd890c5c76688f67f1898dc7b97Seigo Nonaka        return nAddFont(builderPtr, font, ttcIndex, -1, -1);
1482660aca4912b4bd890c5c76688f67f1898dc7b97Seigo Nonaka    }
1492660aca4912b4bd890c5c76688f67f1898dc7b97Seigo Nonaka
1508b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private static native long nInitBuilder(String lang, int variant);
1518b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
1528b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    @CriticalNative
1538b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private static native long nCreateFamily(long mBuilderPtr);
1548b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
1558b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    @CriticalNative
1568b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private static native void nAbort(long mBuilderPtr);
1578b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka
1588b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    @CriticalNative
159d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    private static native void nUnrefFamily(long nativePtr);
16020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
16120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
16220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
16320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            int weight, int isItalic);
1648b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
16520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            int ttcIndex, int weight, int isItalic);
1668b48e624457e438fcc2b6b9363329036ef2f7743Seigo Nonaka    private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
16720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
168ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka
169ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka    // The added axis values are only valid for the next nAddFont* method call.
170ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka    @CriticalNative
171ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka    private static native void nAddAxisValue(long builderPtr, int tag, float value);
1721a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
173