1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "font_collection.h"
18
19 #include <algorithm>
20 #include <list>
21 #include <memory>
22 #include <mutex>
23 #include <set>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27 #ifdef OHOS_PLATFORM
28 #include "skia/src/ports/SkFontMgr_ohos.h"
29 #endif
30 #include "flutter/fml/logging.h"
31 #include "flutter/fml/trace_event.h"
32 #include "font_skia.h"
33 #include "txt/text_style.h"
34
35 namespace txt {
36
37 namespace {
38
39 const std::shared_ptr<minikin::FontFamily> g_null_family;
40
41 } // anonymous namespace
42
FamilyKey(const std::vector<std::string> & families,const std::string & loc)43 FontCollection::FamilyKey::FamilyKey(const std::vector<std::string>& families,
44 const std::string& loc) {
45 locale = loc;
46
47 std::stringstream stream;
48 for_each(families.begin(), families.end(),
49 [&stream](const std::string& str) { stream << str << ','; });
50 font_families = stream.str();
51 }
52
operator ==(const FontCollection::FamilyKey & other) const53 bool FontCollection::FamilyKey::operator==(
54 const FontCollection::FamilyKey& other) const {
55 return font_families == other.font_families && locale == other.locale;
56 }
57
operator ()(const FontCollection::FamilyKey & key) const58 size_t FontCollection::FamilyKey::Hasher::operator()(
59 const FontCollection::FamilyKey& key) const {
60 return std::hash<std::string>()(key.font_families) ^
61 std::hash<std::string>()(key.locale);
62 }
63
64 class TxtFallbackFontProvider
65 : public minikin::FontCollection::FallbackFontProvider {
66 public:
TxtFallbackFontProvider(std::shared_ptr<FontCollection> font_collection)67 TxtFallbackFontProvider(std::shared_ptr<FontCollection> font_collection)
68 : font_collection_(font_collection) {}
69
matchFallbackFont(uint32_t ch,std::string locale)70 virtual const std::shared_ptr<minikin::FontFamily>& matchFallbackFont(
71 uint32_t ch,
72 std::string locale) {
73 std::shared_ptr<FontCollection> fc = font_collection_.lock();
74 if (fc) {
75 return fc->MatchFallbackFont(ch, locale);
76 } else {
77 return g_null_family;
78 }
79 }
80
matchFallbackFontFromHwFont(uint32_t ch,std::string locale)81 virtual const std::shared_ptr<minikin::FontFamily>& matchFallbackFontFromHwFont(
82 uint32_t ch,
83 std::string locale) {
84 #if defined(OHOS_PLATFORM) && !defined(OHOS_STANDARD_SYSTEM)
85 std::shared_ptr<FontCollection> fc = font_collection_.lock();
86 if (fc) {
87 return fc->MatchFallbackFontFromHwFont(ch, locale);
88 } else {
89 return g_null_family;
90 }
91 #endif
92 return g_null_family;
93 }
94
95 private:
96 std::weak_ptr<FontCollection> font_collection_;
97 };
98
FontCollection()99 FontCollection::FontCollection() : enable_font_fallback_(true) {}
100
101 FontCollection::~FontCollection() = default;
102
GetFontManagersCount() const103 size_t FontCollection::GetFontManagersCount() const {
104 return GetFontManagerOrder().size();
105 }
106
SetupDefaultFontManager()107 void FontCollection::SetupDefaultFontManager() {
108 std::lock_guard<std::mutex> lock(fontManagerMutex_);
109 default_font_manager_ = GetDefaultFontManager();
110 }
111
SetDefaultFontManager(sk_sp<SkFontMgr> font_manager)112 void FontCollection::SetDefaultFontManager(sk_sp<SkFontMgr> font_manager) {
113 std::lock_guard<std::mutex> lock(fontManagerMutex_);
114 default_font_manager_ = font_manager;
115 }
116
SetAssetFontManager(sk_sp<SkFontMgr> font_manager)117 void FontCollection::SetAssetFontManager(sk_sp<SkFontMgr> font_manager) {
118 asset_font_manager_ = font_manager;
119 }
120
SetDynamicFontManager(sk_sp<SkFontMgr> font_manager)121 void FontCollection::SetDynamicFontManager(sk_sp<SkFontMgr> font_manager) {
122 dynamic_font_manager_ = font_manager;
123 }
124
SetTestFontManager(sk_sp<SkFontMgr> font_manager)125 void FontCollection::SetTestFontManager(sk_sp<SkFontMgr> font_manager) {
126 test_font_manager_ = font_manager;
127 }
128
GetDefaultFontManagerSafely() const129 sk_sp<SkFontMgr> FontCollection::GetDefaultFontManagerSafely() const {
130 std::lock_guard<std::mutex> lock(fontManagerMutex_);
131 return default_font_manager_;
132 }
133
134 // Return the available font managers in the order they should be queried.
GetFontManagerOrder() const135 std::vector<sk_sp<SkFontMgr>> FontCollection::GetFontManagerOrder() const {
136 std::vector<sk_sp<SkFontMgr>> order;
137 if (dynamic_font_manager_)
138 order.push_back(dynamic_font_manager_);
139 if (asset_font_manager_)
140 order.push_back(asset_font_manager_);
141 if (test_font_manager_)
142 order.push_back(test_font_manager_);
143 auto defaultFontManager = GetDefaultFontManagerSafely();
144 if (defaultFontManager)
145 order.push_back(defaultFontManager);
146 return order;
147 }
148
DisableFontFallback()149 void FontCollection::DisableFontFallback() {
150 enable_font_fallback_ = false;
151 }
152
153 std::shared_ptr<minikin::FontCollection>
GetMinikinFontCollectionForFamilies(const std::vector<std::string> & font_families,const std::string & locale)154 FontCollection::GetMinikinFontCollectionForFamilies(
155 const std::vector<std::string>& font_families,
156 const std::string& locale) {
157 #if defined(OHOS_PLATFORM) && !defined(OHOS_STANDARD_SYSTEM)
158 return GetMinikinFontCollectionForFamiliesWithVariation(font_families, locale);
159 #endif
160 // Look inside the font collections cache first.
161 FamilyKey family_key(font_families, locale);
162 {
163 std::lock_guard<std::mutex> lock(mutex_);
164 auto cached = font_collections_cache_.find(family_key);
165 if (cached != font_collections_cache_.end()) {
166 return cached->second;
167 }
168 }
169
170 std::vector<std::shared_ptr<minikin::FontFamily>> minikin_families;
171
172 // Search for all user provided font families.
173 for (size_t fallback_index = 0; fallback_index < font_families.size();
174 fallback_index++) {
175 std::shared_ptr<minikin::FontFamily> minikin_family =
176 FindFontFamilyInManagers(font_families[fallback_index]);
177 if (minikin_family != nullptr) {
178 minikin_families.push_back(minikin_family);
179 }
180 }
181 // Search for default font family if no user font families were found.
182 if (minikin_families.empty()) {
183 const auto default_font_family = GetDefaultFontFamily();
184 std::shared_ptr<minikin::FontFamily> minikin_family =
185 FindFontFamilyInManagers(default_font_family);
186 if (minikin_family != nullptr) {
187 minikin_families.push_back(minikin_family);
188 }
189 }
190 // Default font family also not found. We fail to get a FontCollection.
191 if (minikin_families.empty()) {
192 std::shared_ptr<minikin::FontCollection> tmp_font_collection;
193 std::lock_guard<std::mutex> lock(mutex_);
194 std::swap(font_collections_cache_[family_key], tmp_font_collection);
195 return nullptr;
196 }
197 if (enable_font_fallback_) {
198 std::lock_guard<std::mutex> lock(mutex_);
199 for (std::string fallback_family : fallback_fonts_for_locale_[locale]) {
200 auto it = fallback_fonts_.find(fallback_family);
201 if (it != fallback_fonts_.end()) {
202 minikin_families.push_back(it->second);
203 }
204 }
205 }
206 // Create the minikin font collection.
207 auto font_collection =
208 std::make_shared<minikin::FontCollection>(std::move(minikin_families));
209 if (enable_font_fallback_) {
210 font_collection->set_fallback_font_provider(
211 std::make_unique<TxtFallbackFontProvider>(shared_from_this()));
212 }
213
214 {
215 std::shared_ptr<minikin::FontCollection> tmp_font_collection =
216 font_collection;
217 std::lock_guard<std::mutex> lock(mutex_);
218 // Cache the font collection for future queries.
219 std::swap(font_collections_cache_[family_key], tmp_font_collection);
220 }
221
222 return font_collection;
223 }
224
FindFontFamilyInManagers(const std::string & family_name)225 std::shared_ptr<minikin::FontFamily> FontCollection::FindFontFamilyInManagers(
226 const std::string& family_name) {
227 TRACE_EVENT0("flutter", "FontCollection::FindFontFamilyInManagers");
228 // Search for the font family in each font manager.
229 for (sk_sp<SkFontMgr>& manager : GetFontManagerOrder()) {
230 std::shared_ptr<minikin::FontFamily> minikin_family =
231 CreateMinikinFontFamily(manager, family_name);
232 if (!minikin_family)
233 continue;
234 return minikin_family;
235 }
236 return nullptr;
237 }
238
CreateMinikinFontFamily(const sk_sp<SkFontMgr> & manager,const std::string & family_name)239 std::shared_ptr<minikin::FontFamily> FontCollection::CreateMinikinFontFamily(
240 const sk_sp<SkFontMgr>& manager,
241 const std::string& family_name) {
242 TRACE_EVENT1("flutter", "FontCollection::CreateMinikinFontFamily",
243 "family_name", family_name.c_str());
244 sk_sp<SkFontStyleSet> font_style_set(
245 manager->matchFamily(family_name.c_str()));
246 if (font_style_set == nullptr || font_style_set->count() == 0) {
247 return nullptr;
248 }
249
250 std::vector<sk_sp<SkTypeface>> skia_typefaces;
251 for (int i = 0; i < font_style_set->count(); ++i) {
252 TRACE_EVENT0("flutter", "CreateSkiaTypeface");
253 sk_sp<SkTypeface> skia_typeface(
254 sk_sp<SkTypeface>(font_style_set->createTypeface(i)));
255 if (skia_typeface != nullptr) {
256 skia_typefaces.emplace_back(std::move(skia_typeface));
257 }
258 }
259
260 std::sort(skia_typefaces.begin(), skia_typefaces.end(),
261 [](const sk_sp<SkTypeface>& a, const sk_sp<SkTypeface>& b) {
262 SkFontStyle a_style = a->fontStyle();
263 SkFontStyle b_style = b->fontStyle();
264 return (a_style.weight() != b_style.weight())
265 ? a_style.weight() < b_style.weight()
266 : a_style.slant() < b_style.slant();
267 });
268
269 std::vector<minikin::Font> minikin_fonts;
270 for (const sk_sp<SkTypeface>& skia_typeface : skia_typefaces) {
271 // Create the minikin font from the skia typeface.
272 // Divide by 100 because the weights are given as "100", "200", etc.
273 minikin_fonts.emplace_back(
274 std::make_shared<FontSkia>(skia_typeface),
275 minikin::FontStyle{skia_typeface->fontStyle().weight() / 100,
276 skia_typeface->isItalic()});
277 }
278
279 return std::make_shared<minikin::FontFamily>(std::move(minikin_fonts));
280 }
281
MatchFallbackFont(uint32_t ch,std::string locale)282 const std::shared_ptr<minikin::FontFamily>& FontCollection::MatchFallbackFont(
283 uint32_t ch,
284 std::string locale) {
285 #if defined(OHOS_PLATFORM) && !defined(OHOS_STANDARD_SYSTEM)
286 return MatchFallbackFontWithVariation(ch, locale);
287 #endif
288 // Check if the ch's matched font has been cached. We cache the results of
289 // this method as repeated matchFamilyStyleCharacter calls can become
290 // extremely laggy when typing a large number of complex emojis.
291 {
292 std::lock_guard<std::mutex> lock(mutex_);
293 auto lookup = fallback_match_cache_.find(ch);
294 if (lookup != fallback_match_cache_.end()) {
295 return *lookup->second;
296 }
297 }
298 const std::shared_ptr<minikin::FontFamily>* match =
299 &DoMatchFallbackFont(ch, locale);
300 {
301 std::lock_guard<std::mutex> lock(mutex_);
302 fallback_match_cache_.insert(std::make_pair(ch, match));
303 }
304 return *match;
305 }
306
DoMatchFallbackFont(uint32_t ch,std::string locale)307 const std::shared_ptr<minikin::FontFamily>& FontCollection::DoMatchFallbackFont(
308 uint32_t ch,
309 std::string locale) {
310 for (const sk_sp<SkFontMgr>& manager : GetFontManagerOrder()) {
311 std::vector<const char*> bcp47;
312 if (!locale.empty())
313 bcp47.push_back(locale.c_str());
314 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
315 0, SkFontStyle(), bcp47.data(), bcp47.size(), ch));
316 if (!typeface)
317 continue;
318
319 SkString sk_family_name;
320 typeface->getFamilyName(&sk_family_name);
321 std::string family_name(sk_family_name.c_str());
322
323 {
324 std::lock_guard<std::mutex> lock(mutex_);
325 fallback_fonts_for_locale_[locale].insert(family_name);
326 }
327
328 return GetFallbackFontFamily(manager, family_name);
329 }
330 return g_null_family;
331 }
332
333 const std::shared_ptr<minikin::FontFamily>&
GetFallbackFontFamily(const sk_sp<SkFontMgr> & manager,const std::string & family_name)334 FontCollection::GetFallbackFontFamily(const sk_sp<SkFontMgr>& manager,
335 const std::string& family_name) {
336 TRACE_EVENT0("flutter", "FontCollection::GetFallbackFontFamily");
337 {
338 std::lock_guard<std::mutex> lock(mutex_);
339 auto fallback_it = fallback_fonts_.find(family_name);
340 if (fallback_it != fallback_fonts_.end()) {
341 return fallback_it->second;
342 }
343 }
344
345 std::shared_ptr<minikin::FontFamily> minikin_family =
346 CreateMinikinFontFamily(manager, family_name);
347 if (!minikin_family)
348 return g_null_family;
349
350 {
351 decltype(font_collections_cache_) font_collections_cache;
352 std::lock_guard<std::mutex> lock(mutex_);
353 auto insert_it =
354 fallback_fonts_.insert(std::make_pair(family_name, minikin_family));
355
356 // Clear the cache to force creation of new font collections that will
357 // include this fallback font.
358 std::swap(font_collections_cache_, font_collections_cache);
359
360 return insert_it.first->second;
361 }
362 }
363
ClearFontFamilyCache()364 void FontCollection::ClearFontFamilyCache() {
365 decltype(font_collections_cache_) font_collections_cache;
366 std::lock_guard<std::mutex> lock(mutex_);
367 std::swap(font_collections_cache_, font_collections_cache);
368 }
369
VaryFontCollectionWithFontWeightScale(float font_weight_scale)370 void FontCollection::VaryFontCollectionWithFontWeightScale(float font_weight_scale) {
371 if (font_weight_scale > 0.0f && font_weight_scale != font_weight_scale_) {
372 decltype(fallback_fonts_) fallback_fonts;
373 std::lock_guard<std::mutex> lock(mutex_);
374 font_weight_scale_ = font_weight_scale;
375 varied_fonts_.clear();
376 fallback_fonts = std::move(fallback_fonts_);
377 fallback_match_cache_.clear();
378 fallback_fonts_for_locale_.clear();
379 }
380 }
381
LoadSystemFont()382 void FontCollection::LoadSystemFont() {
383 #if defined(OHOS_PLATFORM) && !defined(OHOS_STANDARD_SYSTEM)
384 {
385 decltype(fallback_fonts_) fallback_fonts;
386 std::lock_guard<std::mutex> lock(mutex_);
387 varied_fonts_.clear();
388 fallback_fonts = std::move(fallback_fonts_);
389 fallback_match_cache_.clear();
390 fallback_fonts_for_locale_.clear();
391 }
392
393 SetupDefaultFontManager();
394
395 #endif
396 }
397
SetIsZawgyiMyanmar(bool is_zawgyi_myanmar)398 void FontCollection::SetIsZawgyiMyanmar(bool is_zawgyi_myanmar) {
399 if (is_zawgyi_myanmar_ == is_zawgyi_myanmar) {
400 return;
401 }
402 is_zawgyi_myanmar_ = is_zawgyi_myanmar;
403 LoadSystemFont();
404 }
405
406 #if defined(OHOS_PLATFORM) && !defined(OHOS_STANDARD_SYSTEM)
407 // Return the available font managers in the order they should be queried with
408 // type.
409 std::vector<std::pair<sk_sp<SkFontMgr>, txt::FontManagerType>>
GetFontManagerOrderWithType() const410 FontCollection::GetFontManagerOrderWithType() const {
411 std::vector<std::pair<sk_sp<SkFontMgr>, txt::FontManagerType>> order;
412 if (dynamic_font_manager_)
413 order.push_back(
414 std::make_pair(dynamic_font_manager_, txt::FontManagerType::DYNAMIC));
415 if (asset_font_manager_)
416 order.push_back(
417 std::make_pair(asset_font_manager_, txt::FontManagerType::ASSET));
418 if (test_font_manager_)
419 order.push_back(
420 std::make_pair(test_font_manager_, txt::FontManagerType::TEST));
421 auto defaultFontManager = GetDefaultFontManagerSafely();
422 if (defaultFontManager)
423 order.push_back(
424 std::make_pair(defaultFontManager, GetDefaultFontManagerType()));
425 return order;
426 }
427
428 std::shared_ptr<minikin::FontCollection>
GetMinikinFontCollectionForFamiliesWithVariation(const std::vector<std::string> & font_families,const std::string & locale)429 FontCollection::GetMinikinFontCollectionForFamiliesWithVariation(
430 const std::vector<std::string>& font_families,
431 const std::string& locale) {
432 // Look inside the font collections cache first.
433 FamilyKey family_key(font_families, locale);
434 {
435 std::lock_guard<std::mutex> lock(mutex_);
436 auto iter = std::find(varied_fonts_.begin(), varied_fonts_.end(), family_key);
437 if (iter != varied_fonts_.end()) {
438 auto cached = font_collections_cache_.find(family_key);
439 if (cached != font_collections_cache_.end()) {
440 return cached->second;
441 }
442 varied_fonts_.erase(iter);
443 }
444 }
445
446 std::vector<std::shared_ptr<minikin::FontFamily>> minikin_families;
447 // Search for all user provided font families.
448 for (size_t fallback_index = 0; fallback_index < font_families.size();
449 fallback_index++) {
450 std::shared_ptr<minikin::FontFamily> minikin_family =
451 FindFontFamilyInManagersWithType(font_families[fallback_index]);
452 if (minikin_family != nullptr) {
453 minikin_families.push_back(minikin_family);
454 }
455 }
456 // Search for default font family if no user font families were found.
457 if (minikin_families.empty()) {
458 const auto default_font_family = GetDefaultFontFamily();
459 std::shared_ptr<minikin::FontFamily> minikin_family =
460 FindFontFamilyInManagersWithType(default_font_family);
461 if (minikin_family != nullptr) {
462 minikin_families.push_back(minikin_family);
463 }
464 }
465 // Default font family also not found. We fail to get a FontCollection.
466 if (minikin_families.empty()) {
467 std::shared_ptr<minikin::FontCollection> tmp_font_collection;
468 std::lock_guard<std::mutex> lock(mutex_);
469 std::swap(font_collections_cache_[family_key], tmp_font_collection);
470 return nullptr;
471 }
472 if (enable_font_fallback_) {
473 std::lock_guard<std::mutex> lock(mutex_);
474 for (std::string fallback_family : fallback_fonts_for_locale_[locale]) {
475 auto it = fallback_fonts_.find(fallback_family);
476 if (it != fallback_fonts_.end()) {
477 minikin_families.push_back(it->second);
478 }
479 }
480 }
481 // Create the minikin font collection.
482 auto font_collection =
483 std::make_shared<minikin::FontCollection>(std::move(minikin_families));
484 font_collection->SetIsZawgyiMyanmar(is_zawgyi_myanmar_);
485
486 if (enable_font_fallback_) {
487 font_collection->set_fallback_font_provider(
488 std::make_unique<TxtFallbackFontProvider>(shared_from_this()));
489 }
490
491 {
492 std::shared_ptr<minikin::FontCollection> tmp_font_collection =
493 font_collection;
494 std::lock_guard<std::mutex> lock(mutex_);
495 // Cache the font collection for future queries.
496 std::swap(font_collections_cache_[family_key], tmp_font_collection);
497 varied_fonts_.emplace_back(family_key);
498 }
499
500 return font_collection;
501 }
502
503 std::shared_ptr<minikin::FontFamily>
FindFontFamilyInManagersWithType(const std::string & family_name)504 FontCollection::FindFontFamilyInManagersWithType(
505 const std::string& family_name) {
506 TRACE_EVENT0("flutter", "FontCollection::FindFontFamilyInManagersWithType");
507 // Search for the font family in each font manager.
508 for (std::pair<sk_sp<SkFontMgr>, FontManagerType>& managerPair :
509 GetFontManagerOrderWithType()) {
510 std::shared_ptr<minikin::FontFamily> minikin_family;
511 if (managerPair.second == FontManagerType::DEFAULT_OHOS) {
512 minikin_family =
513 CreateMinikinFontFamilyForOHOS(managerPair.first, family_name);
514 } else {
515 minikin_family =
516 CreateMinikinFontFamilyExceptOHOS(managerPair.first, family_name);
517 }
518 if (!minikin_family)
519 continue;
520 return minikin_family;
521 }
522 return nullptr;
523 }
524
525 std::shared_ptr<minikin::FontFamily>
CreateMinikinFontFamilyForOHOS(const sk_sp<SkFontMgr> & manager,const std::string & family_name)526 FontCollection::CreateMinikinFontFamilyForOHOS(
527 const sk_sp<SkFontMgr>& manager,
528 const std::string& family_name) {
529 TRACE_EVENT1("flutter", "FontCollection::CreateMinikinFontFamilyForOHOS",
530 "family_name", family_name.c_str());
531 sk_sp<SkFontStyleSet> font_style_set(
532 manager->matchFamily(family_name.c_str()));
533 if (font_style_set == nullptr || font_style_set->count() == 0) {
534 return nullptr;
535 }
536
537 auto font_style_set_ohos =
538 reinterpret_cast<SkFontStyleSet_OHOS*>(font_style_set.get());
539 if (font_style_set_ohos == nullptr) {
540 return CreateMinikinFontFamilyExceptOHOS(manager, family_name);
541 }
542
543 std::vector<sk_sp<SkTypeface>> skia_typefaces;
544 for (int i = 0; i < font_style_set_ohos->count(); ++i) {
545 TRACE_EVENT0("flutter", "CreateSkiaTypeface");
546 sk_sp<SkTypeface> skia_typeface(
547 sk_sp<SkTypeface>(font_style_set_ohos->createTypeface(i)));
548 float wghtValue = font_style_set_ohos->getWghtValue(i);
549 if (wghtValue <= 0.0f) {
550 wghtValue = font_style_set_ohos->getFontWeight(i);
551 }
552 VaryTypeface(skia_typeface, wghtValue);
553 if (skia_typeface != nullptr) {
554 skia_typefaces.emplace_back(std::move(skia_typeface));
555 }
556 }
557
558 int index = 0;
559 std::vector<minikin::Font> minikin_fonts;
560 for (const sk_sp<SkTypeface>& skia_typeface : skia_typefaces) {
561 // Create the minikin font from the skia typeface.
562 // Divide by 100 because the weights are given as "100", "200", etc.
563 minikin_fonts.emplace_back(
564 std::make_shared<FontSkia>(skia_typeface),
565 minikin::FontStyle{font_style_set_ohos->getFontWeight(index++) / 100,
566 skia_typeface->isItalic()});
567 }
568
569 return std::make_shared<minikin::FontFamily>(std::move(minikin_fonts));
570 }
571
572 std::shared_ptr<minikin::FontFamily>
CreateMinikinFontFamilyExceptOHOS(const sk_sp<SkFontMgr> & manager,const std::string & family_name)573 FontCollection::CreateMinikinFontFamilyExceptOHOS(
574 const sk_sp<SkFontMgr>& manager,
575 const std::string& family_name) {
576 TRACE_EVENT1("flutter",
577 "FontCollection::CreateMinikinFontFamilyExceptOHOS",
578 "family_name", family_name.c_str());
579 sk_sp<SkFontStyleSet> font_style_set(
580 manager->matchFamily(family_name.c_str()));
581 if (font_style_set == nullptr || font_style_set->count() == 0) {
582 return nullptr;
583 }
584
585 std::vector<sk_sp<SkTypeface>> skia_typefaces;
586 for (int i = 0; i < font_style_set->count(); ++i) {
587 TRACE_EVENT0("flutter", "CreateSkiaTypeface");
588 sk_sp<SkTypeface> skia_typeface(
589 sk_sp<SkTypeface>(font_style_set->createTypeface(i)));
590 VaryTypeface(skia_typeface, skia_typeface->fontStyle().weight());
591 if (skia_typeface != nullptr) {
592 skia_typefaces.emplace_back(std::move(skia_typeface));
593 }
594 }
595
596 std::sort(skia_typefaces.begin(), skia_typefaces.end(),
597 [](const sk_sp<SkTypeface>& a, const sk_sp<SkTypeface>& b) {
598 SkFontStyle a_style = a->fontStyle();
599 SkFontStyle b_style = b->fontStyle();
600 return (a_style.weight() != b_style.weight())
601 ? a_style.weight() < b_style.weight()
602 : a_style.slant() < b_style.slant();
603 });
604
605 std::vector<minikin::Font> minikin_fonts;
606 for (const sk_sp<SkTypeface>& skia_typeface : skia_typefaces) {
607 // Create the minikin font from the skia typeface.
608 // Divide by 100 because the weights are given as "100", "200", etc.
609 minikin_fonts.emplace_back(
610 std::make_shared<FontSkia>(skia_typeface),
611 minikin::FontStyle{skia_typeface->fontStyle().weight() / 100,
612 skia_typeface->isItalic()});
613 }
614
615 return std::make_shared<minikin::FontFamily>(std::move(minikin_fonts));
616 }
617
VaryTypeface(sk_sp<SkTypeface> & typeface,float wght)618 void FontCollection::VaryTypeface(sk_sp<SkTypeface>& typeface, float wght) {
619 if (font_weight_scale_ <= 0.0f) {
620 return;
621 }
622 // Value of wght is between 0.0f and 1000.0f, and must be greater than 0.0f,
623 // default value is 400.0f.
624 if (wght <= 0.0) {
625 wght = 400.0f;
626 }
627 float wghtValue = std::min(wght * font_weight_scale_, 1000.0f);
628 SkFontArguments params;
629 int ttcIndex;
630 std::unique_ptr<SkStreamAsset> stream(typeface->openStream(&ttcIndex));
631 params.setCollectionIndex(ttcIndex);
632 std::vector<minikin::FontVariation> variations = {
633 {minikin::MinikinFont::MakeTag('w', 'g', 'h', 't'), wghtValue}};
634 std::vector<SkFontArguments::Axis> skAxes;
635 skAxes.resize(variations.size());
636 for (size_t i = 0; i < variations.size(); i++) {
637 skAxes[i].fTag = variations[i].axisTag;
638 skAxes[i].fStyleValue = variations[i].value;
639 }
640 params.setAxes(skAxes.data(), skAxes.size());
641 sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
642 typeface = fm->makeFromStream(std::move(stream), params);
643 }
644
645 const std::shared_ptr<minikin::FontFamily>&
MatchFallbackFontWithVariation(uint32_t ch,std::string locale)646 FontCollection::MatchFallbackFontWithVariation(uint32_t ch,
647 std::string locale) {
648 {
649 std::lock_guard<std::mutex> lock(mutex_);
650 auto lookup = fallback_match_cache_.find(ch);
651 if (lookup != fallback_match_cache_.end()) {
652 return *lookup->second;
653 }
654 }
655 const std::shared_ptr<minikin::FontFamily>* match =
656 &DoMatchFallbackFontWithVariation(ch, locale);
657 {
658 std::lock_guard<std::mutex> lock(mutex_);
659 fallback_match_cache_.insert(std::make_pair(ch, match));
660 }
661 return *match;
662 }
663
664 const std::shared_ptr<minikin::FontFamily>&
DoMatchFallbackFontWithVariation(uint32_t ch,std::string locale)665 FontCollection::DoMatchFallbackFontWithVariation(uint32_t ch,
666 std::string locale) {
667 for (const std::pair<sk_sp<SkFontMgr>, FontManagerType>& managerPair :
668 GetFontManagerOrderWithType()) {
669 std::vector<const char*> bcp47;
670 if (!locale.empty())
671 bcp47.push_back(locale.c_str());
672
673 if (managerPair.second == FontManagerType::DEFAULT_OHOS) {
674 auto ohosManager = reinterpret_cast<SkFontMgr_OHOS*>(managerPair.first.get());
675 if (ohosManager == nullptr)
676 continue;
677
678 SkString sk_family_name = ohosManager->onMatchFamilyStyleCharacterOHOS(
679 0, SkFontStyle(), bcp47.data(), bcp47.size(), ch);
680 if(sk_family_name.isEmpty())
681 continue;
682
683 return GetFallbackFontFamilyForOHOS(managerPair.first, std::string(sk_family_name.c_str()));
684 } else {
685 sk_sp<SkTypeface> typeface(managerPair.first->matchFamilyStyleCharacter(
686 0, SkFontStyle(), bcp47.data(), bcp47.size(), ch));
687 if (!typeface)
688 continue;
689
690 SkString sk_family_name;
691 typeface->getFamilyName(&sk_family_name);
692 std::string family_name(sk_family_name.c_str());
693
694 {
695 std::lock_guard<std::mutex> lock(mutex_);
696 fallback_fonts_for_locale_[locale].insert(family_name);
697 }
698
699 return GetFallbackFontFamily(managerPair.first, family_name);
700 }
701 }
702 return g_null_family;
703 }
704
705 const std::shared_ptr<minikin::FontFamily>&
GetFallbackFontFamilyForOHOS(const sk_sp<SkFontMgr> & manager,const std::string & family_name)706 FontCollection::GetFallbackFontFamilyForOHOS(
707 const sk_sp<SkFontMgr>& manager,
708 const std::string& family_name) {
709 TRACE_EVENT0("flutter", "FontCollection::GetFallbackFontFamily");
710 {
711 std::lock_guard<std::mutex> lock(mutex_);
712 auto fallback_it = fallback_fonts_.find(family_name);
713 if (fallback_it != fallback_fonts_.end()) {
714 return fallback_it->second;
715 }
716 }
717
718 std::shared_ptr<minikin::FontFamily> minikin_family =
719 CreateMinikinFontFamilyForOHOS(manager, family_name);
720 if (!minikin_family) {
721 minikin_family = CreateMinikinFontFamilyExceptOHOS(manager, family_name);
722 }
723 if (!minikin_family)
724 return g_null_family;
725
726 {
727 decltype(font_collections_cache_) font_collections_cache;
728 std::lock_guard<std::mutex> lock(mutex_);
729 auto insert_it =
730 fallback_fonts_.insert(std::make_pair(family_name, minikin_family));
731
732 // Clear the cache to force creation of new font collections that will
733 // include this fallback font.
734 std::swap(font_collections_cache_, font_collections_cache);
735
736 return insert_it.first->second;
737 }
738 }
739
MatchFallbackFontFromHwFont(uint32_t ch,std::string locale)740 const std::shared_ptr<minikin::FontFamily>& FontCollection::MatchFallbackFontFromHwFont(
741 uint32_t ch,
742 std::string locale) {
743 const std::shared_ptr<minikin::FontFamily>* match =
744 &DoMatchFallbackFontFromHwFont(ch, locale);
745 return *match;
746 }
747
748 const std::shared_ptr<minikin::FontFamily>&
DoMatchFallbackFontFromHwFont(uint32_t ch,std::string locale)749 FontCollection::DoMatchFallbackFontFromHwFont(uint32_t ch,
750 std::string locale) {
751 for (const std::pair<sk_sp<SkFontMgr>, FontManagerType>& managerPair :
752 GetFontManagerOrderWithType()) {
753 std::vector<const char*> bcp47;
754 if (!locale.empty())
755 bcp47.push_back(locale.c_str());
756
757 if (managerPair.second == FontManagerType::DEFAULT_OHOS) {
758 auto ohosManager = reinterpret_cast<SkFontMgr_OHOS*>(managerPair.first.get());
759 if (ohosManager == nullptr)
760 continue;
761
762 SkString sk_family_name = ohosManager->onMatchFamilyStyleCharacterHwFont(
763 0, SkFontStyle(), bcp47.data(), bcp47.size(), ch);
764 if(sk_family_name.isEmpty())
765 continue;
766
767 return GetFallbackFontFamilyForOHOS(managerPair.first, std::string(sk_family_name.c_str()));
768 }
769 }
770 return g_null_family;
771 }
772 #endif
773
774 #if FLUTTER_ENABLE_SKSHAPER
775
776 sk_sp<skia::textlayout::FontCollection>
CreateSktFontCollection()777 FontCollection::CreateSktFontCollection() {
778 sk_sp<skia::textlayout::FontCollection> skt_collection =
779 sk_make_sp<skia::textlayout::FontCollection>();
780
781 skt_collection->setDefaultFontManager(GetDefaultFontManagerSafely(),
782 GetDefaultFontFamily().c_str());
783 skt_collection->setAssetFontManager(asset_font_manager_);
784 skt_collection->setDynamicFontManager(dynamic_font_manager_);
785 skt_collection->setTestFontManager(test_font_manager_);
786 if (!enable_font_fallback_) {
787 skt_collection->disableFontFallback();
788 }
789
790 return skt_collection;
791 }
792
793 #endif // FLUTTER_ENABLE_SKSHAPER
794
795 } // namespace txt
796