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