1 // Copyright 2019 Google LLC.
2 #include "include/core/SkTypeface.h"
3 #include "modules/skparagraph/include/FontCollection.h"
4 #include "modules/skparagraph/include/Paragraph.h"
5 #include "modules/skparagraph/src/ParagraphImpl.h"
6
7 namespace skia {
8 namespace textlayout {
9
operator ==(const FontCollection::FamilyKey & other) const10 bool FontCollection::FamilyKey::operator==(const FontCollection::FamilyKey& other) const {
11 return fFontFamily == other.fFontFamily && fLocale == other.fLocale &&
12 fFontStyle == other.fFontStyle;
13 }
14
operator ()(const FontCollection::FamilyKey & key) const15 size_t FontCollection::FamilyKey::Hasher::operator()(const FontCollection::FamilyKey& key) const {
16 return std::hash<std::string>()(key.fFontFamily.c_str()) ^
17 std::hash<std::string>()(key.fLocale.c_str()) ^
18 std::hash<uint32_t>()(key.fFontStyle.weight()) ^
19 std::hash<uint32_t>()(key.fFontStyle.slant());
20 }
21
FontCollection()22 FontCollection::FontCollection()
23 : fEnableFontFallback(true)
24 , fDefaultFamilyName(DEFAULT_FONT_FAMILY) { }
25
getFontManagersCount() const26 size_t FontCollection::getFontManagersCount() const { return this->getFontManagerOrder().size(); }
27
setAssetFontManager(sk_sp<SkFontMgr> font_manager)28 void FontCollection::setAssetFontManager(sk_sp<SkFontMgr> font_manager) {
29 fAssetFontManager = font_manager;
30 }
31
setDynamicFontManager(sk_sp<SkFontMgr> font_manager)32 void FontCollection::setDynamicFontManager(sk_sp<SkFontMgr> font_manager) {
33 fDynamicFontManager = font_manager;
34 }
35
setTestFontManager(sk_sp<SkFontMgr> font_manager)36 void FontCollection::setTestFontManager(sk_sp<SkFontMgr> font_manager) {
37 fTestFontManager = font_manager;
38 }
39
setDefaultFontManager(sk_sp<SkFontMgr> fontManager,const char defaultFamilyName[])40 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
41 const char defaultFamilyName[]) {
42 fDefaultFontManager = std::move(fontManager);
43 fDefaultFamilyName = defaultFamilyName;
44 }
45
setDefaultFontManager(sk_sp<SkFontMgr> fontManager)46 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager) {
47 fDefaultFontManager = fontManager;
48 }
49
50 // Return the available font managers in the order they should be queried.
getFontManagerOrder() const51 std::vector<sk_sp<SkFontMgr>> FontCollection::getFontManagerOrder() const {
52 std::vector<sk_sp<SkFontMgr>> order;
53 if (fDynamicFontManager) {
54 order.push_back(fDynamicFontManager);
55 }
56 if (fAssetFontManager) {
57 order.push_back(fAssetFontManager);
58 }
59 if (fTestFontManager) {
60 order.push_back(fTestFontManager);
61 }
62 if (fDefaultFontManager && fEnableFontFallback) {
63 order.push_back(fDefaultFontManager);
64 }
65 return order;
66 }
67
matchTypeface(const char familyName[],SkFontStyle fontStyle)68 sk_sp<SkTypeface> FontCollection::matchTypeface(const char familyName[], SkFontStyle fontStyle) {
69 // Look inside the font collections cache first
70 FamilyKey familyKey(familyName, "en", fontStyle);
71 auto found = fTypefaces.find(familyKey);
72 if (found) {
73 return *found;
74 }
75
76 sk_sp<SkTypeface> typeface = nullptr;
77 for (const auto& manager : this->getFontManagerOrder()) {
78 SkFontStyleSet* set = manager->matchFamily(familyName);
79 if (nullptr == set || set->count() == 0) {
80 continue;
81 }
82
83 for (int i = 0; i < set->count(); ++i) {
84 set->createTypeface(i);
85 }
86
87 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
88 if (match) {
89 typeface = std::move(match);
90 return typeface;
91 }
92 }
93
94 return nullptr;
95 }
96
matchDefaultTypeface(SkFontStyle fontStyle)97 sk_sp<SkTypeface> FontCollection::matchDefaultTypeface(SkFontStyle fontStyle) {
98 // Look inside the font collections cache first
99 FamilyKey familyKey(fDefaultFamilyName, "en", fontStyle);
100 auto found = fTypefaces.find(familyKey);
101 if (found) {
102 return *found;
103 }
104
105 sk_sp<SkTypeface> typeface = nullptr;
106 for (const auto& manager : this->getFontManagerOrder()) {
107 SkFontStyleSet* set = manager->matchFamily(fDefaultFamilyName);
108 if (nullptr == set || set->count() == 0) {
109 continue;
110 }
111
112 for (int i = 0; i < set->count(); ++i) {
113 set->createTypeface(i);
114 }
115
116 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
117 if (match) {
118 typeface = std::move(match);
119 return typeface;
120 }
121 }
122
123 return nullptr;
124 }
125
defaultFallback(SkUnichar unicode,SkFontStyle fontStyle,const SkString & locale)126 sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, const SkString& locale) {
127
128 for (const auto& manager : this->getFontManagerOrder()) {
129 std::vector<const char*> bcp47;
130 if (!locale.isEmpty()) {
131 bcp47.push_back(locale.c_str());
132 }
133 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
134 0, fontStyle, bcp47.data(), bcp47.size(), unicode));
135 if (typeface != nullptr) {
136 return typeface;
137 }
138 }
139
140 if (fDefaultFontManager == nullptr) {
141 return nullptr;
142 }
143 auto result = fDefaultFontManager->matchFamilyStyle(fDefaultFamilyName, fontStyle);
144 return sk_ref_sp<SkTypeface>(result);
145 }
146
disableFontFallback()147 void FontCollection::disableFontFallback() { fEnableFontFallback = false; }
148
149 } // namespace textlayout
150 } // namespace skia
151