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) {
233 match = CloneTypeface(match, fontArgs);
234 typefaces.emplace_back(std::move(match));
235 }
236 }
237
238 if (typefaces.empty()) {
239 std::shared_ptr<RSTypeface> match;
240 for (const auto& familyName : fDefaultFamilyNames) {
241 match = matchTypeface(familyName, fontStyle);
242 if (match) {
243 match = CloneTypeface(match, fontArgs);
244 typefaces.emplace_back(std::move(match));
245 }
246 }
247
248 if (typefaces.empty()) {
249 for (const auto& manager : this->getFontManagerOrder()) {
250 match = RSLegacyMakeTypeface(manager, nullptr, fontStyle);
251 if (match) {
252 typefaces.emplace_back(std::move(match));
253 break;
254 }
255 }
256 }
257 }
258
259 std::unique_lock<std::shared_mutex> writeLock(mutex_);
260 fTypefaces.emplace(familyKey, typefaces);
261 return typefaces;
262 }
263 #endif
264
265 #ifndef USE_SKIA_TXT
266 sk_sp<SkTypeface> FontCollection::matchTypeface(const SkString& familyName, SkFontStyle fontStyle) {
267 for (const auto& manager : this->getFontManagerOrder()) {
268 sk_sp<SkFontStyleSet> set(manager->matchFamily(familyName.c_str()));
269 if (!set || set->count() == 0) {
270 continue;
271 }
272
273 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
274 if (match) {
275 return match;
276 }
277 }
278
279 return nullptr;
280 }
281 #else
282 std::shared_ptr<RSTypeface> FontCollection::matchTypeface(const SkString& familyName, RSFontStyle fontStyle) {
283 for (const auto& manager : this->getFontManagerOrder()) {
284 std::shared_ptr<RSFontStyleSet> set(manager->MatchFamily(familyName.c_str()));
285 if (!set || set->Count() == 0) {
286 continue;
287 }
288
289 std::shared_ptr<RSTypeface> match(set->MatchStyle(fontStyle));
290 if (match) {
291 return match;
292 }
293 }
294
295 return nullptr;
296 }
297 #endif
298
299
300 // Find ANY font in available font managers that resolves the unicode codepoint
301 #ifndef USE_SKIA_TXT
302 sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, const SkString& locale) {
303 #else
304 std::shared_ptr<RSTypeface> FontCollection::defaultFallback(
305 SkUnichar unicode, RSFontStyle fontStyle, const SkString& locale)
306 {
307 #endif
308 std::shared_lock<std::shared_mutex> readLock(mutex_);
309 for (const auto& manager : this->getFontManagerOrder()) {
310 std::vector<const char*> bcp47;
311 if (!locale.isEmpty()) {
312 bcp47.push_back(locale.c_str());
313 }
314 #ifndef USE_SKIA_TXT
315 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
316 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
317 #else
318 std::shared_ptr<RSTypeface> typeface(manager->MatchFamilyStyleCharacter(
319 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
320 #endif
321 if (typeface != nullptr) {
322 return typeface;
323 }
324 }
325 return nullptr;
326 }
327
328 #ifndef USE_SKIA_TXT
329 sk_sp<SkTypeface> FontCollection::defaultFallback() {
330 std::shared_lock<std::shared_mutex> readLock(mutex_);
331 if (fDefaultFontManager == nullptr) {
332 return nullptr;
333 }
334 for (const SkString& familyName : fDefaultFamilyNames) {
335 sk_sp<SkTypeface> match = sk_sp<SkTypeface>(fDefaultFontManager->matchFamilyStyle(familyName.c_str(),
336 SkFontStyle()));
337 if (match) {
338 return match;
339 }
340 }
341 return nullptr;
342 }
343 #else
344 std::shared_ptr<RSTypeface> FontCollection::defaultFallback() {
345 std::shared_lock<std::shared_mutex> readLock(mutex_);
346 if (fDefaultFontManager == nullptr) {
347 return nullptr;
348 }
349 for (const auto& familyName : fDefaultFamilyNames) {
350 std::shared_ptr<RSTypeface> match = std::shared_ptr<RSTypeface>(
351 fDefaultFontManager->MatchFamilyStyle(familyName.c_str(), RSFontStyle()));
352 if (match) {
353 return match;
354 }
355 }
356 return nullptr;
357 }
358 #endif
359
360 class SkLRUCacheMgr {
361 public:
362 SkLRUCacheMgr(SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>>& lruCache, SkMutex& mutex)
363 :fLRUCache(lruCache), fMutex(mutex)
364 {
365 fMutex.acquire();
366 }
367 SkLRUCacheMgr(const SkLRUCacheMgr&) = delete;
368 SkLRUCacheMgr(SkLRUCacheMgr&&) = delete;
369 SkLRUCacheMgr& operator=(const SkLRUCacheMgr&) = delete;
370 SkLRUCacheMgr& operator=(SkLRUCacheMgr&&) = delete;
371
372 ~SkLRUCacheMgr() {
373 fMutex.release();
374 }
375
376 std::shared_ptr<RSTypeface> find(uint32_t fontId) {
377 auto face = fLRUCache.find(fontId);
378 return face == nullptr ? nullptr : *face;
379 }
380
381 std::shared_ptr<RSTypeface> insert(uint32_t fontId, std::shared_ptr<RSTypeface> hbFont) {
382 auto face = fLRUCache.insert(fontId, std::move(hbFont));
383 return face == nullptr ? nullptr : *face;
384 }
385
386 void reset() {
387 fLRUCache.reset();
388 }
389
390 private:
391 SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>>& fLRUCache;
392 SkMutex& fMutex;
393 };
394
395 static SkLRUCacheMgr GetLRUCacheInstance() {
396 static SkMutex gFaceCacheMutex;
397 static SkLRUCache<uint32_t, std::shared_ptr<RSTypeface>> gFaceCache(MAX_VARTYPEFACE_SIZE);
398 return SkLRUCacheMgr(gFaceCache, gFaceCacheMutex);
399 }
400
401 #ifndef USE_SKIA_TXT
402 sk_sp<SkTypeface> FontCollection::CloneTypeface(sk_sp<SkTypeface> typeface,
403 const std::optional<FontArguments>& fontArgs)
404 {
405 #else
406 std::shared_ptr<RSTypeface> FontCollection::CloneTypeface(std::shared_ptr<RSTypeface> typeface,
407 const std::optional<FontArguments>& fontArgs)
408 {
409
410 #ifndef USE_SKIA_TXT
411 if (!typeface || !fontArgs || typeface->isCustomTypeface()) {
412 #else
413 if (!typeface || !fontArgs || typeface->IsCustomTypeface()) {
414 #endif
415 return typeface;
416 }
417
418 size_t hash = 0;
419 hash ^= std::hash<FontArguments>()(fontArgs.value());
420 #ifndef USE_SKIA_TXT
421 hash ^= std::hash<uint32_t>()(typeface->uniqueID());
422 #else
423 hash ^= std::hash<uint32_t>()(typeface->GetUniqueID());
424 #endif
425
426 std::unique_lock<std::shared_mutex> writeLock(mutex_);
427 auto cached = GetLRUCacheInstance().find(hash);
428 if (cached) {
429 return cached;
430 } else {
431 auto varTypeface = fontArgs->CloneTypeface(typeface);
432 if (!varTypeface) {
433 return typeface;
434 }
435 GetLRUCacheInstance().insert(hash, varTypeface);
436 return varTypeface;
437 }
438 }
439
440 #endif
441
442 void FontCollection::disableFontFallback() {
443 std::unique_lock<std::shared_mutex> writeLock(mutex_);
444 fEnableFontFallback = false;
445 }
446
447 void FontCollection::enableFontFallback() {
448 std::unique_lock<std::shared_mutex> writeLock(mutex_);
449 fEnableFontFallback = true;
450 }
451
452 void FontCollection::clearCaches() {
453 std::unique_lock<std::shared_mutex> writeLock(mutex_);
454 fParagraphCache.reset();
455 #ifndef USE_SKIA_TXT
456 fTypefaces.reset();
457 #else
458 fTypefaces.clear();
459 #endif
460 SkShaper::PurgeCaches();
461 }
462
463 } // namespace textlayout
464 } // namespace skia
465