1 /*
2  * Copyright (c) 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 "skia_typeface.h"
17 
18 #include "include/core/SkFontMgr.h"
19 #include "include/core/SkFontStyle.h"
20 #include "include/core/SkStream.h"
21 #include "include/core/SkString.h"
22 #include "include/private/SkTHash.h"
23 #include "skia_adapter/skia_convert_utils.h"
24 #include "skia_adapter/skia_data.h"
25 #include "skia_adapter/skia_memory_stream.h"
26 
27 #include "utils/log.h"
28 
29 namespace OHOS {
30 namespace Rosen {
31 namespace Drawing {
SkiaTypeface(sk_sp<SkTypeface> skTypeface)32 SkiaTypeface::SkiaTypeface(sk_sp<SkTypeface> skTypeface) : skTypeface_(skTypeface) {}
33 
GetTypeface() const34 sk_sp<SkTypeface> SkiaTypeface::GetTypeface() const
35 {
36     return skTypeface_;
37 }
38 
GetFamilyName() const39 std::string SkiaTypeface::GetFamilyName() const
40 {
41     std::string name;
42     if (!skTypeface_) {
43         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
44         return name;
45     }
46     SkString skName;
47     skTypeface_->getFamilyName(&skName);
48     SkiaConvertUtils::SkStringCastToStdString(skName, name);
49     return name;
50 }
51 
GetFontPath() const52 std::string SkiaTypeface::GetFontPath() const
53 {
54     std::string path;
55     if (!skTypeface_) {
56         LOGE("SkTypeface nullptr");
57         return path;
58     }
59     SkString skName;
60     skTypeface_->getFontPath(&skName);
61     SkiaConvertUtils::SkStringCastToStdString(skName, path);
62     return path;
63 }
64 
GetFontStyle() const65 FontStyle SkiaTypeface::GetFontStyle() const
66 {
67     FontStyle fontStyle;
68     if (!skTypeface_) {
69         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
70         return fontStyle;
71     }
72     SkFontStyle skFontStyle = skTypeface_->fontStyle();
73     SkiaConvertUtils::SkFontStyleCastToDrawingFontStyle(skFontStyle, fontStyle);
74     return fontStyle;
75 }
76 
GetTableSize(uint32_t tag) const77 size_t SkiaTypeface::GetTableSize(uint32_t tag) const
78 {
79     if (!skTypeface_) {
80         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
81         return 0;
82     }
83     return skTypeface_->getTableSize(tag);
84 }
85 
GetTableData(uint32_t tag,size_t offset,size_t length,void * data) const86 size_t SkiaTypeface::GetTableData(uint32_t tag, size_t offset, size_t length, void* data) const
87 {
88     if (!skTypeface_) {
89         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
90         return 0;
91     }
92     return skTypeface_->getTableData(tag, offset, length, data);
93 }
94 
GetItalic() const95 bool SkiaTypeface::GetItalic() const
96 {
97     if (!skTypeface_) {
98         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
99         return false;
100     }
101     return skTypeface_->isItalic();
102 }
103 
GetUniqueID() const104 uint32_t SkiaTypeface::GetUniqueID() const
105 {
106     if (!skTypeface_) {
107         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
108         return 0;
109     }
110     return skTypeface_->uniqueID();
111 }
112 
GetUnitsPerEm() const113 int32_t SkiaTypeface::GetUnitsPerEm() const
114 {
115     if (!skTypeface_) {
116         LOGD("SkiaTypeface::GetUnitsPerEm, skTypeface nullptr");
117         return 0;
118     }
119     return skTypeface_->getUnitsPerEm();
120 }
121 
MakeClone(const FontArguments & args) const122 std::shared_ptr<Typeface> SkiaTypeface::MakeClone(const FontArguments& args) const
123 {
124     if (!skTypeface_) {
125         LOGD("SkiaTypeface::MakeClone, skTypeface nullptr");
126         return nullptr;
127     }
128 
129     SkFontArguments skArgs;
130     SkiaConvertUtils::DrawingFontArgumentsCastToSkFontArguments(args, skArgs);
131 
132     auto cloned = skTypeface_->makeClone(skArgs);
133     if (!cloned) {
134         return nullptr;
135     }
136     cloned->setIsCustomTypeface(skTypeface_->isCustomTypeface());
137     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(cloned);
138     return std::make_shared<Typeface>(typefaceImpl);
139 }
140 
IsCustomTypeface() const141 bool SkiaTypeface::IsCustomTypeface() const
142 {
143     if (!skTypeface_) {
144         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
145         return false;
146     }
147     return skTypeface_->isCustomTypeface();
148 }
149 
IsThemeTypeface() const150 bool SkiaTypeface::IsThemeTypeface() const
151 {
152     if (!skTypeface_) {
153         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
154         return false;
155     }
156     return skTypeface_->isThemeTypeface();
157 }
158 
GetSkTypeface()159 sk_sp<SkTypeface> SkiaTypeface::GetSkTypeface()
160 {
161     if (!skTypeface_) {
162         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
163         return nullptr;
164     }
165     return skTypeface_;
166 }
167 
MakeDefault()168 std::shared_ptr<Typeface> SkiaTypeface::MakeDefault()
169 {
170     sk_sp<SkTypeface> skTypeface = SkTypeface::MakeDefault();
171     if (!skTypeface) {
172         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
173         return nullptr;
174     }
175     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
176     return std::make_shared<Typeface>(typefaceImpl);
177 }
178 
MakeFromFile(const char path[],int index)179 std::shared_ptr<Typeface> SkiaTypeface::MakeFromFile(const char path[], int index)
180 {
181     sk_sp<SkTypeface> skTypeface = SkTypeface::MakeFromFile(path, index);
182     if (!skTypeface) {
183         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
184         return nullptr;
185     }
186     skTypeface->setIsCustomTypeface(true);
187     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
188     return std::make_shared<Typeface>(typefaceImpl);
189 }
190 
MakeFromFile(const char path[],const FontArguments & fontArguments)191 std::shared_ptr<Typeface> SkiaTypeface::MakeFromFile(const char path[], const FontArguments& fontArguments)
192 {
193     std::unique_ptr<SkStreamAsset> skStream = SkStreamAsset::MakeFromFile(path);
194     if (skStream == nullptr) {
195         LOGD("SkiaTypeface::MakeFromFile, skStream nullptr.");
196         return nullptr;
197     }
198     auto skFontMgr = SkFontMgr::RefDefault();
199     if (skFontMgr == nullptr) {
200         LOGD("SkiaTypeface::MakeFromFile, skFontMgr nullptr.");
201         return nullptr;
202     }
203     SkFontArguments skFontArguments;
204     SkiaConvertUtils::DrawingFontArgumentsCastToSkFontArguments(fontArguments, skFontArguments);
205     sk_sp<SkTypeface> skTypeface = skFontMgr->makeFromStream(std::move(skStream), skFontArguments);
206     if (!skTypeface) {
207         LOGD("SkiaTypeface::MakeFromFile, skTypeface nullptr.");
208         return nullptr;
209     }
210     skTypeface->setIsCustomTypeface(true);
211     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
212     return std::make_shared<Typeface>(typefaceImpl);
213 }
214 
GetSystemFonts()215 std::vector<std::shared_ptr<Typeface>> SkiaTypeface::GetSystemFonts()
216 {
217     std::vector<sk_sp<SkTypeface>> skTypefaces = SkTypeface::GetSystemFonts();
218     if (skTypefaces.empty()) {
219         return {};
220     }
221     std::vector<std::shared_ptr<Typeface>> typefaces;
222     typefaces.reserve(skTypefaces.size());
223     for (auto& item : skTypefaces) {
224         item->setIsCustomTypeface(false);
225         std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(item);
226         typefaces.emplace_back(std::make_shared<Typeface>(typefaceImpl));
227     }
228     return typefaces;
229 }
230 
MakeFromStream(std::unique_ptr<MemoryStream> memoryStream,int32_t index)231 std::shared_ptr<Typeface> SkiaTypeface::MakeFromStream(std::unique_ptr<MemoryStream> memoryStream, int32_t index)
232 {
233     if (!memoryStream) {
234         LOGD("SkiaTypeface::MakeFromStream, memoryStream nullptr");
235         return nullptr;
236     }
237     std::unique_ptr<SkStreamAsset> skMemoryStream = memoryStream->GetImpl<SkiaMemoryStream>()->GetSkMemoryStream();
238     sk_sp<SkTypeface> skTypeface = SkTypeface::MakeFromStream(std::move(skMemoryStream), index);
239     if (!skTypeface) {
240         LOGD("SkiaTypeface::MakeFromStream, skTypeface nullptr");
241         return nullptr;
242     }
243     skTypeface->setIsCustomTypeface(true);
244     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
245     return std::make_shared<Typeface>(typefaceImpl);
246 }
247 
MakeFromName(const char familyName[],FontStyle fontStyle)248 std::shared_ptr<Typeface> SkiaTypeface::MakeFromName(const char familyName[], FontStyle fontStyle)
249 {
250     SkFontStyle skFontStyle;
251     SkiaConvertUtils::DrawingFontStyleCastToSkFontStyle(fontStyle, skFontStyle);
252     sk_sp<SkTypeface> skTypeface = SkTypeface::MakeFromName(familyName, skFontStyle);
253     if (!skTypeface) {
254         LOGD("SkiaTypeface::MakeFromName, skTypeface nullptr");
255         return nullptr;
256     }
257     std::shared_ptr<TypefaceImpl> typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
258     return std::make_shared<Typeface>(typefaceImpl);
259 }
260 
SerializeTypeface(SkTypeface * typeface,void * ctx)261 sk_sp<SkData> SkiaTypeface::SerializeTypeface(SkTypeface* typeface, void* ctx)
262 {
263     if (!typeface) {
264         LOGD("typeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
265         return nullptr;
266     }
267     TextBlob::Context* textblobCtx = reinterpret_cast<TextBlob::Context*>(ctx);
268     if (textblobCtx != nullptr && typeface->isCustomTypeface()) {
269         sk_sp<SkTypeface> typefacePtr = sk_ref_sp(typeface);
270         auto typefaceImpl = std::make_shared<SkiaTypeface>(typefacePtr);
271         auto customTypeface = std::make_shared<Typeface>(typefaceImpl);
272         textblobCtx->SetTypeface(customTypeface);
273     }
274     return typeface->serialize();
275 }
276 
DeserializeTypeface(const void * data,size_t length,void * ctx)277 sk_sp<SkTypeface> SkiaTypeface::DeserializeTypeface(const void* data, size_t length, void* ctx)
278 {
279     if (data == nullptr) {
280         LOGD("data nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
281         return nullptr;
282     }
283 
284     TextBlob::Context* textblobCtx = reinterpret_cast<TextBlob::Context*>(ctx);
285     if (textblobCtx == nullptr || textblobCtx->GetTypeface() == nullptr) {
286         SkMemoryStream stream(data, length);
287         return SkTypeface::MakeDeserialize(&stream);
288     }
289     auto& typeface = textblobCtx->GetTypeface();
290     if (typeface == nullptr) {
291         LOGD("typeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
292         return nullptr;
293     }
294     auto skiaTypeface = typeface->GetImpl<SkiaTypeface>();
295     if (skiaTypeface == nullptr) {
296         LOGD("skiaTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
297         return nullptr;
298     }
299     auto skTypeface = skiaTypeface->GetSkTypeface();
300     return skTypeface;
301 }
302 
Serialize() const303 std::shared_ptr<Data> SkiaTypeface::Serialize() const
304 {
305     if (!skTypeface_) {
306         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
307         return nullptr;
308     }
309     auto skData = skTypeface_->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
310     auto data = std::make_shared<Data>();
311     auto skiaData = data->GetImpl<SkiaData>();
312     if (!skiaData) {
313         LOGD("skiaData nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
314         return nullptr;
315     }
316     skiaData->SetSkData(skData);
317     return data;
318 }
319 
Deserialize(const void * data,size_t size)320 std::shared_ptr<Typeface> SkiaTypeface::Deserialize(const void* data, size_t size)
321 {
322     SkMemoryStream stream(data, size);
323     auto skTypeface = SkTypeface::MakeDeserialize(&stream);
324     if (!skTypeface) {
325         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
326         return nullptr;
327     }
328     auto typefaceImpl = std::make_shared<SkiaTypeface>(skTypeface);
329     return std::make_shared<Typeface>(typefaceImpl);
330 }
331 
GetHash() const332 uint32_t SkiaTypeface::GetHash() const
333 {
334     if (!skTypeface_) {
335         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
336         return 0;
337     }
338     return skTypeface_->GetHash();
339 }
340 
SetHash(uint32_t hash)341 void SkiaTypeface::SetHash(uint32_t hash)
342 {
343     if (!skTypeface_) {
344         LOGD("skTypeface nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
345         return;
346     }
347     skTypeface_->SetHash(hash);
348 }
349 
350 } // namespace Drawing
351 } // namespace Rosen
352 } // namespace OHOS