• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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