1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "font_collection.h"
17
18 #include "convert.h"
19 #include "custom_symbol_config.h"
20 #include "texgine/src/font_descriptor_mgr.h"
21 #include "txt/platform.h"
22 #include "text/typeface.h"
23 #include "utils/text_log.h"
24
25 namespace OHOS {
26 namespace Rosen {
Create()27 std::shared_ptr<FontCollection> FontCollection::Create()
28 {
29 static std::shared_ptr<FontCollection> instance = std::make_shared<AdapterTxt::FontCollection>();
30 return instance;
31 }
32
From(std::shared_ptr<txt::FontCollection> fontCollection)33 std::shared_ptr<FontCollection> FontCollection::From(std::shared_ptr<txt::FontCollection> fontCollection)
34 {
35 return std::make_shared<AdapterTxt::FontCollection>(fontCollection);
36 }
37
38 namespace AdapterTxt {
FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)39 FontCollection::FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)
40 : fontCollection_(fontCollection), dfmanager_(Drawing::FontMgr::CreateDynamicFontMgr())
41 {
42 if (fontCollection_ == nullptr) {
43 fontCollection_ = std::make_shared<txt::FontCollection>();
44 }
45 fontCollection_->SetupDefaultFontManager();
46 fontCollection_->SetDynamicFontManager(dfmanager_);
47 }
48
Get()49 std::shared_ptr<txt::FontCollection> FontCollection::Get()
50 {
51 return fontCollection_;
52 }
53
~FontCollection()54 FontCollection::~FontCollection()
55 {
56 if (Drawing::Typeface::GetTypefaceUnRegisterCallBack() == nullptr) {
57 return;
58 }
59
60 std::unique_lock<std::shared_mutex> lock(mutex_);
61 for (const auto& ta : typefaceSet_) {
62 Drawing::Typeface::GetTypefaceUnRegisterCallBack()(ta.GetTypeface());
63 }
64 for (const auto& family : familyNames_) {
65 FontDescriptorMgrInstance.DeleteDynamicTypefaceFromCache(family.second);
66 }
67 typefaceSet_.clear();
68 familyNames_.clear();
69 }
70
DisableFallback()71 void FontCollection::DisableFallback()
72 {
73 fontCollection_->DisableFontFallback();
74 }
75
DisableSystemFont()76 void FontCollection::DisableSystemFont()
77 {
78 fontCollection_->SetDefaultFontManager(nullptr);
79 }
80
GetFontMgr()81 std::shared_ptr<Drawing::FontMgr> FontCollection::GetFontMgr()
82 {
83 return dfmanager_;
84 }
85
RegisterTypeface(const TypefaceWithAlias & ta)86 RegisterError FontCollection::RegisterTypeface(const TypefaceWithAlias& ta)
87 {
88 if (ta.GetTypeface() == nullptr || Drawing::Typeface::GetTypefaceRegisterCallBack() == nullptr) {
89 return RegisterError::INVALID_INPUT;
90 }
91
92 std::unique_lock<std::shared_mutex> lock(mutex_);
93 if (typefaceSet_.count(ta)) {
94 TEXT_LOGI_LIMIT3_MIN(
95 "Find same typeface: family name: %{public}s, hash: %{public}u", ta.GetAlias().c_str(), ta.GetHash());
96 return RegisterError::ALREADY_EXIST;
97 }
98 if (!Drawing::Typeface::GetTypefaceRegisterCallBack()(ta.GetTypeface())) {
99 return RegisterError::REGISTER_FAILED;
100 }
101 TEXT_LOGI("Succeed in registering typeface, family name: %{public}s, hash: %{public}u", ta.GetAlias().c_str(),
102 ta.GetHash());
103 typefaceSet_.insert(ta);
104 return RegisterError::SUCCESS;
105 }
106
LoadFont(const std::string & familyName,const uint8_t * data,size_t datalen)107 std::shared_ptr<Drawing::Typeface> FontCollection::LoadFont(
108 const std::string& familyName, const uint8_t* data, size_t datalen)
109 {
110 std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadDynamicFont(familyName, data, datalen));
111 TypefaceWithAlias ta(familyName, typeface);
112 RegisterError err = RegisterTypeface(ta);
113 if (err != RegisterError::SUCCESS && err != RegisterError::ALREADY_EXIST) {
114 TEXT_LOGE("Failed to register typeface %{public}s", familyName.c_str());
115 return nullptr;
116 }
117 FontDescriptorMgrInstance.CacheDynamicTypeface(typeface, familyName);
118 familyNames_.emplace(typeface->GetHash(), familyName);
119 fontCollection_->ClearFontFamilyCache();
120 return typeface;
121 }
122
LoadSymbolFont(const std::string & familyName,const uint8_t * data,size_t datalen)123 LoadSymbolErrorCode FontCollection::LoadSymbolFont(const std::string& familyName, const uint8_t* data, size_t datalen)
124 {
125 std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadDynamicFont(familyName, data, datalen));
126 if (typeface == nullptr) {
127 return LoadSymbolErrorCode::LOAD_FAILED;
128 }
129 std::unique_lock<std::shared_mutex> lock(mutex_);
130 TypefaceWithAlias ta(familyName, typeface);
131 if (typefaceSet_.count(ta)) {
132 return LoadSymbolErrorCode::SUCCESS;
133 }
134 typefaceSet_.insert(ta);
135 return LoadSymbolErrorCode::SUCCESS;
136 }
137
LoadSymbolJson(const std::string & familyName,const uint8_t * data,size_t datalen)138 LoadSymbolErrorCode FontCollection::LoadSymbolJson(const std::string& familyName, const uint8_t* data, size_t datalen)
139 {
140 return CustomSymbolConfig::GetInstance()->ParseConfig(familyName, data, datalen);
141 }
142
143
CreateTypeface(const uint8_t * data,size_t datalen)144 static std::shared_ptr<Drawing::Typeface> CreateTypeface(const uint8_t *data, size_t datalen)
145 {
146 if (datalen != 0 && data != nullptr) {
147 auto stream = std::make_unique<Drawing::MemoryStream>(data, datalen, true);
148 return Drawing::Typeface::MakeFromStream(std::move(stream));
149 }
150 return nullptr;
151 }
152
LoadThemeFont(const std::string & familyName,const uint8_t * data,size_t datalen)153 std::shared_ptr<Drawing::Typeface> FontCollection::LoadThemeFont(
154 const std::string& familyName, const uint8_t* data, size_t datalen)
155 {
156 auto res = LoadThemeFont(familyName, { { data, datalen } });
157 return res.empty() ? nullptr : res[0];
158 }
159
LoadThemeFont(const std::string & familyName,const std::vector<std::pair<const uint8_t *,size_t>> & data)160 std::vector<std::shared_ptr<Drawing::Typeface>> FontCollection::LoadThemeFont(
161 const std::string& familyName, const std::vector<std::pair<const uint8_t*, size_t>>& data)
162 {
163 if (familyName.empty()) {
164 ClearThemeFont();
165 return {};
166 }
167
168 std::vector<std::shared_ptr<Drawing::Typeface>> res;
169 size_t index = 0;
170 for (size_t i = 0; i < data.size(); i += 1) {
171 std::string themeFamily = SPText::DefaultFamilyNameMgr::GetInstance().GenerateThemeFamilyName(index);
172 auto face = CreateTypeface(data[i].first, data[i].second);
173 TypefaceWithAlias ta(themeFamily, face);
174 RegisterError err = RegisterTypeface(ta);
175 if (err == RegisterError::ALREADY_EXIST) {
176 res.emplace_back(face);
177 continue;
178 } else if (err != RegisterError::SUCCESS) {
179 TEXT_LOGE("Failed to load font %{public}s", familyName.c_str());
180 continue;
181 }
182 index += 1;
183 res.emplace_back(face);
184 dfmanager_->LoadThemeFont(themeFamily, face);
185 }
186 SPText::DefaultFamilyNameMgr::GetInstance().ModifyThemeFontFamilies(res.size());
187 fontCollection_->ClearFontFamilyCache();
188 fontCollection_->UpdateDefaultFamilies();
189 return res;
190 }
191
ClearThemeFont()192 void FontCollection::ClearThemeFont()
193 {
194 for (const auto& themeFamily : SPText::DefaultFamilyNameMgr::GetInstance().GetThemeFontFamilies()) {
195 std::shared_ptr<Drawing::Typeface> face(dfmanager_->MatchFamilyStyle(themeFamily.c_str(), {}));
196 TypefaceWithAlias ta(themeFamily, face);
197 typefaceSet_.erase(ta);
198 dfmanager_->LoadThemeFont("", themeFamily, nullptr, 0);
199 }
200 fontCollection_->ClearFontFamilyCache();
201 }
202
ClearCaches()203 void FontCollection::ClearCaches()
204 {
205 fontCollection_->ClearFontFamilyCache();
206 }
207
TypefaceWithAlias(const std::string & alias,const std::shared_ptr<Drawing::Typeface> & typeface)208 TypefaceWithAlias::TypefaceWithAlias(const std::string& alias, const std::shared_ptr<Drawing::Typeface>& typeface)
209 : alias_(alias), typeface_(typeface)
210 {}
211
GetHash() const212 uint32_t TypefaceWithAlias::GetHash() const
213 {
214 if (hash_ != 0) {
215 return hash_;
216 }
217 hash_ = Hasher()(*this);
218 return hash_;
219 }
220
operator ()(const TypefaceWithAlias & ta) const221 uint32_t TypefaceWithAlias::Hasher::operator()(const TypefaceWithAlias& ta) const
222 {
223 uint32_t hashS = std::hash<std::string>()(ta.alias_);
224 uint32_t hashT = ta.typeface_ == nullptr ? 0 : ta.typeface_->GetHash();
225 ta.hash_ = std::hash<uint32_t>()(hashS ^ hashT);
226 return ta.hash_;
227 }
228
GetTypeface() const229 const std::shared_ptr<Drawing::Typeface>& TypefaceWithAlias::GetTypeface() const
230 {
231 return typeface_;
232 }
233
GetAlias() const234 const std::string& TypefaceWithAlias::GetAlias() const
235 {
236 return alias_;
237 }
238
operator ==(const TypefaceWithAlias & other) const239 bool TypefaceWithAlias::operator==(const TypefaceWithAlias& other) const
240 {
241 return other.alias_ == this->alias_ && other.GetHash() == this->GetHash();
242 }
243 } // namespace AdapterTxt
244 } // namespace Rosen
245 } // namespace OHOS
246