• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "FontConfig_ohos.h"
6 
7 #include <algorithm>
8 #include <array>
9 #include <cstring>
10 #include <dirent.h>
11 #include <fstream>
12 #include <functional>
13 #include <libgen.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 
18 #if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) or defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_MAC) or \
19     defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_LINUX)
20 #define SK_BUILD_FONT_MGR_FOR_PREVIEW
21 #endif
22 
23 #ifdef SK_BUILD_FONT_MGR_FOR_OHOS
24 #include <parameters.h>
25 #endif
26 
27 #include "SkFontStyle.h"
28 #include "SkString.h"
29 #include "securec.h"
30 
31 using namespace ErrorCode;
32 static const char* PRODUCT_DEFAULT_CONFIG = "/system/etc/productfontconfig.json";
33 
34 #ifdef SK_BUILD_FONT_MGR_FOR_OHOS
35 static const bool G_IS_HMSYMBOL_ENABLE =
36     (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymbolcfg.enable", "1").c_str()) != 0);
37 #else
38 static const bool G_IS_HMSYMBOL_ENABLE = true;
39 #endif
40 
41 #ifdef SK_BUILD_FONT_MGR_FOR_PREVIEW
42 static const char* OHOS_DEFAULT_CONFIG = "fontconfig_ohos.json";
43 /*! Constructor
44  * \param fontScanner the scanner to get the font information from a font file
45  * \param fname the full name of system font configuration document.
46  *     \n The default value is '/system/etc/fontconfig_ohos.json', if fname is given null
47  */
FontConfig_OHOS(const SkTypeface_FreeType::Scanner & fontScanner,const char * fname)48 FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, const char* fname)
49     : fFontScanner(fontScanner)
50 {
51     int err = parseConfig(fname);
52     if (err != NO_ERROR) {
53         return;
54     }
55     loadHMSymbol();
56 }
57 #else
58 static const char* OHOS_DEFAULT_CONFIG = "/system/etc/fontconfig_ohos.json";
59 /*! Constructor
60  * \param fontScanner the scanner to get the font information from a font file
61  * \param fname the full name of system font configuration document.
62  *     \n The default value is '/system/etc/fontconfig_ohos.json', if fname is given null
63  */
FontConfig_OHOS(const SkTypeface_FreeType::Scanner & fontScanner,const char * fname)64 FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, const char* fname)
65     : fFontScanner(fontScanner)
66 {
67     int err = checkProductFile(fname);
68     if (err != NO_ERROR) {
69         return;
70     }
71     loadHMSymbol();
72 }
73 #endif
74 
75 /*! To get the count of font style sets supported in the system
76  *  \return The count of font style sets in generic family
77  */
getFamilyCount() const78 int FontConfig_OHOS::getFamilyCount() const
79 {
80     return fFontCollection.fGeneric.size();
81 }
82 
83 /*! To match the fallback typeface by the given style and character
84  *  this function will traverse all the fallback typefaces
85  *  \param character the character to be matched
86  *  \param style the style to be matched
87  *  \return the matched typeface
88 */
matchFallback(SkUnichar character,const SkFontStyle & style) const89 SkTypeface* FontConfig_OHOS::matchFallback(SkUnichar character, const SkFontStyle& style) const
90 {
91     // find the fallback typeface at emoji first
92     const auto& emoji = getFallbackTypeface(SkString("HMOS Color Emoji"), style);
93     if (emoji && emoji->unicharToGlyph(character)) {
94         return SkSafeRef(emoji.get());
95     }
96 
97     for (auto& f : fFontCollection.fFallback) {
98         const auto& typefaces = f.typefaces;
99         // for the compatibility to the old version
100         if (!typefaces.empty() && (f.containChar(character) || f.family.find("JP") != std::string::npos)) {
101             if (!typefaces[0]->unicharToGlyph(character)) {
102                 continue;
103             }
104             return SkSafeRef(matchFontStyle(typefaces, style).get());
105         }
106     }
107 
108     // find the fallback typeface at emoji flags third
109     const auto& flags = getFallbackTypeface(SkString("HMOS Color Emoji Flags"), style);
110     if (flags && flags->unicharToGlyph(character)) {
111         return SkSafeRef(flags.get());
112     }
113 
114     for (auto& f : fFontCollection.fFallback) {
115         const auto& typefaces = f.typefaces;
116         if (!typefaces.empty() && typefaces[0]->unicharToGlyph(character)) {
117             return SkSafeRef(matchFontStyle(typefaces, style).get());
118         }
119     }
120     return nullptr;
121 }
122 
123 
124 /*! To match the fallback typeface by the given index style and character
125  *  this function only traverse the fallback typefaces in the given index
126  *  \param index the index of fallback typefaces
127  *  \param character the character to be matched
128  *  \param style the style to be matched
129  *  \return the matched typeface
130 */
matchFallback(size_t index,SkUnichar character,const SkFontStyle & style) const131 SkTypeface* FontConfig_OHOS::matchFallback(size_t index, SkUnichar character, const SkFontStyle& style) const
132 {
133     if (index >= fFontCollection.fFallback.size()) {
134         return nullptr;
135     }
136     const auto& typefaces = fFontCollection.fFallback[index].typefaces;
137     if (!typefaces.empty() && typefaces[0]->unicharToGlyph(character)) {
138         auto typeface = matchFontStyle(typefaces, style);
139         return SkSafeRef(typeface.get());
140     }
141     return nullptr;
142 }
143 
144 /*! To match the fallback typeface by the given function
145  *  this function will traverse all the fallback typefaces
146  *  \param func the judge func, if the func return -1, it means the language tag is not matched
147  *  \return the matched fallback typefaces' index set
148 */
matchFallbackByBCP47(std::function<int (const std::string &)> func) const149 std::vector<size_t> FontConfig_OHOS::matchFallbackByBCP47(std::function<int(const std::string&)> func) const
150 {
151     std::vector<size_t> res;
152     for (size_t i = 0; i < fFontCollection.fFallback.size(); i += 1) {
153         if (func(fFontCollection.fFallback[i].lang) != -1) {
154             res.push_back(i);
155         }
156     }
157     return res;
158 }
159 
160 /*! To get a typeface by the given family name and style
161  *  this function will traverse both the fallback and general typefaces
162  *  \param familyName the family name of the fallback typeface
163  *  \param style the style of the fallback typeface
164  *  \return the matched typeface
165 */
getFallbackTypeface(const SkString & familyName,const SkFontStyle & style) const166 sk_sp<SkTypeface_OHOS> FontConfig_OHOS::getFallbackTypeface(const SkString& familyName, const SkFontStyle& style) const
167 {
168     std::pair<size_t, FontType> res;
169     if (!fFontCollection.getIndexByFamilyName(familyName.c_str(), res)) {
170         return nullptr;
171     }
172 
173     const auto& tpSet = fFontCollection.getSet(true)[res.first].typefaces;
174     if (tpSet.size() == 0) {
175         return nullptr;
176     }
177     return FontConfig_OHOS::matchFontStyle(tpSet, style);
178 }
179 
180 /*! To get the family name of the default font style set
181  *  \param[out] familyName a pointer of SkString object, to which the family value will be set.
182  *  \return The count of typeface in this font style set
183  *  \n Return -1, if there is no any font style set in the system.
184  */
getDefaultFamily(SkString & familyName) const185 int FontConfig_OHOS::getDefaultFamily(SkString& familyName) const
186 {
187     return getFamilyName(0, familyName);
188 }
189 
190 /*! To get the family name of a font style set
191  * \param index the index of a font style set in generic family
192  * \param[out] familyName a pointer of SkString object, to which the family value will be set
193  * \return The count of typeface in the font style set
194  * \n      Return -1, if the 'index' is out of range
195  */
getFamilyName(size_t index,SkString & familyName) const196 int FontConfig_OHOS::getFamilyName(size_t index, SkString& familyName) const
197 {
198     if (index >= getFamilyCount()) {
199         familyName = "";
200         return -1;
201     }
202     familyName = fFontCollection.fGeneric[index].alias.c_str();
203     return fFontCollection.fGeneric[index].typefaces.size();
204 }
205 
206 /*! To get the count of a font style set
207  * \param styleIndex the index of a font style set
208  * \param isFallback to indicate the font style set is from generic family or fallback family
209  * \n                 false , the font style set is from generic family list
210  * \n                 true, the font style set is from fallback family list
211  * \return The count of typeface in the font style set
212  */
getTypefaceCount(size_t styleIndex,bool isFallback) const213 size_t FontConfig_OHOS::getTypefaceCount(size_t styleIndex, bool isFallback) const
214 {
215     auto& set = fFontCollection.getSet(isFallback);
216     return (styleIndex < set.size()) ? set[styleIndex].typefaces.size() : 0;
217 }
218 
219 /*! To get a typeface
220  * \param styleIndex the index of a font style set
221  * \param index the index of a typeface in its style set
222  * \param isFallback false, the font style set is generic
223  * \n          true, the font style set is fallback
224  * \return The pointer of a typeface
225  * \n       Return null, if 'styleIndex' or 'index' is out of range
226  */
getTypeface(size_t styleIndex,size_t index,bool isFallback) const227 SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, size_t index, bool isFallback) const
228 {
229     sk_sp<SkTypeface_OHOS> typeface = getTypefaceSP(styleIndex, index, isFallback);
230     return (typeface == nullptr) ? nullptr : typeface.get();
231 }
232 
getTypefaceSP(size_t styleIndex,size_t index,bool isFallback) const233 sk_sp<SkTypeface_OHOS> FontConfig_OHOS::getTypefaceSP(size_t styleIndex, size_t index, bool isFallback) const
234 {
235     auto& fontSet = fFontCollection.getSet(isFallback);
236     if (styleIndex <= fontSet.size()) {
237         // if index less than typefaces' size, return the ptr
238         return (index < fontSet[styleIndex].typefaces.size()) ? fontSet[styleIndex].typefaces[index] : nullptr;
239     }
240     return nullptr;
241 }
242 
243 /*! To get a typeface
244  * \param styleIndex the index a font style set
245  * \param style the font style to be matching
246  * \param isFallback false, the font style set is generic
247  * \n                true, the font style set is fallback
248  * \return An object of typeface whose font style is the closest matching to 'style'
249  * \n      Return null, if 'styleIndex' is out of range
250  */
getTypeface(size_t styleIndex,const SkFontStyle & style,bool isFallback) const251 SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, const SkFontStyle& style, bool isFallback) const
252 {
253     auto& fontSet = fFontCollection.getSet(isFallback);
254     if (styleIndex >= fontSet.size()) {
255         return nullptr;
256     }
257 
258     const std::vector<sk_sp<SkTypeface_OHOS>>& pSet = fontSet[styleIndex].typefaces;
259     sk_sp<SkTypeface_OHOS> tp = matchFontStyle(pSet, style);
260     return tp.get();
261 }
262 
263 /*! To get the index of a font style set
264  *  \param familyName the family name of the font style set
265  *  \n     get the index of default font style set, if 'familyName' is null
266  *  \param[out] isFallback to tell if the family is from generic or fallback to the caller.
267  *  \n          isFallback is false, if the font style is from generic family list
268  *  \n          isFallback is true, if the font style is from fallback family list
269  *  \param[out] index the index of the font set
270  *  \return The index of the font style set
271  *  \n      Return false, if 'familyName' is not found in the system
272  */
getStyleIndex(const char * familyName,bool & isFallback,size_t & index) const273 bool FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback, size_t& index) const
274 {
275     if (familyName == nullptr) {
276         isFallback = false;
277         return true;
278     }
279 
280     std::lock_guard<std::mutex> lock(fFontMutex);
281     std::pair<size_t, FontType> res;
282     if (fFontCollection.getIndexByFamilyName(familyName, res)) {
283         isFallback = res.second == FontType::Fallback;
284         index = res.first;
285         return true;
286     }
287     return false;
288 }
289 
290 /*! Find the closest matching typeface
291  * \param typefaceSet a typeface set belonging to the same font style set
292  * \param pattern the font style to be matching
293  * \return The typeface object which is the closest matching to 'pattern'
294  * \n      Return null, if the count of typeface is 0
295  */
matchFontStyle(const std::vector<sk_sp<SkTypeface_OHOS>> & typefaceSet,const SkFontStyle & pattern)296 sk_sp<SkTypeface_OHOS> FontConfig_OHOS::matchFontStyle(
297     const std::vector<sk_sp<SkTypeface_OHOS>>& typefaceSet, const SkFontStyle& pattern)
298 {
299     int count = typefaceSet.size();
300     if (count == 1) {
301         return typefaceSet[0];
302     }
303     sk_sp<SkTypeface_OHOS> res = nullptr;
304     uint32_t minDiff = 0xFFFFFFFF;
305     for (int i = 0; i < count; i++) {
306         const SkFontStyle& fontStyle = typefaceSet[i]->fontStyle();
307         uint32_t diff = getFontStyleDifference(pattern, fontStyle);
308         if (diff < minDiff) {
309             minDiff = diff;
310             res = typefaceSet[i];
311         }
312     }
313     return res;
314 }
315 
316 /*! To get the difference between a font style and the matching font style
317  * \param dstStyle the style to be matching
318  * \param srcStyle a font style
319  * \return The difference value of a specified style with the matching style
320  */
getFontStyleDifference(const SkFontStyle & dstStyle,const SkFontStyle & srcStyle)321 uint32_t FontConfig_OHOS::getFontStyleDifference(const SkFontStyle& dstStyle,
322     const SkFontStyle& srcStyle)
323 {
324     int normalWidth = SkFontStyle::kNormal_Width;
325     int dstWidth = dstStyle.width();
326     int srcWidth = srcStyle.width();
327 
328     uint32_t widthDiff = 0;
329     // The maximum font width is kUltraExpanded_Width i.e. '9'.
330     // If dstWidth <= kNormal_Width (5), first check narrower values, then wider values.
331     // If dstWidth > kNormal_Width, first check wider values, then narrower values.
332     // When dstWidth and srcWidth are at different side of kNormal_Width,
333     // the width difference between them should be more than 5 (9/2+1)
334     constexpr int kWidthDiffThreshold = 9 / 2 + 1;
335     if (dstWidth <= normalWidth) {
336         widthDiff = (srcWidth <= dstWidth) ? (dstWidth - srcWidth)
337                                            : (srcWidth - dstWidth + kWidthDiffThreshold);
338     } else {
339         widthDiff = (srcWidth >= dstWidth) ? (srcWidth - dstWidth)
340                                            : (dstWidth - srcWidth + kWidthDiffThreshold);
341     }
342 
343     constexpr int SLANT_RANGE = 3;
344     int diffSlantValue[SLANT_RANGE][SLANT_RANGE] = {
345         {0, 2, 1},
346         {2, 0, 1},
347         {2, 1, 0}
348     };
349     if (dstStyle.slant() < 0 || dstStyle.slant() >= SLANT_RANGE ||
350         srcStyle.slant() < 0 || srcStyle.slant() >= SLANT_RANGE) {
351         return 0;
352     }
353     uint32_t slantDiff = diffSlantValue[dstStyle.slant()][srcStyle.slant()];
354 
355     int dstWeight = dstStyle.weight();
356     int srcWeight = srcStyle.weight();
357     uint32_t weightDiff = 0;
358 
359     // The maximum weight is kExtraBlack_Weight (1000), when dstWeight and srcWeight are at the different
360     // side of kNormal_Weight, the weight difference between them should be more than 500 (1000/2)
361     constexpr int kWeightDiffThreshold = 1000 / 2;
362     if ((dstWeight == SkFontStyle::kNormal_Weight && srcWeight == SkFontStyle::kMedium_Weight) ||
363         (dstWeight == SkFontStyle::kMedium_Weight && srcWeight == SkFontStyle::kNormal_Weight)) {
364         weightDiff = 50;
365     } else if (dstWeight <= SkFontStyle::kNormal_Weight) {
366         weightDiff = (srcWeight <= dstWeight) ? (dstWeight - srcWeight)
367                                               : (srcWeight - dstWeight + kWeightDiffThreshold);
368     } else if (dstWeight > SkFontStyle::kNormal_Weight) {
369         weightDiff = (srcWeight >= dstWeight) ? (srcWeight - dstWeight)
370                                               : (dstWeight - srcWeight + kWeightDiffThreshold);
371     }
372     // The first 2 bytes to save weight difference, the third byte to save slant difference,
373     // and the fourth byte to save width difference
374     uint32_t diff = (widthDiff << 24) + (slantDiff << 16) + weightDiff;
375     return diff;
376 }
377 
parseConfig(const char * fname)378 int FontConfig_OHOS::parseConfig(const char* fname)
379 {
380     if (fname == nullptr) {
381         fname = OHOS_DEFAULT_CONFIG;
382     }
383     Json::Value root;
384     int err = checkConfigFile(fname, root);
385     if (err != NO_ERROR) {
386         return err;
387     }
388 
389     for (const auto& key : root.getMemberNames()) {
390         if (root[key].isArray() && key == "font_dir") {
391             parseFontDir(fname, root[key]);
392         } else if (root[key].isArray() && key == "fonts") {
393             parseFonts(root[key]);
394         }
395     }
396 
397     return NO_ERROR;
398 }
399 
400 template<class T>
GetValue(T & v,const Json::Value & root)401 void GetValue(T& v, const Json::Value& root)
402 {
403     if (root.is<T>()) {
404         v = std::move(root.as<T>());
405     }
406 }
407 
408 #define GEN_GET_FONT_FUNC(f, member) ([](FontJson&(f), const Json::Value& value) { GetValue((f).member, value); })
409 
410 
411 /*! parse the font item from the json document
412  * \param array the font array from the json document
413  * \return NO_ERROR successful
414  */
parseFonts(const Json::Value & array)415 int FontConfig_OHOS::parseFonts(const Json::Value& array)
416 {
417     const std::unordered_map<std::string, std::function<void(FontConfig_OHOS::FontJson&, const Json::Value&)>>
418         funcMap = { { "type", GEN_GET_FONT_FUNC(f, type) }, { "family", GEN_GET_FONT_FUNC(f, family) },
419             { "index", GEN_GET_FONT_FUNC(f, index) }, { "weight", GEN_GET_FONT_FUNC(f, weight) },
420             { "lang", GEN_GET_FONT_FUNC(f, lang) }, { "file", GEN_GET_FONT_FUNC(f, file) },
421             { "alias", GEN_GET_FONT_FUNC(f, alias) } };
422 
423     std::vector<FontJson> fonts;
424 
425     for (const auto& font : array) {
426         if (!font.isObject()) {
427             continue;
428         }
429 
430         FontJson f;
431         for (const auto& key : font.getMemberNames()) {
432             if (funcMap.count(key)) {
433                 funcMap.at(key)(f, font[key]);
434             }
435         }
436 
437         sk_sp<SkTypeface_OHOS> typeface = nullptr;
438         for (auto& dir : fFontDir) {
439             std::string path = dir + f.file;
440             std::array<uint32_t, 4> range{};
441             if (loadFont(path.c_str(), f, typeface, range) == 0) {
442                 fFontCollection.emplaceFont(std::move(f), std::move(typeface), range);
443                 break;
444             }
445         }
446     }
447     forAll([this](Font& f) { sortTypefaceSet(f.typefaces); });
448     return NO_ERROR;
449 }
450 
451 /*! check the system font configuration document
452  * \param fname the full name of the font configuration document
453  * \return NO_ERROR successful
454  * \return ERROR_CONFIG_NOT_FOUND config document is not found
455  * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported
456  */
checkConfigFile(const char * fname,Json::Value & root)457 int FontConfig_OHOS::checkConfigFile(const char* fname, Json::Value& root)
458 {
459     std::ifstream fstream(fname);
460 
461     if (!fstream.is_open()) {
462         return ERROR_CONFIG_NOT_FOUND;
463     }
464 
465     Json::Reader reader;
466     bool isJson = reader.parse(fstream, root, false);
467     if (!isJson) {
468         return ERROR_CONFIG_FORMAT_NOT_SUPPORTED;
469     }
470     return NO_ERROR;
471 }
472 
473 /*! To parse 'fontdir' attribute
474  * \param root the root node of 'fontdir'
475  * \return NO_ERROR successful
476  */
parseFontDir(const char * fname,const Json::Value & root)477 int FontConfig_OHOS::parseFontDir(const char* fname, const Json::Value& root)
478 {
479     for (auto& path : root) {
480         if (!path.isString()) {
481             continue;
482         }
483         std::string dir;
484 #ifdef SK_BUILD_FONT_MGR_FOR_PREVIEW
485         if (strcmp(fname, OHOS_DEFAULT_CONFIG) == 0) {
486             dir = (path.asString() != "/system/fonts/") ? path.asString() : "fonts/";
487         } else {
488             dir = (path.asString() != "/system/fonts/")
489                 ? path.asString() : "../../../../hms/previewer/resources/fonts/";
490         }
491 #else
492         dir = path.asString();
493 #endif
494         fFontDir.push_back(std::move(dir));
495     }
496     return NO_ERROR;
497 }
498 
499 /*! To load font information from a font file
500  * \param fname the full name of a font file
501  * \param info the font information read from json document
502  * \param typeface the typeface to be loaded
503  * \return NO_ERROR successful
504  * \return ERROR_FONT_NOT_EXIST font file is not exist
505  * \return ERROR_FONT_INVALID_STREAM the stream is not recognized
506  */
loadFont(const char * fname,FontJson & info,sk_sp<SkTypeface_OHOS> & typeface,std::array<uint32_t,4> & range)507 int FontConfig_OHOS::loadFont(
508     const char* fname, FontJson& info, sk_sp<SkTypeface_OHOS>& typeface, std::array<uint32_t, 4>& range)
509 {
510     std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fname);
511     if (stream == nullptr) {
512         return ERROR_FONT_NOT_EXIST;
513     }
514     FontInfo font(fname, info.index);
515     SkTypeface_FreeType::Scanner::FontInfo fontInfo{ info.index, font.familyName, font.style, font.isFixedWidth };
516     if (!fFontScanner.scanFont(stream.get(), fontInfo, range)) {
517         return ERROR_FONT_INVALID_STREAM;
518     }
519 
520     const char* temp = (info.type == FontType::Generic) ? info.alias.c_str() : "";
521     SkString family(temp);
522     typeface = sk_make_sp<SkTypeface_OHOS>(family, font);
523     return NO_ERROR;
524 }
525 
loadHMSymbol()526 void FontConfig_OHOS::loadHMSymbol()
527 {
528     if (!G_IS_HMSYMBOL_ENABLE) {
529         return;
530     }
531     for (auto& dir : fFontDir) {
532         if (HmSymbolConfig_OHOS::GetInstance()->ParseConfigOfHmSymbol(
533             "hm_symbol_config_next.json", SkString(dir.c_str())) == NO_ERROR) {
534             return;
535         }
536     }
537 }
538 
539 /*! To sort the typeface set
540  * \param typefaceSet the typeface set to be sorted
541  */
sortTypefaceSet(std::vector<sk_sp<SkTypeface_OHOS>> & typefaceSet)542 void FontConfig_OHOS::sortTypefaceSet(std::vector<sk_sp<SkTypeface_OHOS>>& typefaceSet)
543 {
544     std::sort(typefaceSet.begin(), typefaceSet.end(), [](const auto& a, const auto& b) {
545         return (a->fontStyle().weight() < b->fontStyle().weight()) ||
546                (a->fontStyle().weight() == b->fontStyle().weight() && a->fontStyle().slant() < b->fontStyle().slant());
547     });
548 }
549 
550 
judgeFileExist()551 bool FontConfig_OHOS::judgeFileExist()
552 {
553     bool haveFile = false;
554     for (const auto& path : fFontDir) {
555         DIR* dir = opendir(path.c_str());
556         if (dir == nullptr) {
557             continue;
558         }
559         struct dirent* node = nullptr;
560 #if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN)
561         struct stat fileStat;
562 #endif
563         while ((node = readdir(dir))) {
564 #if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN)
565             stat(node->d_name, &fileStat);
566             if (S_ISDIR(fileStat.st_mode)) {
567                 continue;
568             }
569 #else
570             if (node->d_type != DT_REG) {
571                 continue;
572             }
573 #endif
574             const char* fileName = node->d_name;
575             int len = strlen(fileName);
576             int suffixLen = strlen(".ttf");
577             if (len < suffixLen ||
578                 (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) != 0 &&
579                 strncmp(fileName + len - suffixLen, ".otf", suffixLen) != 0 &&
580                 strncmp(fileName + len - suffixLen, ".ttc", suffixLen) != 0 &&
581                 strncmp(fileName + len - suffixLen, ".otc", suffixLen) != 0)) {
582                 continue;
583             }
584             haveFile = true;
585             break;
586         }
587         (void)closedir(dir);
588         if (haveFile) {
589             break;
590         }
591     }
592     return haveFile;
593 }
594 
checkProductFile(const char * fname)595 int FontConfig_OHOS::checkProductFile(const char* fname)
596 {
597     std::lock_guard<std::mutex> lock(fFontMutex);
598     int err = parseConfig(PRODUCT_DEFAULT_CONFIG);
599     if (err != NO_ERROR || !judgeFileExist()) {
600         err = parseConfig(OHOS_DEFAULT_CONFIG);
601     }
602     return err;
603 }
604 
605 static const std::map<std::pair<uint32_t, uint32_t>, int8_t> gRangeMap {
606     { { 0x0000, 0x007F }, 0 },
607     { { 0x0080, 0x00FF }, 1 },
608     { { 0x0100, 0x017F }, 2 },
609     { { 0x0180, 0x024F }, 3 },
610     { { 0x0250, 0x02AF }, 4 },
611     { { 0x1D00, 0x1DBF }, 4 },
612     { { 0x02B0, 0x02FF }, 5 },
613     { { 0xA700, 0xA71F }, 5 },
614     { { 0x0300, 0x036F }, 6 },
615     { { 0x1DC0, 0x1DFF }, 6 },
616     { { 0x0370, 0x03FF }, 7 },
617     { { 0x2C80, 0x2CFF }, 8 },
618     { { 0x0400, 0x052F }, 9 },
619     { { 0x2DE0, 0x2DFF }, 9 },
620     { { 0xA640, 0xA69F }, 9 },
621     { { 0x0530, 0x058F }, 10 },
622     { { 0x0590, 0x05FF }, 11 },
623     { { 0xA500, 0xA63F }, 12 },
624     { { 0x0600, 0x06FF }, 13 },
625     { { 0x0750, 0x077F }, 13 },
626     { { 0x07C0, 0x07FF }, 14 },
627     { { 0x0900, 0x097F }, 15 },
628     { { 0x0980, 0x09FF }, 16 },
629     { { 0x0A00, 0x0A7F }, 17 },
630     { { 0x0A80, 0x0AFF }, 18 },
631     { { 0x0B00, 0x0B7F }, 19 },
632     { { 0x0B80, 0x0BFF }, 20 },
633     { { 0x0C00, 0x0C7F }, 21 },
634     { { 0x0C80, 0x0CFF }, 22 },
635     { { 0x0D00, 0x0D7F }, 23 },
636     { { 0x0E00, 0x0E7F }, 24 },
637     { { 0x0E80, 0x0EFF }, 25 },
638     { { 0x10A0, 0x10FF }, 26 },
639     { { 0x2D00, 0x2D2F }, 26 },
640     { { 0x1B00, 0x1B7F }, 27 },
641     { { 0x1100, 0x11FF }, 28 },
642     { { 0x1E00, 0x1EFF }, 29 },
643     { { 0x2C60, 0x2C7F }, 29 },
644     { { 0xA720, 0xA7FF }, 29 },
645     { { 0x1F00, 0x1FFF }, 30 },
646     { { 0x2000, 0x206F }, 31 },
647     { { 0x2E00, 0x2E7F }, 31 },
648     { { 0x2070, 0x209F }, 32 },
649     { { 0x20A0, 0x20CF }, 33 },
650     { { 0x20D0, 0x20FF }, 34 },
651     { { 0x2100, 0x214F }, 35 },
652     { { 0x2150, 0x218F }, 36 },
653     { { 0x2190, 0x21FF }, 37 },
654     { { 0x27F0, 0x27FF }, 37 },
655     { { 0x2900, 0x297F }, 37 },
656     { { 0x2B00, 0x2BFF }, 37 },
657     { { 0x2200, 0x22FF }, 38 },
658     { { 0x2A00, 0x2AFF }, 38 },
659     { { 0x27C0, 0x27EF }, 38 },
660     { { 0x2980, 0x29FF }, 38 },
661     { { 0x2300, 0x23FF }, 39 },
662     { { 0x2400, 0x243F }, 40 },
663     { { 0x2440, 0x245F }, 41 },
664     { { 0x2460, 0x24FF }, 42 },
665     { { 0x2500, 0x257F }, 43 },
666     { { 0x2580, 0x259F }, 44 },
667     { { 0x25A0, 0x25FF }, 45 },
668     { { 0x2600, 0x26FF }, 46 },
669     { { 0x2700, 0x27BF }, 47 },
670     { { 0x3000, 0x303F }, 48 },
671     { { 0x3040, 0x309F }, 49 },
672     { { 0x30A0, 0x30FF }, 50 },
673     { { 0x31F0, 0x31FF }, 50 },
674     { { 0x3100, 0x312F }, 51 },
675     { { 0x31A0, 0x31BF }, 51 },
676     { { 0x3130, 0x318F }, 52 },
677     { { 0xA840, 0xA87F }, 53 },
678     { { 0x3200, 0x32FF }, 54 },
679     { { 0x3300, 0x33FF }, 55 },
680     { { 0xAC00, 0xD7AF }, 56 },
681     // Ignore Non-Plane 0 (57), since this is not a real range.
682     { { 0x10900, 0x1091F }, 58 },
683     { { 0x4E00, 0x9FFF }, 59 },
684     { { 0x2E80, 0x2FDF }, 59 },
685     { { 0x2FF0, 0x2FFF }, 59 },
686     { { 0x3400, 0x4DBF }, 59 },
687     { { 0x20000, 0x2A6DF }, 59 },
688     { { 0x3190, 0x319F }, 59 },
689     { { 0xE000, 0xF8FF }, 60 },
690     { { 0x31C0, 0x31EF }, 61 },
691     { { 0xF900, 0xFAFF }, 61 },
692     { { 0x2F800, 0x2FA1F }, 61 },
693     { { 0xFB00, 0xFB4F }, 62 },
694     { { 0xFB50, 0xFDFF }, 63 },
695     { { 0xFE20, 0xFE2F }, 64 },
696     { { 0xFE10, 0xFE1F }, 65 },
697     { { 0xFE30, 0xFE4F }, 65 },
698     { { 0xFE50, 0xFE6F }, 66 },
699     { { 0xFE70, 0xFEFF }, 67 },
700     { { 0xFF00, 0xFFEF }, 68 },
701     { { 0xFFF0, 0xFFFF }, 69 },
702     { { 0x0F00, 0x0FFF }, 70 },
703     { { 0x0700, 0x074F }, 71 },
704     { { 0x0780, 0x07BF }, 72 },
705     { { 0x0D80, 0x0DFF }, 73 },
706     { { 0x1000, 0x109F }, 74 },
707     { { 0x1200, 0x139F }, 75 },
708     { { 0x2D80, 0x2DDF }, 75 },
709     { { 0x13A0, 0x13FF }, 76 },
710     { { 0x1400, 0x167F }, 77 },
711     { { 0x1680, 0x169F }, 78 },
712     { { 0x16A0, 0x16FF }, 79 },
713     { { 0x1780, 0x17FF }, 80 },
714     { { 0x19E0, 0x19FF }, 80 },
715     { { 0x1800, 0x18AF }, 81 },
716     { { 0x2800, 0x28FF }, 82 },
717     { { 0xA000, 0xA48F }, 83 },
718     { { 0xA490, 0xA4CF }, 83 },
719     { { 0x1700, 0x177F }, 84 },
720     { { 0x10300, 0x1032F }, 85 },
721     { { 0x10330, 0x1034F }, 86 },
722     { { 0x10400, 0x1044F }, 87 },
723     { { 0x1D000, 0x1D24F }, 88 },
724     { { 0x1D400, 0x1D7FF }, 89 },
725     { { 0xF0000, 0xFFFFD }, 90 },
726     { { 0x100000, 0x10FFFD }, 90 },
727     { { 0xFE00, 0xFE0F }, 91 },
728     { { 0xE0100, 0xE01EF }, 91 },
729     { { 0xE0000, 0xE007F }, 92 },
730     { { 0x1900, 0x194F }, 93 },
731     { { 0x1950, 0x197F }, 94 },
732     { { 0x1980, 0x19DF }, 95 },
733     { { 0x1A00, 0x1A1F }, 96 },
734     { { 0x2C00, 0x2C5F }, 97 },
735     { { 0x2D30, 0x2D7F }, 98 },
736     { { 0x4DC0, 0x4DFF }, 99 },
737     { { 0xA800, 0xA82F }, 100 },
738     { { 0x10000, 0x1013F }, 101 },
739     { { 0x10140, 0x1018F }, 102 },
740     { { 0x10380, 0x1039F }, 103 },
741     { { 0x103A0, 0x103DF }, 104 },
742     { { 0x10450, 0x1047F }, 105 },
743     { { 0x10480, 0x104AF }, 106 },
744     { { 0x10800, 0x1083F }, 107 },
745     { { 0x10A00, 0x10A5F }, 108 },
746     { { 0x1D300, 0x1D35F }, 109 },
747     { { 0x12000, 0x123FF }, 110 },
748     { { 0x12400, 0x1247F }, 110 },
749     { { 0x1D360, 0x1D37F }, 111 },
750     { { 0x1B80, 0x1BBF }, 112 },
751     { { 0x1C00, 0x1C4F }, 113 },
752     { { 0x1C50, 0x1C7F }, 114 },
753     { { 0xA880, 0xA8DF }, 115 },
754     { { 0xA900, 0xA92F }, 116 },
755     { { 0xA930, 0xA95F }, 117 },
756     { { 0xAA00, 0xAA5F }, 118 },
757     { { 0x10190, 0x101CF }, 119 },
758     { { 0x101D0, 0x101FF }, 120 },
759     { { 0x102A0, 0x102DF }, 121 },
760     { { 0x10280, 0x1029F }, 121 },
761     { { 0x10920, 0x1093F }, 121 },
762     { { 0x1F030, 0x1F09F }, 122 },
763     { { 0x1F000, 0x1F02F }, 122 },
764 };
765 
charRangeIndex(SkUnichar unicode)766 static int8_t charRangeIndex(SkUnichar unicode)
767 {
768     auto it = gRangeMap.upper_bound({ unicode, INT32_MAX });
769     if (it != gRangeMap.begin()) {
770         --it;
771     }
772     if (unicode >= it->first.first && unicode <= it->first.second) {
773         return it->second;
774     }
775     return -1;
776 }
777 
containChar(SkUnichar unicode) const778 bool FontConfig_OHOS::Font::containChar(SkUnichar unicode) const
779 {
780     int8_t r = charRangeIndex(unicode);
781     if (r < 0) {
782         return false;
783     }
784     // because the range is 128-bit, so we need to split it into 4 32-bit, / 32 means >> 5
785     int8_t i = r >> 5;
786     // get the bit position by mod 32 which means & 31
787     int8_t bit = r & 31;
788     return ((range[i] >> bit) & 1) != 0;
789 }