blob: 1facb537096b53d7c50b7f4e7bcf51d732a8ed5d [file] [log] [blame]
bungeman8d84c992014-07-24 08:05:09 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkFontConfigParser_android.h"
9#include "SkFontDescriptor.h"
10#include "SkFontHost_FreeType_common.h"
11#include "SkFontMgr.h"
12#include "SkFontStyle.h"
13#include "SkStream.h"
14#include "SkTDArray.h"
15#include "SkTSearch.h"
16#include "SkTypeface.h"
17#include "SkTypefaceCache.h"
18
19#include <limits>
20#include <stdlib.h>
21
22#ifndef SK_FONT_FILE_PREFIX
23# define SK_FONT_FILE_PREFIX "/fonts/"
24#endif
25
26#ifndef SK_DEBUG_FONTS
27 #define SK_DEBUG_FONTS 0
28#endif
29
30#if SK_DEBUG_FONTS
31# define DEBUG_FONT(args) SkDebugf args
32#else
33# define DEBUG_FONT(args)
34#endif
35
36class SkTypeface_Android : public SkTypeface_FreeType {
37public:
38 SkTypeface_Android(int index,
39 Style style,
40 bool isFixedPitch,
41 const SkString familyName)
42 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
43 , fIndex(index)
tomhudson3a914242014-07-29 06:52:38 -070044 , fFamilyName(familyName) { }
bungeman8d84c992014-07-24 08:05:09 -070045
46 const SkString& name() const { return fFamilyName; }
47
48protected:
49 int fIndex;
50 SkString fFamilyName;
51
52private:
53 typedef SkTypeface_FreeType INHERITED;
54};
55
56class SkTypeface_AndroidSystem : public SkTypeface_Android {
57public:
58 SkTypeface_AndroidSystem(const SkString pathName,
59 int index,
60 Style style,
61 bool isFixedPitch,
62 const SkString familyName)
63 : INHERITED(index, style, isFixedPitch, familyName)
tomhudson3a914242014-07-29 06:52:38 -070064 , fPathName(pathName) { }
bungeman8d84c992014-07-24 08:05:09 -070065
66 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
tomhudson3a914242014-07-29 06:52:38 -070067 bool* serialize) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -070068 SkASSERT(desc);
69 SkASSERT(serialize);
70 desc->setFamilyName(fFamilyName.c_str());
71 desc->setFontFileName(fPathName.c_str());
72 *serialize = false;
73 }
74 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
75 *ttcIndex = fIndex;
76 return SkStream::NewFromFile(fPathName.c_str());
77 }
78
79private:
80 SkString fPathName;
81
82 typedef SkTypeface_Android INHERITED;
83};
84
85class SkTypeface_AndroidStream : public SkTypeface_Android {
86public:
87 SkTypeface_AndroidStream(SkStream* stream,
88 int index,
89 Style style,
90 bool isFixedPitch,
91 const SkString familyName)
92 : INHERITED(index, style, isFixedPitch, familyName)
tomhudson3a914242014-07-29 06:52:38 -070093 , fStream(stream) { }
bungeman8d84c992014-07-24 08:05:09 -070094
95 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
96 bool* serialize) const SK_OVERRIDE {
97 SkASSERT(desc);
98 SkASSERT(serialize);
99 desc->setFamilyName(fFamilyName.c_str());
100 desc->setFontFileName(NULL);
101 *serialize = true;
102 }
103
104 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
105 *ttcIndex = fIndex;
106 return fStream->duplicate();
107 }
108
109private:
110 SkAutoTUnref<SkStream> fStream;
111
112 typedef SkTypeface_Android INHERITED;
113};
114
115void get_path_for_sys_fonts(SkString* full, const SkString& name) {
116 full->set(getenv("ANDROID_ROOT"));
117 full->append(SK_FONT_FILE_PREFIX);
118 full->append(name);
119}
120
121class SkFontStyleSet_Android : public SkFontStyleSet {
122public:
123 explicit SkFontStyleSet_Android(FontFamily* family) : fFontFamily(family) {
124 // TODO? make this lazy
125 for (int i = 0; i < family->fFontFiles.count(); ++i) {
126 const SkString& fileName = family->fFontFiles[i].fFileName;
127
128 SkString pathName;
129 get_path_for_sys_fonts(&pathName, fileName);
130
131 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
132 if (!stream.get()) {
tomhudson3a914242014-07-29 06:52:38 -0700133 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, fileName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700134 continue;
135 }
136
137 SkString fontName;
138 SkTypeface::Style style;
139 bool isFixedWidth;
140 if (!SkTypeface_FreeType::ScanFont(stream.get(), family->fFontFiles[i].fIndex,
tomhudson3a914242014-07-29 06:52:38 -0700141 &fontName, &style, &isFixedWidth)) {
142 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, fileName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700143 continue;
144 }
145
146 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
147 (pathName, 0,
148 style, isFixedWidth, fontName)));
149 }
150 }
151
152 virtual int count() SK_OVERRIDE {
153 return fStyles.count();
154 }
155 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
156 if (index < 0 || fStyles.count() <= index) {
157 return;
158 }
159 if (style) {
160 *style = this->style(index);
161 }
162 if (name) {
163 name->reset();
164 }
165 }
166 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
167 if (index < 0 || fStyles.count() <= index) {
168 return NULL;
169 }
170 return SkRef(fStyles[index].get());
171 }
172
173 /** Find the typeface in this style set that most closely matches the given pattern.
174 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
175 * this simpler version using match_score() passes all our tests.
176 */
177 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
178 if (0 == fStyles.count()) {
179 return NULL;
180 }
181 SkTypeface* closest = fStyles[0];
182 int minScore = std::numeric_limits<int>::max();
183 for (int i = 0; i < fStyles.count(); ++i) {
184 SkFontStyle style = this->style(i);
185 int score = match_score(pattern, style);
186 if (score < minScore) {
187 closest = fStyles[i];
188 minScore = score;
189 }
190 }
191 return SkRef(closest);
192 }
193
194private:
195 SkFontStyle style(int index) {
196 return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width,
197 this->slant(index));
198 }
199 SkFontStyle::Weight weight(int index) {
200 if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight;
201 return SkFontStyle::kNormal_Weight;
202 }
203 SkFontStyle::Slant slant(int index) {
204 if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant;
205 return SkFontStyle::kUpright_Slant;
206 }
207 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
208 int score = 0;
209 score += abs((pattern.width() - candidate.width()) * 100);
210 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
211 score += abs(pattern.weight() - candidate.weight());
212 return score;
213 }
214
215
216 FontFamily* fFontFamily;
217 SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles;
218
219 friend struct NameToFamily;
220 friend class SkFontMgr_Android;
221
222 typedef SkFontStyleSet INHERITED;
223};
224
225/** On Android a single family can have many names, but our API assumes unique names.
226 * Map names to the back end so that all names for a given family refer to the same
227 * (non-replicated) set of typefaces.
228 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
229 */
230struct NameToFamily {
231 SkString name;
232 SkFontStyleSet_Android* styleSet;
233};
234
235class SkFontMgr_Android : public SkFontMgr {
236public:
237 SkFontMgr_Android() {
238 SkTDArray<FontFamily*> fontFamilies;
239 SkFontConfigParser::GetFontFamilies(fontFamilies);
240 this->buildNameToFamilyMap(fontFamilies);
241 this->findDefaultFont();
242 }
243
244protected:
245 /** Returns not how many families we have, but how many unique names
246 * exist among the families.
247 */
248 virtual int onCountFamilies() const SK_OVERRIDE {
249 return fNameToFamilyMap.count();
250 }
251
252 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
253 if (index < 0 || fNameToFamilyMap.count() <= index) {
254 familyName->reset();
255 return;
256 }
257 familyName->set(fNameToFamilyMap[index].name);
258 }
259
260 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
261 if (index < 0 || fNameToFamilyMap.count() <= index) {
262 return NULL;
263 }
264 return SkRef(fNameToFamilyMap[index].styleSet);
265 }
266
267 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
268 if (!familyName) {
269 return NULL;
270 }
271 SkAutoAsciiToLC tolc(familyName);
272 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
273 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
274 return SkRef(fNameToFamilyMap[i].styleSet);
275 }
276 }
277 return NULL;
278 }
279
280 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
281 const SkFontStyle& style) const SK_OVERRIDE {
282 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
283 return sset->matchStyle(style);
284 }
285
286 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
287 const SkFontStyle& style) const SK_OVERRIDE {
288 for (int i = 0; i < fFontStyleSets.count(); ++i) {
289 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
290 if (fFontStyleSets[i]->fStyles[j] == typeface) {
291 return fFontStyleSets[i]->matchStyle(style);
292 }
293 }
294 }
295 return NULL;
296 }
297
298 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
299 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
300 return this->createFromStream(stream, ttcIndex);
301 }
302
303 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
304 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
305 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
306 }
307
308 virtual SkTypeface* onCreateFromStream(SkStream* s, int ttcIndex) const SK_OVERRIDE {
309 SkAutoTUnref<SkStream> stream(s);
310
311 bool isFixedPitch;
312 SkTypeface::Style style;
313 SkString name;
314 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
315 return NULL;
316 }
317 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream.detach(), ttcIndex,
318 style, isFixedPitch, name));
319 }
320
321
322 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
323 unsigned styleBits) const SK_OVERRIDE {
324 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
325 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
326 ? SkFontStyle::kBold_Weight
327 : SkFontStyle::kNormal_Weight,
328 SkFontStyle::kNormal_Width,
329 oldStyle & SkTypeface::kItalic
330 ? SkFontStyle::kItalic_Slant
331 : SkFontStyle::kUpright_Slant);
332 SkTypeface* tf = NULL;
333
334 if (NULL != familyName) {
335 // On Android, we must return NULL when we can't find the requested
336 // named typeface so that the system/app can provide their own recovery
337 // mechanism. On other platforms we'd provide a typeface from the
338 // default family instead.
339 tf = this->onMatchFamilyStyle(familyName, style);
340 } else {
341 tf = fDefaultFamily->matchStyle(style);
342 }
343
344 // TODO: double ref? qv matchStyle()
345 return SkSafeRef(tf);
346 }
347
348
349private:
350
351 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
352 SkFontStyleSet* fDefaultFamily;
353 SkTypeface* fDefaultTypeface;
354
355 SkTDArray<NameToFamily> fNameToFamilyMap;
356
357 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
358 for (int i = 0; i < families.count(); i++) {
359 fFontStyleSets.push_back().reset(
360 SkNEW_ARGS(SkFontStyleSet_Android, (families[i])));
361 for (int j = 0; j < families[i]->fNames.count(); j++) {
362 NameToFamily* nextEntry = fNameToFamilyMap.append();
363 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->fNames[j]));
364 nextEntry->styleSet = fFontStyleSets.back().get();
365 }
366 }
367 }
368
369 void findDefaultFont() {
370 SkASSERT(!fFontStyleSets.empty());
371
372 static const char* gDefaultNames[] = { "sans-serif" };
373 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
374 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
375 if (NULL == set) {
376 continue;
377 }
378 SkTypeface* tf = set->matchStyle(SkFontStyle());
379 if (NULL == tf) {
380 continue;
381 }
382 fDefaultFamily = set;
383 fDefaultTypeface = tf;
384 break;
385 }
386 if (NULL == fDefaultTypeface) {
387 fDefaultFamily = fFontStyleSets[0];
388 fDefaultTypeface = fDefaultFamily->createTypeface(0);
389 }
390 SkASSERT(fDefaultFamily);
391 SkASSERT(fDefaultTypeface);
392 }
393
394 typedef SkFontMgr INHERITED;
395};
396
397///////////////////////////////////////////////////////////////////////////////
398
399SkFontMgr* SkFontMgr::Factory() {
400 return SkNEW(SkFontMgr_Android);
401}