TypefaceImpl.cpp revision e95b5850ac2e56330abf68362451e7614b3dfe16
1/*
2 * Copyright (C) 2013 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/**
18 * This is the implementation of the Typeface object. Historically, it has
19 * just been SkTypeface, but we are migrating to Minikin. For the time
20 * being, that choice is hidden under the USE_MINIKIN compile-time flag.
21 */
22
23#define LOG_TAG "TypefaceImpl"
24
25#include "jni.h"  // for jlong, remove when being passed proper type
26
27#include "SkStream.h"
28#include "SkTypeface.h"
29
30#ifdef USE_MINIKIN
31#include <vector>
32#include <minikin/FontCollection.h>
33#include <minikin/FontFamily.h>
34#include <minikin/Layout.h>
35#include "SkPaint.h"
36#include "MinikinSkia.h"
37#endif
38
39#include "TypefaceImpl.h"
40#include "Utils.h"
41
42namespace android {
43
44#ifdef USE_MINIKIN
45
46// Any weight greater than or equal to this is considered "bold" for
47// legacy API.
48static const int kBoldThreshold = 6;
49
50static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
51    int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
52    bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
53    return FontStyle(weight, italic);
54}
55
56TypefaceImpl* gDefaultTypeface = NULL;
57pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
58
59// This installs a default typeface (from a hardcoded path) that allows
60// layouts to work (not crash on null pointer) before the default
61// typeface is set.
62// TODO: investigate why layouts are being created before Typeface.java
63// class initialization.
64static FontCollection *makeFontCollection() {
65    std::vector<FontFamily *>typefaces;
66    const char *fns[] = {
67        "/system/fonts/Roboto-Regular.ttf",
68    };
69
70    FontFamily *family = new FontFamily();
71    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
72        const char *fn = fns[i];
73        ALOGD("makeFontCollection adding %s", fn);
74        SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
75        if (skFace != NULL) {
76            MinikinFont *font = new MinikinFontSkia(skFace);
77            family->addFont(font);
78            font->Unref();
79        } else {
80            ALOGE("failed to create font %s", fn);
81        }
82    }
83    typefaces.push_back(family);
84
85    FontCollection *result = new FontCollection(typefaces);
86    family->Unref();
87    return result;
88}
89
90static void getDefaultTypefaceOnce() {
91    Layout::init();
92    if (gDefaultTypeface == NULL) {
93        // We expect the client to set a default typeface, but provide a
94        // default so we can make progress before that happens.
95        gDefaultTypeface = new TypefaceImpl;
96        gDefaultTypeface->fFontCollection = makeFontCollection();
97        gDefaultTypeface->fStyle = FontStyle();
98    }
99}
100
101TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
102    if (src == NULL) {
103        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
104        return gDefaultTypeface;
105    } else {
106        return src;
107    }
108}
109
110TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
111    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
112    TypefaceImpl* result = new TypefaceImpl;
113    if (result != 0) {
114        result->fFontCollection = resolvedFace->fFontCollection;
115        result->fFontCollection->Ref();
116        result->fStyle = styleFromSkiaStyle(style);
117    }
118    return result;
119}
120
121static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
122    if (typeface == NULL) {
123        return NULL;
124    }
125    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
126    std::vector<FontFamily *> typefaces;
127    FontFamily* family = new FontFamily();
128    family->addFont(minikinFont);
129    minikinFont->Unref();
130    typefaces.push_back(family);
131    TypefaceImpl* result = new TypefaceImpl;
132    result->fFontCollection = new FontCollection(typefaces);
133    family->Unref();
134    result->fStyle = FontStyle();  // TODO: improve
135    return result;
136}
137
138TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
139    // TODO: should create a font collection with all styles corresponding to
140    // the name
141    SkTypeface* face = SkTypeface::CreateFromName(name, style);
142    return createFromSkTypeface(face);
143}
144
145TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
146    SkTypeface* face = SkTypeface::CreateFromFile(filename);
147    return createFromSkTypeface(face);
148}
149
150TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
151    SkStream* stream = new AssetStreamAdaptor(asset,
152                                              AssetStreamAdaptor::kYes_OwnAsset,
153                                              AssetStreamAdaptor::kYes_HasMemoryBase);
154    SkTypeface* face = SkTypeface::CreateFromStream(stream);
155    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
156    // need to unref it here or it won't be freed later on
157    stream->unref();
158    return createFromSkTypeface(face);
159}
160
161TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
162    ALOGD("createFromFamilies size=%d", size);
163    std::vector<FontFamily *>familyVec;
164    for (size_t i = 0; i < size; i++) {
165        FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
166        familyVec.push_back(family);
167    }
168    TypefaceImpl* result = new TypefaceImpl;
169    result->fFontCollection = new FontCollection(familyVec);
170    result->fStyle = FontStyle();  // TODO: improve
171    return result;
172}
173
174void TypefaceImpl_unref(TypefaceImpl* face) {
175    if (face != NULL) {
176        face->fFontCollection->Unref();
177    }
178    delete face;
179}
180
181int TypefaceImpl_getStyle(TypefaceImpl* face) {
182    FontStyle style = face->fStyle;
183    int result = style.getItalic() ? SkTypeface::kItalic : 0;
184    if (style.getWeight() >= kBoldThreshold) {
185        result |= SkTypeface::kBold;
186    }
187    return result;
188}
189
190void TypefaceImpl_setDefault(TypefaceImpl* face) {
191    gDefaultTypeface = face;
192}
193
194#else  // USE_MINIKIN
195
196/* Just use SkTypeface instead. */
197
198typedef SkTypeface TypefaceImpl;
199
200TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
201    return SkTypeface::CreateFromTypeface(src, style);
202}
203
204TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
205    return SkTypeface::CreateFromName(name, style);
206}
207
208TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
209    return SkTypeface::CreateFromFile(filename);
210}
211
212TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
213    SkStream* stream = new AssetStreamAdaptor(asset,
214                                              AssetStreamAdaptor::kYes_OwnAsset,
215                                              AssetStreamAdaptor::kYes_HasMemoryBase);
216    SkTypeface* face = SkTypeface::CreateFromStream(stream);
217    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
218    // need to unref it here or it won't be freed later on
219    stream->unref();
220
221    return face;
222}
223
224TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
225    // Should never be called in non-Minikin builds
226    return 0;
227}
228
229void TypefaceImpl_unref(TypefaceImpl* face) {
230    SkSafeUnref(face);
231}
232
233int TypefaceImpl_getStyle(TypefaceImpl* face) {
234    return face->style();
235}
236
237void TypefaceImpl_setDefault(TypefaceImpl* face) {
238}
239
240#endif  // USE_MINIKIN
241
242}
243