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