blob: 7ce7cb09b6363cd967c5b132fe382399054d5d28 [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,
bungeman65fcd3d2014-08-06 11:12:20 -070062 const SkString familyName,
63 const SkLanguage& lang,
Derek Sollenberger27fb9492014-08-06 16:30:51 -040064 FontVariant variantStyle)
bungeman8d84c992014-07-24 08:05:09 -070065 : INHERITED(index, style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070066 , fPathName(pathName)
67 , fLang(lang)
68 , fVariantStyle(variantStyle) { }
bungeman8d84c992014-07-24 08:05:09 -070069
70 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
tomhudson3a914242014-07-29 06:52:38 -070071 bool* serialize) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -070072 SkASSERT(desc);
73 SkASSERT(serialize);
74 desc->setFamilyName(fFamilyName.c_str());
75 desc->setFontFileName(fPathName.c_str());
76 *serialize = false;
77 }
78 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
79 *ttcIndex = fIndex;
80 return SkStream::NewFromFile(fPathName.c_str());
81 }
82
bungeman65fcd3d2014-08-06 11:12:20 -070083 const SkString fPathName;
84 const SkLanguage fLang;
Derek Sollenberger27fb9492014-08-06 16:30:51 -040085 const FontVariant fVariantStyle;
bungeman8d84c992014-07-24 08:05:09 -070086
87 typedef SkTypeface_Android INHERITED;
88};
89
90class SkTypeface_AndroidStream : public SkTypeface_Android {
91public:
92 SkTypeface_AndroidStream(SkStream* stream,
93 int index,
94 Style style,
95 bool isFixedPitch,
96 const SkString familyName)
97 : INHERITED(index, style, isFixedPitch, familyName)
bungeman8560cd52014-08-06 13:20:59 -070098 , fStream(SkRef(stream)) { }
bungeman8d84c992014-07-24 08:05:09 -070099
100 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
101 bool* serialize) const SK_OVERRIDE {
102 SkASSERT(desc);
103 SkASSERT(serialize);
104 desc->setFamilyName(fFamilyName.c_str());
105 desc->setFontFileName(NULL);
106 *serialize = true;
107 }
108
109 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
110 *ttcIndex = fIndex;
111 return fStream->duplicate();
112 }
113
114private:
115 SkAutoTUnref<SkStream> fStream;
116
117 typedef SkTypeface_Android INHERITED;
118};
119
120void get_path_for_sys_fonts(SkString* full, const SkString& name) {
121 full->set(getenv("ANDROID_ROOT"));
122 full->append(SK_FONT_FILE_PREFIX);
123 full->append(name);
124}
125
126class SkFontStyleSet_Android : public SkFontStyleSet {
127public:
bungeman65fcd3d2014-08-06 11:12:20 -0700128 explicit SkFontStyleSet_Android(const FontFamily& family) {
129 const SkString* cannonicalFamilyName = NULL;
130 if (family.fNames.count() > 0) {
131 cannonicalFamilyName = &family.fNames[0];
132 }
bungeman8d84c992014-07-24 08:05:09 -0700133 // TODO? make this lazy
bungeman65fcd3d2014-08-06 11:12:20 -0700134 for (int i = 0; i < family.fFontFiles.count(); ++i) {
135 const FontFileInfo& fontFile = family.fFontFiles[i];
bungeman8d84c992014-07-24 08:05:09 -0700136
137 SkString pathName;
bungeman65fcd3d2014-08-06 11:12:20 -0700138 get_path_for_sys_fonts(&pathName, fontFile.fFileName);
bungeman8d84c992014-07-24 08:05:09 -0700139
140 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
141 if (!stream.get()) {
bungeman65fcd3d2014-08-06 11:12:20 -0700142 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700143 continue;
144 }
145
bungeman65fcd3d2014-08-06 11:12:20 -0700146 const int ttcIndex = fontFile.fIndex;
147 SkString familyName;
bungeman8d84c992014-07-24 08:05:09 -0700148 SkTypeface::Style style;
149 bool isFixedWidth;
bungeman07cfb202014-07-30 11:05:22 -0700150 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex,
bungeman65fcd3d2014-08-06 11:12:20 -0700151 &familyName, &style, &isFixedWidth)) {
152 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700153 continue;
154 }
155
Derek Sollenberger27fb9492014-08-06 16:30:51 -0400156 const SkLanguage& lang = family.fLanguage;
157 uint32_t variant = family.fVariant;
158 if (kDefault_FontVariant == variant) {
159 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700160 }
161
162 // The first specified family name overrides the family name found in the font.
163 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
164 // all of the specified family names in addition to the names found in the font.
165 if (cannonicalFamilyName != NULL) {
166 familyName = *cannonicalFamilyName;
167 }
168
bungeman8d84c992014-07-24 08:05:09 -0700169 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
bungeman07cfb202014-07-30 11:05:22 -0700170 (pathName, ttcIndex,
bungeman65fcd3d2014-08-06 11:12:20 -0700171 style, isFixedWidth, familyName,
172 lang, variant)));
bungeman8d84c992014-07-24 08:05:09 -0700173 }
174 }
175
176 virtual int count() SK_OVERRIDE {
177 return fStyles.count();
178 }
179 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
180 if (index < 0 || fStyles.count() <= index) {
181 return;
182 }
183 if (style) {
184 *style = this->style(index);
185 }
186 if (name) {
187 name->reset();
188 }
189 }
bungeman65fcd3d2014-08-06 11:12:20 -0700190 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700191 if (index < 0 || fStyles.count() <= index) {
192 return NULL;
193 }
194 return SkRef(fStyles[index].get());
195 }
196
197 /** Find the typeface in this style set that most closely matches the given pattern.
198 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
199 * this simpler version using match_score() passes all our tests.
200 */
bungeman65fcd3d2014-08-06 11:12:20 -0700201 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700202 if (0 == fStyles.count()) {
203 return NULL;
204 }
bungeman65fcd3d2014-08-06 11:12:20 -0700205 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700206 int minScore = std::numeric_limits<int>::max();
207 for (int i = 0; i < fStyles.count(); ++i) {
208 SkFontStyle style = this->style(i);
209 int score = match_score(pattern, style);
210 if (score < minScore) {
211 closest = fStyles[i];
212 minScore = score;
213 }
214 }
215 return SkRef(closest);
216 }
217
218private:
219 SkFontStyle style(int index) {
220 return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width,
221 this->slant(index));
222 }
223 SkFontStyle::Weight weight(int index) {
224 if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight;
225 return SkFontStyle::kNormal_Weight;
226 }
227 SkFontStyle::Slant slant(int index) {
228 if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant;
229 return SkFontStyle::kUpright_Slant;
230 }
231 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
232 int score = 0;
233 score += abs((pattern.width() - candidate.width()) * 100);
234 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
235 score += abs(pattern.weight() - candidate.weight());
236 return score;
237 }
238
bungeman65fcd3d2014-08-06 11:12:20 -0700239 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700240
241 friend struct NameToFamily;
242 friend class SkFontMgr_Android;
243
244 typedef SkFontStyleSet INHERITED;
245};
246
247/** On Android a single family can have many names, but our API assumes unique names.
248 * Map names to the back end so that all names for a given family refer to the same
249 * (non-replicated) set of typefaces.
250 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
251 */
252struct NameToFamily {
253 SkString name;
254 SkFontStyleSet_Android* styleSet;
255};
256
257class SkFontMgr_Android : public SkFontMgr {
258public:
259 SkFontMgr_Android() {
260 SkTDArray<FontFamily*> fontFamilies;
261 SkFontConfigParser::GetFontFamilies(fontFamilies);
262 this->buildNameToFamilyMap(fontFamilies);
263 this->findDefaultFont();
264 }
265
266protected:
267 /** Returns not how many families we have, but how many unique names
268 * exist among the families.
269 */
270 virtual int onCountFamilies() const SK_OVERRIDE {
271 return fNameToFamilyMap.count();
272 }
273
274 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
275 if (index < 0 || fNameToFamilyMap.count() <= index) {
276 familyName->reset();
277 return;
278 }
279 familyName->set(fNameToFamilyMap[index].name);
280 }
281
282 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
283 if (index < 0 || fNameToFamilyMap.count() <= index) {
284 return NULL;
285 }
286 return SkRef(fNameToFamilyMap[index].styleSet);
287 }
288
289 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
290 if (!familyName) {
291 return NULL;
292 }
293 SkAutoAsciiToLC tolc(familyName);
294 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
295 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
296 return SkRef(fNameToFamilyMap[i].styleSet);
297 }
298 }
bungeman65fcd3d2014-08-06 11:12:20 -0700299 // TODO: eventually we should not need to name fallback families.
300 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
301 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
302 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
303 }
304 }
bungeman8d84c992014-07-24 08:05:09 -0700305 return NULL;
306 }
307
308 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
309 const SkFontStyle& style) const SK_OVERRIDE {
310 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
311 return sset->matchStyle(style);
312 }
313
314 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
315 const SkFontStyle& style) const SK_OVERRIDE {
316 for (int i = 0; i < fFontStyleSets.count(); ++i) {
317 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
318 if (fFontStyleSets[i]->fStyles[j] == typeface) {
319 return fFontStyleSets[i]->matchStyle(style);
320 }
321 }
322 }
323 return NULL;
324 }
325
bungeman65fcd3d2014-08-06 11:12:20 -0700326 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
327 const SkFontStyle& style,
328 const char bpc47[],
329 uint32_t character) const SK_OVERRIDE
330 {
331 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
332 // The variant 'default' means 'compact and elegant'.
333 // As a result, it is not possible to know the variant context from the font alone.
334 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
335
336 // For compatibility, try 'elegant' fonts first in fallback.
Derek Sollenberger27fb9492014-08-06 16:30:51 -0400337 uint32_t variantMask = kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700338
339 // The first time match anything in the mask, second time anything not in the mask.
340 for (bool maskMatches = true; maskMatches != false; maskMatches = false) {
341 SkLanguage lang(bpc47);
342 // Match against the language, removing a segment each time.
343 // The last time through the loop, the language will be empty.
344 // The empty language is special, and matches all languages.
345 do {
346 const SkString& langTag = lang.getTag();
347 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
348 SkFontStyleSet_Android* family = fFallbackNameToFamilyMap[i].styleSet;
349 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
350
351 if (!langTag.isEmpty() && langTag != face->fLang.getTag()) {
352 continue;
353 }
354
355 if (SkToBool(face->fVariantStyle & variantMask) != maskMatches) {
356 continue;
357 }
358
359 SkPaint paint;
360 paint.setTypeface(face);
361 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
362
363 uint16_t glyphID;
364 paint.textToGlyphs(&character, sizeof(character), &glyphID);
365 if (glyphID != 0) {
366 return face.detach();
367 }
368 }
369 } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true));
370 }
371 return NULL;
372 }
373
bungeman8d84c992014-07-24 08:05:09 -0700374 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
375 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
376 return this->createFromStream(stream, ttcIndex);
377 }
378
379 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
380 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
381 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
382 }
383
bungeman8560cd52014-08-06 13:20:59 -0700384 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700385 bool isFixedPitch;
386 SkTypeface::Style style;
387 SkString name;
388 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
389 return NULL;
390 }
bungeman8560cd52014-08-06 13:20:59 -0700391 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
bungeman8d84c992014-07-24 08:05:09 -0700392 style, isFixedPitch, name));
393 }
394
395
396 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
397 unsigned styleBits) const SK_OVERRIDE {
398 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
399 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
400 ? SkFontStyle::kBold_Weight
401 : SkFontStyle::kNormal_Weight,
402 SkFontStyle::kNormal_Width,
403 oldStyle & SkTypeface::kItalic
404 ? SkFontStyle::kItalic_Slant
405 : SkFontStyle::kUpright_Slant);
bungeman8d84c992014-07-24 08:05:09 -0700406
407 if (NULL != familyName) {
408 // On Android, we must return NULL when we can't find the requested
409 // named typeface so that the system/app can provide their own recovery
410 // mechanism. On other platforms we'd provide a typeface from the
411 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700412 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700413 }
bungeman07cfb202014-07-30 11:05:22 -0700414 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700415 }
416
417
418private:
419
420 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
421 SkFontStyleSet* fDefaultFamily;
422 SkTypeface* fDefaultTypeface;
423
424 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700425 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700426
427 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
428 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700429 FontFamily& family = *families[i];
430
431 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
432 if (family.fIsFallbackFont) {
433 nameToFamily = &fFallbackNameToFamilyMap;
434
435 if (0 == family.fNames.count()) {
436 SkString& fallbackName = family.fNames.push_back();
437 fallbackName.printf("%.2x##fallback", i);
438 }
439 }
440
441 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family));
442 if (0 == newSet->count()) {
443 SkDELETE(newSet);
444 continue;
445 }
446 fFontStyleSets.push_back().reset(newSet);
447
448 for (int j = 0; j < family.fNames.count(); j++) {
449 NameToFamily* nextEntry = nameToFamily->append();
450 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
451 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700452 }
453 }
454 }
455
456 void findDefaultFont() {
457 SkASSERT(!fFontStyleSets.empty());
458
459 static const char* gDefaultNames[] = { "sans-serif" };
460 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
461 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
462 if (NULL == set) {
463 continue;
464 }
465 SkTypeface* tf = set->matchStyle(SkFontStyle());
466 if (NULL == tf) {
467 continue;
468 }
469 fDefaultFamily = set;
470 fDefaultTypeface = tf;
471 break;
472 }
473 if (NULL == fDefaultTypeface) {
474 fDefaultFamily = fFontStyleSets[0];
475 fDefaultTypeface = fDefaultFamily->createTypeface(0);
476 }
477 SkASSERT(fDefaultFamily);
478 SkASSERT(fDefaultTypeface);
479 }
480
481 typedef SkFontMgr INHERITED;
482};
483
484///////////////////////////////////////////////////////////////////////////////
485
486SkFontMgr* SkFontMgr::Factory() {
487 return SkNEW(SkFontMgr_Android);
488}