1 /*
2  * Copyright (c) 2023-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 "skia_font_mgr.h"
17 #include <codecvt>
18 #include <locale>
19 #include <securec.h>
20 
21 #include "include/core/SkString.h"
22 #include "include/core/SkTypeface.h"
23 #ifndef USE_TEXGINE
24 #include "txt/asset_font_manager.h"
25 #endif
26 
27 #include "text/font_mgr.h"
28 #include "skia_adapter/skia_convert_utils.h"
29 #include "skia_adapter/skia_font_style_set.h"
30 #include "skia_adapter/skia_typeface.h"
31 #include "text/common_utils.h"
32 #include "utils/log.h"
33 #include "utils/text_log.h"
34 
35 
36 namespace OHOS {
37 namespace Rosen {
38 namespace Drawing {
39 namespace {
40 const uint8_t MOVEBITS = 8;
SwapBytes(char16_t * srcStr,uint32_t len)41 void SwapBytes(char16_t* srcStr, uint32_t len)
42 {
43     if (srcStr == nullptr || len == 0) {
44         return;
45     }
46     // if is big endian, high-order byte first
47     int num = 1;
48     if (*(reinterpret_cast<const uint8_t*>(&num)) == 0) {
49         return;
50     }
51     // swap bytes
52     for (uint32_t i = 0; i < len; i++) {
53         uint16_t temp = static_cast<uint16_t>(srcStr[i]);
54         // Swap the byte order of the 16-bit value
55         srcStr[i] = static_cast<char16_t>((temp & 0xff) << MOVEBITS | (temp & 0xff00) >> MOVEBITS);
56     }
57 }
58 
ConvertToUTF16BE(uint8_t * data,uint32_t dataLen,FontByteArray & fullname)59 bool ConvertToUTF16BE(uint8_t* data, uint32_t dataLen, FontByteArray& fullname)
60 {
61     if (data == nullptr || dataLen == 0) {
62         return false;
63     }
64     std::unique_ptr<uint8_t[]> newData = std::make_unique<uint8_t[]>(dataLen + 1);
65     if (memcpy_s(newData.get(), dataLen + 1, data, dataLen) != EOK) {
66         return false;
67     }
68     newData[dataLen] = '\0';
69     // If the encoding format of data is UTF-16, copy it directly
70     if (strlen(reinterpret_cast<char*>(newData.get())) < dataLen ||
71         !IsUtf8(reinterpret_cast<const char*>(newData.get()), dataLen)) {
72         fullname.strData = std::move(newData);
73         fullname.strLen = dataLen;
74         return true;
75     }
76     // If the data format is utf-8, create a converter from UTF-8 to UTF-16
77     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
78     std::string utf8String(reinterpret_cast<char*>(data), dataLen);
79     std::u16string utf16String = converter.from_bytes(utf8String);
80     // Get the byte length and copy the data
81     size_t strByteLen = utf16String.size() * sizeof(char16_t);
82     if (strByteLen == 0) {
83         return false;
84     }
85     SwapBytes(const_cast<char16_t*>(utf16String.c_str()), strByteLen / sizeof(char16_t));
86     fullname.strData = std::make_unique<uint8_t[]>(strByteLen);
87     if (memcpy_s(fullname.strData.get(), strByteLen,
88         reinterpret_cast<const void*>(utf16String.c_str()), strByteLen) == EOK) {
89         fullname.strLen = strByteLen;
90         return true;
91     }
92     return false;
93 }
94 }
95 
SkiaFontMgr(sk_sp<SkFontMgr> skFontMgr)96 SkiaFontMgr::SkiaFontMgr(sk_sp<SkFontMgr> skFontMgr) : skFontMgr_(skFontMgr) {}
97 
CreateDefaultFontMgr()98 std::shared_ptr<FontMgrImpl> SkiaFontMgr::CreateDefaultFontMgr()
99 {
100     return std::make_shared<SkiaFontMgr>(SkFontMgr::RefDefault());
101 }
102 
103 #ifndef USE_TEXGINE
CreateDynamicFontMgr()104 std::shared_ptr<FontMgrImpl> SkiaFontMgr::CreateDynamicFontMgr()
105 {
106     sk_sp<txt::DynamicFontManager> dynamicFontManager = sk_make_sp<txt::DynamicFontManager>();
107     return std::make_shared<SkiaFontMgr>(dynamicFontManager);
108 }
109 
LoadDynamicFont(const std::string & familyName,const uint8_t * data,size_t dataLength)110 Typeface* SkiaFontMgr::LoadDynamicFont(const std::string& familyName, const uint8_t* data, size_t dataLength)
111 {
112     auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
113     if (dynamicFontMgr == nullptr) {
114         LOGD("SkiaFontMgr::LoadDynamicFont, dynamicFontMgr nullptr");
115         return nullptr;
116     }
117     auto stream = std::make_unique<SkMemoryStream>(data, dataLength, true);
118     auto typeface = SkTypeface::MakeFromStream(std::move(stream));
119     if (familyName.empty()) {
120         dynamicFontMgr->font_provider().RegisterTypeface(typeface);
121     } else {
122         dynamicFontMgr->font_provider().RegisterTypeface(typeface, familyName);
123     }
124     if (!typeface) {
125         return nullptr;
126     }
127     typeface->setIsCustomTypeface(true);
128     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(typeface);
129     return new Typeface(typefaceImpl);
130 }
131 
LoadThemeFont(const std::string & themeName,std::shared_ptr<Typeface> typeface)132 void SkiaFontMgr::LoadThemeFont(const std::string& themeName, std::shared_ptr<Typeface> typeface)
133 {
134     if (typeface == nullptr) {
135         return;
136     }
137     auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
138     if (dynamicFontMgr == nullptr) {
139         LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
140         return;
141     }
142     SkiaTypeface *skiaTypeFace = typeface->GetImpl<SkiaTypeface>();
143     if (skiaTypeFace == nullptr) {
144         return;
145     }
146     dynamicFontMgr->font_provider().RegisterTypeface(skiaTypeFace->GetTypeface(), themeName);
147 }
148 
LoadThemeFont(const std::string & familyName,const std::string & themeName,const uint8_t * data,size_t dataLength)149 Typeface* SkiaFontMgr::LoadThemeFont(const std::string& familyName, const std::string& themeName,
150     const uint8_t* data, size_t dataLength)
151 {
152     auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
153     if (dynamicFontMgr == nullptr) {
154         TEXT_LOGE("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
155         return nullptr;
156     }
157     if (familyName.empty() || data == nullptr || dataLength == 0) {
158         dynamicFontMgr->font_provider().RegisterTypeface(nullptr, themeName);
159         return nullptr;
160     } else {
161         auto stream = std::make_unique<SkMemoryStream>(data, dataLength, true);
162         auto typeface = SkTypeface::MakeFromStream(std::move(stream));
163         if (!typeface) {
164             return nullptr;
165         } else {
166             dynamicFontMgr->font_provider().RegisterTypeface(typeface, themeName);
167             typeface->setIsCustomTypeface(true);
168             typeface->setIsThemeTypeface(true);
169             std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(typeface);
170             return new Typeface(typefaceImpl);
171         }
172     }
173 }
174 #endif
175 
MatchFamilyStyleCharacter(const char familyName[],const FontStyle & fontStyle,const char * bcp47[],int bcp47Count,int32_t character)176 Typeface* SkiaFontMgr::MatchFamilyStyleCharacter(const char familyName[], const FontStyle& fontStyle,
177                                                  const char* bcp47[], int bcp47Count,
178                                                  int32_t character)
179 {
180     if (skFontMgr_ == nullptr) {
181         LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
182         return nullptr;
183     }
184     SkFontStyle skFontStyle;
185     SkiaConvertUtils::DrawingFontStyleCastToSkFontStyle(fontStyle, skFontStyle);
186     SkTypeface* skTypeface =
187         skFontMgr_->matchFamilyStyleCharacter(familyName, skFontStyle, bcp47, bcp47Count, character);
188     if (!skTypeface) {
189         return nullptr;
190     }
191     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(sk_sp(skTypeface));
192     return new Typeface(typefaceImpl);
193 }
194 
MatchFamily(const char familyName[]) const195 FontStyleSet* SkiaFontMgr::MatchFamily(const char familyName[]) const
196 {
197     if (skFontMgr_ == nullptr) {
198         LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
199         return nullptr;
200     }
201     SkFontStyleSet* skFontStyleSetPtr = skFontMgr_->matchFamily(familyName);
202     if (!skFontStyleSetPtr) {
203         return nullptr;
204     }
205     sk_sp<SkFontStyleSet> skFontStyleSet{skFontStyleSetPtr};
206     std::shared_ptr<FontStyleSetImpl> fontStyleSetImpl = std::make_shared<SkiaFontStyleSet>(skFontStyleSet);
207     return new FontStyleSet(fontStyleSetImpl);
208 }
209 
MatchFamilyStyle(const char familyName[],const FontStyle & fontStyle) const210 Typeface* SkiaFontMgr::MatchFamilyStyle(const char familyName[], const FontStyle& fontStyle) const
211 {
212     if (skFontMgr_ == nullptr) {
213         LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
214         return nullptr;
215     }
216     SkFontStyle skFontStyle;
217     SkiaConvertUtils::DrawingFontStyleCastToSkFontStyle(fontStyle, skFontStyle);
218     SkTypeface* skTypeface =
219         skFontMgr_->matchFamilyStyle(familyName, skFontStyle);
220     if (!skTypeface) {
221         return nullptr;
222     }
223     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(sk_sp(skTypeface));
224     return new Typeface(typefaceImpl);
225 }
226 
CountFamilies() const227 int SkiaFontMgr::CountFamilies() const
228 {
229     if (skFontMgr_ == nullptr) {
230         return 0;
231     }
232     return skFontMgr_->countFamilies();
233 }
234 
GetFamilyName(int index,std::string & str) const235 void SkiaFontMgr::GetFamilyName(int index, std::string& str) const
236 {
237     if (index < 0 || skFontMgr_ == nullptr) {
238         return;
239     }
240     SkString skName;
241     skFontMgr_->getFamilyName(index, &skName);
242     str.assign(skName.c_str());
243 }
244 
CreateStyleSet(int index) const245 FontStyleSet* SkiaFontMgr::CreateStyleSet(int index) const
246 {
247     if (index < 0 || skFontMgr_ == nullptr) {
248         return nullptr;
249     }
250     SkFontStyleSet* skFontStyleSetPtr = skFontMgr_->createStyleSet(index);
251     if (!skFontStyleSetPtr) {
252         return nullptr;
253     }
254     sk_sp<SkFontStyleSet> skFontStyleSet{skFontStyleSetPtr};
255     std::shared_ptr<FontStyleSetImpl> fontStyleSetImpl = std::make_shared<SkiaFontStyleSet>(skFontStyleSet);
256     return new FontStyleSet(fontStyleSetImpl);
257 }
258 
GetFontFullName(int fontFd,std::vector<FontByteArray> & fullnameVec)259 int SkiaFontMgr::GetFontFullName(int fontFd, std::vector<FontByteArray>& fullnameVec)
260 {
261     if (skFontMgr_ == nullptr) {
262         return ERROR_TYPE_OTHER;
263     }
264     std::vector<SkByteArray> skFullnameVec;
265     int ret = skFontMgr_->GetFontFullName(fontFd, skFullnameVec);
266     if (ret != SUCCESSED) {
267         return ret;
268     }
269     for (SkByteArray &skFullname : skFullnameVec) {
270         FontByteArray newFullname = {nullptr, 0};
271         if (ConvertToUTF16BE(skFullname.strData.get(), skFullname.strLen, newFullname)) {
272             fullnameVec.push_back(std::move(newFullname));
273         } else {
274             return ERROR_TYPE_OTHER;
275         }
276     }
277     return SUCCESSED;
278 }
279 
ParseInstallFontConfig(const std::string & configPath,std::vector<std::string> & fontPathVec)280 int SkiaFontMgr::ParseInstallFontConfig(const std::string& configPath, std::vector<std::string>& fontPathVec)
281 {
282     if (skFontMgr_ == nullptr) {
283         return ERROR_TYPE_OTHER;
284     }
285     return skFontMgr_->ParseInstallFontConfig(configPath, fontPathVec);
286 }
287 } // namespace Drawing
288 } // namespace Rosen
289 } // namespace OHOS