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 #include "modules/skshaper/include/SkShaper.h"
7
8 namespace skia {
9 namespace textlayout {
10
operator ==(const FontCollection::FamilyKey & other) const11 bool FontCollection::FamilyKey::operator==(const FontCollection::FamilyKey& other) const {
12 return fFamilyNames == other.fFamilyNames &&
13 fFontStyle == other.fFontStyle &&
14 fFontArguments == other.fFontArguments;
15 }
16
operator ()(const FontCollection::FamilyKey & key) const17 size_t FontCollection::FamilyKey::Hasher::operator()(const FontCollection::FamilyKey& key) const {
18 size_t hash = 0;
19 for (const SkString& family : key.fFamilyNames) {
20 hash ^= std::hash<std::string>()(family.c_str());
21 }
22 return hash ^
23 std::hash<uint32_t>()(key.fFontStyle.weight()) ^
24 std::hash<uint32_t>()(key.fFontStyle.slant()) ^
25 std::hash<std::optional<FontArguments>>()(key.fFontArguments);
26 }
27
FontCollection()28 FontCollection::FontCollection()
29 : fEnableFontFallback(true)
30 , fDefaultFamilyNames({SkString(DEFAULT_FONT_FAMILY)}) { }
31
getFontManagersCount() const32 size_t FontCollection::getFontManagersCount() const { return this->getFontManagerOrder().size(); }
33
setAssetFontManager(sk_sp<SkFontMgr> font_manager)34 void FontCollection::setAssetFontManager(sk_sp<SkFontMgr> font_manager) {
35 fAssetFontManager = font_manager;
36 }
37
setDynamicFontManager(sk_sp<SkFontMgr> font_manager)38 void FontCollection::setDynamicFontManager(sk_sp<SkFontMgr> font_manager) {
39 fDynamicFontManager = font_manager;
40 }
41
setTestFontManager(sk_sp<SkFontMgr> font_manager)42 void FontCollection::setTestFontManager(sk_sp<SkFontMgr> font_manager) {
43 fTestFontManager = font_manager;
44 }
45
setDefaultFontManager(sk_sp<SkFontMgr> fontManager,const char defaultFamilyName[])46 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
47 const char defaultFamilyName[]) {
48 fDefaultFontManager = std::move(fontManager);
49 fDefaultFamilyNames.emplace_back(defaultFamilyName);
50 }
51
setDefaultFontManager(sk_sp<SkFontMgr> fontManager,const std::vector<SkString> & defaultFamilyNames)52 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
53 const std::vector<SkString>& defaultFamilyNames) {
54 fDefaultFontManager = std::move(fontManager);
55 fDefaultFamilyNames = defaultFamilyNames;
56 }
57
setDefaultFontManager(sk_sp<SkFontMgr> fontManager)58 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager) {
59 fDefaultFontManager = fontManager;
60 }
61
62 // Return the available font managers in the order they should be queried.
getFontManagerOrder() const63 std::vector<sk_sp<SkFontMgr>> FontCollection::getFontManagerOrder() const {
64 std::vector<sk_sp<SkFontMgr>> order;
65 if (fDynamicFontManager) {
66 order.push_back(fDynamicFontManager);
67 }
68 if (fAssetFontManager) {
69 order.push_back(fAssetFontManager);
70 }
71 if (fTestFontManager) {
72 order.push_back(fTestFontManager);
73 }
74 if (fDefaultFontManager && fEnableFontFallback) {
75 order.push_back(fDefaultFontManager);
76 }
77 return order;
78 }
79
findTypefaces(const std::vector<SkString> & familyNames,SkFontStyle fontStyle)80 std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle) {
81 return findTypefaces(familyNames, fontStyle, std::nullopt);
82 }
83
findTypefaces(const std::vector<SkString> & familyNames,SkFontStyle fontStyle,const std::optional<FontArguments> & fontArgs)84 std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle, const std::optional<FontArguments>& fontArgs) {
85 // Look inside the font collections cache first
86 FamilyKey familyKey(familyNames, fontStyle, fontArgs);
87 auto found = fTypefaces.find(familyKey);
88 if (found) {
89 return *found;
90 }
91
92 std::vector<sk_sp<SkTypeface>> typefaces;
93 for (const SkString& familyName : familyNames) {
94 sk_sp<SkTypeface> match = matchTypeface(familyName, fontStyle);
95 if (match && fontArgs) {
96 match = fontArgs->CloneTypeface(match);
97 }
98 if (match) {
99 typefaces.emplace_back(std::move(match));
100 }
101 }
102
103 if (typefaces.empty()) {
104 sk_sp<SkTypeface> match;
105 for (const SkString& familyName : fDefaultFamilyNames) {
106 match = matchTypeface(familyName, fontStyle);
107 if (match) {
108 break;
109 }
110 }
111 if (!match) {
112 for (const auto& manager : this->getFontManagerOrder()) {
113 match = manager->legacyMakeTypeface(nullptr, fontStyle);
114 if (match) {
115 break;
116 }
117 }
118 }
119 if (match) {
120 typefaces.emplace_back(std::move(match));
121 }
122 }
123
124 fTypefaces.set(familyKey, typefaces);
125 return typefaces;
126 }
127
matchTypeface(const SkString & familyName,SkFontStyle fontStyle)128 sk_sp<SkTypeface> FontCollection::matchTypeface(const SkString& familyName, SkFontStyle fontStyle) {
129 for (const auto& manager : this->getFontManagerOrder()) {
130 sk_sp<SkFontStyleSet> set(manager->matchFamily(familyName.c_str()));
131 if (!set || set->count() == 0) {
132 continue;
133 }
134
135 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
136 if (match) {
137 return match;
138 }
139 }
140
141 return nullptr;
142 }
143
144 // Find ANY font in available font managers that resolves the unicode codepoint
defaultFallback(SkUnichar unicode,SkFontStyle fontStyle,const SkString & locale)145 sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, const SkString& locale) {
146
147 for (const auto& manager : this->getFontManagerOrder()) {
148 std::vector<const char*> bcp47;
149 if (!locale.isEmpty()) {
150 bcp47.push_back(locale.c_str());
151 }
152 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
153 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
154 if (typeface != nullptr) {
155 return typeface;
156 }
157 }
158 return nullptr;
159 }
160
defaultFallback()161 sk_sp<SkTypeface> FontCollection::defaultFallback() {
162 if (fDefaultFontManager == nullptr) {
163 return nullptr;
164 }
165 for (const SkString& familyName : fDefaultFamilyNames) {
166 SkTypeface* match = fDefaultFontManager->matchFamilyStyle(familyName.c_str(),
167 SkFontStyle());
168 if (match) {
169 return sk_sp<SkTypeface>(match);
170 }
171 }
172 return nullptr;
173 }
174
175
disableFontFallback()176 void FontCollection::disableFontFallback() { fEnableFontFallback = false; }
enableFontFallback()177 void FontCollection::enableFontFallback() { fEnableFontFallback = true; }
178
clearCaches()179 void FontCollection::clearCaches() {
180 fParagraphCache.reset();
181 fTypefaces.reset();
182 SkShaper::PurgeCaches();
183 }
184
185 } // namespace textlayout
186 } // namespace skia
187