1 /*
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 "SkFontMgr_android.h"
13 #include "SkFontStyle.h"
14 #include "SkStream.h"
15 #include "SkTDArray.h"
16 #include "SkTSearch.h"
17 #include "SkTypeface.h"
18 #include "SkTypeface_android.h"
19 #include "SkTypefaceCache.h"
20
21 #include <limits>
22
23 // For test only.
24 static const char* gTestFontsXml = NULL;
25 static const char* gTestFallbackFontsXml = NULL;
26 static const char* gTestBasePath = NULL;
27
28 class SkTypeface_Android : public SkTypeface_FreeType {
29 public:
SkTypeface_Android(int index,const SkFontStyle & style,bool isFixedPitch,const SkString & familyName)30 SkTypeface_Android(int index,
31 const SkFontStyle& style,
32 bool isFixedPitch,
33 const SkString& familyName)
34 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
35 , fIndex(index)
36 , fFamilyName(familyName) { }
37
38 protected:
onGetFamilyName(SkString * familyName) const39 void onGetFamilyName(SkString* familyName) const override {
40 *familyName = fFamilyName;
41 }
42
43 int fIndex;
44 SkString fFamilyName;
45
46 private:
47 typedef SkTypeface_FreeType INHERITED;
48 };
49
50 class SkTypeface_AndroidSystem : public SkTypeface_Android {
51 public:
SkTypeface_AndroidSystem(const SkString & pathName,int index,const SkFontStyle & style,bool isFixedPitch,const SkString & familyName,const SkLanguage & lang,FontVariant variantStyle)52 SkTypeface_AndroidSystem(const SkString& pathName,
53 int index,
54 const SkFontStyle& style,
55 bool isFixedPitch,
56 const SkString& familyName,
57 const SkLanguage& lang,
58 FontVariant variantStyle)
59 : INHERITED(index, style, isFixedPitch, familyName)
60 , fPathName(pathName)
61 , fLang(lang)
62 , fVariantStyle(variantStyle) { }
63
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const64 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
65 bool* serialize) const override {
66 SkASSERT(desc);
67 SkASSERT(serialize);
68 desc->setFamilyName(fFamilyName.c_str());
69 desc->setFontIndex(fIndex);
70 *serialize = false;
71 }
onOpenStream(int * ttcIndex) const72 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
73 *ttcIndex = fIndex;
74 return SkStream::NewFromFile(fPathName.c_str());
75 }
76
77 const SkString fPathName;
78 const SkLanguage fLang;
79 const FontVariant fVariantStyle;
80
81 typedef SkTypeface_Android INHERITED;
82 };
83
84 class SkTypeface_AndroidStream : public SkTypeface_Android {
85 public:
SkTypeface_AndroidStream(SkStreamAsset * stream,int index,const SkFontStyle & style,bool isFixedPitch,const SkString & familyName)86 SkTypeface_AndroidStream(SkStreamAsset* stream,
87 int index,
88 const SkFontStyle& style,
89 bool isFixedPitch,
90 const SkString& familyName)
91 : INHERITED(index, style, isFixedPitch, familyName)
92 , fStream(stream) { }
93
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const94 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
95 bool* serialize) const override {
96 SkASSERT(desc);
97 SkASSERT(serialize);
98 desc->setFamilyName(fFamilyName.c_str());
99 *serialize = true;
100 }
101
onOpenStream(int * ttcIndex) const102 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
103 *ttcIndex = fIndex;
104 return fStream->duplicate();
105 }
106
107 private:
108 SkAutoTDelete<SkStreamAsset> fStream;
109
110 typedef SkTypeface_Android INHERITED;
111 };
112
113 class SkFontStyleSet_Android : public SkFontStyleSet {
114 public:
SkFontStyleSet_Android(const FontFamily & family,const SkTypeface_FreeType::Scanner & scanner)115 explicit SkFontStyleSet_Android(const FontFamily& family,
116 const SkTypeface_FreeType::Scanner& scanner)
117 {
118 const SkString* cannonicalFamilyName = NULL;
119 if (family.fNames.count() > 0) {
120 cannonicalFamilyName = &family.fNames[0];
121 }
122 // TODO? make this lazy
123 for (int i = 0; i < family.fFonts.count(); ++i) {
124 const FontFileInfo& fontFile = family.fFonts[i];
125
126 SkString pathName(family.fBasePath);
127 pathName.append(fontFile.fFileName);
128
129 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
130 if (!stream.get()) {
131 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
132 pathName.c_str()));
133 continue;
134 }
135
136 const int ttcIndex = fontFile.fIndex;
137 SkString familyName;
138 SkFontStyle style;
139 bool isFixedWidth;
140 if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) {
141 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
142 pathName.c_str()));
143 continue;
144 }
145
146 int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
147 SkFontStyle::Slant slant = style.slant();
148 switch (fontFile.fStyle) {
149 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
150 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
151 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
152 default: SkASSERT(false); break;
153 }
154 style = SkFontStyle(weight, style.width(), slant);
155
156 const SkLanguage& lang = family.fLanguage;
157 uint32_t variant = family.fVariant;
158 if (kDefault_FontVariant == variant) {
159 variant = kCompact_FontVariant | kElegant_FontVariant;
160 }
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
169 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
170 (pathName, ttcIndex,
171 style, isFixedWidth, familyName,
172 lang, variant)));
173 }
174 }
175
count()176 int count() override {
177 return fStyles.count();
178 }
getStyle(int index,SkFontStyle * style,SkString * name)179 void getStyle(int index, SkFontStyle* style, SkString* name) 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 }
createTypeface(int index)190 SkTypeface_AndroidSystem* createTypeface(int index) override {
191 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 */
matchStyle(const SkFontStyle & pattern)201 SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
202 if (0 == fStyles.count()) {
203 return NULL;
204 }
205 SkTypeface_AndroidSystem* closest = fStyles[0];
206 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
218 private:
style(int index)219 SkFontStyle style(int index) {
220 return fStyles[index]->fontStyle();
221 }
match_score(const SkFontStyle & pattern,const SkFontStyle & candidate)222 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
223 int score = 0;
224 score += abs((pattern.width() - candidate.width()) * 100);
225 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
226 score += abs(pattern.weight() - candidate.weight());
227 return score;
228 }
229
230 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
231
232 friend struct NameToFamily;
233 friend class SkFontMgr_Android;
234
235 typedef SkFontStyleSet INHERITED;
236 };
237
238 /** On Android a single family can have many names, but our API assumes unique names.
239 * Map names to the back end so that all names for a given family refer to the same
240 * (non-replicated) set of typefaces.
241 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
242 */
243 struct NameToFamily {
244 SkString name;
245 SkFontStyleSet_Android* styleSet;
246 };
247
248 class SkFontMgr_Android : public SkFontMgr {
249 public:
SkFontMgr_Android(const SkFontMgr_Android_CustomFonts * custom)250 SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
251 SkTDArray<FontFamily*> families;
252 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
253 SkString base(custom->fBasePath);
254 SkFontConfigParser::GetCustomFontFamilies(families, base,
255 custom->fFontsXml, custom->fFallbackFontsXml);
256 }
257 if (!custom ||
258 (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
259 {
260 SkFontConfigParser::GetSystemFontFamilies(families);
261 }
262 if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
263 SkString base(custom->fBasePath);
264 SkFontConfigParser::GetCustomFontFamilies(families, base,
265 custom->fFontsXml, custom->fFallbackFontsXml);
266 }
267 this->buildNameToFamilyMap(families);
268 this->findDefaultFont();
269 families.deleteAll();
270 }
271
272 protected:
273 /** Returns not how many families we have, but how many unique names
274 * exist among the families.
275 */
onCountFamilies() const276 int onCountFamilies() const override {
277 return fNameToFamilyMap.count();
278 }
279
onGetFamilyName(int index,SkString * familyName) const280 void onGetFamilyName(int index, SkString* familyName) const override {
281 if (index < 0 || fNameToFamilyMap.count() <= index) {
282 familyName->reset();
283 return;
284 }
285 familyName->set(fNameToFamilyMap[index].name);
286 }
287
onCreateStyleSet(int index) const288 SkFontStyleSet* onCreateStyleSet(int index) const override {
289 if (index < 0 || fNameToFamilyMap.count() <= index) {
290 return NULL;
291 }
292 return SkRef(fNameToFamilyMap[index].styleSet);
293 }
294
onMatchFamily(const char familyName[]) const295 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
296 if (!familyName) {
297 return NULL;
298 }
299 SkAutoAsciiToLC tolc(familyName);
300 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
301 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
302 return SkRef(fNameToFamilyMap[i].styleSet);
303 }
304 }
305 // TODO: eventually we should not need to name fallback families.
306 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
307 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
308 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
309 }
310 }
311 return NULL;
312 }
313
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const314 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
315 const SkFontStyle& style) const override {
316 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
317 return sset->matchStyle(style);
318 }
319
onMatchFaceStyle(const SkTypeface * typeface,const SkFontStyle & style) const320 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
321 const SkFontStyle& style) const override {
322 for (int i = 0; i < fFontStyleSets.count(); ++i) {
323 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
324 if (fFontStyleSets[i]->fStyles[j] == typeface) {
325 return fFontStyleSets[i]->matchStyle(style);
326 }
327 }
328 }
329 return NULL;
330 }
331
find_family_style_character(const SkTDArray<NameToFamily> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)332 static SkTypeface_AndroidSystem* find_family_style_character(
333 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
334 const SkFontStyle& style, bool elegant,
335 const SkString& langTag, SkUnichar character)
336 {
337 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
338 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
339 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
340
341 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
342 continue;
343 }
344
345 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
346 continue;
347 }
348
349 SkPaint paint;
350 paint.setTypeface(face);
351 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
352
353 uint16_t glyphID;
354 paint.textToGlyphs(&character, sizeof(character), &glyphID);
355 if (glyphID != 0) {
356 return face.detach();
357 }
358 }
359 return NULL;
360 }
361
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const362 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
363 const SkFontStyle& style,
364 const char* bcp47[],
365 int bcp47Count,
366 SkUnichar character) const override
367 {
368 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
369 // The variant 'default' means 'compact and elegant'.
370 // As a result, it is not possible to know the variant context from the font alone.
371 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
372
373 // The first time match anything elegant, second time anything not elegant.
374 for (int elegant = 2; elegant --> 0;) {
375 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
376 SkLanguage lang(bcp47[bcp47Index]);
377 while (!lang.getTag().isEmpty()) {
378 SkTypeface_AndroidSystem* matchingTypeface =
379 find_family_style_character(fFallbackNameToFamilyMap,
380 style, SkToBool(elegant),
381 lang.getTag(), character);
382 if (matchingTypeface) {
383 return matchingTypeface;
384 }
385
386 lang = lang.getParent();
387 }
388 }
389 SkTypeface_AndroidSystem* matchingTypeface =
390 find_family_style_character(fFallbackNameToFamilyMap,
391 style, SkToBool(elegant),
392 SkString(), character);
393 if (matchingTypeface) {
394 return matchingTypeface;
395 }
396 }
397 return NULL;
398 }
399
onCreateFromData(SkData * data,int ttcIndex) const400 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
401 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
402 }
403
onCreateFromFile(const char path[],int ttcIndex) const404 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
405 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
406 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
407 }
408
onCreateFromStream(SkStreamAsset * bareStream,int ttcIndex) const409 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
410 SkAutoTDelete<SkStreamAsset> stream(bareStream);
411 bool isFixedPitch;
412 SkFontStyle style;
413 SkString name;
414 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
415 return NULL;
416 }
417 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream.detach(), ttcIndex,
418 style, isFixedPitch, name));
419 }
420
421
onLegacyCreateTypeface(const char familyName[],unsigned styleBits) const422 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
423 unsigned styleBits) const override {
424 SkFontStyle style = SkFontStyle(styleBits);
425
426 if (familyName) {
427 // On Android, we must return NULL when we can't find the requested
428 // named typeface so that the system/app can provide their own recovery
429 // mechanism. On other platforms we'd provide a typeface from the
430 // default family instead.
431 return this->onMatchFamilyStyle(familyName, style);
432 }
433 return fDefaultFamily->matchStyle(style);
434 }
435
436
437 private:
438
439 SkTypeface_FreeType::Scanner fScanner;
440
441 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
442 SkFontStyleSet* fDefaultFamily;
443 SkTypeface* fDefaultTypeface;
444
445 SkTDArray<NameToFamily> fNameToFamilyMap;
446 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
447
buildNameToFamilyMap(SkTDArray<FontFamily * > families)448 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
449 for (int i = 0; i < families.count(); i++) {
450 FontFamily& family = *families[i];
451
452 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
453 if (family.fIsFallbackFont) {
454 nameToFamily = &fFallbackNameToFamilyMap;
455
456 if (0 == family.fNames.count()) {
457 SkString& fallbackName = family.fNames.push_back();
458 fallbackName.printf("%.2x##fallback", i);
459 }
460 }
461
462 SkFontStyleSet_Android* newSet =
463 SkNEW_ARGS(SkFontStyleSet_Android, (family, fScanner));
464 if (0 == newSet->count()) {
465 SkDELETE(newSet);
466 continue;
467 }
468 fFontStyleSets.push_back().reset(newSet);
469
470 for (int j = 0; j < family.fNames.count(); j++) {
471 NameToFamily* nextEntry = nameToFamily->append();
472 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
473 nextEntry->styleSet = newSet;
474 }
475 }
476 }
477
findDefaultFont()478 void findDefaultFont() {
479 SkASSERT(!fFontStyleSets.empty());
480
481 static const char* gDefaultNames[] = { "sans-serif" };
482 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
483 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
484 if (NULL == set) {
485 continue;
486 }
487 SkTypeface* tf = set->matchStyle(SkFontStyle());
488 if (NULL == tf) {
489 continue;
490 }
491 fDefaultFamily = set;
492 fDefaultTypeface = tf;
493 break;
494 }
495 if (NULL == fDefaultTypeface) {
496 fDefaultFamily = fFontStyleSets[0];
497 fDefaultTypeface = fDefaultFamily->createTypeface(0);
498 }
499 SkASSERT(fDefaultFamily);
500 SkASSERT(fDefaultTypeface);
501 }
502
503 typedef SkFontMgr INHERITED;
504 };
505
506 ///////////////////////////////////////////////////////////////////////////////
507 #ifdef SK_DEBUG
508 static char const * const gSystemFontUseStrings[] = {
509 "OnlyCustom", "PreferCustom", "PreferSystem"
510 };
511 #endif
SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts * custom)512 SkFontMgr* SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
513 if (custom) {
514 SkASSERT(0 <= custom->fSystemFontUse);
515 SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
516 SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
517 gSystemFontUseStrings[custom->fSystemFontUse],
518 custom->fBasePath,
519 custom->fFontsXml,
520 custom->fFallbackFontsXml));
521 }
522
523 return SkNEW_ARGS(SkFontMgr_Android, (custom));
524 }
525
Factory()526 SkFontMgr* SkFontMgr::Factory() {
527 // These globals exist so that Chromium can override the environment.
528 // TODO: these globals need to be removed, and Chromium use SkFontMgr_New_Android instead.
529 if ((gTestFontsXml || gTestFallbackFontsXml) && gTestBasePath) {
530 SkFontMgr_Android_CustomFonts custom = {
531 SkFontMgr_Android_CustomFonts::kOnlyCustom,
532 gTestBasePath,
533 gTestFontsXml,
534 gTestFallbackFontsXml
535 };
536 return SkFontMgr_New_Android(&custom);
537 }
538
539 return SkFontMgr_New_Android(NULL);
540 }
541
SkUseTestFontConfigFile(const char * fontsXml,const char * fallbackFontsXml,const char * basePath)542 void SkUseTestFontConfigFile(const char* fontsXml, const char* fallbackFontsXml,
543 const char* basePath)
544 {
545 gTestFontsXml = fontsXml;
546 gTestFallbackFontsXml = fallbackFontsXml;
547 gTestBasePath = basePath;
548 SkASSERT(gTestFontsXml);
549 SkASSERT(gTestFallbackFontsXml);
550 SkASSERT(gTestBasePath);
551 SkDEBUGF(("Test BasePath: %s Fonts: %s FallbackFonts: %s\n",
552 gTestBasePath, gTestFontsXml, gTestFallbackFontsXml));
553 }
554