• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "utils/text_trace.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 FontCollection::FontCallback FontCollection::loadFontStartCallback_ {};
29 FontCollection::FontCallback FontCollection::loadFontFinishCallback_ {};
30 FontCollection::FontCallback FontCollection::unloadFontStartCallback_ {};
31 FontCollection::FontCallback FontCollection::unloadFontFinishCallback_ {};
32 
Create()33 std::shared_ptr<FontCollection> FontCollection::Create()
34 {
35     static std::shared_ptr<FontCollection> instance = std::make_shared<AdapterTxt::FontCollection>();
36     return instance;
37 }
38 
From(std::shared_ptr<txt::FontCollection> fontCollection)39 std::shared_ptr<FontCollection> FontCollection::From(std::shared_ptr<txt::FontCollection> fontCollection)
40 {
41     return std::make_shared<AdapterTxt::FontCollection>(fontCollection);
42 }
43 
44 namespace AdapterTxt {
FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)45 FontCollection::FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)
46     : fontCollection_(fontCollection), dfmanager_(Drawing::FontMgr::CreateDynamicFontMgr())
47 {
48     if (fontCollection_ == nullptr) {
49         fontCollection_ = std::make_shared<txt::FontCollection>();
50     }
51     fontCollection_->SetupDefaultFontManager();
52     fontCollection_->SetDynamicFontManager(dfmanager_);
53 }
54 
Get()55 std::shared_ptr<txt::FontCollection> FontCollection::Get()
56 {
57     return fontCollection_;
58 }
59 
~FontCollection()60 FontCollection::~FontCollection()
61 {
62     if (Drawing::Typeface::GetTypefaceUnRegisterCallBack() == nullptr) {
63         return;
64     }
65 
66     std::unique_lock<std::shared_mutex> lock(mutex_);
67     for (const auto& ta : typefaceSet_) {
68         Drawing::Typeface::GetTypefaceUnRegisterCallBack()(ta.GetTypeface());
69     }
70     for (const auto& family : familyNames_) {
71         FontDescriptorMgrInstance.DeleteDynamicTypefaceFromCache(family.second);
72     }
73     typefaceSet_.clear();
74     familyNames_.clear();
75 }
76 
DisableFallback()77 void FontCollection::DisableFallback()
78 {
79     fontCollection_->DisableFontFallback();
80 }
81 
DisableSystemFont()82 void FontCollection::DisableSystemFont()
83 {
84     fontCollection_->SetDefaultFontManager(nullptr);
85 }
86 
GetFontMgr()87 std::shared_ptr<Drawing::FontMgr> FontCollection::GetFontMgr()
88 {
89     return dfmanager_;
90 }
91 
RegisterTypeface(const TypefaceWithAlias & ta)92 RegisterError FontCollection::RegisterTypeface(const TypefaceWithAlias& ta)
93 {
94     if (ta.GetTypeface() == nullptr || Drawing::Typeface::GetTypefaceRegisterCallBack() == nullptr) {
95         return RegisterError::INVALID_INPUT;
96     }
97 
98     std::unique_lock<std::shared_mutex> lock(mutex_);
99     if (typefaceSet_.count(ta)) {
100         TEXT_LOGI_LIMIT3_MIN(
101             "Find same typeface, family name: %{public}s, hash: %{public}u", ta.GetAlias().c_str(), ta.GetHash());
102         return RegisterError::ALREADY_EXIST;
103     }
104     if (!Drawing::Typeface::GetTypefaceRegisterCallBack()(ta.GetTypeface())) {
105         return RegisterError::REGISTER_FAILED;
106     }
107     TEXT_LOGI("Succeed in registering typeface, family name: %{public}s, hash: %{public}u", ta.GetAlias().c_str(),
108         ta.GetHash());
109     typefaceSet_.insert(ta);
110     return RegisterError::SUCCESS;
111 }
112 
LoadFont(const std::string & familyName,const uint8_t * data,size_t datalen)113 std::shared_ptr<Drawing::Typeface> FontCollection::LoadFont(
114     const std::string& familyName, const uint8_t* data, size_t datalen)
115 {
116     TEXT_TRACE_FUNC();
117     std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadDynamicFont(familyName, data, datalen));
118     if (typeface == nullptr) {
119         TEXT_LOGE("Failed to load font %{public}s", familyName.c_str());
120         return nullptr;
121     }
122     TypefaceWithAlias ta(familyName, typeface);
123     FontCallbackGuard cb(this, ta.GetAlias(), loadFontStartCallback_, loadFontFinishCallback_);
124     RegisterError err = RegisterTypeface(ta);
125     if (err != RegisterError::SUCCESS && err != RegisterError::ALREADY_EXIST) {
126         TEXT_LOGE("Failed to register typeface %{public}s", ta.GetAlias().c_str());
127         return nullptr;
128     }
129     FontDescriptorMgrInstance.CacheDynamicTypeface(typeface, ta.GetAlias());
130     familyNames_.emplace(ta.GetHash(), ta.GetAlias());
131     fontCollection_->ClearFontFamilyCache();
132     return typeface;
133 }
134 
LoadSymbolFont(const std::string & familyName,const uint8_t * data,size_t datalen)135 LoadSymbolErrorCode FontCollection::LoadSymbolFont(const std::string& familyName, const uint8_t* data, size_t datalen)
136 {
137     TEXT_TRACE_FUNC();
138     std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadDynamicFont(familyName, data, datalen));
139     if (typeface == nullptr) {
140         return LoadSymbolErrorCode::LOAD_FAILED;
141     }
142     std::unique_lock<std::shared_mutex> lock(mutex_);
143     TypefaceWithAlias ta(familyName, typeface);
144     FontCallbackGuard cb(this, familyName, loadFontStartCallback_, loadFontFinishCallback_);
145     if (typefaceSet_.count(ta)) {
146         return LoadSymbolErrorCode::SUCCESS;
147     }
148     typefaceSet_.insert(ta);
149     return LoadSymbolErrorCode::SUCCESS;
150 }
151 
LoadSymbolJson(const std::string & familyName,const uint8_t * data,size_t datalen)152 LoadSymbolErrorCode FontCollection::LoadSymbolJson(const std::string& familyName, const uint8_t* data, size_t datalen)
153 {
154     TEXT_TRACE_FUNC();
155     return OHOS::Rosen::Symbol::CustomSymbolConfig::GetInstance()->ParseConfig(familyName, data, datalen);
156 }
157 
CreateTypeface(const uint8_t * data,size_t datalen)158 static std::shared_ptr<Drawing::Typeface> CreateTypeface(const uint8_t *data, size_t datalen)
159 {
160     if (datalen != 0 && data != nullptr) {
161         auto stream = std::make_unique<Drawing::MemoryStream>(data, datalen, true);
162         return Drawing::Typeface::MakeFromStream(std::move(stream));
163     }
164     return nullptr;
165 }
166 
LoadThemeFont(const std::string & familyName,const uint8_t * data,size_t datalen)167 std::shared_ptr<Drawing::Typeface> FontCollection::LoadThemeFont(
168     const std::string& familyName, const uint8_t* data, size_t datalen)
169 {
170     TEXT_TRACE_FUNC();
171     auto res = LoadThemeFont(familyName, { { data, datalen } });
172     return res.empty() ? nullptr : res[0];
173 }
174 
LoadThemeFont(const std::string & familyName,const std::vector<std::pair<const uint8_t *,size_t>> & data)175 std::vector<std::shared_ptr<Drawing::Typeface>> FontCollection::LoadThemeFont(
176     const std::string& familyName, const std::vector<std::pair<const uint8_t*, size_t>>& data)
177 {
178     if (familyName.empty()) {
179         ClearThemeFont();
180         return {};
181     }
182 
183     std::vector<std::shared_ptr<Drawing::Typeface>> res;
184     size_t index = 0;
185     for (size_t i = 0; i < data.size(); i += 1) {
186         std::string themeFamily = SPText::DefaultFamilyNameMgr::GetInstance().GenerateThemeFamilyName(index);
187         auto face = CreateTypeface(data[i].first, data[i].second);
188         TypefaceWithAlias ta(themeFamily, face);
189         RegisterError err = RegisterTypeface(ta);
190         if (err == RegisterError::ALREADY_EXIST) {
191             res.emplace_back(face);
192             continue;
193         } else if (err != RegisterError::SUCCESS) {
194             TEXT_LOGE("Failed to load font %{public}s", familyName.c_str());
195             continue;
196         }
197         index += 1;
198         res.emplace_back(face);
199         dfmanager_->LoadThemeFont(themeFamily, face);
200     }
201     SPText::DefaultFamilyNameMgr::GetInstance().ModifyThemeFontFamilies(res.size());
202     fontCollection_->ClearFontFamilyCache();
203     fontCollection_->UpdateDefaultFamilies();
204     return res;
205 }
206 
ClearThemeFont()207 void FontCollection::ClearThemeFont()
208 {
209     std::unique_lock lock(mutex_);
210     for (const auto& themeFamily : SPText::DefaultFamilyNameMgr::GetInstance().GetThemeFontFamilies()) {
211         std::shared_ptr<Drawing::Typeface> face(dfmanager_->MatchFamilyStyle(themeFamily.c_str(), {}));
212         TypefaceWithAlias ta(themeFamily, face);
213         typefaceSet_.erase(ta);
214         dfmanager_->LoadThemeFont("", themeFamily, nullptr, 0);
215     }
216     fontCollection_->ClearFontFamilyCache();
217     SPText::DefaultFamilyNameMgr::GetInstance().ModifyThemeFontFamilies(0);
218 }
219 
ClearCaches()220 void FontCollection::ClearCaches()
221 {
222     fontCollection_->ClearFontFamilyCache();
223 }
224 
UnloadFont(const std::string & familyName)225 bool FontCollection::UnloadFont(const std::string& familyName)
226 {
227     if (Drawing::Typeface::GetTypefaceUnRegisterCallBack() == nullptr ||
228         SPText::DefaultFamilyNameMgr::IsThemeFontFamily(familyName) || familyName.empty()) {
229         TEXT_LOGE("Failed to unload font: %{public}s", familyName.c_str());
230         return false;
231     }
232 
233     std::shared_lock readLock(mutex_);
234     if (std::none_of(typefaceSet_.begin(), typefaceSet_.end(),
235         [&familyName](const auto& ta) { return ta.GetAlias() == familyName; })) {
236         TEXT_LOGE("Unload a font which is not loaded: %{public}s", familyName.c_str());
237         return true;
238     }
239     readLock.unlock();
240 
241     FontCallbackGuard cb(this, familyName, unloadFontStartCallback_, unloadFontFinishCallback_);
242     std::unique_lock<std::shared_mutex> lock(mutex_);
243     for (auto it = typefaceSet_.begin(); it != typefaceSet_.end();) {
244         if (it->GetAlias() == familyName) {
245             dfmanager_->LoadDynamicFont(familyName, nullptr, 0);
246             FontDescriptorMgrInstance.DeleteDynamicTypefaceFromCache(familyName);
247             ClearCaches();
248             Drawing::Typeface::GetTypefaceUnRegisterCallBack()(it->GetTypeface());
249             familyNames_.erase(it->GetHash());
250             typefaceSet_.erase(it++);
251         } else {
252             ++it;
253         }
254     }
255 
256     return true;
257 }
258 
FontCallbackGuard(const FontCollection * fc,const std::string & familyName,const FontCallback & begin,const FontCallback & end)259 FontCollection::FontCallbackGuard::FontCallbackGuard(
260     const FontCollection* fc, const std::string& familyName, const FontCallback& begin, const FontCallback& end)
261     : fc_(fc), familyName_(familyName), begin_(begin), end_(end)
262 {
263     begin_.ExecuteCallback(fc_, familyName_);
264 }
265 
~FontCallbackGuard()266 FontCollection::FontCallbackGuard::~FontCallbackGuard()
267 {
268     end_.ExecuteCallback(fc_, familyName_);
269 }
270 
TypefaceWithAlias(const std::string & alias,const std::shared_ptr<Drawing::Typeface> & typeface)271 TypefaceWithAlias::TypefaceWithAlias(const std::string& alias, const std::shared_ptr<Drawing::Typeface>& typeface)
272     : alias_(alias), typeface_(typeface)
273 {
274     if (alias.empty() && typeface != nullptr) {
275         alias_ = typeface->GetFamilyName();
276     }
277 }
278 
GetHash() const279 uint32_t TypefaceWithAlias::GetHash() const
280 {
281     if (hash_ != 0) {
282         return hash_;
283     }
284     hash_ = Hasher()(*this);
285     return hash_;
286 }
287 
operator ()(const TypefaceWithAlias & ta) const288 uint32_t TypefaceWithAlias::Hasher::operator()(const TypefaceWithAlias& ta) const
289 {
290     uint32_t hashS = static_cast<uint32_t>(std::hash<std::string>()(ta.alias_));
291     uint32_t hashT = ta.typeface_ == nullptr ? 0 : ta.typeface_->GetHash();
292     ta.hash_ = static_cast<uint32_t>(std::hash<uint32_t>()(hashS ^ hashT));
293     return ta.hash_;
294 }
295 
GetTypeface() const296 const std::shared_ptr<Drawing::Typeface>& TypefaceWithAlias::GetTypeface() const
297 {
298     return typeface_;
299 }
300 
GetAlias() const301 const std::string& TypefaceWithAlias::GetAlias() const
302 {
303     return alias_;
304 }
305 
operator ==(const TypefaceWithAlias & other) const306 bool TypefaceWithAlias::operator==(const TypefaceWithAlias& other) const
307 {
308     return other.alias_ == this->alias_ && other.GetHash() == this->GetHash();
309 }
310 } // namespace AdapterTxt
311 
RegisterLoadFontStartCallback(FontCallbackType cb)312 void FontCollection::RegisterLoadFontStartCallback(FontCallbackType cb)
313 {
314     loadFontStartCallback_.AddCallback(cb);
315 }
316 
RegisterUnloadFontStartCallback(FontCallbackType cb)317 void FontCollection::RegisterUnloadFontStartCallback(FontCallbackType cb)
318 {
319     unloadFontStartCallback_.AddCallback(cb);
320 }
321 
RegisterLoadFontFinishCallback(FontCallbackType cb)322 void FontCollection::RegisterLoadFontFinishCallback(FontCallbackType cb)
323 {
324     loadFontFinishCallback_.AddCallback(cb);
325 }
326 
RegisterUnloadFontFinishCallback(FontCallbackType cb)327 void FontCollection::RegisterUnloadFontFinishCallback(FontCallbackType cb)
328 {
329     unloadFontFinishCallback_.AddCallback(cb);
330 }
331 
AddCallback(FontCallbackType cb)332 void FontCollection::FontCallback::AddCallback(FontCallbackType cb)
333 {
334     std::lock_guard lock(mutex_);
335     if (cb != nullptr) {
336         callback_.emplace(cb);
337     } else {
338         TEXT_LOGE("Failed to register callback, cb is nullptr");
339     }
340 }
341 
ExecuteCallback(const FontCollection * fc,const std::string & family) const342 void FontCollection::FontCallback::ExecuteCallback(const FontCollection* fc, const std::string& family) const
343 {
344     std::lock_guard lock(mutex_);
345     for (auto& cb : callback_) {
346         cb(fc, family);
347     }
348 }
349 } // namespace Rosen
350 } // namespace OHOS
351