blob: 2865d800b7c34c0d40d7bdb09cbe52aadf375702 [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"
bungeman4e3523c2014-08-08 12:06:51 -070017#include "SkTypeface_android.h"
bungeman8d84c992014-07-24 08:05:09 -070018#include "SkTypefaceCache.h"
19
20#include <limits>
21#include <stdlib.h>
22
23#ifndef SK_FONT_FILE_PREFIX
24# define SK_FONT_FILE_PREFIX "/fonts/"
25#endif
26
27#ifndef SK_DEBUG_FONTS
28 #define SK_DEBUG_FONTS 0
29#endif
30
31#if SK_DEBUG_FONTS
32# define DEBUG_FONT(args) SkDebugf args
33#else
34# define DEBUG_FONT(args)
35#endif
36
tomhudsonc7733902014-08-13 10:41:25 -070037// For test only.
38static const char* gTestMainConfigFile = NULL;
39static const char* gTestFallbackConfigFile = NULL;
40static const char* gTestFontFilePrefix = NULL;
41
bungeman8d84c992014-07-24 08:05:09 -070042class SkTypeface_Android : public SkTypeface_FreeType {
43public:
44 SkTypeface_Android(int index,
bungemana4c4a2d2014-10-20 13:33:19 -070045 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070046 bool isFixedPitch,
47 const SkString familyName)
48 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
49 , fIndex(index)
tomhudson3a914242014-07-29 06:52:38 -070050 , fFamilyName(familyName) { }
bungeman8d84c992014-07-24 08:05:09 -070051
bungeman8d84c992014-07-24 08:05:09 -070052protected:
bungemanb374d6a2014-09-17 07:48:59 -070053 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
54 *familyName = fFamilyName;
55 }
56
bungeman8d84c992014-07-24 08:05:09 -070057 int fIndex;
58 SkString fFamilyName;
59
60private:
61 typedef SkTypeface_FreeType INHERITED;
62};
63
64class SkTypeface_AndroidSystem : public SkTypeface_Android {
65public:
66 SkTypeface_AndroidSystem(const SkString pathName,
67 int index,
bungemana4c4a2d2014-10-20 13:33:19 -070068 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070069 bool isFixedPitch,
bungeman65fcd3d2014-08-06 11:12:20 -070070 const SkString familyName,
71 const SkLanguage& lang,
djsollen3b625542014-08-14 06:29:02 -070072 FontVariant variantStyle)
bungeman8d84c992014-07-24 08:05:09 -070073 : INHERITED(index, style, isFixedPitch, familyName)
bungeman65fcd3d2014-08-06 11:12:20 -070074 , fPathName(pathName)
75 , fLang(lang)
76 , fVariantStyle(variantStyle) { }
bungeman8d84c992014-07-24 08:05:09 -070077
78 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
tomhudson3a914242014-07-29 06:52:38 -070079 bool* serialize) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -070080 SkASSERT(desc);
81 SkASSERT(serialize);
82 desc->setFamilyName(fFamilyName.c_str());
83 desc->setFontFileName(fPathName.c_str());
bungemand71b7572014-09-18 10:55:32 -070084 desc->setFontIndex(fIndex);
bungeman8d84c992014-07-24 08:05:09 -070085 *serialize = false;
86 }
87 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
88 *ttcIndex = fIndex;
89 return SkStream::NewFromFile(fPathName.c_str());
90 }
91
bungeman65fcd3d2014-08-06 11:12:20 -070092 const SkString fPathName;
93 const SkLanguage fLang;
djsollen3b625542014-08-14 06:29:02 -070094 const FontVariant fVariantStyle;
bungeman8d84c992014-07-24 08:05:09 -070095
96 typedef SkTypeface_Android INHERITED;
97};
98
99class SkTypeface_AndroidStream : public SkTypeface_Android {
100public:
101 SkTypeface_AndroidStream(SkStream* stream,
102 int index,
bungemana4c4a2d2014-10-20 13:33:19 -0700103 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -0700104 bool isFixedPitch,
105 const SkString familyName)
106 : INHERITED(index, style, isFixedPitch, familyName)
bungeman8560cd52014-08-06 13:20:59 -0700107 , fStream(SkRef(stream)) { }
bungeman8d84c992014-07-24 08:05:09 -0700108
109 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
110 bool* serialize) const SK_OVERRIDE {
111 SkASSERT(desc);
112 SkASSERT(serialize);
113 desc->setFamilyName(fFamilyName.c_str());
114 desc->setFontFileName(NULL);
115 *serialize = true;
116 }
117
118 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
119 *ttcIndex = fIndex;
120 return fStream->duplicate();
121 }
122
123private:
124 SkAutoTUnref<SkStream> fStream;
125
126 typedef SkTypeface_Android INHERITED;
127};
128
bungeman4e3523c2014-08-08 12:06:51 -0700129void get_path_for_sys_fonts(const char* basePath, const SkString& name, SkString* full) {
130 if (basePath) {
131 full->set(basePath);
132 } else {
133 full->set(getenv("ANDROID_ROOT"));
134 full->append(SK_FONT_FILE_PREFIX);
135 }
bungeman8d84c992014-07-24 08:05:09 -0700136 full->append(name);
137}
138
139class SkFontStyleSet_Android : public SkFontStyleSet {
140public:
bungeman4e3523c2014-08-08 12:06:51 -0700141 explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath) {
bungeman65fcd3d2014-08-06 11:12:20 -0700142 const SkString* cannonicalFamilyName = NULL;
143 if (family.fNames.count() > 0) {
144 cannonicalFamilyName = &family.fNames[0];
145 }
bungeman8d84c992014-07-24 08:05:09 -0700146 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700147 for (int i = 0; i < family.fFonts.count(); ++i) {
148 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700149
150 SkString pathName;
bungeman4e3523c2014-08-08 12:06:51 -0700151 get_path_for_sys_fonts(basePath, fontFile.fFileName, &pathName);
bungeman8d84c992014-07-24 08:05:09 -0700152
153 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
154 if (!stream.get()) {
bungeman65fcd3d2014-08-06 11:12:20 -0700155 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700156 continue;
157 }
158
bungeman65fcd3d2014-08-06 11:12:20 -0700159 const int ttcIndex = fontFile.fIndex;
160 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700161 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700162 bool isFixedWidth;
bungeman07cfb202014-07-30 11:05:22 -0700163 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex,
bungeman65fcd3d2014-08-06 11:12:20 -0700164 &familyName, &style, &isFixedWidth)) {
165 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700166 continue;
167 }
168
djsollen3b625542014-08-14 06:29:02 -0700169 const SkLanguage& lang = family.fLanguage;
170 uint32_t variant = family.fVariant;
171 if (kDefault_FontVariant == variant) {
172 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700173 }
174
175 // The first specified family name overrides the family name found in the font.
176 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
177 // all of the specified family names in addition to the names found in the font.
178 if (cannonicalFamilyName != NULL) {
179 familyName = *cannonicalFamilyName;
180 }
181
bungeman8d84c992014-07-24 08:05:09 -0700182 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
bungeman07cfb202014-07-30 11:05:22 -0700183 (pathName, ttcIndex,
bungeman65fcd3d2014-08-06 11:12:20 -0700184 style, isFixedWidth, familyName,
185 lang, variant)));
bungeman8d84c992014-07-24 08:05:09 -0700186 }
187 }
188
189 virtual int count() SK_OVERRIDE {
190 return fStyles.count();
191 }
192 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
193 if (index < 0 || fStyles.count() <= index) {
194 return;
195 }
196 if (style) {
197 *style = this->style(index);
198 }
199 if (name) {
200 name->reset();
201 }
202 }
bungeman65fcd3d2014-08-06 11:12:20 -0700203 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700204 if (index < 0 || fStyles.count() <= index) {
205 return NULL;
206 }
207 return SkRef(fStyles[index].get());
208 }
209
210 /** Find the typeface in this style set that most closely matches the given pattern.
211 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
212 * this simpler version using match_score() passes all our tests.
213 */
bungeman65fcd3d2014-08-06 11:12:20 -0700214 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700215 if (0 == fStyles.count()) {
216 return NULL;
217 }
bungeman65fcd3d2014-08-06 11:12:20 -0700218 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700219 int minScore = std::numeric_limits<int>::max();
220 for (int i = 0; i < fStyles.count(); ++i) {
221 SkFontStyle style = this->style(i);
222 int score = match_score(pattern, style);
223 if (score < minScore) {
224 closest = fStyles[i];
225 minScore = score;
226 }
227 }
228 return SkRef(closest);
229 }
230
231private:
232 SkFontStyle style(int index) {
233 return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width,
234 this->slant(index));
235 }
236 SkFontStyle::Weight weight(int index) {
237 if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight;
238 return SkFontStyle::kNormal_Weight;
239 }
240 SkFontStyle::Slant slant(int index) {
241 if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant;
242 return SkFontStyle::kUpright_Slant;
243 }
244 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
245 int score = 0;
246 score += abs((pattern.width() - candidate.width()) * 100);
247 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
248 score += abs(pattern.weight() - candidate.weight());
249 return score;
250 }
251
bungeman65fcd3d2014-08-06 11:12:20 -0700252 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700253
254 friend struct NameToFamily;
255 friend class SkFontMgr_Android;
256
257 typedef SkFontStyleSet INHERITED;
258};
259
260/** On Android a single family can have many names, but our API assumes unique names.
261 * Map names to the back end so that all names for a given family refer to the same
262 * (non-replicated) set of typefaces.
263 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
264 */
265struct NameToFamily {
266 SkString name;
267 SkFontStyleSet_Android* styleSet;
268};
269
270class SkFontMgr_Android : public SkFontMgr {
271public:
272 SkFontMgr_Android() {
273 SkTDArray<FontFamily*> fontFamilies;
274 SkFontConfigParser::GetFontFamilies(fontFamilies);
bungeman4e3523c2014-08-08 12:06:51 -0700275 this->buildNameToFamilyMap(fontFamilies, NULL);
276 this->findDefaultFont();
277 }
278 SkFontMgr_Android(const char* mainConfigFile, const char* fallbackConfigFile,
279 const char* basePath)
280 {
281 SkTDArray<FontFamily*> fontFamilies;
282 SkFontConfigParser::GetTestFontFamilies(fontFamilies, mainConfigFile, fallbackConfigFile);
283 this->buildNameToFamilyMap(fontFamilies, basePath);
bungeman8d84c992014-07-24 08:05:09 -0700284 this->findDefaultFont();
285 }
286
287protected:
288 /** Returns not how many families we have, but how many unique names
289 * exist among the families.
290 */
291 virtual int onCountFamilies() const SK_OVERRIDE {
292 return fNameToFamilyMap.count();
293 }
294
295 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
296 if (index < 0 || fNameToFamilyMap.count() <= index) {
297 familyName->reset();
298 return;
299 }
300 familyName->set(fNameToFamilyMap[index].name);
301 }
302
303 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
304 if (index < 0 || fNameToFamilyMap.count() <= index) {
305 return NULL;
306 }
307 return SkRef(fNameToFamilyMap[index].styleSet);
308 }
309
310 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
311 if (!familyName) {
312 return NULL;
313 }
314 SkAutoAsciiToLC tolc(familyName);
315 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
316 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
317 return SkRef(fNameToFamilyMap[i].styleSet);
318 }
319 }
bungeman65fcd3d2014-08-06 11:12:20 -0700320 // TODO: eventually we should not need to name fallback families.
321 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
322 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
323 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
324 }
325 }
bungeman8d84c992014-07-24 08:05:09 -0700326 return NULL;
327 }
328
329 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
330 const SkFontStyle& style) const SK_OVERRIDE {
331 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
332 return sset->matchStyle(style);
333 }
334
335 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
336 const SkFontStyle& style) const SK_OVERRIDE {
337 for (int i = 0; i < fFontStyleSets.count(); ++i) {
338 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
339 if (fFontStyleSets[i]->fStyles[j] == typeface) {
340 return fFontStyleSets[i]->matchStyle(style);
341 }
342 }
343 }
344 return NULL;
345 }
346
bungemanc20386e2014-10-23 07:08:05 -0700347static SkTypeface_AndroidSystem* find_family_style_character(
348 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
349 const SkFontStyle& style, bool elegant,
350 const SkString& langTag, SkUnichar character)
351{
352 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
353 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
354 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
355
356 if (!langTag.isEmpty() && langTag != face->fLang.getTag()) {
357 continue;
358 }
359
360 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
361 continue;
362 }
363
364 SkPaint paint;
365 paint.setTypeface(face);
366 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
367
368 uint16_t glyphID;
369 paint.textToGlyphs(&character, sizeof(character), &glyphID);
370 if (glyphID != 0) {
371 return face.detach();
372 }
373 }
374 return NULL;
375}
376#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
bungeman65fcd3d2014-08-06 11:12:20 -0700377 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
378 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700379 const char* bcp47[],
380 int bcp47Count,
381 SkUnichar character) const SK_OVERRIDE
bungeman65fcd3d2014-08-06 11:12:20 -0700382 {
bungemanc20386e2014-10-23 07:08:05 -0700383#else
384 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
385 const SkFontStyle& style,
386 const char bcp47_val[],
387 SkUnichar character) const SK_OVERRIDE
388 {
389 const char** bcp47 = &bcp47_val;
390 int bcp47Count = bcp47_val ? 1 : 0;
391#endif
bungeman65fcd3d2014-08-06 11:12:20 -0700392 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
393 // The variant 'default' means 'compact and elegant'.
394 // As a result, it is not possible to know the variant context from the font alone.
395 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
396
bungemanc20386e2014-10-23 07:08:05 -0700397 // The first time match anything elegant, second time anything not elegant.
398 for (int elegant = 2; elegant --> 0;) {
399 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
400 SkLanguage lang(bcp47[bcp47Index]);
401 while (!lang.getTag().isEmpty()) {
402 SkTypeface_AndroidSystem* matchingTypeface =
403 find_family_style_character(fFallbackNameToFamilyMap,
404 style, SkToBool(elegant),
405 lang.getTag(), character);
406 if (matchingTypeface) {
407 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700408 }
409
bungemanc20386e2014-10-23 07:08:05 -0700410 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700411 }
bungemanc20386e2014-10-23 07:08:05 -0700412 }
413 SkTypeface_AndroidSystem* matchingTypeface =
414 find_family_style_character(fFallbackNameToFamilyMap,
415 style, SkToBool(elegant),
416 SkString(), character);
417 if (matchingTypeface) {
418 return matchingTypeface;
419 }
bungeman65fcd3d2014-08-06 11:12:20 -0700420 }
421 return NULL;
422 }
423
bungeman8d84c992014-07-24 08:05:09 -0700424 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
425 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
426 return this->createFromStream(stream, ttcIndex);
427 }
428
429 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
430 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
431 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
432 }
433
bungeman8560cd52014-08-06 13:20:59 -0700434 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700435 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700436 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700437 SkString name;
438 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
439 return NULL;
440 }
bungeman8560cd52014-08-06 13:20:59 -0700441 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
bungeman8d84c992014-07-24 08:05:09 -0700442 style, isFixedPitch, name));
443 }
444
445
446 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
447 unsigned styleBits) const SK_OVERRIDE {
bungemana4c4a2d2014-10-20 13:33:19 -0700448 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700449
bsalomon49f085d2014-09-05 13:34:00 -0700450 if (familyName) {
bungeman8d84c992014-07-24 08:05:09 -0700451 // On Android, we must return NULL when we can't find the requested
452 // named typeface so that the system/app can provide their own recovery
453 // mechanism. On other platforms we'd provide a typeface from the
454 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700455 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700456 }
bungeman07cfb202014-07-30 11:05:22 -0700457 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700458 }
459
460
461private:
462
463 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
464 SkFontStyleSet* fDefaultFamily;
465 SkTypeface* fDefaultTypeface;
466
467 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700468 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700469
bungeman4e3523c2014-08-08 12:06:51 -0700470 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const char* basePath) {
bungeman8d84c992014-07-24 08:05:09 -0700471 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700472 FontFamily& family = *families[i];
473
474 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
475 if (family.fIsFallbackFont) {
476 nameToFamily = &fFallbackNameToFamilyMap;
477
478 if (0 == family.fNames.count()) {
479 SkString& fallbackName = family.fNames.push_back();
480 fallbackName.printf("%.2x##fallback", i);
481 }
482 }
483
bungeman4e3523c2014-08-08 12:06:51 -0700484 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath));
bungeman65fcd3d2014-08-06 11:12:20 -0700485 if (0 == newSet->count()) {
486 SkDELETE(newSet);
487 continue;
488 }
489 fFontStyleSets.push_back().reset(newSet);
490
491 for (int j = 0; j < family.fNames.count(); j++) {
492 NameToFamily* nextEntry = nameToFamily->append();
493 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
494 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700495 }
496 }
497 }
498
499 void findDefaultFont() {
500 SkASSERT(!fFontStyleSets.empty());
501
502 static const char* gDefaultNames[] = { "sans-serif" };
503 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
504 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
505 if (NULL == set) {
506 continue;
507 }
508 SkTypeface* tf = set->matchStyle(SkFontStyle());
509 if (NULL == tf) {
510 continue;
511 }
512 fDefaultFamily = set;
513 fDefaultTypeface = tf;
514 break;
515 }
516 if (NULL == fDefaultTypeface) {
517 fDefaultFamily = fFontStyleSets[0];
518 fDefaultTypeface = fDefaultFamily->createTypeface(0);
519 }
520 SkASSERT(fDefaultFamily);
521 SkASSERT(fDefaultTypeface);
522 }
523
524 typedef SkFontMgr INHERITED;
525};
526
527///////////////////////////////////////////////////////////////////////////////
528
529SkFontMgr* SkFontMgr::Factory() {
bungeman4e3523c2014-08-08 12:06:51 -0700530 // The call to SkGetTestFontConfiguration is so that Chromium can override the environment.
531 // TODO: these globals need to be removed, in favor of a constructor / separate Factory
532 // which can be used instead.
533 const char* mainConfigFile;
534 const char* fallbackConfigFile;
535 const char* basePath;
536 SkGetTestFontConfiguration(&mainConfigFile, &fallbackConfigFile, &basePath);
537 if (mainConfigFile) {
bungeman3e30af22014-08-11 10:53:29 -0700538 return SkNEW_ARGS(SkFontMgr_Android, (mainConfigFile, fallbackConfigFile, basePath));
bungeman4e3523c2014-08-08 12:06:51 -0700539 }
540
bungeman8d84c992014-07-24 08:05:09 -0700541 return SkNEW(SkFontMgr_Android);
542}
tomhudsonc7733902014-08-13 10:41:25 -0700543
544void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
545 const char* fontsdir) {
546 gTestMainConfigFile = mainconf;
547 gTestFallbackConfigFile = fallbackconf;
548 gTestFontFilePrefix = fontsdir;
549 SkASSERT(gTestMainConfigFile);
550 SkASSERT(gTestFallbackConfigFile);
551 SkASSERT(gTestFontFilePrefix);
552 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
553 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
554}
555
556void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf,
557 const char** fontsdir) {
558 *mainconf = gTestMainConfigFile;
559 *fallbackconf = gTestFallbackConfigFile;
560 *fontsdir = gTestFontFilePrefix;
561}