• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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