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
operator ==(const FontCollection::FamilyKey & other) const11 bool FontCollection::FamilyKey::operator==(const FontCollection::FamilyKey& other) const {
12 return fFamilyNames == other.fFamilyNames && fFontStyle == other.fFontStyle;
13 }
14
operator ()(const FontCollection::FamilyKey & key) const15 size_t FontCollection::FamilyKey::Hasher::operator()(const FontCollection::FamilyKey& key) const {
16 size_t hash = 0;
17 for (const SkString& family : key.fFamilyNames) {
18 hash ^= std::hash<std::string>()(family.c_str());
19 }
20 return hash ^
21 std::hash<uint32_t>()(key.fFontStyle.weight()) ^
22 std::hash<uint32_t>()(key.fFontStyle.slant());
23 }
24
FontCollection()25 FontCollection::FontCollection()
26 : fEnableFontFallback(true)
27 , fDefaultFamilyNames({SkString(DEFAULT_FONT_FAMILY)}) { }
28
getFontManagersCount() const29 size_t FontCollection::getFontManagersCount() const { return this->getFontManagerOrder().size(); }
30
setAssetFontManager(sk_sp<SkFontMgr> font_manager)31 void FontCollection::setAssetFontManager(sk_sp<SkFontMgr> font_manager) {
32 fAssetFontManager = font_manager;
33 }
34
setDynamicFontManager(sk_sp<SkFontMgr> font_manager)35 void FontCollection::setDynamicFontManager(sk_sp<SkFontMgr> font_manager) {
36 fDynamicFontManager = font_manager;
37 }
38
setTestFontManager(sk_sp<SkFontMgr> font_manager)39 void FontCollection::setTestFontManager(sk_sp<SkFontMgr> font_manager) {
40 fTestFontManager = font_manager;
41 }
42
setDefaultFontManager(sk_sp<SkFontMgr> fontManager,const char defaultFamilyName[])43 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
44 const char defaultFamilyName[]) {
45 fDefaultFontManager = std::move(fontManager);
46 fDefaultFamilyNames.emplace_back(defaultFamilyName);
47 }
48
setDefaultFontManager(sk_sp<SkFontMgr> fontManager,const std::vector<SkString> & defaultFamilyNames)49 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager,
50 const std::vector<SkString>& defaultFamilyNames) {
51 fDefaultFontManager = std::move(fontManager);
52 fDefaultFamilyNames = defaultFamilyNames;
53 }
54
setDefaultFontManager(sk_sp<SkFontMgr> fontManager)55 void FontCollection::setDefaultFontManager(sk_sp<SkFontMgr> fontManager) {
56 fDefaultFontManager = fontManager;
57 }
58
59 // Return the available font managers in the order they should be queried.
getFontManagerOrder() const60 std::vector<sk_sp<SkFontMgr>> FontCollection::getFontManagerOrder() const {
61 std::vector<sk_sp<SkFontMgr>> order;
62 if (fDynamicFontManager) {
63 order.push_back(fDynamicFontManager);
64 }
65 if (fAssetFontManager) {
66 order.push_back(fAssetFontManager);
67 }
68 if (fTestFontManager) {
69 order.push_back(fTestFontManager);
70 }
71 if (fDefaultFontManager && fEnableFontFallback) {
72 order.push_back(fDefaultFontManager);
73 }
74 return order;
75 }
76
findTypefaces(const std::vector<SkString> & familyNames,SkFontStyle fontStyle)77 std::vector<sk_sp<SkTypeface>> FontCollection::findTypefaces(const std::vector<SkString>& familyNames, SkFontStyle fontStyle) {
78 // Look inside the font collections cache first
79 FamilyKey familyKey(familyNames, fontStyle);
80 auto found = fTypefaces.find(familyKey);
81 if (found) {
82 return *found;
83 }
84
85 std::vector<sk_sp<SkTypeface>> typefaces;
86 for (const SkString& familyName : familyNames) {
87 sk_sp<SkTypeface> match = matchTypeface(familyName, fontStyle);
88 if (match) {
89 typefaces.emplace_back(std::move(match));
90 }
91 }
92
93 if (typefaces.empty()) {
94 sk_sp<SkTypeface> match;
95 for (const SkString& familyName : fDefaultFamilyNames) {
96 match = matchTypeface(familyName, fontStyle);
97 if (match) {
98 break;
99 }
100 }
101 if (!match) {
102 for (const auto& manager : this->getFontManagerOrder()) {
103 match = manager->legacyMakeTypeface(nullptr, fontStyle);
104 if (match) {
105 break;
106 }
107 }
108 }
109 if (match) {
110 typefaces.emplace_back(std::move(match));
111 }
112 }
113
114 fTypefaces.set(familyKey, typefaces);
115 return typefaces;
116 }
117
matchTypeface(const SkString & familyName,SkFontStyle fontStyle)118 sk_sp<SkTypeface> FontCollection::matchTypeface(const SkString& familyName, SkFontStyle fontStyle) {
119 for (const auto& manager : this->getFontManagerOrder()) {
120 sk_sp<SkFontStyleSet> set(manager->matchFamily(familyName.c_str()));
121 if (!set || set->count() == 0) {
122 continue;
123 }
124
125 sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
126 if (match) {
127 return match;
128 }
129 }
130
131 return nullptr;
132 }
133
134 // Find ANY font in available font managers that resolves the unicode codepoint
defaultFallback(SkUnichar unicode,SkFontStyle fontStyle,const SkString & locale)135 sk_sp<SkTypeface> FontCollection::defaultFallback(SkUnichar unicode, SkFontStyle fontStyle, const SkString& locale) {
136
137 for (const auto& manager : this->getFontManagerOrder()) {
138 std::vector<const char*> bcp47;
139 if (!locale.isEmpty()) {
140 bcp47.push_back(locale.c_str());
141 }
142 sk_sp<SkTypeface> typeface(manager->matchFamilyStyleCharacter(
143 nullptr, fontStyle, bcp47.data(), bcp47.size(), unicode));
144 if (typeface != nullptr) {
145 return typeface;
146 }
147 }
148 return nullptr;
149 }
150
defaultFallback()151 sk_sp<SkTypeface> FontCollection::defaultFallback() {
152 if (fDefaultFontManager == nullptr) {
153 return nullptr;
154 }
155 for (const SkString& familyName : fDefaultFamilyNames) {
156 SkTypeface* match = fDefaultFontManager->matchFamilyStyle(familyName.c_str(),
157 SkFontStyle());
158 if (match) {
159 return sk_sp<SkTypeface>(match);
160 }
161 }
162 return nullptr;
163 }
164
165
disableFontFallback()166 void FontCollection::disableFontFallback() { fEnableFontFallback = false; }
enableFontFallback()167 void FontCollection::enableFontFallback() { fEnableFontFallback = true; }
168
clearCaches()169 void FontCollection::clearCaches() {
170 fParagraphCache.reset();
171 fTypefaces.reset();
172 SkShaper::PurgeCaches();
173 }
174
175 } // namespace textlayout
176 } // namespace skia
177