1 // Copyright 2019 Google LLC.
2 #include "include/core/SkTypeface.h"
3 #include "include/core/SkGraphics.h"
4 #include "modules/skparagraph/include/FontCollection.h"
5 #include "modules/skparagraph/include/Paragraph.h"
6 #include "modules/skparagraph/src/ParagraphImpl.h"
7 #include "modules/skshaper/include/SkShaper.h"
8
9 namespace skia {
10 namespace textlayout {
11
12 namespace {
13 #ifdef USE_SKIA_TXT
RSLegacyMakeTypeface(std::shared_ptr<RSFontMgr> fontMgr,const char familyName[],RSFontStyle style)14 std::shared_ptr<RSTypeface> RSLegacyMakeTypeface(
15 std::shared_ptr<RSFontMgr> fontMgr, const char familyName[], RSFontStyle style)
16 {
17 RSTypeface* typeface = fontMgr->MatchFamilyStyle(familyName, style);
18 if (typeface == nullptr && familyName != nullptr) {
19 typeface = fontMgr->MatchFamilyStyle(nullptr, style);
20 }
21
22 if (typeface) {
23 return std::shared_ptr<RSTypeface>(typeface);
24 }
25 return nullptr;
26 }
27 #endif
28
29 constexpr int MAX_VARTYPEFACE_SIZE = 32;
30 #ifdef OHOS_SUPPORT
31 std::unordered_map<uint32_t, std::shared_ptr<RSTypeface>> g_faceTypeCache(MAX_VARTYPEFACE_SIZE);
32 #endif
33 }
34
35 #ifdef OHOS_SUPPORT
36 bool FontCollection::fIsAdpaterTextHeightEnabled = false;
37 #endif
38
operator ==(const FontCollection::FamilyKey & other) const39 bool FontCollection::FamilyKey::operator==(const FontCollection::FamilyKey& other) const {
40 return fFamilyNames == other.fFamilyNames &&
41 fFontStyle == other.fFontStyle &&
42 fFontArguments == other.fFontArguments;
43 }
44
operator ()(const FontCollection::FamilyKey & key) const45 size_t FontCollection::FamilyKey::Hasher::operator()(const FontCollection::FamilyKey& key) const {
46 size_t hash = 0;
47 for (const SkString& family : key.fFamilyNames) {
48 hash ^= std::hash<std::string>()(family.c_str());
49 }
50 #ifndef USE_SKIA_TXT
51 return hash ^
52 std::hash<uint32_t>()(key.fFontStyle.weight()) ^
53 std::hash<uint32_t>()(key.fFontStyle.slant()) ^
54 std::hash<std::optional<FontArguments>>()(key.fFontArguments);
55 #else
56 return hash ^
57 std::hash<uint32_t>()(key.fFontStyle.GetWeight()) ^
58 std::hash<uint32_t>()(static_cast<uint32_t>(key.fFontStyle.GetSlant())) ^
59 std::hash<std::optional<FontArguments>>()(key.fFontArguments);
60 #endif
61 }
62
FontCollection()63 FontCollection::FontCollection()
64 : fEnableFontFallback(true),
65 fDefaultFamilyNames({SkString(DEFAULT_FONT_FAMILY)}) {}
66
getFontManagersCount() const67 size_t FontCollection::getFontManagersCount() const {
68 std::shared_lock<std::shared_mutex> readLock(mutex_);
69 return this->getFontManagerOrder().size();
70 }
71
72 #ifndef USE_SKIA_TXT
setAssetFontManager(sk_sp<SkFontMgr> font_manager)73 void FontCollection::setAssetFontManager(sk_sp<SkFontMgr> font_manager) {
74 #else
75 void FontCollection::setAssetFontManager(std::shared_ptr<RSFontMgr> font_manager) {
76 #endif
77 std::unique_lock<std::shared_mutex> writeLock(mutex_);
78 fAssetFontManager = font_manager;
79 }
80
81 #ifndef USE_SKIA_TXT
82 void FontCollection::setDynamicFontManager(sk_sp<SkFontMgr> font_manager) {
83 #else
84 void FontCollection::setDynamicFontManager(std::shared_ptr<RSFontMgr> font_manager) {
85 #endif
86 std::unique_lock<std::shared_mutex> writeLock(mutex_);
87 fDynamicFontManager = font_manager;
88 }
89
90 #ifndef USE_SKIA_TXT
91 void FontCollection::setTestFontManager(sk_sp<SkFontMgr> font_manager) {
92 #else
93 void FontCollection::setTestFontManager(std::shared_ptr<RSFontMgr> font_manager)
94 {
95 #endif
96 std::unique_lock<std::shared_mutex> writeLock(mutex_);
97 fTestFontManager = font_manager;
98 }
99
100 #ifndef USE_SKIA_TXT
101 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
102 const char defaultFamilyName[]) {
103 #else
104 void FontCollection::setDefaultFontManager(std::shared_ptr<RSFontMgr> fontManager,
105 const char defaultFamilyName[]) {
106 #endif
107 std::unique_lock<std::shared_mutex> writeLock(mutex_);
108 fDefaultFontManager = std::move(fontManager);
109 fDefaultFamilyNames.emplace_back(defaultFamilyName);
110 }
111
112 #ifndef USE_SKIA_TXT
113 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
114 const std::vector<SkString>& defaultFamilyNames) {
115 #else
116 void FontCollection::setDefaultFontManager(std::shared_ptr<RSFontMgr> fontManager,
117 const std::vector<SkString>& defaultFamilyNames) {
118 #endif
119 std::unique_lock<std::shared_mutex> writeLock(mutex_);
120 fDefaultFontManager = std::move(fontManager);
121 fDefaultFamilyNames = defaultFamilyNames;
122 }
123
124 #ifndef USE_SKIA_TXT
125 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager) {
126 #else
127 void FontCollection::setDefaultFontManager(std::shared_ptr<RSFontMgr> fontManager) {
128 #endif
129 std::unique_lock<std::shared_mutex> writeLock(mutex_);
130 fDefaultFontManager = fontManager;
131 }
132
133 // Return the available font managers in the order they should be queried.
134 #ifndef USE_SKIA_TXT
135 std::vector<sk_sp<SkFontMgr>> FontCollection::getFontManagerOrder() const {
136 std::vector<sk_sp<SkFontMgr>> order;
137 #else
138 std::vector<std::shared_ptr<RSFontMgr>> FontCollection::getFontManagerOrder() const {
139 std::vector<std::shared_ptr<RSFontMgr>> order;
140 #endif
141 if (fDynamicFontManager) {
142 order.push_back(fDynamicFontManager);
143 }
144 if (fAssetFontManager) {
145 order.push_back(fAssetFontManager);
146 }
147 if (fTestFontManager) {
148 order.push_back(fTestFontManager);
149 }
150 if (fDefaultFontManager && fEnableFontFallback) {
151 order.push_back(fDefaultFontManager);
152 }
153 return order;
154 }
155
156 #ifndef USE_SKIA_TXT
157 std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle) {
158 #else
159 std::vector<std::shared_ptr<RSTypeface>> FontCollection::findTypefaces(
160 const std::vector<SkString>& familyNames, RSFontStyle fontStyle)
161 {
162 #endif
163 return findTypefaces(familyNames, fontStyle, std::nullopt);
164 }
165
166 #ifndef USE_SKIA_TXT
167 std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames,
168 SkFontStyle fontStyle, const std::optional<FontArguments>& fontArgs) {
169 // Look inside the font collections cache first
170 FamilyKey familyKey(familyNames, fontStyle, fontArgs);
171 {
172 std::shared_lock<std::shared_mutex> readLock(mutex_);
173 auto found = fTypefaces.find(familyKey);
174 if (found) {
175 return *found;
176 }
177 }
178
179 std::vector<sk_sp<SkTypeface>> typefaces;
180 for (const SkString& familyName : familyNames) {
181 sk_sp<SkTypeface> match = matchTypeface(familyName, fontStyle);
182 if (match && fontArgs) {
183 match = CloneTypeface(match, fontArgs);
184 }
185 if (match) {
186 typefaces.emplace_back(std::move(match));
187 }
188 }
189
190 if (typefaces.empty()) {
191 sk_sp<SkTypeface> match;
192 for (const SkString& familyName : fDefaultFamilyNames) {
193 match = matchTypeface(familyName, fontStyle);
194 if (match) {
195 match = CloneTypeface(match, fontArgs);
196 break;
197 }
198 }
199 if (!match) {
200 for (const auto& manager : this->getFontManagerOrder()) {
201 match = manager->legacyMakeTypeface(nullptr, fontStyle);
202 if (match) {
203 break;
204 }
205 }
206 }
207 if (match) {
208 typefaces.emplace_back(std::move(match));
209 }
210 }
211
212 std::unique_lock<std::shared_mutex> writeLock(mutex_);
213 fTypefaces.set(familyKey, typefaces);
214 return typefaces;
215 }
216 #else
217 std::vector<std::shared_ptr<RSTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames,
218 RSFontStyle fontStyle, const std::optional<FontArguments>& fontArgs)
219 {
220 // Look inside the font collections cache first
221 FamilyKey familyKey(familyNames, fontStyle, fontArgs);
222 {
223 std::shared_lock<std::shared_mutex> readLock(mutex_);
224 auto found = fTypefaces.find(familyKey);
225 if (found != fTypefaces.end()) {
226 return found->second;
227 }
228 }
229
230 std::vector<std::shared_ptr<RSTypeface>> typefaces;
231 for (const auto& familyName : familyNames) {
232 std::shared_ptr<RSTypeface> match = matchTypeface(familyName, fontStyle);
233 if (match) {
234 match = CloneTypeface(match, fontArgs);
235 typefaces.emplace_back(std::move(match));
236 }
237 }
238
239 if (typefaces.empty()) {
240 std::shared_ptr<RSTypeface> match;
241 for (const auto& familyName : fDefaultFamilyNames) {
242 match = matchTypeface(familyName, fontStyle);
243 if (match) {
244 match = CloneTypeface(match, fontArgs);
245 typefaces.emplace_back(std::move(match));
246 }
247 }
248
249 if (typefaces.empty()) {
250 for (const auto& manager : this->getFontManagerOrder()) {
251 match = RSLegacyMakeTypeface(manager, nullptr, fontStyle);
252 if (match) {
253 typefaces.emplace_back(std::move(match));
254 break;
255 }
256 }
257 }
258 }
259
260 std::unique_lock<std::shared_mutex> writeLock(mutex_);
261 fTypefaces.emplace(familyKey, typefaces);
262 return typefaces;
263 }
264 #endif
265
266 #ifndef USE_SKIA_TXT
267 sk_sp<SkTypeface> FontCollection::matchTypeface(const SkString& familyName, SkFontStyle fontStyle) {
268 for (const auto& manager : this->getFontManagerOrder()) {
269 sk_sp<SkFontStyleSet> set(manager->matchFamily(familyName.c_str()));
270 if (!set || set->count() == 0) {
271 continue;
272 }
273
274 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
275 if (match) {
276 return match;
277 }
278 }
279
280 return nullptr;
281 }
282 #else
283 std::shared_ptr<RSTypeface> FontCollection::matchTypeface(const SkString& familyName, RSFontStyle fontStyle) {
284 for (const auto& manager : this->getFontManagerOrder()) {
285 std::shared_ptr<RSFontStyleSet> set(manager->MatchFamily(familyName.c_str()));
286 if (!set || set->Count() == 0) {
287 continue;
288 }
289
290 std::shared_ptr<RSTypeface> match(set->MatchStyle(fontStyle));
291 if (match) {
292 return match;
293 }
294 }
295
296 return nullptr;
297 }
298 #endif
299
300
301 // Find ANY font in available font managers that resolves the unicode codepoint
302 #ifndef USE_SKIA_TXT
303 sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, const SkString& locale) {
304 #else
305 std::shared_ptr<RSTypeface> FontCollection::defaultFallback(
306 SkUnichar unicode, RSFontStyle fontStyle, const SkString& locale)
307 {
308 #endif
309 std::shared_lock<std::shared_mutex> readLock(mutex_);
310 for (const auto& manager : this->getFontManagerOrder()) {
311 std::vector<const char*> bcp47;
312 if (!locale.isEmpty()) {
313 bcp47.push_back(locale.c_str());
314 }
315 #ifndef USE_SKIA_TXT
316 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
317 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
318 #else
319 std::shared_ptr<RSTypeface> typeface(manager->MatchFamilyStyleCharacter(
320 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
321 #endif
322 if (typeface != nullptr) {
323 return typeface;
324 }
325 }
326 return nullptr;
327 }
328
329 #ifndef USE_SKIA_TXT
330 sk_sp<SkTypeface> FontCollection::defaultFallback() {
331 std::shared_lock<std::shared_mutex> readLock(mutex_);
332 if (fDefaultFontManager == nullptr) {
333 return nullptr;
334 }
335 for (const SkString& familyName : fDefaultFamilyNames) {
336 sk_sp<SkTypeface> match = sk_sp<SkTypeface>(fDefaultFontManager->matchFamilyStyle(familyName.c_str(),
337 SkFontStyle()));
338 if (match) {
339 return match;
340 }
341 }
342 return nullptr;
343 }
344 #else
345 std::shared_ptr<RSTypeface> FontCollection::defaultFallback() {
346 std::shared_lock<std::shared_mutex> readLock(mutex_);
347 if (fDefaultFontManager == nullptr) {
348 return nullptr;
349 }
350 for (const auto& familyName : fDefaultFamilyNames) {
351 std::shared_ptr<RSTypeface> match = std::shared_ptr<RSTypeface>(
352 fDefaultFontManager->MatchFamilyStyle(familyName.c_str(), RSFontStyle()));
353 if (match) {
354 return match;
355 }
356 }
357 return nullptr;
358 }
359 #endif
360
361 class SkLRUCacheMgr {
362 public:
363 SkLRUCacheMgr(SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>>& lruCache, SkMutex& mutex)
364 :fLRUCache(lruCache), fMutex(mutex)
365 {
366 fMutex.acquire();
367 }
368 SkLRUCacheMgr(const SkLRUCacheMgr&) = delete;
369 SkLRUCacheMgr(SkLRUCacheMgr&&) = delete;
370 SkLRUCacheMgr& operator=(const SkLRUCacheMgr&) = delete;
371 SkLRUCacheMgr& operator=(SkLRUCacheMgr&&) = delete;
372
373 ~SkLRUCacheMgr() {
374 fMutex.release();
375 }
376
377 std::shared_ptr<RSTypeface> find(uint32_t fontId) {
378 auto face = fLRUCache.find(fontId);
379 return face == nullptr ? nullptr : *face;
380 }
381
382 std::shared_ptr<RSTypeface> insert(uint32_t fontId, std::shared_ptr<RSTypeface> hbFont) {
383 auto face = fLRUCache.insert(fontId, std::move(hbFont));
384 return face == nullptr ? nullptr : *face;
385 }
386
387 void reset() {
388 fLRUCache.reset();
389 }
390
391 private:
392 SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>>& fLRUCache;
393 SkMutex& fMutex;
394 };
395
396 static SkLRUCacheMgr GetLRUCacheInstance() {
397 static SkMutex gFaceCacheMutex;
398 static SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>> gFaceCache(MAX_VARTYPEFACE_SIZE);
399 return SkLRUCacheMgr(gFaceCache, gFaceCacheMutex);
400 }
401
402 #ifndef USE_SKIA_TXT
403 sk_sp<SkTypeface> FontCollection::CloneTypeface(sk_sp<SkTypeface> typeface,
404 const std::optional<FontArguments>& fontArgs)
405 {
406 #else
407 std::shared_ptr<RSTypeface> FontCollection::CloneTypeface(std::shared_ptr<RSTypeface> typeface,
408 const std::optional<FontArguments>& fontArgs)
409 {
410
411 #ifndef USE_SKIA_TXT
412 if (!typeface || !fontArgs || typeface->isCustomTypeface()) {
413 #else
414 if (!typeface || !fontArgs || typeface->IsCustomTypeface()) {
415 #endif
416 return typeface;
417 }
418
419 size_t hash = 0;
420 hash ^= std::hash<FontArguments>()(fontArgs.value());
421 #ifndef USE_SKIA_TXT
422 hash ^= std::hash<uint32_t>()(typeface->uniqueID());
423 #else
424 hash ^= std::hash<uint32_t>()(typeface->GetUniqueID());
425 #endif
426
427 std::unique_lock<std::shared_mutex> writeLock(mutex_);
428 auto cached = GetLRUCacheInstance().find(hash);
429 if (cached) {
430 return cached;
431 } else {
432 auto varTypeface = fontArgs->CloneTypeface(typeface);
433 if (!varTypeface) {
434 return typeface;
435 }
436 GetLRUCacheInstance().insert(hash, varTypeface);
437 return varTypeface;
438 }
439 }
440
441 #endif
442
443 void FontCollection::disableFontFallback() {
444 std::unique_lock<std::shared_mutex> writeLock(mutex_);
445 fEnableFontFallback = false;
446 }
447
448 void FontCollection::enableFontFallback() {
449 std::unique_lock<std::shared_mutex> writeLock(mutex_);
450 fEnableFontFallback = true;
451 }
452
453 void FontCollection::clearCaches() {
454 std::unique_lock<std::shared_mutex> writeLock(mutex_);
455 fParagraphCache.reset();
456 #ifndef USE_SKIA_TXT
457 fTypefaces.reset();
458 #else
459 fTypefaces.clear();
460 SkGraphics::PurgeFontCache();
461 #endif
462 SkShaper::PurgeCaches();
463 }
464
465 } // namespace textlayout
466 } // namespace skia
467