1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 * 2021.2.10 SkFontMgr on ohos.
7 * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
8 */
9
10 #include "src/ports/SkFontMgr_ohos.h"
11
12 SkFontMgr_OHOS::BuildFamilyMapCallback SkFontMgr_OHOS::buildFamilyMapCallback;
13
SkFontMgr_OHOS()14 SkFontMgr_OHOS::SkFontMgr_OHOS()
15 {
16 this->buildNameToFamilyMap();
17 this->findDefaultStyleSet();
18 }
19
onCountFamilies() const20 int SkFontMgr_OHOS::onCountFamilies() const
21 {
22 return fNameToFamilyMap.count();
23 }
24
onGetFamilyName(int index,SkString * familyName) const25 void SkFontMgr_OHOS::onGetFamilyName(int index, SkString* familyName) const
26 {
27 if (index < 0 || fNameToFamilyMap.count() <= index) {
28 familyName->reset();
29 return;
30 }
31 familyName->set(fNameToFamilyMap[index].name);
32 }
33
onCreateStyleSet(int index) const34 SkFontStyleSet* SkFontMgr_OHOS::onCreateStyleSet(int index) const
35 {
36 if (index < 0 || fNameToFamilyMap.count() <= index) {
37 return nullptr;
38 }
39 return SkRef(fNameToFamilyMap[index].styleSet);
40 }
41
onMatchFamily(const char familyName[]) const42 SkFontStyleSet* SkFontMgr_OHOS::onMatchFamily(const char familyName[]) const
43 {
44 if (!familyName) {
45 return nullptr;
46 }
47 std::string familyNameStr(familyName);
48 std::transform(familyNameStr.begin(), familyNameStr.end(), familyNameStr.begin(),
49 [](unsigned char c) -> unsigned char { return std::tolower(c); });
50
51 std::string aliasTo;
52 const auto& iter = fAliasMap.find(familyNameStr);
53 if (iter != fAliasMap.end()) {
54 aliasTo = iter->second.toName;
55 }
56 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
57 if (fNameToFamilyMap[i].name.equals(familyNameStr.c_str())) {
58 return SkRef(fNameToFamilyMap[i].styleSet);
59 }
60 if (!aliasTo.empty() && fNameToFamilyMap[i].name.equals(aliasTo.c_str())) {
61 return SkRef(fNameToFamilyMap[i].styleSet);
62 }
63 }
64
65 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
66 if (fFallbackNameToFamilyMap[i].name.equals(familyNameStr.c_str())) {
67 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
68 }
69 }
70
71 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
72 const auto& styleSet = fFallbackNameToFamilyMap[i].styleSet;
73 if (styleSet) {
74 const auto& host = styleSet->fStylesHost;
75 for (int j = 0; j < host.count(); ++j) {
76 if (host[j]->getFamilyName().equals(familyNameStr.c_str())) {
77 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
78 }
79 }
80 }
81 }
82 return nullptr;
83 }
84
onMatchFamilyStyle(const char familyName[],const SkFontStyle & style) const85 SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const
86 {
87 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
88 return sset->matchStyle(style);
89 }
90
onMatchFaceStyle(const SkTypeface * typeface,const SkFontStyle & style) const91 SkTypeface* SkFontMgr_OHOS::onMatchFaceStyle(const SkTypeface* typeface, const SkFontStyle& style) const
92 {
93 for (int i = 0; i < fStyleSets.count(); ++i) {
94 for (int j = 0; j < fStyleSets[i]->fStyles.count(); ++j) {
95 if (fStyleSets[i]->fStyles[j].get() == typeface) {
96 return fStyleSets[i]->matchStyle(style);
97 }
98 }
99 }
100 return nullptr;
101 }
102
find_family_style_character(const SkString & familyName,const SkTArray<NameToFamily,true> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)103 sk_sp<SkTypeface> SkFontMgr_OHOS::find_family_style_character(const SkString& familyName,
104 const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap, const SkFontStyle& style, bool elegant,
105 const SkString& langTag, SkUnichar character)
106 {
107 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
108 SkFontStyleSet_OHOS* family = fallbackNameToFamilyMap[i].styleSet;
109 // TODO: process fallbackFor
110 SkTypeface* face = family->matchStyle(style);
111 if (!face) {
112 SkDEBUGF("face is null");
113 continue;
114 }
115
116 if (!family->matchLanguage(langTag)) {
117 continue;
118 }
119
120 if (family->haveVariant(kElegant_FontVariant) != elegant) {
121 continue;
122 }
123
124 if (face->unicharToGlyph(character) != 0) {
125 return sk_sp<SkTypeface>(face);
126 }
127 }
128 return nullptr;
129 }
130
find_family_style_character_ohos(const SkString & familyName,const SkTArray<NameToFamily,true> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)131 SkString SkFontMgr_OHOS::find_family_style_character_ohos(const SkString& familyName,
132 const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap, const SkFontStyle& style, bool elegant,
133 const SkString& langTag, SkUnichar character)
134 {
135 SkString matchingName = findFromCache(familyName, style, elegant, langTag, character);
136 if (!matchingName.isEmpty()) {
137 return matchingName;
138 }
139
140 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
141 SkFontStyleSet_OHOS* family = fallbackNameToFamilyMap[i].styleSet;
142 // TODO: process fallbackFor
143 SkTypeface* face = family->matchStyle(style);
144 if (!face) {
145 SkDEBUGF("face is null");
146 continue;
147 }
148
149 if (!family->matchLanguage(langTag)) {
150 continue;
151 }
152
153 if (family->haveVariant(kElegant_FontVariant) != elegant) {
154 continue;
155 }
156
157 if (face->unicharToGlyph(character) != 0) {
158 addToCache(&(fallbackNameToFamilyMap[i]));
159 return fallbackNameToFamilyMap[i].name;
160 }
161 }
162 return SkString();
163 }
164
find_family_style_character_hwfont(const SkString & familyName,const SkTArray<NameToFamily,true> & fallbackNameToFamilyMap,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)165 SkString SkFontMgr_OHOS::find_family_style_character_hwfont(
166 const SkString &familyName,
167 const SkTArray<NameToFamily, true> &fallbackNameToFamilyMap,
168 const SkFontStyle &style, bool elegant, const SkString &langTag,
169 SkUnichar character) {
170 SkString matchingName =
171 findFromHwFontCache(familyName, style, elegant, langTag, character);
172 if (!matchingName.isEmpty()) {
173 return matchingName;
174 }
175
176 // First find in HwThemeFont.
177 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
178 SkFontStyleSet_OHOS *family = fallbackNameToFamilyMap[i].styleSet;
179 if (family->getHwFontFamilyType() > 0) {
180 SkTypeface *face = family->matchStyle(style);
181 if (!face) {
182 SkDEBUGF("face is null");
183 continue;
184 }
185
186 if (!family->matchLanguage(langTag)) {
187 continue;
188 }
189
190 if (family->haveVariant(kElegant_FontVariant) != elegant) {
191 continue;
192 }
193
194 if (face->unicharToGlyph(character) != 0) {
195 addToHwFontCache(&(fallbackNameToFamilyMap[i]));
196 return fallbackNameToFamilyMap[i].name;
197 }
198 }
199 }
200 return SkString();
201 }
202
findFromCache(const SkString & familyName,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)203 SkString SkFontMgr_OHOS::findFromCache(const SkString& familyName, const SkFontStyle& style, bool elegant,
204 const SkString& langTag, SkUnichar character)
205 {
206 std::lock_guard<std::mutex> lock(mutexCache);
207 for (int i = 0; i < familyMapCache.count(); ++i) {
208 SkFontStyleSet_OHOS* family = familyMapCache[i]->styleSet;
209 // TODO: process fallbackFor
210 SkTypeface* face = family->matchStyle(style);
211 if (!face) {
212 SkDEBUGF("face is null");
213 continue;
214 }
215
216 if (!family->matchLanguage(langTag)) {
217 continue;
218 }
219
220 if (family->haveVariant(kElegant_FontVariant) != elegant) {
221 continue;
222 }
223
224 if (face->unicharToGlyph(character) != 0) {
225 return familyMapCache[i]->name;
226 }
227 }
228 return SkString();
229 }
230
addToCache(const NameToFamily * item)231 void SkFontMgr_OHOS::addToCache(const NameToFamily* item)
232 {
233 std::lock_guard<std::mutex> lock(mutexCache);
234 for (int i = 0; i < familyMapCache.count(); ++i) {
235 if (item == familyMapCache[i]) {
236 return;
237 }
238 }
239 familyMapCache.emplace_back(item);
240 }
241
findFromHwFontCache(const SkString & familyName,const SkFontStyle & style,bool elegant,const SkString & langTag,SkUnichar character)242 SkString SkFontMgr_OHOS::findFromHwFontCache(const SkString& familyName, const SkFontStyle& style, bool elegant,
243 const SkString& langTag, SkUnichar character)
244 {
245 std::lock_guard<std::mutex> lock(mutexCache);
246 for (int i = 0; i < hwFontFamilyMapCache.count(); ++i) {
247 SkFontStyleSet_OHOS* family = hwFontFamilyMapCache[i]->styleSet;
248 // TODO: process fallbackFor
249 SkTypeface* face = family->matchStyle(style);
250 if (!face) {
251 SkDEBUGF("face is null");
252 continue;
253 }
254
255 if (!family->matchLanguage(langTag)) {
256 continue;
257 }
258
259 if (family->haveVariant(kElegant_FontVariant) != elegant) {
260 continue;
261 }
262
263 if (face->unicharToGlyph(character) != 0) {
264 return hwFontFamilyMapCache[i]->name;
265 }
266 }
267 return SkString();
268 }
269
addToHwFontCache(const NameToFamily * item)270 void SkFontMgr_OHOS::addToHwFontCache(const NameToFamily* item)
271 {
272 std::lock_guard<std::mutex> lock(mutexCache);
273 for (int i = 0; i < hwFontFamilyMapCache.count(); ++i) {
274 if (item == hwFontFamilyMapCache[i]) {
275 return;
276 }
277 }
278 hwFontFamilyMapCache.emplace_back(item);
279 }
280
onMatchFamilyStyleCharacter(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character) const281 SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyleCharacter(
282 const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const
283 {
284 SkString familyNameString(familyName);
285 for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
286 // The first time match anything elegant, second time anything not elegant.
287 for (int elegant = 2; elegant-- > 0;) {
288 for (int bcp47Index = bcp47Count; bcp47Index-- > 0;) {
289 SkLanguage lang(bcp47[bcp47Index]);
290 while (!lang.getTag().isEmpty()) {
291 sk_sp<SkTypeface> matchingTypeface = find_family_style_character(currentFamilyName,
292 fFallbackNameToFamilyMap, style, SkToBool(elegant), lang.getTag(), character);
293 if (matchingTypeface) {
294 return matchingTypeface.release();
295 }
296 lang = lang.getParent();
297 }
298 }
299 sk_sp<SkTypeface> matchingTypeface = find_family_style_character(
300 currentFamilyName, fFallbackNameToFamilyMap, style, SkToBool(elegant), SkString(), character);
301 if (matchingTypeface) {
302 return matchingTypeface.release();
303 }
304 }
305 }
306 return nullptr;
307 }
308
onMatchFamilyStyleCharacterOHOS(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character)309 SkString SkFontMgr_OHOS::onMatchFamilyStyleCharacterOHOS(
310 const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character)
311 {
312 SkString familyNameString(familyName);
313 for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
314 // The first time match anything elegant, second time anything not elegant.
315 for (int bcp47Index = bcp47Count; bcp47Index-- > 0;) {
316 SkLanguage lang(bcp47[bcp47Index]);
317 while (!lang.getTag().isEmpty()) {
318 SkString matchingName = find_family_style_character_ohos(
319 currentFamilyName, fFallbackNameToFamilyMap, style, false, lang.getTag(), character);
320 if (!matchingName.isEmpty()) {
321 return matchingName;
322 }
323 lang = lang.getParent();
324 }
325 }
326 SkString matchingName = find_family_style_character_ohos(
327 currentFamilyName, fFallbackNameToFamilyMap, style, false, SkString(), character);
328 if (!matchingName.isEmpty()) {
329 return matchingName;
330 }
331 }
332 return SkString();
333 }
334
onMatchFamilyStyleCharacterHwFont(const char familyName[],const SkFontStyle & style,const char * bcp47[],int bcp47Count,SkUnichar character)335 SkString SkFontMgr_OHOS::onMatchFamilyStyleCharacterHwFont(
336 const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character)
337 {
338 SkString familyNameString(familyName);
339 for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
340 // The first time match anything elegant, second time anything not elegant.
341 for (int bcp47Index = bcp47Count; bcp47Index-- > 0;) {
342 SkLanguage lang(bcp47[bcp47Index]);
343 while (!lang.getTag().isEmpty()) {
344 SkString matchingName = find_family_style_character_hwfont(
345 currentFamilyName, fFallbackNameToFamilyMap, style, false, lang.getTag(), character);
346 if (!matchingName.isEmpty()) {
347 return matchingName;
348 }
349 lang = lang.getParent();
350 }
351 }
352 SkString matchingName = find_family_style_character_hwfont(
353 currentFamilyName, fFallbackNameToFamilyMap, style, false, SkString(), character);
354 if (!matchingName.isEmpty()) {
355 return matchingName;
356 }
357 }
358 return SkString();
359 }
360
onMakeFromData(sk_sp<SkData> data,int ttcIndex) const361 sk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const
362 {
363 return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))), ttcIndex);
364 }
365
onMakeFromFile(const char path[],int ttcIndex) const366 sk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromFile(const char path[], int ttcIndex) const
367 {
368 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
369 return stream.get() ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
370 }
371
onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,int ttcIndex) const372 sk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, int ttcIndex) const
373 {
374 SkDEBUGF("onMakeFromStreamIndex not support");
375 return nullptr;
376 }
377
onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments & args) const378 sk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromStreamArgs(
379 std::unique_ptr<SkStreamAsset> stream, const SkFontArguments& args) const
380 {
381 SkDEBUGF("onMakeFromStreamArgs not support");
382 return nullptr;
383 }
384
onMakeFromFontData(std::unique_ptr<SkFontData> data) const385 sk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromFontData(std::unique_ptr<SkFontData> data) const
386 {
387 SkDEBUGF("onMakeFromFontData not support");
388 return nullptr;
389 }
390
onLegacyMakeTypeface(const char familyName[],SkFontStyle style) const391 sk_sp<SkTypeface> SkFontMgr_OHOS::onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const
392 {
393 if (familyName) {
394 return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
395 }
396 return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
397 }
398
buildNameToFamilyMap()399 void SkFontMgr_OHOS::buildNameToFamilyMap()
400 {
401 if (buildFamilyMapCallback) {
402 buildFamilyMapCallback(fNameToFamilyMap, fFallbackNameToFamilyMap, fStyleSets, fAliasMap);
403 }
404 }
405
findDefaultStyleSet()406 void SkFontMgr_OHOS::findDefaultStyleSet()
407 {
408 if (fStyleSets.empty()) {
409 return;
410 }
411
412 static const char* defaultNames[] = { "sans-serif" };
413 for (const char* defaultName : defaultNames) {
414 fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
415 if (fDefaultStyleSet) {
416 break;
417 }
418 }
419 if (nullptr == fDefaultStyleSet) {
420 fDefaultStyleSet = fStyleSets[0];
421 }
422 SkASSERT(fDefaultStyleSet);
423 }
424
SkFontMgr_New_OHOS()425 sk_sp<SkFontMgr> SkFontMgr_New_OHOS()
426 {
427 return sk_make_sp<SkFontMgr_OHOS>();
428 }
429