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