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 "text/typeface.h"
20 #include "utils/text_log.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 #define OHOS_THEME_FONT "OhosThemeFont"
25 
Create()26 std::shared_ptr<FontCollection> FontCollection::Create()
27 {
28     static std::shared_ptr<FontCollection> instance = std::make_shared<AdapterTxt::FontCollection>();
29     return instance;
30 }
31 
From(std::shared_ptr<txt::FontCollection> fontCollection)32 std::shared_ptr<FontCollection> FontCollection::From(std::shared_ptr<txt::FontCollection> fontCollection)
33 {
34     return std::make_shared<AdapterTxt::FontCollection>(fontCollection);
35 }
36 
37 namespace AdapterTxt {
FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)38 FontCollection::FontCollection(std::shared_ptr<txt::FontCollection> fontCollection)
39     : fontCollection_(fontCollection), dfmanager_(Drawing::FontMgr::CreateDynamicFontMgr())
40 {
41     if (fontCollection_ == nullptr) {
42         fontCollection_ = std::make_shared<txt::FontCollection>();
43     }
44     fontCollection_->SetupDefaultFontManager();
45     fontCollection_->SetDynamicFontManager(dfmanager_);
46 }
47 
Get()48 std::shared_ptr<txt::FontCollection> FontCollection::Get()
49 {
50     return fontCollection_;
51 }
52 
~FontCollection()53 FontCollection::~FontCollection()
54 {
55     if (Drawing::Typeface::GetTypefaceUnRegisterCallBack() == nullptr) {
56         return;
57     }
58 
59     std::unique_lock<std::mutex> lock(mutex_);
60     for (const auto& [id, typeface] : typefaces_) {
61         Drawing::Typeface::GetTypefaceUnRegisterCallBack()(typeface);
62     }
63     typefaces_.clear();
64 }
65 
DisableFallback()66 void FontCollection::DisableFallback()
67 {
68     fontCollection_->DisableFontFallback();
69 }
70 
DisableSystemFont()71 void FontCollection::DisableSystemFont()
72 {
73     fontCollection_->SetDefaultFontManager(nullptr);
74 }
75 
GetFontMgr()76 std::shared_ptr<Drawing::FontMgr> FontCollection::GetFontMgr()
77 {
78     return dfmanager_;
79 }
80 
RegisterTypeface(std::shared_ptr<Drawing::Typeface> typeface)81 bool FontCollection::RegisterTypeface(std::shared_ptr<Drawing::Typeface> typeface)
82 {
83     if (!typeface || !Drawing::Typeface::GetTypefaceRegisterCallBack()) {
84         return false;
85     }
86 
87     std::unique_lock<std::mutex> lock(mutex_);
88     if (typefaces_.find(typeface->GetUniqueID()) != typefaces_.end()) {
89         return true;
90     }
91     if (!Drawing::Typeface::GetTypefaceRegisterCallBack()(typeface)) {
92         return false;
93     }
94 
95     typefaces_.emplace(typeface->GetUniqueID(), typeface);
96     return true;
97 }
98 
LoadFont(const std::string & familyName,const uint8_t * data,size_t datalen)99 std::shared_ptr<Drawing::Typeface> FontCollection::LoadFont(
100     const std::string &familyName, const uint8_t *data, size_t datalen)
101 {
102     std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadDynamicFont(familyName, data, datalen));
103     if (!RegisterTypeface(typeface)) {
104         TEXT_LOGE("Failed to register typeface %{public}s", familyName.c_str());
105         return nullptr;
106     }
107     fontCollection_->ClearFontFamilyCache();
108     return typeface;
109 }
110 
CreateTypeFace(const uint8_t * data,size_t datalen)111 static std::shared_ptr<Drawing::Typeface> CreateTypeFace(const uint8_t *data, size_t datalen)
112 {
113     if (datalen != 0 && data != nullptr) {
114         auto stream = std::make_unique<Drawing::MemoryStream>(data, datalen, true);
115         return Drawing::Typeface::MakeFromStream(std::move(stream));
116     }
117     return nullptr;
118 }
119 
LoadThemeFont(const std::string & familyName,const uint8_t * data,size_t datalen)120 std::shared_ptr<Drawing::Typeface> FontCollection::LoadThemeFont(
121     const std::string &familyName, const uint8_t *data, size_t datalen)
122 {
123     std::shared_ptr<Drawing::Typeface> face = CreateTypeFace(data, datalen);
124     if (face != nullptr) {
125         std::string name = face->GetFamilyName();
126         uint32_t faceHash = face->GetHash();
127         for (auto item : typefaces_) {
128             if (faceHash == item.second->GetHash()) {
129                 TEXT_LOGI("Find same theme font:family name:%{public}s, uniqueid:%{public}u, hash:%{public}u",
130                     name.c_str(), item.second->GetUniqueID(), faceHash);
131                 dfmanager_->LoadThemeFont(OHOS_THEME_FONT, item.second);
132                 fontCollection_->ClearFontFamilyCache();
133                 return item.second;
134             }
135         }
136     }
137 
138     std::shared_ptr<Drawing::Typeface> typeface(dfmanager_->LoadThemeFont(familyName, OHOS_THEME_FONT, data, datalen));
139     if (!RegisterTypeface(typeface)) {
140         TEXT_LOGE("Failed to register typeface %{public}s", familyName.c_str());
141     }
142     fontCollection_->ClearFontFamilyCache();
143     return typeface;
144 }
145 
ClearCaches()146 void FontCollection::ClearCaches()
147 {
148     fontCollection_->ClearFontFamilyCache();
149 }
150 } // namespace AdapterTxt
151 } // namespace Rosen
152 } // namespace OHOS
153