blob: 794790be5909cd729a50841c785e88b94d81795d [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,
bungeman4b86bac2014-11-04 10:54:31 -080047 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -070048 : 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:
mtklein72c9faa2015-01-09 10:06:39 -080053 void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
bungemanb374d6a2014-09-17 07:48:59 -070054 *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:
bungeman4b86bac2014-11-04 10:54:31 -080066 SkTypeface_AndroidSystem(const SkString& pathName,
bungeman8d84c992014-07-24 08:05:09 -070067 int index,
bungemana4c4a2d2014-10-20 13:33:19 -070068 const SkFontStyle& style,
bungeman8d84c992014-07-24 08:05:09 -070069 bool isFixedPitch,
bungeman4b86bac2014-11-04 10:54:31 -080070 const SkString& familyName,
bungeman65fcd3d2014-08-06 11:12:20 -070071 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 }
mtklein72c9faa2015-01-09 10:06:39 -080087 SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -070088 *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,
bungeman4b86bac2014-11-04 10:54:31 -0800105 const SkString& familyName)
bungeman8d84c992014-07-24 08:05:09 -0700106 : 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
mtklein72c9faa2015-01-09 10:06:39 -0800118 SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700119 *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:
bungeman14df8332014-10-28 15:07:23 -0700141 explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath,
142 const SkTypeface_FreeType::Scanner& scanner)
143 {
bungeman65fcd3d2014-08-06 11:12:20 -0700144 const SkString* cannonicalFamilyName = NULL;
145 if (family.fNames.count() > 0) {
146 cannonicalFamilyName = &family.fNames[0];
147 }
bungeman8d84c992014-07-24 08:05:09 -0700148 // TODO? make this lazy
tomhudsond3ddea22014-08-11 11:28:00 -0700149 for (int i = 0; i < family.fFonts.count(); ++i) {
150 const FontFileInfo& fontFile = family.fFonts[i];
bungeman8d84c992014-07-24 08:05:09 -0700151
152 SkString pathName;
bungeman4e3523c2014-08-08 12:06:51 -0700153 get_path_for_sys_fonts(basePath, fontFile.fFileName, &pathName);
bungeman8d84c992014-07-24 08:05:09 -0700154
155 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
156 if (!stream.get()) {
bungeman65fcd3d2014-08-06 11:12:20 -0700157 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700158 continue;
159 }
160
bungeman65fcd3d2014-08-06 11:12:20 -0700161 const int ttcIndex = fontFile.fIndex;
162 SkString familyName;
bungemana4c4a2d2014-10-20 13:33:19 -0700163 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700164 bool isFixedWidth;
bungeman14df8332014-10-28 15:07:23 -0700165 if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) {
bungeman65fcd3d2014-08-06 11:12:20 -0700166 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
bungeman8d84c992014-07-24 08:05:09 -0700167 continue;
168 }
169
bungeman4b86bac2014-11-04 10:54:31 -0800170 if (fontFile.fWeight != 0) {
171 style = SkFontStyle(fontFile.fWeight, style.width(), style.slant());
172 }
173
djsollen3b625542014-08-14 06:29:02 -0700174 const SkLanguage& lang = family.fLanguage;
175 uint32_t variant = family.fVariant;
176 if (kDefault_FontVariant == variant) {
177 variant = kCompact_FontVariant | kElegant_FontVariant;
bungeman65fcd3d2014-08-06 11:12:20 -0700178 }
179
180 // The first specified family name overrides the family name found in the font.
181 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
182 // all of the specified family names in addition to the names found in the font.
183 if (cannonicalFamilyName != NULL) {
184 familyName = *cannonicalFamilyName;
185 }
186
bungeman8d84c992014-07-24 08:05:09 -0700187 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
bungeman07cfb202014-07-30 11:05:22 -0700188 (pathName, ttcIndex,
bungeman65fcd3d2014-08-06 11:12:20 -0700189 style, isFixedWidth, familyName,
190 lang, variant)));
bungeman8d84c992014-07-24 08:05:09 -0700191 }
192 }
193
mtklein72c9faa2015-01-09 10:06:39 -0800194 int count() SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700195 return fStyles.count();
196 }
mtklein72c9faa2015-01-09 10:06:39 -0800197 void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700198 if (index < 0 || fStyles.count() <= index) {
199 return;
200 }
201 if (style) {
202 *style = this->style(index);
203 }
204 if (name) {
205 name->reset();
206 }
207 }
mtklein72c9faa2015-01-09 10:06:39 -0800208 SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700209 if (index < 0 || fStyles.count() <= index) {
210 return NULL;
211 }
212 return SkRef(fStyles[index].get());
213 }
214
215 /** Find the typeface in this style set that most closely matches the given pattern.
216 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
217 * this simpler version using match_score() passes all our tests.
218 */
mtklein72c9faa2015-01-09 10:06:39 -0800219 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700220 if (0 == fStyles.count()) {
221 return NULL;
222 }
bungeman65fcd3d2014-08-06 11:12:20 -0700223 SkTypeface_AndroidSystem* closest = fStyles[0];
bungeman8d84c992014-07-24 08:05:09 -0700224 int minScore = std::numeric_limits<int>::max();
225 for (int i = 0; i < fStyles.count(); ++i) {
226 SkFontStyle style = this->style(i);
227 int score = match_score(pattern, style);
228 if (score < minScore) {
229 closest = fStyles[i];
230 minScore = score;
231 }
232 }
233 return SkRef(closest);
234 }
235
236private:
237 SkFontStyle style(int index) {
bungeman4b86bac2014-11-04 10:54:31 -0800238 return fStyles[index]->fontStyle();
bungeman8d84c992014-07-24 08:05:09 -0700239 }
240 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
241 int score = 0;
242 score += abs((pattern.width() - candidate.width()) * 100);
243 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
244 score += abs(pattern.weight() - candidate.weight());
245 return score;
246 }
247
bungeman65fcd3d2014-08-06 11:12:20 -0700248 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
bungeman8d84c992014-07-24 08:05:09 -0700249
250 friend struct NameToFamily;
251 friend class SkFontMgr_Android;
252
253 typedef SkFontStyleSet INHERITED;
254};
255
256/** On Android a single family can have many names, but our API assumes unique names.
257 * Map names to the back end so that all names for a given family refer to the same
258 * (non-replicated) set of typefaces.
259 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
260 */
261struct NameToFamily {
262 SkString name;
263 SkFontStyleSet_Android* styleSet;
264};
265
266class SkFontMgr_Android : public SkFontMgr {
267public:
268 SkFontMgr_Android() {
269 SkTDArray<FontFamily*> fontFamilies;
270 SkFontConfigParser::GetFontFamilies(fontFamilies);
bungeman4e3523c2014-08-08 12:06:51 -0700271 this->buildNameToFamilyMap(fontFamilies, NULL);
272 this->findDefaultFont();
273 }
274 SkFontMgr_Android(const char* mainConfigFile, const char* fallbackConfigFile,
275 const char* basePath)
276 {
277 SkTDArray<FontFamily*> fontFamilies;
278 SkFontConfigParser::GetTestFontFamilies(fontFamilies, mainConfigFile, fallbackConfigFile);
279 this->buildNameToFamilyMap(fontFamilies, basePath);
bungeman8d84c992014-07-24 08:05:09 -0700280 this->findDefaultFont();
281 }
282
283protected:
284 /** Returns not how many families we have, but how many unique names
285 * exist among the families.
286 */
mtklein72c9faa2015-01-09 10:06:39 -0800287 int onCountFamilies() const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700288 return fNameToFamilyMap.count();
289 }
290
mtklein72c9faa2015-01-09 10:06:39 -0800291 void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700292 if (index < 0 || fNameToFamilyMap.count() <= index) {
293 familyName->reset();
294 return;
295 }
296 familyName->set(fNameToFamilyMap[index].name);
297 }
298
mtklein72c9faa2015-01-09 10:06:39 -0800299 SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700300 if (index < 0 || fNameToFamilyMap.count() <= index) {
301 return NULL;
302 }
303 return SkRef(fNameToFamilyMap[index].styleSet);
304 }
305
mtklein72c9faa2015-01-09 10:06:39 -0800306 SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700307 if (!familyName) {
308 return NULL;
309 }
310 SkAutoAsciiToLC tolc(familyName);
311 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
312 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
313 return SkRef(fNameToFamilyMap[i].styleSet);
314 }
315 }
bungeman65fcd3d2014-08-06 11:12:20 -0700316 // TODO: eventually we should not need to name fallback families.
317 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
318 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
319 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
320 }
321 }
bungeman8d84c992014-07-24 08:05:09 -0700322 return NULL;
323 }
324
325 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
326 const SkFontStyle& style) const SK_OVERRIDE {
327 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
328 return sset->matchStyle(style);
329 }
330
331 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
332 const SkFontStyle& style) const SK_OVERRIDE {
333 for (int i = 0; i < fFontStyleSets.count(); ++i) {
334 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
335 if (fFontStyleSets[i]->fStyles[j] == typeface) {
336 return fFontStyleSets[i]->matchStyle(style);
337 }
338 }
339 }
340 return NULL;
341 }
342
bungemanc9232dc2014-11-10 13:29:33 -0800343 static SkTypeface_AndroidSystem* find_family_style_character(
344 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
345 const SkFontStyle& style, bool elegant,
346 const SkString& langTag, SkUnichar character)
347 {
348 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
349 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
350 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
bungemanc20386e2014-10-23 07:08:05 -0700351
bungemanc9232dc2014-11-10 13:29:33 -0800352 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
353 continue;
354 }
355
356 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
357 continue;
358 }
359
360 SkPaint paint;
361 paint.setTypeface(face);
362 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
363
364 uint16_t glyphID;
365 paint.textToGlyphs(&character, sizeof(character), &glyphID);
366 if (glyphID != 0) {
367 return face.detach();
368 }
bungemanc20386e2014-10-23 07:08:05 -0700369 }
bungemanc9232dc2014-11-10 13:29:33 -0800370 return NULL;
bungemanc20386e2014-10-23 07:08:05 -0700371 }
bungemanc9232dc2014-11-10 13:29:33 -0800372
bungeman65fcd3d2014-08-06 11:12:20 -0700373 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
374 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700375 const char* bcp47[],
376 int bcp47Count,
377 SkUnichar character) const SK_OVERRIDE
bungeman65fcd3d2014-08-06 11:12:20 -0700378 {
379 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
380 // The variant 'default' means 'compact and elegant'.
381 // As a result, it is not possible to know the variant context from the font alone.
382 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
383
bungemanc20386e2014-10-23 07:08:05 -0700384 // The first time match anything elegant, second time anything not elegant.
385 for (int elegant = 2; elegant --> 0;) {
386 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
387 SkLanguage lang(bcp47[bcp47Index]);
388 while (!lang.getTag().isEmpty()) {
389 SkTypeface_AndroidSystem* matchingTypeface =
390 find_family_style_character(fFallbackNameToFamilyMap,
391 style, SkToBool(elegant),
392 lang.getTag(), character);
393 if (matchingTypeface) {
394 return matchingTypeface;
bungeman65fcd3d2014-08-06 11:12:20 -0700395 }
396
bungemanc20386e2014-10-23 07:08:05 -0700397 lang = lang.getParent();
bungeman65fcd3d2014-08-06 11:12:20 -0700398 }
bungemanc20386e2014-10-23 07:08:05 -0700399 }
400 SkTypeface_AndroidSystem* matchingTypeface =
401 find_family_style_character(fFallbackNameToFamilyMap,
402 style, SkToBool(elegant),
403 SkString(), character);
404 if (matchingTypeface) {
405 return matchingTypeface;
406 }
bungeman65fcd3d2014-08-06 11:12:20 -0700407 }
408 return NULL;
409 }
410
mtklein72c9faa2015-01-09 10:06:39 -0800411 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700412 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
413 return this->createFromStream(stream, ttcIndex);
414 }
415
mtklein72c9faa2015-01-09 10:06:39 -0800416 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700417 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
418 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
419 }
420
mtklein72c9faa2015-01-09 10:06:39 -0800421 SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
bungeman8d84c992014-07-24 08:05:09 -0700422 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700423 SkFontStyle style;
bungeman8d84c992014-07-24 08:05:09 -0700424 SkString name;
bungeman14df8332014-10-28 15:07:23 -0700425 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
bungeman8d84c992014-07-24 08:05:09 -0700426 return NULL;
427 }
bungeman8560cd52014-08-06 13:20:59 -0700428 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
bungeman8d84c992014-07-24 08:05:09 -0700429 style, isFixedPitch, name));
430 }
431
432
433 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
434 unsigned styleBits) const SK_OVERRIDE {
bungemana4c4a2d2014-10-20 13:33:19 -0700435 SkFontStyle style = SkFontStyle(styleBits);
bungeman8d84c992014-07-24 08:05:09 -0700436
bsalomon49f085d2014-09-05 13:34:00 -0700437 if (familyName) {
bungeman8d84c992014-07-24 08:05:09 -0700438 // On Android, we must return NULL when we can't find the requested
439 // named typeface so that the system/app can provide their own recovery
440 // mechanism. On other platforms we'd provide a typeface from the
441 // default family instead.
bungeman07cfb202014-07-30 11:05:22 -0700442 return this->onMatchFamilyStyle(familyName, style);
bungeman8d84c992014-07-24 08:05:09 -0700443 }
bungeman07cfb202014-07-30 11:05:22 -0700444 return fDefaultFamily->matchStyle(style);
bungeman8d84c992014-07-24 08:05:09 -0700445 }
446
447
448private:
449
bungeman14df8332014-10-28 15:07:23 -0700450 SkTypeface_FreeType::Scanner fScanner;
451
bungeman8d84c992014-07-24 08:05:09 -0700452 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
453 SkFontStyleSet* fDefaultFamily;
454 SkTypeface* fDefaultTypeface;
455
456 SkTDArray<NameToFamily> fNameToFamilyMap;
bungeman65fcd3d2014-08-06 11:12:20 -0700457 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
bungeman8d84c992014-07-24 08:05:09 -0700458
bungeman4e3523c2014-08-08 12:06:51 -0700459 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const char* basePath) {
bungeman8d84c992014-07-24 08:05:09 -0700460 for (int i = 0; i < families.count(); i++) {
bungeman65fcd3d2014-08-06 11:12:20 -0700461 FontFamily& family = *families[i];
462
463 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
464 if (family.fIsFallbackFont) {
465 nameToFamily = &fFallbackNameToFamilyMap;
466
467 if (0 == family.fNames.count()) {
468 SkString& fallbackName = family.fNames.push_back();
469 fallbackName.printf("%.2x##fallback", i);
470 }
471 }
472
bungeman14df8332014-10-28 15:07:23 -0700473 SkFontStyleSet_Android* newSet =
474 SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath, fScanner));
bungeman65fcd3d2014-08-06 11:12:20 -0700475 if (0 == newSet->count()) {
476 SkDELETE(newSet);
477 continue;
478 }
479 fFontStyleSets.push_back().reset(newSet);
480
481 for (int j = 0; j < family.fNames.count(); j++) {
482 NameToFamily* nextEntry = nameToFamily->append();
483 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
484 nextEntry->styleSet = newSet;
bungeman8d84c992014-07-24 08:05:09 -0700485 }
486 }
487 }
488
489 void findDefaultFont() {
490 SkASSERT(!fFontStyleSets.empty());
491
492 static const char* gDefaultNames[] = { "sans-serif" };
493 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
494 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
495 if (NULL == set) {
496 continue;
497 }
498 SkTypeface* tf = set->matchStyle(SkFontStyle());
499 if (NULL == tf) {
500 continue;
501 }
502 fDefaultFamily = set;
503 fDefaultTypeface = tf;
504 break;
505 }
506 if (NULL == fDefaultTypeface) {
507 fDefaultFamily = fFontStyleSets[0];
508 fDefaultTypeface = fDefaultFamily->createTypeface(0);
509 }
510 SkASSERT(fDefaultFamily);
511 SkASSERT(fDefaultTypeface);
512 }
513
514 typedef SkFontMgr INHERITED;
515};
516
517///////////////////////////////////////////////////////////////////////////////
518
519SkFontMgr* SkFontMgr::Factory() {
bungeman4e3523c2014-08-08 12:06:51 -0700520 // The call to SkGetTestFontConfiguration is so that Chromium can override the environment.
521 // TODO: these globals need to be removed, in favor of a constructor / separate Factory
522 // which can be used instead.
523 const char* mainConfigFile;
524 const char* fallbackConfigFile;
525 const char* basePath;
526 SkGetTestFontConfiguration(&mainConfigFile, &fallbackConfigFile, &basePath);
527 if (mainConfigFile) {
bungeman3e30af22014-08-11 10:53:29 -0700528 return SkNEW_ARGS(SkFontMgr_Android, (mainConfigFile, fallbackConfigFile, basePath));
bungeman4e3523c2014-08-08 12:06:51 -0700529 }
530
bungeman8d84c992014-07-24 08:05:09 -0700531 return SkNEW(SkFontMgr_Android);
532}
tomhudsonc7733902014-08-13 10:41:25 -0700533
534void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
535 const char* fontsdir) {
536 gTestMainConfigFile = mainconf;
537 gTestFallbackConfigFile = fallbackconf;
538 gTestFontFilePrefix = fontsdir;
539 SkASSERT(gTestMainConfigFile);
540 SkASSERT(gTestFallbackConfigFile);
541 SkASSERT(gTestFontFilePrefix);
542 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
543 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
544}
545
546void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf,
547 const char** fontsdir) {
548 *mainconf = gTestMainConfigFile;
549 *fallbackconf = gTestFallbackConfigFile;
550 *fontsdir = gTestFontFilePrefix;
551}