TypefaceImpl.cpp revision 1a73f732f91e97c9c66b808c245ddda36a10e987
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 "MinikinSkia.h"
36#endif
37
38#include "TypefaceImpl.h"
39#include "Utils.h"
40
41namespace android {
42
43#ifdef USE_MINIKIN
44
45// Any weight greater than or equal to this is considered "bold" for
46// legacy API.
47static const int kBoldThreshold = 6;
48
49static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
50    int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
51    bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
52    return FontStyle(weight, italic);
53}
54
55TypefaceImpl* gDefaultTypeface;
56pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
57
58// TODO: this currently builds a font collection from hardcoded paths.
59// It will get replaced by an implementation that parses the XML files.
60static FontCollection *makeFontCollection() {
61    std::vector<FontFamily *>typefaces;
62    const char *fns[] = {
63        "/system/fonts/Roboto-Regular.ttf",
64        "/system/fonts/Roboto-Italic.ttf",
65        "/system/fonts/Roboto-BoldItalic.ttf",
66        "/system/fonts/Roboto-Light.ttf",
67        "/system/fonts/Roboto-Thin.ttf",
68        "/system/fonts/Roboto-Bold.ttf",
69        "/system/fonts/Roboto-ThinItalic.ttf",
70        "/system/fonts/Roboto-LightItalic.ttf"
71    };
72
73    FontFamily *family = new FontFamily();
74    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
75        const char *fn = fns[i];
76        SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
77        MinikinFont *font = new MinikinFontSkia(skFace);
78        family->addFont(font);
79    }
80    typefaces.push_back(family);
81
82    family = new FontFamily();
83    const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf";
84    SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
85    MinikinFont *font = new MinikinFontSkia(skFace);
86    family->addFont(font);
87    typefaces.push_back(family);
88
89    return new FontCollection(typefaces);
90}
91
92static void getDefaultTypefaceOnce() {
93    Layout::init();
94    gDefaultTypeface = new TypefaceImpl;
95    gDefaultTypeface->fFontCollection = makeFontCollection();
96    gDefaultTypeface->fStyle = FontStyle();
97}
98
99TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
100    if (src == NULL) {
101        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
102        return gDefaultTypeface;
103    } else {
104        return src;
105    }
106}
107
108TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
109    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
110    TypefaceImpl* result = new TypefaceImpl;
111    if (result != 0) {
112        result->fFontCollection = resolvedFace->fFontCollection;
113        result->fStyle = styleFromSkiaStyle(style);
114    }
115    return result;
116}
117
118static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
119    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
120    std::vector<FontFamily *> typefaces;
121    FontFamily* family = new FontFamily();
122    family->addFont(minikinFont);
123    typefaces.push_back(family);
124    TypefaceImpl* result = new TypefaceImpl;
125    result->fFontCollection = new FontCollection(typefaces);
126    result->fStyle = FontStyle();  // TODO: improve
127    return result;
128}
129
130TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
131    // TODO: should create a font collection with all styles corresponding to
132    // the name
133    SkTypeface* face = SkTypeface::CreateFromName(name, style);
134    return createFromSkTypeface(face);
135}
136
137TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
138    SkTypeface* face = SkTypeface::CreateFromFile(filename);
139    return createFromSkTypeface(face);
140}
141
142TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
143    SkStream* stream = new AssetStreamAdaptor(asset,
144                                              AssetStreamAdaptor::kYes_OwnAsset,
145                                              AssetStreamAdaptor::kYes_HasMemoryBase);
146    SkTypeface* face = SkTypeface::CreateFromStream(stream);
147    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
148    // need to unref it here or it won't be freed later on
149    stream->unref();
150    return createFromSkTypeface(face);
151}
152
153TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
154    ALOGD("createFromFamilies size=%d", size);
155    std::vector<FontFamily *>familyVec;
156    for (size_t i = 0; i < size; i++) {
157        FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
158        familyVec.push_back(family);
159    }
160    TypefaceImpl* result = new TypefaceImpl;
161    result->fFontCollection = new FontCollection(familyVec);
162    result->fStyle = FontStyle();  // TODO: improve
163    return result;
164}
165
166void TypefaceImpl_unref(TypefaceImpl* face) {
167    delete face;
168}
169
170int TypefaceImpl_getStyle(TypefaceImpl* face) {
171    FontStyle style = face->fStyle;
172    int result = style.getItalic() ? SkTypeface::kItalic : 0;
173    if (style.getWeight() >= kBoldThreshold) {
174        result |= SkTypeface::kBold;
175    }
176    return result;
177}
178
179#else  // USE_MINIKIN
180
181/* Just use SkTypeface instead. */
182
183typedef SkTypeface TypefaceImpl;
184
185TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
186    return SkTypeface::CreateFromTypeface(src, style);
187}
188
189TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
190    return SkTypeface::CreateFromName(name, style);
191}
192
193TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
194    return SkTypeface::CreateFromFile(filename);
195}
196
197TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
198    SkStream* stream = new AssetStreamAdaptor(asset,
199                                              AssetStreamAdaptor::kYes_OwnAsset,
200                                              AssetStreamAdaptor::kYes_HasMemoryBase);
201    SkTypeface* face = SkTypeface::CreateFromStream(stream);
202    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
203    // need to unref it here or it won't be freed later on
204    stream->unref();
205
206    return face;
207}
208
209TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
210    // Should never be called in non-Minikin builds
211    return 0;
212}
213
214void TypefaceImpl_unref(TypefaceImpl* face) {
215    SkSafeUnref(face);
216}
217
218int TypefaceImpl_getStyle(TypefaceImpl* face) {
219    return face->style();
220}
221
222#endif  // USE_MINIKIN
223
224}
225