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