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