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