1/*
2 * Copyright (C) 2006 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
19import android.content.res.AssetManager;
20import android.util.SparseArray;
21
22import java.io.File;
23
24/**
25 * The Typeface class specifies the typeface and intrinsic style of a font.
26 * This is used in the paint, along with optionally Paint settings like
27 * textSize, textSkewX, textScaleX to specify
28 * how text appears when drawn (and measured).
29 */
30public class Typeface {
31
32    /** The default NORMAL typeface object */
33    public static final Typeface DEFAULT;
34    /**
35     * The default BOLD typeface object. Note: this may be not actually be
36     * bold, depending on what fonts are installed. Call getStyle() to know
37     * for sure.
38     */
39    public static final Typeface DEFAULT_BOLD;
40    /** The NORMAL style of the default sans serif typeface. */
41    public static final Typeface SANS_SERIF;
42    /** The NORMAL style of the default serif typeface. */
43    public static final Typeface SERIF;
44    /** The NORMAL style of the default monospace typeface. */
45    public static final Typeface MONOSPACE;
46
47    static Typeface[] sDefaults;
48    private static final SparseArray<SparseArray<Typeface>> sTypefaceCache =
49            new SparseArray<SparseArray<Typeface>>(3);
50
51    int native_instance;
52
53    // Style
54    public static final int NORMAL = 0;
55    public static final int BOLD = 1;
56    public static final int ITALIC = 2;
57    public static final int BOLD_ITALIC = 3;
58
59    private int mStyle = 0;
60
61    /** Returns the typeface's intrinsic style attributes */
62    public int getStyle() {
63        return mStyle;
64    }
65
66    /** Returns true if getStyle() has the BOLD bit set. */
67    public final boolean isBold() {
68        return (mStyle & BOLD) != 0;
69    }
70
71    /** Returns true if getStyle() has the ITALIC bit set. */
72    public final boolean isItalic() {
73        return (mStyle & ITALIC) != 0;
74    }
75
76    /**
77     * Create a typeface object given a family name, and option style information.
78     * If null is passed for the name, then the "default" font will be chosen.
79     * The resulting typeface object can be queried (getStyle()) to discover what
80     * its "real" style characteristics are.
81     *
82     * @param familyName May be null. The name of the font family.
83     * @param style  The style (normal, bold, italic) of the typeface.
84     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
85     * @return The best matching typeface.
86     */
87    public static Typeface create(String familyName, int style) {
88        return new Typeface(nativeCreate(familyName, style));
89    }
90
91    /**
92     * Create a typeface object that best matches the specified existing
93     * typeface and the specified Style. Use this call if you want to pick a new
94     * style from the same family of an existing typeface object. If family is
95     * null, this selects from the default font's family.
96     *
97     * @param family May be null. The name of the existing type face.
98     * @param style  The style (normal, bold, italic) of the typeface.
99     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
100     * @return The best matching typeface.
101     */
102    public static Typeface create(Typeface family, int style) {
103        int ni = 0;
104        if (family != null) {
105            // Return early if we're asked for the same face/style
106            if (family.mStyle == style) {
107                return family;
108            }
109
110            ni = family.native_instance;
111        }
112
113        Typeface typeface;
114        SparseArray<Typeface> styles = sTypefaceCache.get(ni);
115
116        if (styles != null) {
117            typeface = styles.get(style);
118            if (typeface != null) {
119                return typeface;
120            }
121        }
122
123        typeface = new Typeface(nativeCreateFromTypeface(ni, style));
124        if (styles == null) {
125            styles = new SparseArray<Typeface>(4);
126            sTypefaceCache.put(ni, styles);
127        }
128        styles.put(style, typeface);
129
130        return typeface;
131    }
132
133    /**
134     * Returns one of the default typeface objects, based on the specified style
135     *
136     * @return the default typeface that corresponds to the style
137     */
138    public static Typeface defaultFromStyle(int style) {
139        return sDefaults[style];
140    }
141
142    /**
143     * Create a new typeface from the specified font data.
144     * @param mgr The application's asset manager
145     * @param path  The file name of the font data in the assets directory
146     * @return The new typeface.
147     */
148    public static Typeface createFromAsset(AssetManager mgr, String path) {
149        return new Typeface(nativeCreateFromAsset(mgr, path));
150    }
151
152    /**
153     * Create a new typeface from the specified font file.
154     *
155     * @param path The path to the font data.
156     * @return The new typeface.
157     */
158    public static Typeface createFromFile(File path) {
159        return new Typeface(nativeCreateFromFile(path.getAbsolutePath()));
160    }
161
162    /**
163     * Create a new typeface from the specified font file.
164     *
165     * @param path The full path to the font data.
166     * @return The new typeface.
167     */
168    public static Typeface createFromFile(String path) {
169        return new Typeface(nativeCreateFromFile(path));
170    }
171
172    // don't allow clients to call this directly
173    private Typeface(int ni) {
174        if (ni == 0) {
175            throw new RuntimeException("native typeface cannot be made");
176        }
177
178        native_instance = ni;
179        mStyle = nativeGetStyle(ni);
180    }
181
182    static {
183        DEFAULT         = create((String) null, 0);
184        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
185        SANS_SERIF      = create("sans-serif", 0);
186        SERIF           = create("serif", 0);
187        MONOSPACE       = create("monospace", 0);
188
189        sDefaults = new Typeface[] {
190            DEFAULT,
191            DEFAULT_BOLD,
192            create((String) null, Typeface.ITALIC),
193            create((String) null, Typeface.BOLD_ITALIC),
194        };
195    }
196
197    protected void finalize() throws Throwable {
198        try {
199            nativeUnref(native_instance);
200        } finally {
201            super.finalize();
202        }
203    }
204
205    @Override
206    public boolean equals(Object o) {
207        if (this == o) return true;
208        if (o == null || getClass() != o.getClass()) return false;
209
210        Typeface typeface = (Typeface) o;
211
212        return mStyle == typeface.mStyle && native_instance == typeface.native_instance;
213    }
214
215    @Override
216    public int hashCode() {
217        int result = native_instance;
218        result = 31 * result + mStyle;
219        return result;
220    }
221
222    private static native int  nativeCreate(String familyName, int style);
223    private static native int  nativeCreateFromTypeface(int native_instance, int style);
224    private static native void nativeUnref(int native_instance);
225    private static native int  nativeGetStyle(int native_instance);
226    private static native int  nativeCreateFromAsset(AssetManager mgr, String path);
227    private static native int nativeCreateFromFile(String path);
228
229    /**
230     * Set the global gamma coefficients for black and white text. This call is
231     * usually a no-op in shipping products, and only exists for testing during
232     * development.
233     *
234     * @param blackGamma gamma coefficient for black text
235     * @param whiteGamma gamma coefficient for white text
236     *
237     * @hide - this is just for calibrating devices, not for normal apps
238     */
239    public static native void setGammaForText(float blackGamma, float whiteGamma);
240}
241