• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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