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