blob: a60dd7e57b464ece1480c37990d210c33a517853 [file] [log] [blame]
Raph Leviena0336302013-05-22 16:16:59 -07001/*
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
Raph Levien1a73f7322014-01-30 16:06:28 -080023#define LOG_TAG "TypefaceImpl"
24
25#include "jni.h" // for jlong, remove when being passed proper type
26
Raph Leviena0336302013-05-22 16:16:59 -070027#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"
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -050039#include "Utils.h"
Raph Leviena0336302013-05-22 16:16:59 -070040
41namespace android {
42
Raph Leviena0336302013-05-22 16:16:59 -070043#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) {
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -0500143 SkStream* stream = new AssetStreamAdaptor(asset,
144 AssetStreamAdaptor::kYes_OwnAsset,
145 AssetStreamAdaptor::kYes_HasMemoryBase);
Raph Leviena0336302013-05-22 16:16:59 -0700146 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
Raph Levien1a73f7322014-01-30 16:06:28 -0800153TypefaceImpl* 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
Raph Leviena0336302013-05-22 16:16:59 -0700166void 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) {
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -0500198 SkStream* stream = new AssetStreamAdaptor(asset,
199 AssetStreamAdaptor::kYes_OwnAsset,
200 AssetStreamAdaptor::kYes_HasMemoryBase);
Raph Leviena0336302013-05-22 16:16:59 -0700201 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
Raph Levien1a73f7322014-01-30 16:06:28 -0800209TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
210 // Should never be called in non-Minikin builds
211 return 0;
212}
213
Raph Leviena0336302013-05-22 16:16:59 -0700214void 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}