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 #ifdef USE_M133_SKIA
22 #include "include/core/SkFontMgr.h"
23 #endif
24 #include "include/core/SkString.h"
25 #include "include/core/SkTypeface.h"
26 #include "txt/asset_font_manager.h"
27
28 #include "text/font_mgr.h"
29 #include "txt/platform.h"
30 #include "skia_adapter/skia_convert_utils.h"
31 #include "skia_adapter/skia_font_style_set.h"
32 #include "skia_adapter/skia_typeface.h"
33 #include "text/common_utils.h"
34 #include "utils/log.h"
35 #include "utils/text_log.h"
36
37
38 namespace OHOS {
39 namespace Rosen {
40 namespace Drawing {
41 namespace {
42 const uint8_t MOVEBITS = 8;
SwapBytes(char16_t * srcStr,uint32_t len)43 void SwapBytes(char16_t* srcStr, uint32_t len)
44 {
45 if (srcStr == nullptr || len == 0) {
46 return;
47 }
48 // if is big endian, high-order byte first
49 int num = 1;
50 if (*(reinterpret_cast<const uint8_t*>(&num)) == 0) {
51 return;
52 }
53 // swap bytes
54 for (uint32_t i = 0; i < len; i++) {
55 uint16_t temp = static_cast<uint16_t>(srcStr[i]);
56 // Swap the byte order of the 16-bit value
57 srcStr[i] = static_cast<char16_t>((temp & 0xff) << MOVEBITS | (temp & 0xff00) >> MOVEBITS);
58 }
59 }
60
ConvertToUTF16BE(uint8_t * data,uint32_t dataLen,FontByteArray & fullname)61 bool ConvertToUTF16BE(uint8_t* data, uint32_t dataLen, FontByteArray& fullname)
62 {
63 if (data == nullptr || dataLen == 0) {
64 return false;
65 }
66 std::unique_ptr<uint8_t[]> newData = std::make_unique<uint8_t[]>(dataLen + 1);
67 if (memcpy_s(newData.get(), dataLen + 1, data, dataLen) != EOK) {
68 return false;
69 }
70 newData[dataLen] = '\0';
71 // If the encoding format of data is UTF-16, copy it directly
72 if (strlen(reinterpret_cast<char*>(newData.get())) < dataLen ||
73 !IsUtf8(reinterpret_cast<const char*>(newData.get()), dataLen)) {
74 fullname.strData = std::move(newData);
75 fullname.strLen = dataLen;
76 return true;
77 }
78 // If the data format is utf-8, create a converter from UTF-8 to UTF-16
79 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
80 std::string utf8String(reinterpret_cast<char*>(data), dataLen);
81 std::u16string utf16String = converter.from_bytes(utf8String);
82 // Get the byte length and copy the data
83 size_t strByteLen = utf16String.size() * sizeof(char16_t);
84 if (strByteLen == 0) {
85 return false;
86 }
87 SwapBytes(const_cast<char16_t*>(utf16String.c_str()), strByteLen / sizeof(char16_t));
88 fullname.strData = std::make_unique<uint8_t[]>(strByteLen);
89 if (memcpy_s(fullname.strData.get(), strByteLen,
90 reinterpret_cast<const void*>(utf16String.c_str()), strByteLen) == EOK) {
91 fullname.strLen = strByteLen;
92 return true;
93 }
94 return false;
95 }
96 }
97
SkiaFontMgr(sk_sp<SkFontMgr> skFontMgr)98 SkiaFontMgr::SkiaFontMgr(sk_sp<SkFontMgr> skFontMgr) : skFontMgr_(skFontMgr) {}
99
CreateDefaultFontMgr()100 std::shared_ptr<FontMgrImpl> SkiaFontMgr::CreateDefaultFontMgr()
101 {
102 return std::make_shared<SkiaFontMgr>(SkFontMgr::RefDefault());
103 }
104
CheckDynamicFontValid(const std::string & familyName,sk_sp<SkTypeface> typeface)105 bool SkiaFontMgr::CheckDynamicFontValid(const std::string &familyName, sk_sp<SkTypeface> typeface)
106 {
107 if (typeface == nullptr) {
108 TEXT_LOGE("Failed to extract typeface");
109 return true;
110 }
111
112 std::string checkStr = familyName;
113 if (familyName.empty()) {
114 SkString name;
115 typeface->getFamilyName(&name);
116 checkStr.assign(name.c_str(), name.size());
117 }
118
119 if (SPText::DefaultFamilyNameMgr::IsThemeFontFamily(checkStr)) {
120 TEXT_LOGE("Prohibited to use OhosThemeFont registered dynamic fonts");
121 return false;
122 }
123
124 return true;
125 }
126
CreateDynamicFontMgr()127 std::shared_ptr<FontMgrImpl> SkiaFontMgr::CreateDynamicFontMgr()
128 {
129 sk_sp<txt::DynamicFontManager> dynamicFontManager = sk_make_sp<txt::DynamicFontManager>();
130 return std::make_shared<SkiaFontMgr>(dynamicFontManager);
131 }
132
LoadDynamicFont(const std::string & familyName,const uint8_t * data,size_t dataLength)133 Typeface* SkiaFontMgr::LoadDynamicFont(const std::string& familyName, const uint8_t* data, size_t dataLength)
134 {
135 auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
136 if (dynamicFontMgr == nullptr) {
137 LOGD("SkiaFontMgr::LoadDynamicFont, dynamicFontMgr nullptr");
138 return nullptr;
139 }
140 auto stream = std::make_unique<SkMemoryStream>(data, dataLength, true);
141 auto typeface = SkTypeface::MakeFromStream(std::move(stream));
142 if (!CheckDynamicFontValid(familyName, typeface)) {
143 return nullptr;
144 }
145 if (familyName.empty()) {
146 dynamicFontMgr->font_provider().RegisterTypeface(typeface);
147 } else {
148 dynamicFontMgr->font_provider().RegisterTypeface(typeface, familyName);
149 }
150 if (!typeface) {
151 return nullptr;
152 }
153 typeface->setIsCustomTypeface(true);
154 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(typeface);
155 return new Typeface(typefaceImpl);
156 }
157
LoadThemeFont(const std::string & themeName,std::shared_ptr<Typeface> typeface)158 void SkiaFontMgr::LoadThemeFont(const std::string& themeName, std::shared_ptr<Typeface> typeface)
159 {
160 if (typeface == nullptr) {
161 return;
162 }
163 auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
164 if (dynamicFontMgr == nullptr) {
165 LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
166 return;
167 }
168 SkiaTypeface *skiaTypeFace = typeface->GetImpl<SkiaTypeface>();
169 if (skiaTypeFace == nullptr) {
170 return;
171 }
172 dynamicFontMgr->font_provider().RegisterTypeface(skiaTypeFace->GetTypeface(), themeName);
173 }
174
LoadThemeFont(const std::string & familyName,const std::string & themeName,const uint8_t * data,size_t dataLength)175 Typeface* SkiaFontMgr::LoadThemeFont(const std::string& familyName, const std::string& themeName,
176 const uint8_t* data, size_t dataLength)
177 {
178 auto dynamicFontMgr = static_cast<txt::DynamicFontManager*>(skFontMgr_.get());
179 if (dynamicFontMgr == nullptr) {
180 TEXT_LOGE("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
181 return nullptr;
182 }
183 if (familyName.empty() || data == nullptr || dataLength == 0) {
184 dynamicFontMgr->font_provider().RegisterTypeface(nullptr, themeName);
185 return nullptr;
186 } else {
187 auto stream = std::make_unique<SkMemoryStream>(data, dataLength, true);
188 auto typeface = SkTypeface::MakeFromStream(std::move(stream));
189 if (!typeface) {
190 return nullptr;
191 } else {
192 dynamicFontMgr->font_provider().RegisterTypeface(typeface, themeName);
193 typeface->setIsCustomTypeface(true);
194 typeface->setIsThemeTypeface(true);
195 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(typeface);
196 return new Typeface(typefaceImpl);
197 }
198 }
199 }
200
MatchFamilyStyleCharacter(const char familyName[],const FontStyle & fontStyle,const char * bcp47[],int bcp47Count,int32_t character)201 Typeface* SkiaFontMgr::MatchFamilyStyleCharacter(const char familyName[], const FontStyle& fontStyle,
202 const char* bcp47[], int bcp47Count,
203 int32_t character)
204 {
205 if (skFontMgr_ == nullptr) {
206 LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
207 return nullptr;
208 }
209 SkFontStyle skFontStyle;
210 SkiaConvertUtils::DrawingFontStyleCastToSkFontStyle(fontStyle, skFontStyle);
211 #ifdef USE_M133_SKIA
212 sk_sp<SkTypeface> skTypeface =
213 skFontMgr_->matchFamilyStyleCharacter(familyName, skFontStyle, bcp47, bcp47Count, character);
214 #else
215 SkTypeface* skTypeface =
216 skFontMgr_->matchFamilyStyleCharacter(familyName, skFontStyle, bcp47, bcp47Count, character);
217 #endif
218 if (!skTypeface) {
219 return nullptr;
220 }
221 #ifdef USE_M133_SKIA
222 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
223 #else
224 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(sk_sp(skTypeface));
225 #endif
226 return new Typeface(typefaceImpl);
227 }
228
229 #ifdef USE_M133_SKIA
MatchFamily(const char familyName[]) const230 FontStyleSet* SkiaFontMgr::MatchFamily(const char familyName[]) const
231 {
232 if (skFontMgr_ == nullptr) {
233 LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
234 return nullptr;
235 }
236 sk_sp<SkFontStyleSet> skFontStyleSetPtr = skFontMgr_->matchFamily(familyName);
237 if (!skFontStyleSetPtr) {
238 return nullptr;
239 }
240 std::shared_ptr<FontStyleSetImpl> fontStyleSetImpl = std::make_shared<SkiaFontStyleSet>(skFontStyleSetPtr);
241 return new FontStyleSet(fontStyleSetImpl);
242 }
243 #else
MatchFamily(const char familyName[]) const244 FontStyleSet* SkiaFontMgr::MatchFamily(const char familyName[]) const
245 {
246 if (skFontMgr_ == nullptr) {
247 LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
248 return nullptr;
249 }
250 SkFontStyleSet* skFontStyleSetPtr = skFontMgr_->matchFamily(familyName);
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 #endif
259
MatchFamilyStyle(const char familyName[],const FontStyle & fontStyle) const260 Typeface* SkiaFontMgr::MatchFamilyStyle(const char familyName[], const FontStyle& fontStyle) const
261 {
262 if (skFontMgr_ == nullptr) {
263 LOGD("SkiaFontMgr::LoadThemeFont, dynamicFontMgr nullptr");
264 return nullptr;
265 }
266 SkFontStyle skFontStyle;
267 SkiaConvertUtils::DrawingFontStyleCastToSkFontStyle(fontStyle, skFontStyle);
268 #ifdef USE_M133_SKIA
269 sk_sp<SkTypeface> skTypeface =
270 skFontMgr_->matchFamilyStyle(familyName, skFontStyle);
271 #else
272 SkTypeface* skTypeface =
273 skFontMgr_->matchFamilyStyle(familyName, skFontStyle);
274 #endif
275 if (!skTypeface) {
276 return nullptr;
277 }
278 #ifdef USE_M133_SKIA
279 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
280 #else
281 std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(sk_sp(skTypeface));
282 #endif
283 return new Typeface(typefaceImpl);
284 }
285
CountFamilies() const286 int SkiaFontMgr::CountFamilies() const
287 {
288 if (skFontMgr_ == nullptr) {
289 return 0;
290 }
291 return skFontMgr_->countFamilies();
292 }
293
GetFamilyName(int index,std::string & str) const294 void SkiaFontMgr::GetFamilyName(int index, std::string& str) const
295 {
296 if (index < 0 || skFontMgr_ == nullptr) {
297 return;
298 }
299 SkString skName;
300 skFontMgr_->getFamilyName(index, &skName);
301 str.assign(skName.c_str());
302 }
303
304 #ifdef USE_M133_SKIA
CreateStyleSet(int index) const305 FontStyleSet* SkiaFontMgr::CreateStyleSet(int index) const
306 {
307 if (index < 0 || skFontMgr_ == nullptr) {
308 return nullptr;
309 }
310 sk_sp<SkFontStyleSet> skFontStyleSetPtr = skFontMgr_->createStyleSet(index);
311 if (!skFontStyleSetPtr) {
312 return nullptr;
313 }
314 std::shared_ptr<FontStyleSetImpl> fontStyleSetImpl = std::make_shared<SkiaFontStyleSet>(skFontStyleSetPtr);
315 return new FontStyleSet(fontStyleSetImpl);
316 }
317 #else
CreateStyleSet(int index) const318 FontStyleSet* SkiaFontMgr::CreateStyleSet(int index) const
319 {
320 if (index < 0 || skFontMgr_ == nullptr) {
321 return nullptr;
322 }
323 SkFontStyleSet* skFontStyleSetPtr = skFontMgr_->createStyleSet(index);
324 if (!skFontStyleSetPtr) {
325 return nullptr;
326 }
327 sk_sp<SkFontStyleSet> skFontStyleSet{skFontStyleSetPtr};
328 std::shared_ptr<FontStyleSetImpl> fontStyleSetImpl = std::make_shared<SkiaFontStyleSet>(skFontStyleSet);
329 return new FontStyleSet(fontStyleSetImpl);
330 }
331 #endif
332
GetFontFullName(int fontFd,std::vector<FontByteArray> & fullnameVec)333 int SkiaFontMgr::GetFontFullName(int fontFd, std::vector<FontByteArray>& fullnameVec)
334 {
335 if (skFontMgr_ == nullptr) {
336 return ERROR_TYPE_OTHER;
337 }
338 std::vector<SkByteArray> skFullnameVec;
339 int ret = skFontMgr_->GetFontFullName(fontFd, skFullnameVec);
340 if (ret != SUCCESSED) {
341 return ret;
342 }
343 for (SkByteArray &skFullname : skFullnameVec) {
344 FontByteArray newFullname = {nullptr, 0};
345 if (ConvertToUTF16BE(skFullname.strData.get(), skFullname.strLen, newFullname)) {
346 fullnameVec.push_back(std::move(newFullname));
347 } else {
348 return ERROR_TYPE_OTHER;
349 }
350 }
351 return SUCCESSED;
352 }
353
ParseInstallFontConfig(const std::string & configPath,std::vector<std::string> & fontPathVec)354 int SkiaFontMgr::ParseInstallFontConfig(const std::string& configPath, std::vector<std::string>& fontPathVec)
355 {
356 if (skFontMgr_ == nullptr) {
357 return ERROR_TYPE_OTHER;
358 }
359 return skFontMgr_->ParseInstallFontConfig(configPath, fontPathVec);
360 }
361 } // namespace Drawing
362 } // namespace Rosen
363 } // namespace OHOS