Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FontCollection.cpp
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
3
8
9namespace {
10#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
11 const char* kColorEmojiFontMac = "Apple Color Emoji";
12#else
13 const char* kColorEmojiLocale = "und-Zsye";
14#endif
15}
16namespace skia {
17namespace textlayout {
18
19bool FontCollection::FamilyKey::operator==(const FontCollection::FamilyKey& other) const {
20 return fFamilyNames == other.fFamilyNames &&
21 fFontStyle == other.fFontStyle &&
22 fFontArguments == other.fFontArguments;
23}
24
25size_t FontCollection::FamilyKey::Hasher::operator()(const FontCollection::FamilyKey& key) const {
26 size_t hash = 0;
27 for (const SkString& family : key.fFamilyNames) {
28 hash ^= std::hash<std::string>()(family.c_str());
29 }
30 return hash ^
31 std::hash<uint32_t>()(key.fFontStyle.weight()) ^
32 std::hash<uint32_t>()(key.fFontStyle.slant()) ^
33 std::hash<std::optional<FontArguments>>()(key.fFontArguments);
34}
35
37 : fEnableFontFallback(true)
38 , fDefaultFamilyNames({SkString(DEFAULT_FONT_FAMILY)}) { }
39
40size_t FontCollection::getFontManagersCount() const { return this->getFontManagerOrder().size(); }
41
43 fAssetFontManager = std::move(font_manager);
44}
45
47 fDynamicFontManager = std::move(font_manager);
48}
49
51 fTestFontManager = std::move(font_manager);
52}
53
55 const char defaultFamilyName[]) {
56 fDefaultFontManager = std::move(fontManager);
57 fDefaultFamilyNames.emplace_back(defaultFamilyName);
58}
59
61 const std::vector<SkString>& defaultFamilyNames) {
62 fDefaultFontManager = std::move(fontManager);
63 fDefaultFamilyNames = defaultFamilyNames;
64}
65
67 fDefaultFontManager = std::move(fontManager);
68}
69
70// Return the available font managers in the order they should be queried.
71std::vector<sk_sp<SkFontMgr>> FontCollection::getFontManagerOrder() const {
72 std::vector<sk_sp<SkFontMgr>> order;
73 if (fDynamicFontManager) {
74 order.push_back(fDynamicFontManager);
75 }
76 if (fAssetFontManager) {
77 order.push_back(fAssetFontManager);
78 }
79 if (fTestFontManager) {
80 order.push_back(fTestFontManager);
81 }
82 if (fDefaultFontManager && fEnableFontFallback) {
83 order.push_back(fDefaultFontManager);
84 }
85 return order;
86}
87
88std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle) {
89 return findTypefaces(familyNames, fontStyle, std::nullopt);
90}
91
92std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle, const std::optional<FontArguments>& fontArgs) {
93 // Look inside the font collections cache first
94 FamilyKey familyKey(familyNames, fontStyle, fontArgs);
95 auto found = fTypefaces.find(familyKey);
96 if (found) {
97 return *found;
98 }
99
100 std::vector<sk_sp<SkTypeface>> typefaces;
101 for (const SkString& familyName : familyNames) {
102 sk_sp<SkTypeface> match = matchTypeface(familyName, fontStyle);
103 if (match && fontArgs) {
104 match = fontArgs->CloneTypeface(match);
105 }
106 if (match) {
107 typefaces.emplace_back(std::move(match));
108 }
109 }
110
111 if (typefaces.empty()) {
113 for (const SkString& familyName : fDefaultFamilyNames) {
114 match = matchTypeface(familyName, fontStyle);
115 if (match) {
116 break;
117 }
118 }
119 if (!match) {
120 for (const auto& manager : this->getFontManagerOrder()) {
121 match = manager->legacyMakeTypeface(nullptr, fontStyle);
122 if (match) {
123 break;
124 }
125 }
126 }
127 if (match) {
128 typefaces.emplace_back(std::move(match));
129 }
130 }
131
132 fTypefaces.set(familyKey, typefaces);
133 return typefaces;
134}
135
136sk_sp<SkTypeface> FontCollection::matchTypeface(const SkString& familyName, SkFontStyle fontStyle) {
137 for (const auto& manager : this->getFontManagerOrder()) {
138 sk_sp<SkFontStyleSet> set(manager->matchFamily(familyName.c_str()));
139 if (!set || set->count() == 0) {
140 continue;
141 }
142
143 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
144 if (match) {
145 return match;
146 }
147 }
148
149 return nullptr;
150}
151
152// Find ANY font in available font managers that resolves the unicode codepoint
154 SkFontStyle fontStyle,
155 const SkString& locale) {
156
157 for (const auto& manager : this->getFontManagerOrder()) {
158 std::vector<const char*> bcp47;
159 if (!locale.isEmpty()) {
160 bcp47.push_back(locale.c_str());
161 }
162 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
163 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
164
165 if (typeface != nullptr) {
166 return typeface;
167 }
168 }
169 return nullptr;
170}
171
172// Find ANY font in available font managers that resolves this emojiStart
174 SkFontStyle fontStyle,
175 const SkString& locale) {
176
177 for (const auto& manager : this->getFontManagerOrder()) {
178 std::vector<const char*> bcp47;
179#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
180 sk_sp<SkTypeface> emojiTypeface =
181 fDefaultFontManager->matchFamilyStyle(kColorEmojiFontMac, SkFontStyle());
182 if (emojiTypeface != nullptr) {
183 return emojiTypeface;
184 }
185#else
186 bcp47.push_back(kColorEmojiLocale);
187#endif
188 if (!locale.isEmpty()) {
189 bcp47.push_back(locale.c_str());
190 }
191
192 // Not really ideal since the first codepoint may not be the best one
193 // but we start from a good colored emoji at least
194 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
195 nullptr, fontStyle, bcp47.data(), bcp47.size(), emojiStart));
196 if (typeface != nullptr) {
197 // ... and stop as soon as we find something in hope it will work for all of them
198 return typeface;
199 }
200 }
201 return nullptr;
202}
203
205 if (fDefaultFontManager == nullptr) {
206 return nullptr;
207 }
208 for (const SkString& familyName : fDefaultFamilyNames) {
209 sk_sp<SkTypeface> match = fDefaultFontManager->matchFamilyStyle(familyName.c_str(),
210 SkFontStyle());
211 if (match) {
212 return match;
213 }
214 }
215 return nullptr;
216}
217
218void FontCollection::disableFontFallback() { fEnableFontFallback = false; }
219void FontCollection::enableFontFallback() { fEnableFontFallback = true; }
220
222 fParagraphCache.reset();
223 fTypefaces.reset();
225}
226
227} // namespace textlayout
228} // namespace skia
static bool match(const char *needle, const char *haystack)
Definition DM.cpp:1132
static uint32_t hash(const SkShaderBase::GradientInfo &v)
int32_t SkUnichar
Definition SkTypes.h:175
#define DEFAULT_FONT_FAMILY
Definition TextStyle.h:19
sk_sp< SkTypeface > matchFamilyStyle(const char familyName[], const SkFontStyle &) const
bool isEmpty() const
Definition SkString.h:130
const char * c_str() const
Definition SkString.h:133
sk_sp< SkTypeface > defaultEmojiFallback(SkUnichar emojiStart, SkFontStyle fontStyle, const SkString &locale)
std::vector< sk_sp< SkTypeface > > findTypefaces(const std::vector< SkString > &familyNames, SkFontStyle fontStyle)
void setDefaultFontManager(sk_sp< SkFontMgr > fontManager)
void setAssetFontManager(sk_sp< SkFontMgr > fontManager)
void setDynamicFontManager(sk_sp< SkFontMgr > fontManager)
void setTestFontManager(sk_sp< SkFontMgr > fontManager)
sk_sp< SkTypeface > defaultFallback()
SKSHAPER_API void PurgeCaches()
size_t operator()(const FamilyKey &key) const