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