1 /*
2  * Copyright (c) 2021-2023 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 "core/components/font/rosen_font_collection.h"
17 
18 #ifndef USE_GRAPHIC_TEXT_GINE
19 #include "txt/src/minikin/FontFamily.h"
20 #include "txt/src/minikin/FontLanguageListCache.h"
21 #else
22 #include "core/components_ng/render/adapter/txt_font_collection.h"
23 #include "rosen_text/font_collection.h"
24 #endif
25 #ifndef USE_ROSEN_DRAWING
26 #include "include/core/SkTypeface.h"
27 #endif
28 #include "core/common/ace_engine.h"
29 
30 namespace OHOS::Ace {
31 
32 RosenFontCollection RosenFontCollection::instance;
33 
34 #ifndef USE_GRAPHIC_TEXT_GINE
GetFontCollection()35 std::shared_ptr<txt::FontCollection> RosenFontCollection::GetFontCollection()
36 {
37     std::call_once(fontFlag_, [this]() {
38         auto rosenCollection = RSFontCollection::GetInstance(false);
39         auto collectionTxtBase = rosenCollection->GetFontCollection();
40         auto collectionTxt = std::static_pointer_cast<rosen::FontCollectionTxt>(collectionTxtBase);
41         if (collectionTxt) {
42             fontCollection_ = collectionTxt->GetFontCollection();
43             dynamicFontManager_ = collectionTxt->GetDynamicFontManager();
44         } else {
45             TAG_LOGW(AceLogTag::ACE_FONT, "Fail to get font Follection!");
46         }
47     });
48     return fontCollection_;
49 }
50 
51 #ifndef USE_ROSEN_DRAWING
GetDynamicFontManager()52 sk_sp<txt::DynamicFontManager> RosenFontCollection::GetDynamicFontManager()
53 #else
54 std::shared_ptr<RSFontMgr> RosenFontCollection::GetDynamicFontManager()
55 #endif
56 {
57     return dynamicFontManager_;
58 }
59 #else
GetFontCollection()60 std::shared_ptr<Rosen::FontCollection> RosenFontCollection::GetFontCollection()
61 {
62     std::call_once(fontFlag_, [this]() {
63         auto fontCollection = AceType::DynamicCast<NG::TxtFontCollection>(NG::FontCollection::Current());
64         fontCollection_ = fontCollection->GetRawFontCollection();
65     });
66     return fontCollection_;
67 }
68 #endif
69 
LoadFontFromList(const uint8_t * fontData,size_t length,std::string familyName)70 void RosenFontCollection::LoadFontFromList(const uint8_t* fontData, size_t length, std::string familyName)
71 {
72     std::call_once(fontFlag_, [this]() {
73 #ifndef USE_GRAPHIC_TEXT_GINE
74         auto rosenCollection = RSFontCollection::GetInstance(false);
75         auto collectionTxtBase = rosenCollection->GetFontCollection();
76         auto collectionTxt = std::static_pointer_cast<rosen::FontCollectionTxt>(collectionTxtBase);
77         if (collectionTxt) {
78             fontCollection_ = collectionTxt->GetFontCollection();
79             dynamicFontManager_ = collectionTxt->GetDynamicFontManager();
80         }
81 #else
82         auto fontCollection = AceType::DynamicCast<NG::TxtFontCollection>(NG::FontCollection::Current());
83         fontCollection_ = fontCollection->GetRawFontCollection();
84 #endif
85     });
86 
87     if (families_.find(familyName) != families_.end()) {
88         return;
89     }
90 
91     families_.emplace(familyName);
92 
93     if (fontCollection_) {
94 #ifndef USE_GRAPHIC_TEXT_GINE
95 #ifndef USE_ROSEN_DRAWING
96         std::unique_ptr<SkStreamAsset> font_stream = std::make_unique<SkMemoryStream>(fontData, length, true);
97         sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(std::move(font_stream));
98         txt::TypefaceFontAssetProvider& font_provider = dynamicFontManager_->font_provider();
99         if (familyName.empty()) {
100             font_provider.RegisterTypeface(typeface);
101         } else {
102             font_provider.RegisterTypeface(typeface, familyName);
103         }
104         fontCollection_->ClearFontFamilyCache();
105 #else
106         TAG_LOGW(AceLogTag::ACE_FONT, "Drawing is not supported dynamic font");
107 #endif
108 #else
109         fontCollection_->LoadFont(familyName, fontData, length);
110 #endif
111     }
112 }
113 
InitializeFontCollection()114 void RosenFontCollection::InitializeFontCollection()
115 {
116     std::call_once(fontFlag_, [this]() {
117 #ifndef USE_GRAPHIC_TEXT_GINE
118     auto rosenCollection = RSFontCollection::GetInstance(false);
119     auto collectionTxtBase = rosenCollection->GetFontCollection();
120     auto collectionTxt = std::static_pointer_cast<rosen::FontCollectionTxt>(collectionTxtBase);
121     if (collectionTxt) {
122         fontCollection_ = collectionTxt->GetFontCollection();
123         dynamicFontManager_ = collectionTxt->GetDynamicFontManager();
124     }
125 #else
126     auto fontCollection = AceType::DynamicCast<NG::TxtFontCollection>(NG::FontCollection::Current());
127     fontCollection_ = fontCollection->GetRawFontCollection();
128 #endif
129     });
130 }
131 
LoadThemeFont(const char * fontFamily,std::unique_ptr<char[]> buffer,size_t size)132 void RosenFontCollection::LoadThemeFont(const char* fontFamily, std::unique_ptr<char[]> buffer, size_t size)
133 {
134     const std::string familyName = fontFamily;
135     const uint8_t* data = reinterpret_cast<uint8_t*>(buffer.get());
136     if (fontCollection_) {
137 #ifndef USE_GRAPHIC_TEXT_GINE
138 #ifndef USE_ROSEN_DRAWING
139         std::unique_ptr<SkStreamAsset> font_stream = std::make_unique<SkMemoryStream>(data, size, true);
140         sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(std::move(font_stream));
141         txt::TypefaceFontAssetProvider& font_provider = dynamicFontManager_->font_provider();
142         if (familyName.empty()) {
143             font_provider.RegisterTypeface(typeface);
144         } else {
145             font_provider.RegisterTypeface(typeface, familyName);
146         }
147         fontCollection_->ClearFontFamilyCache();
148 #else
149         TAG_LOGW(AceLogTag::ACE_FONT, "Drawing is not supported");
150 #endif
151 #else
152         fontCollection_->LoadThemeFont("", nullptr, 0);
153         TAG_LOGI(AceLogTag::ACE_FONT, "LoadThemeFont [%{public}s:%{public}d]", familyName.c_str(),
154             static_cast<int32_t>(size));
155         fontCollection_->LoadThemeFont(familyName, data, size);
156 #endif
157     }
158 }
159 
LoadFontFamily(const char * fontFamily,const char * familySrc)160 void RosenFontCollection::LoadFontFamily(const char* fontFamily, const char* familySrc)
161 {
162     const std::string path = familySrc;
163     if (currentFamily_ == path) {
164         TAG_LOGI(AceLogTag::ACE_FONT, "This font has already been registered.");
165         return;
166     }
167     InitializeFontCollection();
168     auto ret = StdFilesystemExists(path);
169     if (!ret) {
170         TAG_LOGW(AceLogTag::ACE_FONT, "FontFamily %{public}s not exist", path.c_str());
171         return;
172     }
173 
174     std::ifstream ifs(path, std::ios_base::in);
175     if (!ifs.is_open()) {
176         TAG_LOGW(AceLogTag::ACE_FONT, "FontFamily file open fail, %{public}s", path.c_str());
177         return;
178     }
179     ifs.seekg(0, ifs.end);
180     if (!ifs.good()) {
181         ifs.close();
182         TAG_LOGW(AceLogTag::ACE_FONT, "font file is bad");
183         return;
184     }
185     auto size = ifs.tellg();
186     if (ifs.fail()) {
187         ifs.close();
188         TAG_LOGW(AceLogTag::ACE_FONT, "get size failed");
189         return;
190     }
191     ifs.seekg(ifs.beg);
192     if (!ifs.good()) {
193         ifs.close();
194         TAG_LOGW(AceLogTag::ACE_FONT, "file seek failed");
195         return;
196     }
197     std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size);
198     ifs.read(buffer.get(), size);
199     if (!ifs.good()) {
200         ifs.close();
201         TAG_LOGW(AceLogTag::ACE_FONT, "read file failed");
202         return;
203     }
204     ifs.close();
205     currentFamily_ = path;
206     LoadThemeFont(fontFamily, std::move(buffer), size);
207 }
208 
StdFilesystemExists(const std::string & path)209 bool RosenFontCollection::StdFilesystemExists(const std::string &path)
210 {
211     std::ifstream f(path.c_str());
212     return f.good();
213 }
214 
GetInstance()215 RosenFontCollection& RosenFontCollection::GetInstance()
216 {
217     return instance;
218 }
219 
VaryFontCollectionWithFontWeightScale(float fontWeightScale)220 void RosenFontCollection::VaryFontCollectionWithFontWeightScale(float fontWeightScale)
221 {
222     if (LessOrEqual(fontWeightScale, 0.0)) {
223         return;
224     }
225 
226 #ifndef USE_GRAPHIC_TEXT_GINE
227     if (fontCollection_) {
228         fontCollection_->VaryFontCollectionWithFontWeightScale(fontWeightScale);
229     }
230 #endif
231 }
232 
LoadSystemFont()233 void RosenFontCollection::LoadSystemFont()
234 {
235     ACE_FUNCTION_TRACE();
236 
237 #ifndef USE_GRAPHIC_TEXT_GINE
238     if (fontCollection_) {
239         fontCollection_->LoadSystemFont();
240     }
241 #endif
242 }
243 
SetIsZawgyiMyanmar(bool isZawgyiMyanmar)244 void RosenFontCollection::SetIsZawgyiMyanmar(bool isZawgyiMyanmar)
245 {
246     ACE_FUNCTION_TRACE();
247 
248     if (isZawgyiMyanmar_ == isZawgyiMyanmar) {
249         return;
250     }
251     isZawgyiMyanmar_ = isZawgyiMyanmar;
252 
253 #ifndef USE_GRAPHIC_TEXT_GINE
254     if (fontCollection_) {
255         fontCollection_->SetIsZawgyiMyanmar(isZawgyiMyanmar);
256     }
257 #endif
258 
259     AceEngine::Get().NotifyContainers([](const RefPtr<Container>& container) {
260         if (container) {
261             container->NotifyFontNodes();
262         }
263     });
264 }
265 
266 } // namespace OHOS::Ace
267