• 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 "include/core/SkTypes.h"
9 
10 #include "include/core/SkData.h"
11 #include "include/core/SkFontMgr.h"
12 #include "include/core/SkFontStyle.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkStream.h"
16 #include "include/core/SkString.h"
17 #include "include/ports/SkFontMgr_android.h"
18 #include "include/private/SkFixed.h"
19 #include "include/private/SkTArray.h"
20 #include "include/private/SkTDArray.h"
21 #include "include/private/SkTemplates.h"
22 #include "src/core/SkFontDescriptor.h"
23 #include "src/core/SkOSFile.h"
24 #include "src/core/SkTSearch.h"
25 #include "src/core/SkTypefaceCache.h"
26 #include "src/ports/SkFontHost_FreeType_common.h"
27 #include "src/ports/SkFontMgr_android_parser.h"
28 
29 #include <algorithm>
30 #include <limits>
31 
32 constexpr char ORIGIN_MY_LOCALE[] = "my-Qaag";
33 constexpr char ANDROID_MY_LOCALE[] = "und-Qaag";
34 
35 class SkData;
36 
37 class SkTypeface_Android : public SkTypeface_FreeType {
38 public:
SkTypeface_Android(const SkFontStyle & style,bool isFixedPitch,const SkString & familyName)39     SkTypeface_Android(const SkFontStyle& style,
40                        bool isFixedPitch,
41                        const SkString& familyName)
42         : INHERITED(style, isFixedPitch)
43         , fFamilyName(familyName)
44         { }
45 
46 protected:
onGetFamilyName(SkString * familyName) const47     void onGetFamilyName(SkString* familyName) const override {
48         *familyName = fFamilyName;
49     }
50 
51     SkString fFamilyName;
52 
53 private:
54     using INHERITED = SkTypeface_FreeType;
55 };
56 
57 class SkTypeface_AndroidSystem : public SkTypeface_Android {
58 public:
SkTypeface_AndroidSystem(const SkString & pathName,const bool cacheFontFiles,int index,const SkFixed * axes,int axesCount,const SkFontStyle & style,bool isFixedPitch,const SkString & familyName,const SkTArray<SkLanguage,true> & lang,FontVariant variantStyle)59     SkTypeface_AndroidSystem(const SkString& pathName,
60                              const bool cacheFontFiles,
61                              int index,
62                              const SkFixed* axes, int axesCount,
63                              const SkFontStyle& style,
64                              bool isFixedPitch,
65                              const SkString& familyName,
66                              const SkTArray<SkLanguage, true>& lang,
67                              FontVariant variantStyle)
68         : INHERITED(style, isFixedPitch, familyName)
69         , fPathName(pathName)
70         , fIndex(index)
71         , fAxes(axes, axesCount)
72         , fLang(lang)
73         , fVariantStyle(variantStyle)
74         , fFile(cacheFontFiles ? sk_fopen(fPathName.c_str(), kRead_SkFILE_Flag) : nullptr) {
75         if (cacheFontFiles) {
76             SkASSERT(fFile);
77         }
78     }
79 
makeStream() const80     std::unique_ptr<SkStreamAsset> makeStream() const {
81         if (fFile) {
82             sk_sp<SkData> data(SkData::MakeFromFILE(fFile));
83             return data ? std::make_unique<SkMemoryStream>(std::move(data)) : nullptr;
84         }
85         return SkStream::MakeFromFile(fPathName.c_str());
86     }
87 
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const88     void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
89         SkASSERT(desc);
90         SkASSERT(serialize);
91         desc->setFamilyName(fFamilyName.c_str());
92         desc->setStyle(this->fontStyle());
93         *serialize = false;
94     }
onOpenStream(int * ttcIndex) const95     std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override {
96         *ttcIndex = fIndex;
97         return this->makeStream();
98     }
onMakeFontData() const99     std::unique_ptr<SkFontData> onMakeFontData() const override {
100         return std::make_unique<SkFontData>(this->makeStream(), fIndex,
101                                               fAxes.begin(), fAxes.count());
102     }
onMakeClone(const SkFontArguments & args) const103     sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
104         std::unique_ptr<SkFontData> data = this->cloneFontData(args);
105         if (!data) {
106             return nullptr;
107         }
108         return sk_make_sp<SkTypeface_AndroidSystem>(fPathName,
109                                                     fFile,
110                                                     fIndex,
111                                                     data->getAxis(),
112                                                     data->getAxisCount(),
113                                                     this->fontStyle(),
114                                                     this->isFixedPitch(),
115                                                     fFamilyName,
116                                                     fLang,
117                                                     fVariantStyle);
118     }
119 
120     const SkString fPathName;
121     int fIndex;
122     const SkSTArray<4, SkFixed, true> fAxes;
123     const SkSTArray<4, SkLanguage, true> fLang;
124     const FontVariant fVariantStyle;
125     SkAutoTCallVProc<FILE, sk_fclose> fFile;
126 
127     using INHERITED = SkTypeface_Android;
128 };
129 
130 class SkTypeface_AndroidStream : public SkTypeface_Android {
131 public:
SkTypeface_AndroidStream(std::unique_ptr<SkFontData> data,const SkFontStyle & style,bool isFixedPitch,const SkString & familyName)132     SkTypeface_AndroidStream(std::unique_ptr<SkFontData> data,
133                              const SkFontStyle& style,
134                              bool isFixedPitch,
135                              const SkString& familyName)
136         : INHERITED(style, isFixedPitch, familyName)
137         , fData(std::move(data))
138     { }
139 
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const140     void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
141         SkASSERT(desc);
142         SkASSERT(serialize);
143         desc->setFamilyName(fFamilyName.c_str());
144         *serialize = true;
145     }
146 
onOpenStream(int * ttcIndex) const147     std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override {
148         *ttcIndex = fData->getIndex();
149         return fData->getStream()->duplicate();
150     }
151 
onMakeFontData() const152     std::unique_ptr<SkFontData> onMakeFontData() const override {
153         return std::make_unique<SkFontData>(*fData);
154     }
155 
onMakeClone(const SkFontArguments & args) const156     sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
157         std::unique_ptr<SkFontData> data = this->cloneFontData(args);
158         if (!data) {
159             return nullptr;
160         }
161         return sk_make_sp<SkTypeface_AndroidStream>(std::move(data),
162                                                     this->fontStyle(),
163                                                     this->isFixedPitch(),
164                                                     fFamilyName);
165     }
166 
167 private:
168     const std::unique_ptr<const SkFontData> fData;
169     using INHERITED = SkTypeface_Android;
170 };
171 
172 class SkFontStyleSet_Android : public SkFontStyleSet {
173     typedef SkTypeface_FreeType::Scanner Scanner;
174 
175 public:
SkFontStyleSet_Android(const FontFamily & family,const Scanner & scanner,const bool cacheFontFiles)176     explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner,
177                                     const bool cacheFontFiles) {
178         const SkString* cannonicalFamilyName = nullptr;
179         if (family.fNames.count() > 0) {
180             cannonicalFamilyName = &family.fNames[0];
181         }
182         fFallbackFor = family.fFallbackFor;
183 
184         // TODO? make this lazy
185         for (int i = 0; i < family.fFonts.count(); ++i) {
186             const FontFileInfo& fontFile = family.fFonts[i];
187 
188             SkString pathName(family.fBasePath);
189             pathName.append(fontFile.fFileName);
190 
191             std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(pathName.c_str());
192             if (!stream) {
193                 SkDEBUGF("Requested font file %s does not exist or cannot be opened.\n",
194                          pathName.c_str());
195                 continue;
196             }
197 
198             const int ttcIndex = fontFile.fIndex;
199             SkString familyName;
200             SkFontStyle style;
201             bool isFixedWidth;
202             Scanner::AxisDefinitions axisDefinitions;
203             if (!scanner.scanFont(stream.get(), ttcIndex,
204                                   &familyName, &style, &isFixedWidth, &axisDefinitions))
205             {
206                 SkDEBUGF("Requested font file %s exists, but is not a valid font.\n",
207                          pathName.c_str());
208                 continue;
209             }
210 
211             int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
212             SkFontStyle::Slant slant = style.slant();
213             switch (fontFile.fStyle) {
214                 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
215                 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
216                 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
217                 default: SkASSERT(false); break;
218             }
219             style = SkFontStyle(weight, style.width(), slant);
220 
221             uint32_t variant = family.fVariant;
222             if (kDefault_FontVariant == variant) {
223                 variant = kCompact_FontVariant | kElegant_FontVariant;
224             }
225 
226             // The first specified family name overrides the family name found in the font.
227             // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
228             // all of the specified family names in addition to the names found in the font.
229             if (cannonicalFamilyName != nullptr) {
230                 familyName = *cannonicalFamilyName;
231             }
232 
233             SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
234             SkFontArguments::VariationPosition position = {
235                 fontFile.fVariationDesignPosition.begin(),
236                 fontFile.fVariationDesignPosition.count()
237             };
238             Scanner::computeAxisValues(axisDefinitions, position,
239                                        axisValues, familyName);
240 
241             fStyles.push_back().reset(new SkTypeface_AndroidSystem(
242                     pathName, cacheFontFiles, ttcIndex, axisValues.get(), axisDefinitions.count(),
243                     style, isFixedWidth, familyName, family.fLanguages, variant));
244         }
245     }
246 
count()247     int count() override {
248         return fStyles.count();
249     }
getStyle(int index,SkFontStyle * style,SkString * name)250     void getStyle(int index, SkFontStyle* style, SkString* name) override {
251         if (index < 0 || fStyles.count() <= index) {
252             return;
253         }
254         if (style) {
255             *style = fStyles[index]->fontStyle();
256         }
257         if (name) {
258             name->reset();
259         }
260     }
createTypeface(int index)261     SkTypeface_AndroidSystem* createTypeface(int index) override {
262         if (index < 0 || fStyles.count() <= index) {
263             return nullptr;
264         }
265         return SkRef(fStyles[index].get());
266     }
267 
matchStyle(const SkFontStyle & pattern)268     SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
269         return static_cast<SkTypeface_AndroidSystem*>(this->matchStyleCSS3(pattern));
270     }
271 
272 private:
273     SkTArray<sk_sp<SkTypeface_AndroidSystem>> fStyles;
274     SkString fFallbackFor;
275 
276     friend struct NameToFamily;
277     friend class SkFontMgr_Android;
278 
279     using INHERITED = SkFontStyleSet;
280 };
281 
282 /** On Android a single family can have many names, but our API assumes unique names.
283  *  Map names to the back end so that all names for a given family refer to the same
284  *  (non-replicated) set of typefaces.
285  *  SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
286  */
287 struct NameToFamily {
288     SkString name;
289     SkFontStyleSet_Android* styleSet;
290 };
291 
292 class SkFontMgr_Android : public SkFontMgr {
293 public:
SkFontMgr_Android(const SkFontMgr_Android_CustomFonts * custom)294     SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
295         SkTDArray<FontFamily*> families;
296         if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
297             SkString base(custom->fBasePath);
298             SkFontMgr_Android_Parser::GetCustomFontFamilies(
299                 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
300         }
301         if (!custom ||
302             (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
303         {
304             SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
305         }
306         if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
307             SkString base(custom->fBasePath);
308             SkFontMgr_Android_Parser::GetCustomFontFamilies(
309                 families, base, custom->fFontsXml, custom->fFallbackFontsXml);
310         }
311         this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false);
312         this->findDefaultStyleSet();
313         families.deleteAll();
314     }
315 
316 protected:
317     /** Returns not how many families we have, but how many unique names
318      *  exist among the families.
319      */
onCountFamilies() const320     int onCountFamilies() const override {
321         return fNameToFamilyMap.count();
322     }
323 
onGetFamilyName(int index,SkString * familyName) const324     void onGetFamilyName(int index, SkString* familyName) const override {
325         if (index < 0 || fNameToFamilyMap.count() <= index) {
326             familyName->reset();
327             return;
328         }
329         familyName->set(fNameToFamilyMap[index].name);
330     }
331 
onCreateStyleSet(int index) const332     SkFontStyleSet* onCreateStyleSet(int index) const override {
333         if (index < 0 || fNameToFamilyMap.count() <= index) {
334             return nullptr;
335         }
336         return SkRef(fNameToFamilyMap[index].styleSet);
337     }
338 
onMatchFamily(const char familyName[]) const339     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
340         if (!familyName) {
341             return nullptr;
342         }
343         SkAutoAsciiToLC tolc(familyName);
344         for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
345             if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
346                 return SkRef(fNameToFamilyMap[i].styleSet);
347             }
348         }
349         // TODO: eventually we should not need to name fallback families.
350         for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
351             if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
352                 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
353             }
354         }
355         return nullptr;
356     }
357 
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const358     SkTypeface* onMatchFamilyStyle(const char familyName[],
359                                    const SkFontStyle& style) const override {
360         sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
361         return sset->matchStyle(style);
362     }
363 
find_family_style_character(const SkString & familyName,const SkTArray<NameToFamily,true> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)364     static sk_sp<SkTypeface_AndroidSystem> find_family_style_character(
365             const SkString& familyName,
366             const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap,
367             const SkFontStyle& style, bool elegant,
368             const SkString& langTag, SkUnichar character)
369     {
370         SkString localeLangTag = langTag;
371         if (localeLangTag.find(ORIGIN_MY_LOCALE) >= 0) {
372             localeLangTag = ANDROID_MY_LOCALE;
373         }
374 
375         for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
376             SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
377             if (familyName != family->fFallbackFor) {
378                 continue;
379             }
380             sk_sp<SkTypeface_AndroidSystem> face(family->matchStyle(style));
381 
382             if (!localeLangTag.isEmpty() &&
383                 std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang) {
384                     return lang.getTag().startsWith(localeLangTag.c_str());
385                 }))
386             {
387                 continue;
388             }
389 
390             if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
391                 continue;
392             }
393 
394             if (face->unicharToGlyph(character) != 0) {
395                 return face;
396             }
397         }
398         return nullptr;
399     }
400 
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const401     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
402                                             const SkFontStyle& style,
403                                             const char* bcp47[],
404                                             int bcp47Count,
405                                             SkUnichar character) const override {
406         // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
407         // The variant 'default' means 'compact and elegant'.
408         // As a result, it is not possible to know the variant context from the font alone.
409         // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
410 
411         SkString familyNameString(familyName);
412         for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
413             // The first time match anything elegant, second time anything not elegant.
414             for (int elegant = 2; elegant --> 0;) {
415                 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
416                     SkLanguage lang(bcp47[bcp47Index]);
417                     while (!lang.getTag().isEmpty()) {
418                         sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
419                             find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
420                                                         style, SkToBool(elegant),
421                                                         lang.getTag(), character);
422                         if (matchingTypeface) {
423                             return matchingTypeface.release();
424                         }
425 
426                         lang = lang.getParent();
427                     }
428                 }
429                 sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
430                     find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
431                                                 style, SkToBool(elegant),
432                                                 SkString(), character);
433                 if (matchingTypeface) {
434                     return matchingTypeface.release();
435                 }
436             }
437         }
438         return nullptr;
439     }
440 
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const441     sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
442         return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
443                                     ttcIndex);
444     }
445 
onMakeFromFile(const char path[],int ttcIndex) const446     sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
447         std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
448         return stream ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
449     }
450 
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const451     sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
452                                             int ttcIndex) const override {
453         bool isFixedPitch;
454         SkFontStyle style;
455         SkString name;
456         if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
457             return nullptr;
458         }
459         auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
460         return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
461                                                               style, isFixedPitch, name));
462     }
463 
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args) const464     sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
465                                            const SkFontArguments& args) const override {
466         using Scanner = SkTypeface_FreeType::Scanner;
467         bool isFixedPitch;
468         SkFontStyle style;
469         SkString name;
470         Scanner::AxisDefinitions axisDefinitions;
471         if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
472                                &name, &style, &isFixedPitch, &axisDefinitions))
473         {
474             return nullptr;
475         }
476 
477         SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
478         Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
479                                    axisValues, name);
480 
481         auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
482                                                    axisValues.get(), axisDefinitions.count());
483         return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
484                                                               style, isFixedPitch, name));
485     }
486 
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const487     sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
488         if (familyName) {
489             // On Android, we must return nullptr when we can't find the requested
490             // named typeface so that the system/app can provide their own recovery
491             // mechanism. On other platforms we'd provide a typeface from the
492             // default family instead.
493             return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
494         }
495         return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
496     }
497 
498 
499 private:
500 
501     SkTypeface_FreeType::Scanner fScanner;
502 
503     SkTArray<sk_sp<SkFontStyleSet_Android>> fStyleSets;
504     sk_sp<SkFontStyleSet> fDefaultStyleSet;
505 
506     SkTArray<NameToFamily, true> fNameToFamilyMap;
507     SkTArray<NameToFamily, true> fFallbackNameToFamilyMap;
508 
addFamily(FontFamily & family,const bool isolated,int familyIndex)509     void addFamily(FontFamily& family, const bool isolated, int familyIndex) {
510         SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
511         if (family.fIsFallbackFont) {
512             nameToFamily = &fFallbackNameToFamilyMap;
513 
514             if (0 == family.fNames.count()) {
515                 SkString& fallbackName = family.fNames.push_back();
516                 fallbackName.printf("%.2x##fallback", familyIndex);
517             }
518         }
519 
520         sk_sp<SkFontStyleSet_Android> newSet =
521             sk_make_sp<SkFontStyleSet_Android>(family, fScanner, isolated);
522         if (0 == newSet->count()) {
523             return;
524         }
525 
526         for (const SkString& name : family.fNames) {
527             nameToFamily->emplace_back(NameToFamily{name, newSet.get()});
528         }
529         fStyleSets.emplace_back(std::move(newSet));
530     }
buildNameToFamilyMap(SkTDArray<FontFamily * > families,const bool isolated)531     void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
532         int familyIndex = 0;
533         for (FontFamily* family : families) {
534             addFamily(*family, isolated, familyIndex++);
535             for (const auto& [unused, fallbackFamily] : family->fallbackFamilies) {
536                 addFamily(*fallbackFamily, isolated, familyIndex++);
537             }
538         }
539     }
540 
findDefaultStyleSet()541     void findDefaultStyleSet() {
542         SkASSERT(!fStyleSets.empty());
543 
544         static const char* defaultNames[] = { "sans-serif" };
545         for (const char* defaultName : defaultNames) {
546             fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
547             if (fDefaultStyleSet) {
548                 break;
549             }
550         }
551         if (nullptr == fDefaultStyleSet) {
552             fDefaultStyleSet = fStyleSets[0];
553         }
554         SkASSERT(fDefaultStyleSet);
555     }
556 
557     using INHERITED = SkFontMgr;
558 };
559 
560 #ifdef SK_DEBUG
561 static char const * const gSystemFontUseStrings[] = {
562     "OnlyCustom", "PreferCustom", "PreferSystem"
563 };
564 #endif
565 
SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts * custom)566 sk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
567     if (custom) {
568         SkASSERT(0 <= custom->fSystemFontUse);
569         SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
570         SkDEBUGF("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
571                  gSystemFontUseStrings[custom->fSystemFontUse],
572                  custom->fBasePath,
573                  custom->fFontsXml,
574                  custom->fFallbackFontsXml);
575     }
576     return sk_make_sp<SkFontMgr_Android>(custom);
577 }
578