1cb93a386Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved 2cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 3cb93a386Sopenharmony_ci// found in the LICENSE file. 4cb93a386Sopenharmony_ci 5cb93a386Sopenharmony_ci#include "FontConfig_ohos.h" 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci#include<array> 8cb93a386Sopenharmony_ci#include <cstring> 9cb93a386Sopenharmony_ci#include <dirent.h> 10cb93a386Sopenharmony_ci#include <libgen.h> 11cb93a386Sopenharmony_ci#include <sys/stat.h> 12cb93a386Sopenharmony_ci#include <sys/types.h> 13cb93a386Sopenharmony_ci#include <unistd.h> 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#ifdef SK_BUILD_FONT_MGR_FOR_OHOS 16cb93a386Sopenharmony_ci#include <parameters.h> 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include "securec.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#include "SkFontStyle.h" 22cb93a386Sopenharmony_ci#include "SkString.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciusing namespace ErrorCode; 25cb93a386Sopenharmony_cistatic const char* PRODUCT_DEFAULT_CONFIG = "/system/etc/productfontconfig.json"; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci#ifdef SK_BUILD_FONT_MGR_FOR_OHOS 28cb93a386Sopenharmony_ci static const bool G_IS_HMSYMBOL_ENABLE = 29cb93a386Sopenharmony_ci (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymbolcfg.enable", "1").c_str()) != 0); 30cb93a386Sopenharmony_ci#else 31cb93a386Sopenharmony_ci static const bool G_IS_HMSYMBOL_ENABLE = true; 32cb93a386Sopenharmony_ci#endif 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) or defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_MAC) or defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_LINUX) 35cb93a386Sopenharmony_cistatic const char* OHOS_DEFAULT_CONFIG = "fontconfig.json"; 36cb93a386Sopenharmony_ci/*! Constructor 37cb93a386Sopenharmony_ci * \param fontScanner the scanner to get the font information from a font file 38cb93a386Sopenharmony_ci * \param fname the full name of system font configuration document. 39cb93a386Sopenharmony_ci * \n The default value is '/system/etc/fontconfig.json', if fname is given null 40cb93a386Sopenharmony_ci */ 41cb93a386Sopenharmony_ciFontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, 42cb93a386Sopenharmony_ci const char* fname) 43cb93a386Sopenharmony_ci{ 44cb93a386Sopenharmony_ci int err = parseConfig(fname); 45cb93a386Sopenharmony_ci if (err != NO_ERROR) { 46cb93a386Sopenharmony_ci return; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci scanFonts(fontScanner); 49cb93a386Sopenharmony_ci resetGenericValue(); 50cb93a386Sopenharmony_ci resetFallbackValue(); 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci#else 53cb93a386Sopenharmony_cistatic const char* OHOS_DEFAULT_CONFIG = "/system/etc/fontconfig.json"; 54cb93a386Sopenharmony_ci/*! Constructor 55cb93a386Sopenharmony_ci * \param fontScanner the scanner to get the font information from a font file 56cb93a386Sopenharmony_ci * \param fname the full name of system font configuration document. 57cb93a386Sopenharmony_ci * \n The default value is '/system/etc/fontconfig.json', if fname is given null 58cb93a386Sopenharmony_ci */ 59cb93a386Sopenharmony_ciFontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, 60cb93a386Sopenharmony_ci const char* fname) 61cb93a386Sopenharmony_ci{ 62cb93a386Sopenharmony_ci int err = checkProductFile(fname); 63cb93a386Sopenharmony_ci if (err != NO_ERROR) { 64cb93a386Sopenharmony_ci return; 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci scanFonts(fontScanner); 67cb93a386Sopenharmony_ci resetGenericValue(); 68cb93a386Sopenharmony_ci resetFallbackValue(); 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci#endif 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci/*! To get the fallbackForMap 73cb93a386Sopenharmony_ci * \return The reference of fallbackForMap 74cb93a386Sopenharmony_ci */ 75cb93a386Sopenharmony_ciconst FallbackForMap& FontConfig_OHOS::getFallbackForMap() const 76cb93a386Sopenharmony_ci{ 77cb93a386Sopenharmony_ci return fallbackForMap; 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci/*! To get the fallback set 81cb93a386Sopenharmony_ci * \return The reference of fallbackSet 82cb93a386Sopenharmony_ci */ 83cb93a386Sopenharmony_ciconst FallbackSet& FontConfig_OHOS::getFallbackSet() const 84cb93a386Sopenharmony_ci{ 85cb93a386Sopenharmony_ci return fallbackSet; 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci/*! To get the count of font style sets supported in the system 89cb93a386Sopenharmony_ci * \return The count of font style sets in generic family 90cb93a386Sopenharmony_ci */ 91cb93a386Sopenharmony_ciint FontConfig_OHOS::getFamilyCount() const 92cb93a386Sopenharmony_ci{ 93cb93a386Sopenharmony_ci return genericFamilySet.size(); 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci/*! To get the family name of the default font style set 97cb93a386Sopenharmony_ci * \param[out] familyName a pointer of SkString object, to which the family value will be set. 98cb93a386Sopenharmony_ci * \return The count of typeface in this font style set 99cb93a386Sopenharmony_ci * \n Return -1, if there is no any font style set in the system. 100cb93a386Sopenharmony_ci */ 101cb93a386Sopenharmony_ciint FontConfig_OHOS::getDefaultFamily(SkString* familyName) const 102cb93a386Sopenharmony_ci{ 103cb93a386Sopenharmony_ci return getFamilyName(0, familyName); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci/*! To get the family name of a font style set 107cb93a386Sopenharmony_ci * \param index the index of a font style set in generic family 108cb93a386Sopenharmony_ci * \param[out] familyName a pointer of SkString object, to which the family value will be set 109cb93a386Sopenharmony_ci * \return The count of typeface in the font style set 110cb93a386Sopenharmony_ci * \n Return -1, if the 'index' is out of range 111cb93a386Sopenharmony_ci */ 112cb93a386Sopenharmony_ciint FontConfig_OHOS::getFamilyName(int index, SkString* familyName) const 113cb93a386Sopenharmony_ci{ 114cb93a386Sopenharmony_ci if (index < 0 || index >= this->getFamilyCount()) { 115cb93a386Sopenharmony_ci if (familyName) { 116cb93a386Sopenharmony_ci familyName->reset(); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci return -1; 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci if (familyName) { 121cb93a386Sopenharmony_ci *familyName = genericFamilySet[index]->familyName; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci return genericFamilySet[index]->typefaceSet->size(); 124cb93a386Sopenharmony_ci} 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci/*! To get the count of a font style set 127cb93a386Sopenharmony_ci * \param styleIndex the index of a font style set 128cb93a386Sopenharmony_ci * \param isFallback to indicate the font style set is from generic family or fallback family 129cb93a386Sopenharmony_ci * \n false , the font style set is from generic family list 130cb93a386Sopenharmony_ci * \n true, the font style set is from fallback family list 131cb93a386Sopenharmony_ci * \return The count of typeface in the font style set 132cb93a386Sopenharmony_ci */ 133cb93a386Sopenharmony_ciint FontConfig_OHOS::getTypefaceCount(int styleIndex, bool isFallback) const 134cb93a386Sopenharmony_ci{ 135cb93a386Sopenharmony_ci if (styleIndex < 0) { 136cb93a386Sopenharmony_ci return -1; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci if (isFallback) { 139cb93a386Sopenharmony_ci if ((unsigned int)styleIndex < fallbackSet.size()) { 140cb93a386Sopenharmony_ci return fallbackSet[styleIndex]->typefaceSet->size(); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci } else { 143cb93a386Sopenharmony_ci if ((unsigned int)styleIndex < genericFamilySet.size()) { 144cb93a386Sopenharmony_ci return genericFamilySet[styleIndex]->typefaceSet->size(); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci return -1; 148cb93a386Sopenharmony_ci} 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci/*! To get a typeface 151cb93a386Sopenharmony_ci * \param styleIndex the index of a font style set 152cb93a386Sopenharmony_ci * \param index the index of a typeface in its style set 153cb93a386Sopenharmony_ci * \param isFallback false, the font style set is generic 154cb93a386Sopenharmony_ci * \n true, the font style set is fallback 155cb93a386Sopenharmony_ci * \return The pointer of a typeface 156cb93a386Sopenharmony_ci * \n Return null, if 'styleIndex' or 'index' is out of range 157cb93a386Sopenharmony_ci */ 158cb93a386Sopenharmony_ciSkTypeface_OHOS* FontConfig_OHOS::getTypeface(int styleIndex, int index, 159cb93a386Sopenharmony_ci bool isFallback) const 160cb93a386Sopenharmony_ci{ 161cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> typeface = getTypefaceSP(styleIndex, index, isFallback); 162cb93a386Sopenharmony_ci return (typeface == nullptr) ? nullptr : typeface.get(); 163cb93a386Sopenharmony_ci} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_cisk_sp<SkTypeface_OHOS> FontConfig_OHOS::getTypefaceSP(int styleIndex, int index, bool isFallback) const 166cb93a386Sopenharmony_ci{ 167cb93a386Sopenharmony_ci if (styleIndex < 0 || index < 0 || 168cb93a386Sopenharmony_ci (isFallback && (unsigned int)styleIndex >= fallbackSet.size()) || 169cb93a386Sopenharmony_ci (!isFallback && (unsigned int)styleIndex >= genericFamilySet.size())) { 170cb93a386Sopenharmony_ci return nullptr; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci if (isFallback) { 173cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(fallbackSet[styleIndex]->typefaceSet.get()); 174cb93a386Sopenharmony_ci if ((unsigned int)index < tpSet.size()) { 175cb93a386Sopenharmony_ci return tpSet[index]; 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci } else { 178cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(genericFamilySet[styleIndex]->typefaceSet.get()); 179cb93a386Sopenharmony_ci if ((unsigned int)index < tpSet.size()) { 180cb93a386Sopenharmony_ci return tpSet[index]; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci return nullptr; 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci/*! To get a typeface 187cb93a386Sopenharmony_ci * \param styleIndex the index a font style set 188cb93a386Sopenharmony_ci * \param style the font style to be matching 189cb93a386Sopenharmony_ci * \param isFallback false, the font style set is generic 190cb93a386Sopenharmony_ci * \n true, the font style set is fallback 191cb93a386Sopenharmony_ci * \return An object of typeface whose font style is the closest matching to 'style' 192cb93a386Sopenharmony_ci * \n Return null, if 'styleIndex' is out of range 193cb93a386Sopenharmony_ci */ 194cb93a386Sopenharmony_ciSkTypeface_OHOS* FontConfig_OHOS::getTypeface(int styleIndex, const SkFontStyle& style, 195cb93a386Sopenharmony_ci bool isFallback) const 196cb93a386Sopenharmony_ci{ 197cb93a386Sopenharmony_ci if (styleIndex < 0 || 198cb93a386Sopenharmony_ci (isFallback && (unsigned int)styleIndex >= fallbackSet.size()) || 199cb93a386Sopenharmony_ci (!isFallback && (unsigned int)styleIndex >= genericFamilySet.size())) { 200cb93a386Sopenharmony_ci return nullptr; 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci const TypefaceSet* pSet = nullptr; 203cb93a386Sopenharmony_ci if (isFallback) { 204cb93a386Sopenharmony_ci pSet = fallbackSet[styleIndex]->typefaceSet.get(); 205cb93a386Sopenharmony_ci } else { 206cb93a386Sopenharmony_ci pSet = genericFamilySet[styleIndex]->typefaceSet.get(); 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> tp = matchFontStyle(*pSet, style); 209cb93a386Sopenharmony_ci return tp.get(); 210cb93a386Sopenharmony_ci} 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci/*! To get the index of a font style set 213cb93a386Sopenharmony_ci * \param familyName the family name of the font style set 214cb93a386Sopenharmony_ci * \n get the index of default font style set, if 'familyName' is null 215cb93a386Sopenharmony_ci * \param[out] isFallback to tell if the family is from generic or fallback to the caller. 216cb93a386Sopenharmony_ci * \n isFallback is false, if the font style is from generic family list 217cb93a386Sopenharmony_ci * \n isFallback is true, if the font style is from fallback family list 218cb93a386Sopenharmony_ci * \return The index of the font style set 219cb93a386Sopenharmony_ci * \n Return -1, if 'familyName' is not found in the system 220cb93a386Sopenharmony_ci */ 221cb93a386Sopenharmony_ciint FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback) const 222cb93a386Sopenharmony_ci{ 223cb93a386Sopenharmony_ci if (familyName == nullptr) { 224cb93a386Sopenharmony_ci isFallback = false; 225cb93a386Sopenharmony_ci return 0; 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(fontMutex); 229cb93a386Sopenharmony_ci if (genericNames.count() == 0) { 230cb93a386Sopenharmony_ci return -1; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci SkString fname(familyName); 234cb93a386Sopenharmony_ci int* p = genericNames.find(fname); 235cb93a386Sopenharmony_ci if (p) { 236cb93a386Sopenharmony_ci isFallback = false; 237cb93a386Sopenharmony_ci return *p; 238cb93a386Sopenharmony_ci } else { 239cb93a386Sopenharmony_ci if (fallbackNames.count() == 0) { 240cb93a386Sopenharmony_ci return -1; 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci p = fallbackNames.find(fname); 244cb93a386Sopenharmony_ci if (p) { 245cb93a386Sopenharmony_ci isFallback = true; 246cb93a386Sopenharmony_ci return *p; 247cb93a386Sopenharmony_ci } 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci return -1; 250cb93a386Sopenharmony_ci} 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci/*! Find the closest matching typeface 253cb93a386Sopenharmony_ci * \param typefaceSet a typeface set belonging to the same font style set 254cb93a386Sopenharmony_ci * \param pattern the font style to be matching 255cb93a386Sopenharmony_ci * \return The typeface object which is the closest matching to 'pattern' 256cb93a386Sopenharmony_ci * \n Return null, if the count of typeface is 0 257cb93a386Sopenharmony_ci */ 258cb93a386Sopenharmony_cisk_sp<SkTypeface_OHOS> FontConfig_OHOS::matchFontStyle(const TypefaceSet& typefaceSet, 259cb93a386Sopenharmony_ci const SkFontStyle& pattern) 260cb93a386Sopenharmony_ci{ 261cb93a386Sopenharmony_ci int count = typefaceSet.size(); 262cb93a386Sopenharmony_ci if (count == 1) { 263cb93a386Sopenharmony_ci return typefaceSet[0]; 264cb93a386Sopenharmony_ci } 265cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> res = nullptr; 266cb93a386Sopenharmony_ci uint32_t minDiff = 0xFFFFFFFF; 267cb93a386Sopenharmony_ci for (int i = 0; i < count; i++) { 268cb93a386Sopenharmony_ci const SkFontStyle& fontStyle = typefaceSet[i]->fontStyle(); 269cb93a386Sopenharmony_ci uint32_t diff = getFontStyleDifference(pattern, fontStyle); 270cb93a386Sopenharmony_ci if (diff < minDiff) { 271cb93a386Sopenharmony_ci minDiff = diff; 272cb93a386Sopenharmony_ci res = typefaceSet[i]; 273cb93a386Sopenharmony_ci } 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci return res; 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci/*! To get the difference between a font style and the matching font style 279cb93a386Sopenharmony_ci * \param dstStyle the style to be matching 280cb93a386Sopenharmony_ci * \param srcStyle a font style 281cb93a386Sopenharmony_ci * \return The difference value of a specified style with the matching style 282cb93a386Sopenharmony_ci */ 283cb93a386Sopenharmony_ciuint32_t FontConfig_OHOS::getFontStyleDifference(const SkFontStyle& dstStyle, 284cb93a386Sopenharmony_ci const SkFontStyle& srcStyle) 285cb93a386Sopenharmony_ci{ 286cb93a386Sopenharmony_ci int normalWidth = SkFontStyle::kNormal_Width; 287cb93a386Sopenharmony_ci int dstWidth = dstStyle.width(); 288cb93a386Sopenharmony_ci int srcWidth = srcStyle.width(); 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci uint32_t widthDiff = 0; 291cb93a386Sopenharmony_ci // The maximum font width is kUltraExpanded_Width i.e. '9'. 292cb93a386Sopenharmony_ci // If dstWidth <= kNormal_Width (5), first check narrower values, then wider values. 293cb93a386Sopenharmony_ci // If dstWidth > kNormal_Width, first check wider values, then narrower values. 294cb93a386Sopenharmony_ci // When dstWidth and srcWidth are at different side of kNormal_Width, 295cb93a386Sopenharmony_ci // the width difference between them should be more than 5 (9/2+1) 296cb93a386Sopenharmony_ci constexpr int kWidthDiffThreshold = 9 / 2 + 1; 297cb93a386Sopenharmony_ci if (dstWidth <= normalWidth) { 298cb93a386Sopenharmony_ci widthDiff = (srcWidth <= dstWidth) ? (dstWidth - srcWidth) 299cb93a386Sopenharmony_ci : (srcWidth - dstWidth + kWidthDiffThreshold); 300cb93a386Sopenharmony_ci } else { 301cb93a386Sopenharmony_ci widthDiff = (srcWidth >= dstWidth) ? (srcWidth - dstWidth) 302cb93a386Sopenharmony_ci : (dstWidth - srcWidth + kWidthDiffThreshold); 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci 305cb93a386Sopenharmony_ci constexpr int SLANT_RANGE = 3; 306cb93a386Sopenharmony_ci int diffSlantValue[SLANT_RANGE][SLANT_RANGE] = { 307cb93a386Sopenharmony_ci {0, 2, 1}, 308cb93a386Sopenharmony_ci {2, 0, 1}, 309cb93a386Sopenharmony_ci {2, 1, 0} 310cb93a386Sopenharmony_ci }; 311cb93a386Sopenharmony_ci if (dstStyle.slant() < 0 || dstStyle.slant() >= SLANT_RANGE || 312cb93a386Sopenharmony_ci srcStyle.slant() < 0 || srcStyle.slant() >= SLANT_RANGE) { 313cb93a386Sopenharmony_ci LOGE("Slant out of range, dst:%{public}d, src:%{public}d", dstStyle.slant(), srcStyle.slant()); 314cb93a386Sopenharmony_ci return 0; 315cb93a386Sopenharmony_ci } 316cb93a386Sopenharmony_ci uint32_t slantDiff = diffSlantValue[dstStyle.slant()][srcStyle.slant()]; 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci int dstWeight = dstStyle.weight(); 319cb93a386Sopenharmony_ci int srcWeight = srcStyle.weight(); 320cb93a386Sopenharmony_ci uint32_t weightDiff = 0; 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_ci // The maximum weight is kExtraBlack_Weight (1000), when dstWeight and srcWeight are at the different 323cb93a386Sopenharmony_ci // side of kNormal_Weight, the weight difference between them should be more than 500 (1000/2) 324cb93a386Sopenharmony_ci constexpr int kWeightDiffThreshold = 1000 / 2; 325cb93a386Sopenharmony_ci if ((dstWeight == SkFontStyle::kNormal_Weight && srcWeight == SkFontStyle::kMedium_Weight) || 326cb93a386Sopenharmony_ci (dstWeight == SkFontStyle::kMedium_Weight && srcWeight == SkFontStyle::kNormal_Weight)) { 327cb93a386Sopenharmony_ci weightDiff = 50; 328cb93a386Sopenharmony_ci } else if (dstWeight <= SkFontStyle::kNormal_Weight) { 329cb93a386Sopenharmony_ci weightDiff = (srcWeight <= dstWeight) ? (dstWeight - srcWeight) 330cb93a386Sopenharmony_ci : (srcWeight - dstWeight + kWeightDiffThreshold); 331cb93a386Sopenharmony_ci } else if (dstWeight > SkFontStyle::kNormal_Weight) { 332cb93a386Sopenharmony_ci weightDiff = (srcWeight >= dstWeight) ? (srcWeight - dstWeight) 333cb93a386Sopenharmony_ci : (dstWeight - srcWeight + kWeightDiffThreshold); 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci // The first 2 bytes to save weight difference, the third byte to save slant difference, 336cb93a386Sopenharmony_ci // and the fourth byte to save width difference 337cb93a386Sopenharmony_ci uint32_t diff = (widthDiff << 24) + (slantDiff << 16) + weightDiff; 338cb93a386Sopenharmony_ci return diff; 339cb93a386Sopenharmony_ci} 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci/*! To get the data of font configuration file 342cb93a386Sopenharmony_ci * \param fname the full name of the font configuration file 343cb93a386Sopenharmony_ci * \param[out] size the size of data returned to the caller 344cb93a386Sopenharmony_ci * \return The pointer of content of the file 345cb93a386Sopenharmony_ci * \note The returned pointer should be freed by the caller 346cb93a386Sopenharmony_ci */ 347cb93a386Sopenharmony_cichar* FontConfig_OHOS::getFileData(const char* fname, int& size) 348cb93a386Sopenharmony_ci{ 349cb93a386Sopenharmony_ci FILE* fp = fopen(fname, "r"); 350cb93a386Sopenharmony_ci if (fp == nullptr) { 351cb93a386Sopenharmony_ci return nullptr; 352cb93a386Sopenharmony_ci } 353cb93a386Sopenharmony_ci fseek(fp, 0L, SEEK_END); 354cb93a386Sopenharmony_ci size = ftell(fp) + 1; 355cb93a386Sopenharmony_ci rewind(fp); 356cb93a386Sopenharmony_ci void* data = malloc(size); 357cb93a386Sopenharmony_ci if (data == nullptr) { 358cb93a386Sopenharmony_ci fclose(fp); 359cb93a386Sopenharmony_ci return nullptr; 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci memset_s(data, size, 0, size); 362cb93a386Sopenharmony_ci (void) fread(data, size, 1, fp); 363cb93a386Sopenharmony_ci fclose(fp); 364cb93a386Sopenharmony_ci return (char*)data; 365cb93a386Sopenharmony_ci} 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ci/*! parse the system font configuration document 368cb93a386Sopenharmony_ci * \param fname the full name of the font configuration document 369cb93a386Sopenharmony_ci * \return NO_ERROR successful 370cb93a386Sopenharmony_ci * \return ERROR_CONFIG_NOT_FOUND config document is not found 371cb93a386Sopenharmony_ci * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported 372cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE wrong type of value in the configuration 373cb93a386Sopenharmony_ci */ 374cb93a386Sopenharmony_ciint FontConfig_OHOS::parseConfig(const char* fname) 375cb93a386Sopenharmony_ci{ 376cb93a386Sopenharmony_ci if (fname == nullptr) { 377cb93a386Sopenharmony_ci fname = OHOS_DEFAULT_CONFIG; 378cb93a386Sopenharmony_ci } 379cb93a386Sopenharmony_ci Json::Value root; 380cb93a386Sopenharmony_ci int err = checkConfigFile(fname, root); 381cb93a386Sopenharmony_ci if (err != NO_ERROR) { 382cb93a386Sopenharmony_ci return err; 383cb93a386Sopenharmony_ci } 384cb93a386Sopenharmony_ci // "fontdir" - optional, the data type should be string 385cb93a386Sopenharmony_ci const char* key = "fontdir"; 386cb93a386Sopenharmony_ci if (root.isMember(key)) { 387cb93a386Sopenharmony_ci if (root[key].isArray()) { 388cb93a386Sopenharmony_ci parseFontDir(fname, root[key]); 389cb93a386Sopenharmony_ci } else { 390cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key); 391cb93a386Sopenharmony_ci } 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci // "generic", "fallback" - necessary, the data type should be array 394cb93a386Sopenharmony_ci const char* keys[] = {"generic", "fallback", nullptr}; 395cb93a386Sopenharmony_ci int index = 0; 396cb93a386Sopenharmony_ci while (true) { 397cb93a386Sopenharmony_ci if (keys[index] == nullptr) { 398cb93a386Sopenharmony_ci break; 399cb93a386Sopenharmony_ci } 400cb93a386Sopenharmony_ci key = keys[index++]; 401cb93a386Sopenharmony_ci if (!root.isMember(key)) { 402cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); 403cb93a386Sopenharmony_ci } else if (!root[key].isArray()) { 404cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci const Json::Value& arr = root[key]; 407cb93a386Sopenharmony_ci for (unsigned int i = 0; i < arr.size(); i++) { 408cb93a386Sopenharmony_ci if (arr[i].isObject()) { 409cb93a386Sopenharmony_ci if (!strcmp(key, "generic")) { 410cb93a386Sopenharmony_ci parseGeneric(arr[i]); 411cb93a386Sopenharmony_ci } else if (!strcmp(key, "fallback")) { 412cb93a386Sopenharmony_ci parseFallback(arr[i]); 413cb93a386Sopenharmony_ci } 414cb93a386Sopenharmony_ci } else { 415cb93a386Sopenharmony_ci SkString errKey; 416cb93a386Sopenharmony_ci errKey.appendf("%s#%d", key, i + 1); 417cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, errKey.c_str(), 418cb93a386Sopenharmony_ci Json::objectValue, arr[i].type()); 419cb93a386Sopenharmony_ci } 420cb93a386Sopenharmony_ci } 421cb93a386Sopenharmony_ci } 422cb93a386Sopenharmony_ci root.clear(); 423cb93a386Sopenharmony_ci return NO_ERROR; 424cb93a386Sopenharmony_ci} 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci/*! check the system font configuration document 427cb93a386Sopenharmony_ci * \param fname the full name of the font configuration document 428cb93a386Sopenharmony_ci * \return NO_ERROR successful 429cb93a386Sopenharmony_ci * \return ERROR_CONFIG_NOT_FOUND config document is not found 430cb93a386Sopenharmony_ci * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported 431cb93a386Sopenharmony_ci */ 432cb93a386Sopenharmony_ciint FontConfig_OHOS::checkConfigFile(const char* fname, Json::Value& root) 433cb93a386Sopenharmony_ci{ 434cb93a386Sopenharmony_ci int size = 0; 435cb93a386Sopenharmony_ci char* data = getFileData(fname, size); 436cb93a386Sopenharmony_ci if (data == nullptr) { 437cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_NOT_FOUND, fname); 438cb93a386Sopenharmony_ci } 439cb93a386Sopenharmony_ci JSONCPP_STRING errs; 440cb93a386Sopenharmony_ci Json::CharReaderBuilder charReaderBuilder; 441cb93a386Sopenharmony_ci std::unique_ptr<Json::CharReader> jsonReader(charReaderBuilder.newCharReader()); 442cb93a386Sopenharmony_ci bool isJson = jsonReader->parse(data, data + size, &root, &errs); 443cb93a386Sopenharmony_ci free((void*)data); 444cb93a386Sopenharmony_ci data = nullptr; 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci if (!isJson || !errs.empty()) { 447cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_FORMAT_NOT_SUPPORTED, fname); 448cb93a386Sopenharmony_ci } 449cb93a386Sopenharmony_ci return NO_ERROR; 450cb93a386Sopenharmony_ci} 451cb93a386Sopenharmony_ci#if ENABLE_DEBUG 452cb93a386Sopenharmony_ci/*! To print out the font information 453cb93a386Sopenharmony_ci * \param font the font object to be printed 454cb93a386Sopenharmony_ci */ 455cb93a386Sopenharmony_civoid FontConfig_OHOS::dumpFont(const FontInfo& font) const 456cb93a386Sopenharmony_ci{ 457cb93a386Sopenharmony_ci LOGI("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", 458cb93a386Sopenharmony_ci font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), 459cb93a386Sopenharmony_ci font.index); 460cb93a386Sopenharmony_ci int count = font.axisSet.axis.size(); 461cb93a386Sopenharmony_ci if (count > 0) { 462cb93a386Sopenharmony_ci SkString str; 463cb93a386Sopenharmony_ci for (unsigned int i = 0; i < count; i++) { 464cb93a386Sopenharmony_ci str.appendU32(SkFixedFloorToInt(font.axisSet.axis[i])); 465cb93a386Sopenharmony_ci if (i < count - 1) { 466cb93a386Sopenharmony_ci str.append(","); 467cb93a386Sopenharmony_ci } 468cb93a386Sopenharmony_ci } 469cb93a386Sopenharmony_ci LOGI("axis={%s}\n", str.c_str()); 470cb93a386Sopenharmony_ci } 471cb93a386Sopenharmony_ci} 472cb93a386Sopenharmony_ci 473cb93a386Sopenharmony_ci/*! To print out the information of generic font style set 474cb93a386Sopenharmony_ci */ 475cb93a386Sopenharmony_civoid FontConfig_OHOS::dumpGeneric() const 476cb93a386Sopenharmony_ci{ 477cb93a386Sopenharmony_ci LOGI("\n"); 478cb93a386Sopenharmony_ci for (unsigned int i = 0; i < genericFamilySet.size(); i++) { 479cb93a386Sopenharmony_ci LOGI("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), 480cb93a386Sopenharmony_ci static_cast<int>(genericFamilySet[i]->typefaceSet->size())); 481cb93a386Sopenharmony_ci for (int j = 0; j < genericFamilySet[i]->typefaceSet->size(); j++) { 482cb93a386Sopenharmony_ci if ((*(genericFamilySet[i]->typefaceSet))[j].get()) { 483cb93a386Sopenharmony_ci const FontInfo* font = (*(genericFamilySet[i]->typefaceSet))[j]->getFontInfo(); 484cb93a386Sopenharmony_ci if (font) { 485cb93a386Sopenharmony_ci dumpFont(*font); 486cb93a386Sopenharmony_ci } else { 487cb93a386Sopenharmony_ci LOGE("font [%d] is null\n", j); 488cb93a386Sopenharmony_ci } 489cb93a386Sopenharmony_ci } else { 490cb93a386Sopenharmony_ci LOGE("typefeace [%d] is null\n", j); 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci } 493cb93a386Sopenharmony_ci } 494cb93a386Sopenharmony_ci} 495cb93a386Sopenharmony_ci 496cb93a386Sopenharmony_ci/*! To print out the information of fallback font style set 497cb93a386Sopenharmony_ci */ 498cb93a386Sopenharmony_civoid FontConfig_OHOS::dumpFallback() const 499cb93a386Sopenharmony_ci{ 500cb93a386Sopenharmony_ci LOGI("\n"); 501cb93a386Sopenharmony_ci int count = 0; 502cb93a386Sopenharmony_ci fallbackForMap.foreach([this, &count](const SkString& key, 503cb93a386Sopenharmony_ci const FallbackSetPos& setIndex) { 504cb93a386Sopenharmony_ci LOGI("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); 505cb93a386Sopenharmony_ci for (unsigned int i = setIndex.index; i < setIndex.index + setIndex.count; i++) { 506cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); 507cb93a386Sopenharmony_ci LOGI("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast<int>(tpSet.size())); 508cb93a386Sopenharmony_ci 509cb93a386Sopenharmony_ci for (unsigned int j = 0; j < tpSet.size(); j++) { 510cb93a386Sopenharmony_ci const FontInfo* font = tpSet[j]->getFontInfo(); 511cb93a386Sopenharmony_ci if (font) { 512cb93a386Sopenharmony_ci this->dumpFont(*font); 513cb93a386Sopenharmony_ci } else { 514cb93a386Sopenharmony_ci LOGE("font [%d] is null\n", j); 515cb93a386Sopenharmony_ci } 516cb93a386Sopenharmony_ci } 517cb93a386Sopenharmony_ci } 518cb93a386Sopenharmony_ci }); 519cb93a386Sopenharmony_ci} 520cb93a386Sopenharmony_ci#endif 521cb93a386Sopenharmony_ci 522cb93a386Sopenharmony_ci/*! To parse 'fontdir' attribute 523cb93a386Sopenharmony_ci * \param root the root node of 'fontdir' 524cb93a386Sopenharmony_ci * \return NO_ERROR successful 525cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type 526cb93a386Sopenharmony_ci */ 527cb93a386Sopenharmony_ciint FontConfig_OHOS::parseFontDir(const char* fname, const Json::Value& root) 528cb93a386Sopenharmony_ci{ 529cb93a386Sopenharmony_ci for (unsigned int i = 0; i < root.size(); i++) { 530cb93a386Sopenharmony_ci if (root[i].isString()) { 531cb93a386Sopenharmony_ci const char* dir; 532cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) or defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_MAC) or \ 533cb93a386Sopenharmony_ci defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_LINUX) 534cb93a386Sopenharmony_ci if (strcmp(fname, OHOS_DEFAULT_CONFIG) == 0) { 535cb93a386Sopenharmony_ci dir = strcmp(root[i].asCString(), "/system/fonts/") ? root[i].asCString() : "fonts"; 536cb93a386Sopenharmony_ci } else { 537cb93a386Sopenharmony_ci dir = strcmp(root[i].asCString(), "/system/fonts/") ? 538cb93a386Sopenharmony_ci root[i].asCString() : "../../../../hms/previewer/resources/fonts"; 539cb93a386Sopenharmony_ci } 540cb93a386Sopenharmony_ci#else 541cb93a386Sopenharmony_ci dir = root[i].asCString(); 542cb93a386Sopenharmony_ci#endif 543cb93a386Sopenharmony_ci fontDirSet.emplace_back(SkString(dir)); 544cb93a386Sopenharmony_ci } else { 545cb93a386Sopenharmony_ci SkString text; 546cb93a386Sopenharmony_ci text.appendf("fontdir#%d", i + 1); 547cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::stringValue, root[i].type()); 548cb93a386Sopenharmony_ci } 549cb93a386Sopenharmony_ci } 550cb93a386Sopenharmony_ci return NO_ERROR; 551cb93a386Sopenharmony_ci} 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci/*! To parse an item of 'generic' family 554cb93a386Sopenharmony_ci * \param root the root node of an item in 'generic' list 555cb93a386Sopenharmony_ci * \return NO_ERROR successful 556cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 557cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of 'family' or 'alias' 558cb93a386Sopenharmony_ci */ 559cb93a386Sopenharmony_ciint FontConfig_OHOS::parseGeneric(const Json::Value& root) 560cb93a386Sopenharmony_ci{ 561cb93a386Sopenharmony_ci // "family" - necessary, the data type should be String 562cb93a386Sopenharmony_ci const char* key = "family"; 563cb93a386Sopenharmony_ci if (!root.isMember(key)) { 564cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); 565cb93a386Sopenharmony_ci } else if (!root[key].isString()) { 566cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::stringValue, root[key].type()); 567cb93a386Sopenharmony_ci } 568cb93a386Sopenharmony_ci SkString familyName = SkString(root[key].asCString()); 569cb93a386Sopenharmony_ci // "alias" - necessary, the data type should be Array 570cb93a386Sopenharmony_ci if (!root.isMember("alias")) { 571cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, "alias"); 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci // "adjust", "variation" - optional 574cb93a386Sopenharmony_ci const char* tags[] = {"alias", "adjust", "variations", "index"}; 575cb93a386Sopenharmony_ci std::vector<AliasInfo> aliasSet; 576cb93a386Sopenharmony_ci std::vector<AdjustInfo> adjustSet; 577cb93a386Sopenharmony_ci std::vector<VariationInfo> variationSet; 578cb93a386Sopenharmony_ci for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { 579cb93a386Sopenharmony_ci key = tags[i]; 580cb93a386Sopenharmony_ci if (!root.isMember(key)) { 581cb93a386Sopenharmony_ci continue; 582cb93a386Sopenharmony_ci } 583cb93a386Sopenharmony_ci if (root[key].isArray()) { 584cb93a386Sopenharmony_ci if (!strcmp(key, "index")) { 585cb93a386Sopenharmony_ci parseTtcIndex(root[key], familyName); 586cb93a386Sopenharmony_ci continue; 587cb93a386Sopenharmony_ci } 588cb93a386Sopenharmony_ci const Json::Value& arr = root[key]; 589cb93a386Sopenharmony_ci for (unsigned int j = 0; j < arr.size(); j++) { 590cb93a386Sopenharmony_ci if (arr[j].isObject()) { 591cb93a386Sopenharmony_ci if (!strcmp(key, "alias")) { 592cb93a386Sopenharmony_ci parseAlias(arr[j], aliasSet); 593cb93a386Sopenharmony_ci } else if (!strcmp(key, "adjust")) { 594cb93a386Sopenharmony_ci parseAdjust(arr[j], adjustSet); 595cb93a386Sopenharmony_ci } else { 596cb93a386Sopenharmony_ci parseVariation(arr[j], variationSet); 597cb93a386Sopenharmony_ci } 598cb93a386Sopenharmony_ci } else { 599cb93a386Sopenharmony_ci SkString text; 600cb93a386Sopenharmony_ci text.appendf("%s#%d", key, j + 1); 601cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::objectValue, 602cb93a386Sopenharmony_ci arr[j].type()); 603cb93a386Sopenharmony_ci } 604cb93a386Sopenharmony_ci } 605cb93a386Sopenharmony_ci } else { 606cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); 607cb93a386Sopenharmony_ci } 608cb93a386Sopenharmony_ci if (root.size() == 2) { 609cb93a386Sopenharmony_ci break; 610cb93a386Sopenharmony_ci } 611cb93a386Sopenharmony_ci } 612cb93a386Sopenharmony_ci if (aliasSet.size()) { 613cb93a386Sopenharmony_ci aliasMap.set(SkString(familyName), aliasSet); 614cb93a386Sopenharmony_ci } 615cb93a386Sopenharmony_ci if (adjustSet.size()) { 616cb93a386Sopenharmony_ci adjustMap.set(SkString(familyName), adjustSet); 617cb93a386Sopenharmony_ci } 618cb93a386Sopenharmony_ci if (variationSet.size()) { 619cb93a386Sopenharmony_ci variationMap.set(SkString(familyName), variationSet); 620cb93a386Sopenharmony_ci } 621cb93a386Sopenharmony_ci return NO_ERROR; 622cb93a386Sopenharmony_ci} 623cb93a386Sopenharmony_ci 624cb93a386Sopenharmony_ci/*! To parse an item of 'alias' attribute 625cb93a386Sopenharmony_ci * \param root the root node of an item in an 'alias' list 626cb93a386Sopenharmony_ci * \param[out] aliasSet the value of AliasInfo will be written to and returned to the caller 627cb93a386Sopenharmony_ci * \return NO_ERROR successful 628cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 629cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of alias name 630cb93a386Sopenharmony_ci */ 631cb93a386Sopenharmony_ciint FontConfig_OHOS::parseAlias(const Json::Value& root, std::vector<AliasInfo>& aliasSet) 632cb93a386Sopenharmony_ci{ 633cb93a386Sopenharmony_ci if (root.empty()) { 634cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, "generic-alias-name"); 635cb93a386Sopenharmony_ci } 636cb93a386Sopenharmony_ci Json::Value::Members members = root.getMemberNames(); 637cb93a386Sopenharmony_ci const char* key = members[0].c_str(); 638cb93a386Sopenharmony_ci if (!root[key].isInt()) { 639cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "generic-alias-weight", 640cb93a386Sopenharmony_ci Json::intValue, root[key].type()); 641cb93a386Sopenharmony_ci } 642cb93a386Sopenharmony_ci 643cb93a386Sopenharmony_ci SkString aliasName = SkString(key); 644cb93a386Sopenharmony_ci int weight = root[key].asInt(); 645cb93a386Sopenharmony_ci std::unique_ptr<GenericFamily> genericFamily = std::make_unique<GenericFamily>(); 646cb93a386Sopenharmony_ci genericFamily->familyName = SkString(key); 647cb93a386Sopenharmony_ci if (aliasSet.size() == 0 || weight > 0) { 648cb93a386Sopenharmony_ci genericFamily->typefaceSet = std::make_shared<TypefaceSet>(); 649cb93a386Sopenharmony_ci } else { 650cb93a386Sopenharmony_ci int index = aliasSet[0].pos; 651cb93a386Sopenharmony_ci genericFamily->typefaceSet = genericFamilySet[index]->typefaceSet; 652cb93a386Sopenharmony_ci } 653cb93a386Sopenharmony_ci genericNames.set(SkString(genericFamily->familyName), genericFamilySet.size()); 654cb93a386Sopenharmony_ci 655cb93a386Sopenharmony_ci AliasInfo info = {static_cast<int>(genericFamilySet.size()), weight}; 656cb93a386Sopenharmony_ci aliasSet.emplace_back(std::move(info)); 657cb93a386Sopenharmony_ci genericFamilySet.emplace_back(std::move(genericFamily)); 658cb93a386Sopenharmony_ci return NO_ERROR; 659cb93a386Sopenharmony_ci} 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_ci/*! To parse an item of 'adjust' attribute 662cb93a386Sopenharmony_ci * \param root the root node of an item in an 'adjust' list 663cb93a386Sopenharmony_ci * \param[out] adjustSet the value of AdjustInfo will be written to and returned to the caller 664cb93a386Sopenharmony_ci * \return NO_ERROR successful 665cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 666cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of 'weight' or 'to' 667cb93a386Sopenharmony_ci */ 668cb93a386Sopenharmony_ciint FontConfig_OHOS::parseAdjust(const Json::Value& root, std::vector<AdjustInfo>& adjustSet) 669cb93a386Sopenharmony_ci{ 670cb93a386Sopenharmony_ci const char* tags[] = {"weight", "to"}; 671cb93a386Sopenharmony_ci int values[2]; // value[0] - to save 'weight', value[1] - to save 'to' 672cb93a386Sopenharmony_ci for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { 673cb93a386Sopenharmony_ci const char* key = tags[i]; 674cb93a386Sopenharmony_ci if (!root.isMember(key)) { 675cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); 676cb93a386Sopenharmony_ci } else if (!root[key].isInt()) { 677cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, 678cb93a386Sopenharmony_ci Json::intValue, root[key].type()); 679cb93a386Sopenharmony_ci } else { 680cb93a386Sopenharmony_ci values[i] = root[key].asInt(); 681cb93a386Sopenharmony_ci } 682cb93a386Sopenharmony_ci } 683cb93a386Sopenharmony_ci AdjustInfo info = {values[0], values[1]}; 684cb93a386Sopenharmony_ci adjustSet.push_back(info); 685cb93a386Sopenharmony_ci return NO_ERROR; 686cb93a386Sopenharmony_ci} 687cb93a386Sopenharmony_ci 688cb93a386Sopenharmony_ci/*! To parse an item of 'fallback' attribute 689cb93a386Sopenharmony_ci * \param root the root node of an item in 'fallback' list 690cb93a386Sopenharmony_ci * \return NO_ERROR successful 691cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 692cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of fallbackFor 693cb93a386Sopenharmony_ci */ 694cb93a386Sopenharmony_ciint FontConfig_OHOS::parseFallback(const Json::Value& root) 695cb93a386Sopenharmony_ci{ 696cb93a386Sopenharmony_ci if (root.empty()) { 697cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-fallbackFor"); 698cb93a386Sopenharmony_ci } 699cb93a386Sopenharmony_ci Json::Value::Members members = root.getMemberNames(); 700cb93a386Sopenharmony_ci const char* key = members[0].c_str(); 701cb93a386Sopenharmony_ci if (!root[key].isArray()) { 702cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "fallback-items", 703cb93a386Sopenharmony_ci Json::arrayValue, root[key].type()); 704cb93a386Sopenharmony_ci } 705cb93a386Sopenharmony_ci unsigned int startPos = fallbackSet.size(); 706cb93a386Sopenharmony_ci SkString fallbackFor = SkString(key); 707cb93a386Sopenharmony_ci const Json::Value& fallbackArr = root[key]; 708cb93a386Sopenharmony_ci for (unsigned int i = 0; i < fallbackArr.size(); i++) { 709cb93a386Sopenharmony_ci if (!fallbackArr[i].isObject()) { 710cb93a386Sopenharmony_ci SkString text; 711cb93a386Sopenharmony_ci text.appendf("fallback-%s#%d", key, i + 1); 712cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::objectValue, 713cb93a386Sopenharmony_ci fallbackArr[i].type()); 714cb93a386Sopenharmony_ci continue; 715cb93a386Sopenharmony_ci } 716cb93a386Sopenharmony_ci parseFallbackItem(fallbackArr[i]); 717cb93a386Sopenharmony_ci } 718cb93a386Sopenharmony_ci FallbackSetPos setPos = {startPos, (unsigned int)(fallbackSet.size() - startPos)}; 719cb93a386Sopenharmony_ci fallbackForMap.set(fallbackFor, setPos); 720cb93a386Sopenharmony_ci return NO_ERROR; 721cb93a386Sopenharmony_ci} 722cb93a386Sopenharmony_ci 723cb93a386Sopenharmony_ci/*! To parse an item of fallback family 724cb93a386Sopenharmony_ci * \param root the root node of a fallback item 725cb93a386Sopenharmony_ci * \return NO_ERROR successful 726cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 727cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of language 728cb93a386Sopenharmony_ci */ 729cb93a386Sopenharmony_ciint FontConfig_OHOS::parseFallbackItem(const Json::Value& root) 730cb93a386Sopenharmony_ci{ 731cb93a386Sopenharmony_ci if (root.empty()) { 732cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-item-lang"); 733cb93a386Sopenharmony_ci } 734cb93a386Sopenharmony_ci Json::Value::Members members = root.getMemberNames(); 735cb93a386Sopenharmony_ci const char* key = nullptr; 736cb93a386Sopenharmony_ci bool hasIndex = false; 737cb93a386Sopenharmony_ci bool hasVariations = false; 738cb93a386Sopenharmony_ci for (unsigned int i = 0; i < members.size(); i++) { 739cb93a386Sopenharmony_ci if (members[i] == "variations") { 740cb93a386Sopenharmony_ci hasVariations = true; 741cb93a386Sopenharmony_ci } else if (members[i] == "index") { 742cb93a386Sopenharmony_ci hasIndex = true; 743cb93a386Sopenharmony_ci } else { 744cb93a386Sopenharmony_ci key = members[i].c_str(); 745cb93a386Sopenharmony_ci } 746cb93a386Sopenharmony_ci } 747cb93a386Sopenharmony_ci if (key == nullptr) { 748cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-item-lang"); 749cb93a386Sopenharmony_ci } 750cb93a386Sopenharmony_ci if (!root[key].isString()) { 751cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "fallback-item-family", 752cb93a386Sopenharmony_ci Json::stringValue, root[key].type()); 753cb93a386Sopenharmony_ci } 754cb93a386Sopenharmony_ci SkString lang = SkString(key); 755cb93a386Sopenharmony_ci SkString familyName = SkString(root[key].asCString()); 756cb93a386Sopenharmony_ci if (hasVariations) { 757cb93a386Sopenharmony_ci key = "variations"; 758cb93a386Sopenharmony_ci if (root[key].isArray()) { 759cb93a386Sopenharmony_ci const Json::Value& varArr = root[key]; 760cb93a386Sopenharmony_ci std::vector<VariationInfo> variationSet; 761cb93a386Sopenharmony_ci for (unsigned int i = 0; i < varArr.size(); i++) { 762cb93a386Sopenharmony_ci if (varArr[i].isObject()) { 763cb93a386Sopenharmony_ci parseVariation(varArr[i], variationSet); 764cb93a386Sopenharmony_ci } else { 765cb93a386Sopenharmony_ci SkString text = SkString("variations#"); 766cb93a386Sopenharmony_ci text.appendU32(i + 1); 767cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), 768cb93a386Sopenharmony_ci Json::objectValue, varArr[i].type()); 769cb93a386Sopenharmony_ci } 770cb93a386Sopenharmony_ci } 771cb93a386Sopenharmony_ci if (variationSet.size()) { 772cb93a386Sopenharmony_ci variationMap.set(SkString(familyName), variationSet); 773cb93a386Sopenharmony_ci } 774cb93a386Sopenharmony_ci } else { 775cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, 776cb93a386Sopenharmony_ci root[key].type()); 777cb93a386Sopenharmony_ci } 778cb93a386Sopenharmony_ci } 779cb93a386Sopenharmony_ci if (hasIndex) { 780cb93a386Sopenharmony_ci key = "index"; 781cb93a386Sopenharmony_ci if (root[key].isArray()) { 782cb93a386Sopenharmony_ci parseTtcIndex(root[key], familyName); 783cb93a386Sopenharmony_ci } else { 784cb93a386Sopenharmony_ci (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); 785cb93a386Sopenharmony_ci } 786cb93a386Sopenharmony_ci } 787cb93a386Sopenharmony_ci std::unique_ptr<FallbackInfo> fallback = std::make_unique<FallbackInfo>(); 788cb93a386Sopenharmony_ci fallback->familyName = familyName; 789cb93a386Sopenharmony_ci fallback->langs = lang; 790cb93a386Sopenharmony_ci fallback->typefaceSet = std::make_shared<TypefaceSet>(); 791cb93a386Sopenharmony_ci fallbackNames.set(SkString(familyName), fallbackSet.size()); 792cb93a386Sopenharmony_ci fallbackSet.emplace_back(std::move(fallback)); 793cb93a386Sopenharmony_ci return NO_ERROR; 794cb93a386Sopenharmony_ci} 795cb93a386Sopenharmony_ci 796cb93a386Sopenharmony_ci/*! To parse an item of 'variations' attribute 797cb93a386Sopenharmony_ci * \param root the root node of an item in 'variations' list 798cb93a386Sopenharmony_ci * \param[out] variationSet the value of VariationInfo is written to and returned to the caller 799cb93a386Sopenharmony_ci * \return NO_ERROR successful 800cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 801cb93a386Sopenharmony_ci * \return ERROR_CONFIG_MISSING_TAG missing tag of 'weight' or 'wght' 802cb93a386Sopenharmony_ci */ 803cb93a386Sopenharmony_ciint FontConfig_OHOS::parseVariation(const Json::Value& root, std::vector<VariationInfo>& variationSet) 804cb93a386Sopenharmony_ci{ 805cb93a386Sopenharmony_ci const char* key = nullptr; 806cb93a386Sopenharmony_ci const char* tags[] = {"wght", "wdth", "slnt", "weight", "width", "slant"}; 807cb93a386Sopenharmony_ci VariationInfo info; 808cb93a386Sopenharmony_ci for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { 809cb93a386Sopenharmony_ci key = tags[i]; 810cb93a386Sopenharmony_ci if ((!strcmp(key, "wght") || !strcmp(key, "weight")) && 811cb93a386Sopenharmony_ci !root.isMember(key)) { 812cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); 813cb93a386Sopenharmony_ci } 814cb93a386Sopenharmony_ci if (!root.isMember(key)) { 815cb93a386Sopenharmony_ci continue; 816cb93a386Sopenharmony_ci } 817cb93a386Sopenharmony_ci if (!strcmp(key, "weight")) { 818cb93a386Sopenharmony_ci if (!root[key].isInt()) { 819cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::intValue, root[key].type()); 820cb93a386Sopenharmony_ci } 821cb93a386Sopenharmony_ci info.weight = root[key].asInt(); 822cb93a386Sopenharmony_ci } else if (!strcmp(key, "width")) { 823cb93a386Sopenharmony_ci if (!root[key].isInt()) { 824cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::intValue, root[key].type()); 825cb93a386Sopenharmony_ci } 826cb93a386Sopenharmony_ci info.width = root[key].asInt(); 827cb93a386Sopenharmony_ci } else if (!strcmp(key, "slant")) { 828cb93a386Sopenharmony_ci if (!root[key].isString()) { 829cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::stringValue, root[key].type()); 830cb93a386Sopenharmony_ci } 831cb93a386Sopenharmony_ci const char* str = root[key].asCString(); 832cb93a386Sopenharmony_ci if (!strcmp(str, "normal")) { 833cb93a386Sopenharmony_ci info.slant = static_cast<int>(SkFontStyle::kUpright_Slant); 834cb93a386Sopenharmony_ci } else if (!strcmp(str, "italic")) { 835cb93a386Sopenharmony_ci info.slant = static_cast<int>(SkFontStyle::kItalic_Slant); 836cb93a386Sopenharmony_ci } else if (!strcmp(str, "oblique")) { 837cb93a386Sopenharmony_ci info.slant = static_cast<int>(SkFontStyle::kOblique_Slant); 838cb93a386Sopenharmony_ci } 839cb93a386Sopenharmony_ci } else { 840cb93a386Sopenharmony_ci if (!root[key].isNumeric()) { 841cb93a386Sopenharmony_ci return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::realValue, root[key].type()); 842cb93a386Sopenharmony_ci } 843cb93a386Sopenharmony_ci Coordinate axis; 844cb93a386Sopenharmony_ci axis.axis = SkSetFourByteTag(key[0], key[1], key[2], key[3]); 845cb93a386Sopenharmony_ci axis.value = root[key].asFloat(); 846cb93a386Sopenharmony_ci info.axis.emplace_back(axis); 847cb93a386Sopenharmony_ci } 848cb93a386Sopenharmony_ci } 849cb93a386Sopenharmony_ci variationSet.emplace_back(info); 850cb93a386Sopenharmony_ci return NO_ERROR; 851cb93a386Sopenharmony_ci} 852cb93a386Sopenharmony_ci 853cb93a386Sopenharmony_ci/*! To parse 'index' attribute 854cb93a386Sopenharmony_ci * \param root the root node of 'index' attribute 855cb93a386Sopenharmony_ci * \param familyName the name of the family which the root node belongs to 856cb93a386Sopenharmony_ci * \return NO_ERROR successful 857cb93a386Sopenharmony_ci * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute 858cb93a386Sopenharmony_ci */ 859cb93a386Sopenharmony_ciint FontConfig_OHOS::parseTtcIndex(const Json::Value& root, const SkString& familyName) 860cb93a386Sopenharmony_ci{ 861cb93a386Sopenharmony_ci unsigned int keyCount = 2; // the value of 'index' is an array with 2 items. 862cb93a386Sopenharmony_ci if (root.size() == keyCount && root[0].isString() && root[1].isNumeric()) { 863cb93a386Sopenharmony_ci TtcIndexInfo item = { SkString(root[0].asCString()), root[1].asInt() }; 864cb93a386Sopenharmony_ci if (item.ttcIndex != 0 && ttcIndexMap.find(item.familyName) == nullptr) { 865cb93a386Sopenharmony_ci ttcIndexMap.set(SkString(item.familyName), {SkString(item.familyName), 0}); 866cb93a386Sopenharmony_ci } 867cb93a386Sopenharmony_ci ttcIndexMap.set(SkString(familyName), item); 868cb93a386Sopenharmony_ci } else { 869cb93a386Sopenharmony_ci int ret = ERROR_CONFIG_INVALID_VALUE_TYPE; 870cb93a386Sopenharmony_ci SkString text; 871cb93a386Sopenharmony_ci const char* key = "index"; 872cb93a386Sopenharmony_ci if (root.size() != keyCount) { 873cb93a386Sopenharmony_ci text.appendf("%s#0", key); 874cb93a386Sopenharmony_ci errSet.emplace_back(ret, text.c_str()); 875cb93a386Sopenharmony_ci LOGE("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); 876cb93a386Sopenharmony_ci return ret; 877cb93a386Sopenharmony_ci } else if (!root[0].isString()) { 878cb93a386Sopenharmony_ci text.appendf("%s#1", key); 879cb93a386Sopenharmony_ci return logErrInfo(ret, text.c_str(), Json::stringValue, root[0].type()); 880cb93a386Sopenharmony_ci } else { 881cb93a386Sopenharmony_ci text.appendf("%s#2", key); 882cb93a386Sopenharmony_ci return logErrInfo(ret, text.c_str(), Json::intValue, root[1].type()); 883cb93a386Sopenharmony_ci } 884cb93a386Sopenharmony_ci } 885cb93a386Sopenharmony_ci return NO_ERROR; 886cb93a386Sopenharmony_ci} 887cb93a386Sopenharmony_ci 888cb93a386Sopenharmony_ci/*! To get the axis value and set to 'font' 889cb93a386Sopenharmony_ci * \param axisDefs the axis ranges of a font 890cb93a386Sopenharmony_ci * \param variation the variation data from which axis values are generated 891cb93a386Sopenharmony_ci * \param[out] font the axis values will be written to and returned to the caller 892cb93a386Sopenharmony_ci */ 893cb93a386Sopenharmony_civoid FontConfig_OHOS::getAxisValues(const AxisDefinitions& axisDefs, 894cb93a386Sopenharmony_ci const VariationInfo& variation, FontInfo& font) const 895cb93a386Sopenharmony_ci{ 896cb93a386Sopenharmony_ci SkFontArguments::VariationPosition position; 897cb93a386Sopenharmony_ci position.coordinateCount = variation.axis.size(); 898cb93a386Sopenharmony_ci position.coordinates = variation.axis.data(); 899cb93a386Sopenharmony_ci 900cb93a386Sopenharmony_ci int count = axisDefs.count(); 901cb93a386Sopenharmony_ci if (count <= 0) { 902cb93a386Sopenharmony_ci LOGE("Invalid axis count:%{public}d", count); 903cb93a386Sopenharmony_ci return; 904cb93a386Sopenharmony_ci } 905cb93a386Sopenharmony_ci SkFixed axisValues[count]; 906cb93a386Sopenharmony_ci SkTypeface_FreeType::Scanner::computeAxisValues(axisDefs, position, 907cb93a386Sopenharmony_ci axisValues, font.familyName); 908cb93a386Sopenharmony_ci font.axisSet.axis.clear(); 909cb93a386Sopenharmony_ci font.axisSet.range.clear(); 910cb93a386Sopenharmony_ci for (int i = 0; i < count; i++) { 911cb93a386Sopenharmony_ci font.axisSet.axis.emplace_back(axisValues[i]); 912cb93a386Sopenharmony_ci font.axisSet.range.emplace_back(axisDefs[i]); 913cb93a386Sopenharmony_ci } 914cb93a386Sopenharmony_ci} 915cb93a386Sopenharmony_ci 916cb93a386Sopenharmony_ci/*! To insert a ttc font into a font style set 917cb93a386Sopenharmony_ci * \param count the count of typeface in a ttc font 918cb93a386Sopenharmony_ci * \param font an object of the FontInfo with font information 919cb93a386Sopenharmony_ci * \return true, if the font is a ttc font and added to corresponding font style set 920cb93a386Sopenharmony_ci * \return false, if the font is not a ttc font 921cb93a386Sopenharmony_ci */ 922cb93a386Sopenharmony_cibool FontConfig_OHOS::insertTtcFont(int count, FontInfo& font) 923cb93a386Sopenharmony_ci{ 924cb93a386Sopenharmony_ci bool ret = false; 925cb93a386Sopenharmony_ci ttcIndexMap.foreach([this, count, &font, &ret] 926cb93a386Sopenharmony_ci (const SkString& familyName, TtcIndexInfo* info) { 927cb93a386Sopenharmony_ci if (info->familyName == font.familyName && info->ttcIndex < count) { 928cb93a386Sopenharmony_ci SkString specifiedName; 929cb93a386Sopenharmony_ci TypefaceSet* tpSet = this->getTypefaceSet(familyName, specifiedName); 930cb93a386Sopenharmony_ci if (tpSet) { 931cb93a386Sopenharmony_ci FontInfo newFont(font); 932cb93a386Sopenharmony_ci newFont.familyName = familyName; 933cb93a386Sopenharmony_ci newFont.index = info->ttcIndex; 934cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> typeface = sk_make_sp<SkTypeface_OHOS>(specifiedName, newFont); 935cb93a386Sopenharmony_ci tpSet->push_back(std::move(typeface)); 936cb93a386Sopenharmony_ci ret = true; 937cb93a386Sopenharmony_ci } 938cb93a386Sopenharmony_ci } 939cb93a386Sopenharmony_ci }); 940cb93a386Sopenharmony_ci return ret; 941cb93a386Sopenharmony_ci} 942cb93a386Sopenharmony_ci 943cb93a386Sopenharmony_ci/*! To insert a variable font into a font style set 944cb93a386Sopenharmony_ci * \param axisDefs the axis ranges of a variable font 945cb93a386Sopenharmony_ci * \param font an object of the FontInfo with font information 946cb93a386Sopenharmony_ci * \return true, if the font is a variable and some typefaces are added to the corresponding font style set 947cb93a386Sopenharmony_ci * \return false, if the font is not variable 948cb93a386Sopenharmony_ci */ 949cb93a386Sopenharmony_cibool FontConfig_OHOS::insertVariableFont(const AxisDefinitions& axisDefs, FontInfo& font) 950cb93a386Sopenharmony_ci{ 951cb93a386Sopenharmony_ci const SkString& key = font.familyName; 952cb93a386Sopenharmony_ci if (variationMap.find(key) == nullptr || axisDefs.count() == 0) { 953cb93a386Sopenharmony_ci return false; 954cb93a386Sopenharmony_ci } 955cb93a386Sopenharmony_ci SkString specifiedName; 956cb93a386Sopenharmony_ci TypefaceSet* tpSet = getTypefaceSet(key, specifiedName); 957cb93a386Sopenharmony_ci if (tpSet == nullptr) { 958cb93a386Sopenharmony_ci return false; 959cb93a386Sopenharmony_ci } 960cb93a386Sopenharmony_ci const std::vector<VariationInfo>& variationSet = *(variationMap.find(key)); 961cb93a386Sopenharmony_ci for (unsigned int i = 0; i < variationSet.size(); i++) { 962cb93a386Sopenharmony_ci FontInfo newFont(font); 963cb93a386Sopenharmony_ci getAxisValues(axisDefs, variationSet[i], newFont); 964cb93a386Sopenharmony_ci int width = font.style.width(); 965cb93a386Sopenharmony_ci SkFontStyle::Slant slant = font.style.slant(); 966cb93a386Sopenharmony_ci if (variationSet[i].width != -1) { 967cb93a386Sopenharmony_ci width = variationSet[i].width; 968cb93a386Sopenharmony_ci } 969cb93a386Sopenharmony_ci if (variationSet[i].slant != -1) { 970cb93a386Sopenharmony_ci slant = (SkFontStyle::Slant) variationSet[i].slant; 971cb93a386Sopenharmony_ci } 972cb93a386Sopenharmony_ci newFont.style = SkFontStyle(variationSet[i].weight, width, slant); 973cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> typeface = sk_make_sp<SkTypeface_OHOS>(specifiedName, newFont); 974cb93a386Sopenharmony_ci tpSet->push_back(std::move(typeface)); 975cb93a386Sopenharmony_ci } 976cb93a386Sopenharmony_ci return true; 977cb93a386Sopenharmony_ci} 978cb93a386Sopenharmony_ci 979cb93a386Sopenharmony_ci/*! To get the typeface set of a font style set 980cb93a386Sopenharmony_ci * \param familyName the family name of a font style set 981cb93a386Sopenharmony_ci * \param[out] specifiedName the specified family name of a font style set returned to the caller 982cb93a386Sopenharmony_ci * \return The object of typeface set 983cb93a386Sopenharmony_ci * \n Return null, if the family name is not found in the system 984cb93a386Sopenharmony_ci */ 985cb93a386Sopenharmony_ciTypefaceSet* FontConfig_OHOS::getTypefaceSet(const SkString& familyName, 986cb93a386Sopenharmony_ci SkString& specifiedName) const 987cb93a386Sopenharmony_ci{ 988cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(fontMutex); 989cb93a386Sopenharmony_ci if (aliasMap.find(familyName) != nullptr) { 990cb93a386Sopenharmony_ci const std::vector<AliasInfo>& aliasSet = *(aliasMap.find(familyName)); 991cb93a386Sopenharmony_ci if (aliasSet.size()) { 992cb93a386Sopenharmony_ci int index = aliasSet[0].pos; 993cb93a386Sopenharmony_ci specifiedName = genericFamilySet[index]->familyName; 994cb93a386Sopenharmony_ci return genericFamilySet[index]->typefaceSet.get(); 995cb93a386Sopenharmony_ci } 996cb93a386Sopenharmony_ci } else if (fallbackNames.find(familyName) != nullptr) { 997cb93a386Sopenharmony_ci int index = *(fallbackNames.find(familyName)); 998cb93a386Sopenharmony_ci return fallbackSet[index]->typefaceSet.get(); 999cb93a386Sopenharmony_ci } 1000cb93a386Sopenharmony_ci return nullptr; 1001cb93a386Sopenharmony_ci} 1002cb93a386Sopenharmony_ci 1003cb93a386Sopenharmony_ci/*! To load font information from a font file 1004cb93a386Sopenharmony_ci * \param scanner a scanner used to parse the font file 1005cb93a386Sopenharmony_ci * \param fname the full name of a font file 1006cb93a386Sopenharmony_ci * \return NO_ERROR successful 1007cb93a386Sopenharmony_ci * \return ERROR_FONT_NOT_EXIST font file is not exist 1008cb93a386Sopenharmony_ci * \return ERROR_FONT_INVALID_STREAM the stream is not recognized 1009cb93a386Sopenharmony_ci */ 1010cb93a386Sopenharmony_ciint FontConfig_OHOS::loadFont(const SkTypeface_FreeType::Scanner& scanner, const char* fname) 1011cb93a386Sopenharmony_ci{ 1012cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fname); 1013cb93a386Sopenharmony_ci int count = 1; 1014cb93a386Sopenharmony_ci SkTypeface_FreeType::Scanner::AxisDefinitions axisDefs; 1015cb93a386Sopenharmony_ci FontInfo font(fname, 0); 1016cb93a386Sopenharmony_ci if (stream == nullptr || 1017cb93a386Sopenharmony_ci scanner.recognizedFont(stream.get(), &count) == false || 1018cb93a386Sopenharmony_ci scanner.scanFont(stream.get(), 0, &font.familyName, &font.style, 1019cb93a386Sopenharmony_ci &font.isFixedWidth, &axisDefs) == false) { 1020cb93a386Sopenharmony_ci int err = NO_ERROR; 1021cb93a386Sopenharmony_ci if (stream == nullptr) { 1022cb93a386Sopenharmony_ci err = ERROR_FONT_NOT_EXIST; 1023cb93a386Sopenharmony_ci } else { 1024cb93a386Sopenharmony_ci err = ERROR_FONT_INVALID_STREAM; 1025cb93a386Sopenharmony_ci } 1026cb93a386Sopenharmony_ci LOGE("%s : %s\n", errToString(err), fname); 1027cb93a386Sopenharmony_ci char* fnameCopy = strdup(fname); 1028cb93a386Sopenharmony_ci errSet.emplace_back(err, basename(fnameCopy)); 1029cb93a386Sopenharmony_ci free(fnameCopy); 1030cb93a386Sopenharmony_ci return err; 1031cb93a386Sopenharmony_ci } 1032cb93a386Sopenharmony_ci // for adjustMap - update weight 1033cb93a386Sopenharmony_ci if (adjustMap.find(font.familyName) != nullptr) { 1034cb93a386Sopenharmony_ci const std::vector<AdjustInfo> adjustSet = *(adjustMap.find(font.familyName)); 1035cb93a386Sopenharmony_ci for (unsigned int i = 0; i < adjustSet.size(); i++) { 1036cb93a386Sopenharmony_ci if (font.style.weight() == adjustSet[i].origValue) { 1037cb93a386Sopenharmony_ci font.style = SkFontStyle(adjustSet[i].newValue, font.style.width(), font.style.slant()); 1038cb93a386Sopenharmony_ci break; 1039cb93a386Sopenharmony_ci } 1040cb93a386Sopenharmony_ci } 1041cb93a386Sopenharmony_ci } 1042cb93a386Sopenharmony_ci bool ret = false; 1043cb93a386Sopenharmony_ci if (count > 1) { 1044cb93a386Sopenharmony_ci ret = insertTtcFont(count, font); 1045cb93a386Sopenharmony_ci } else if (axisDefs.count() > 0) { 1046cb93a386Sopenharmony_ci ret = insertVariableFont(axisDefs, font); 1047cb93a386Sopenharmony_ci } 1048cb93a386Sopenharmony_ci if (!ret) { 1049cb93a386Sopenharmony_ci SkString specifiedName; 1050cb93a386Sopenharmony_ci TypefaceSet* tpSet = getTypefaceSet(font.familyName, specifiedName); 1051cb93a386Sopenharmony_ci if (tpSet) { 1052cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> typeface = sk_make_sp<SkTypeface_OHOS>(specifiedName, font); 1053cb93a386Sopenharmony_ci tpSet->push_back(std::move(typeface)); 1054cb93a386Sopenharmony_ci } 1055cb93a386Sopenharmony_ci } 1056cb93a386Sopenharmony_ci return NO_ERROR; 1057cb93a386Sopenharmony_ci} 1058cb93a386Sopenharmony_ci 1059cb93a386Sopenharmony_ci/*! To scan the system font directories 1060cb93a386Sopenharmony_ci * \param fontScanner the scanner used to parse a font file 1061cb93a386Sopenharmony_ci * \return NO_ERROR success 1062cb93a386Sopenharmony_ci * \return ERROR_DIR_NOT_FOUND a font directory is not exist 1063cb93a386Sopenharmony_ci */ 1064cb93a386Sopenharmony_ciint FontConfig_OHOS::scanFonts(const SkTypeface_FreeType::Scanner& fontScanner) 1065cb93a386Sopenharmony_ci{ 1066cb93a386Sopenharmony_ci int err = NO_ERROR; 1067cb93a386Sopenharmony_ci if (fontDirSet.size() == 0) { 1068cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) or defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_MAC) or \ 1069cb93a386Sopenharmony_ci defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_LINUX) 1070cb93a386Sopenharmony_ci fontDirSet.emplace_back(SkString("fonts")); 1071cb93a386Sopenharmony_ci#else 1072cb93a386Sopenharmony_ci fontDirSet.emplace_back(SkString("/system/fonts/")); 1073cb93a386Sopenharmony_ci#endif 1074cb93a386Sopenharmony_ci } 1075cb93a386Sopenharmony_ci for (unsigned int i = 0; i < fontDirSet.size(); i++) { 1076cb93a386Sopenharmony_ci DIR* dir = opendir(fontDirSet[i].c_str()); 1077cb93a386Sopenharmony_ci if (dir == nullptr) { 1078cb93a386Sopenharmony_ci err = logErrInfo(ERROR_DIR_NOT_FOUND, fontDirSet[i].c_str()); 1079cb93a386Sopenharmony_ci continue; 1080cb93a386Sopenharmony_ci } 1081cb93a386Sopenharmony_ci struct dirent* node = nullptr; 1082cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) 1083cb93a386Sopenharmony_ci struct stat filestat; 1084cb93a386Sopenharmony_ci#endif 1085cb93a386Sopenharmony_ci while ((node = readdir(dir))) { 1086cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) 1087cb93a386Sopenharmony_ci stat(node->d_name, &filestat); 1088cb93a386Sopenharmony_ci if(S_ISDIR(filestat.st_mode)) { 1089cb93a386Sopenharmony_ci continue; 1090cb93a386Sopenharmony_ci } 1091cb93a386Sopenharmony_ci#else 1092cb93a386Sopenharmony_ci if (node->d_type != DT_REG) { 1093cb93a386Sopenharmony_ci continue; 1094cb93a386Sopenharmony_ci } 1095cb93a386Sopenharmony_ci#endif 1096cb93a386Sopenharmony_ci const char* fname = node->d_name; 1097cb93a386Sopenharmony_ci 1098cb93a386Sopenharmony_ci if (G_IS_HMSYMBOL_ENABLE && (strcmp(fname, "hm_symbol_config_next.json") == 0)) { 1099cb93a386Sopenharmony_ci HmSymbolConfig_OHOS::GetInstance()->ParseConfigOfHmSymbol(fname, fontDirSet[i]); 1100cb93a386Sopenharmony_ci continue; 1101cb93a386Sopenharmony_ci } 1102cb93a386Sopenharmony_ci 1103cb93a386Sopenharmony_ci int len = strlen(fname); 1104cb93a386Sopenharmony_ci int suffixLen = strlen(".ttf"); 1105cb93a386Sopenharmony_ci if (len < suffixLen || (strncmp(fname + len - suffixLen, ".ttf", suffixLen) && 1106cb93a386Sopenharmony_ci strncmp(fname + len - suffixLen, ".otf", suffixLen) && 1107cb93a386Sopenharmony_ci strncmp(fname + len - suffixLen, ".ttc", suffixLen) && 1108cb93a386Sopenharmony_ci strncmp(fname + len - suffixLen, ".otc", suffixLen))) { 1109cb93a386Sopenharmony_ci continue; 1110cb93a386Sopenharmony_ci } 1111cb93a386Sopenharmony_ci len += (fontDirSet[i].size() + 2); // 2 more characters for '/' and '\0' 1112cb93a386Sopenharmony_ci char fullname[len]; 1113cb93a386Sopenharmony_ci memset_s(fullname, len, 0, len); 1114cb93a386Sopenharmony_ci strcpy_s(fullname, len, fontDirSet[i].c_str()); 1115cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) 1116cb93a386Sopenharmony_ci if (fontDirSet[i][fontDirSet[i].size() - 1] != '\\') { 1117cb93a386Sopenharmony_ci strcat_s(fullname, len, "\\"); 1118cb93a386Sopenharmony_ci } 1119cb93a386Sopenharmony_ci#else 1120cb93a386Sopenharmony_ci if (fontDirSet[i][fontDirSet[i].size() - 1] != '/') { 1121cb93a386Sopenharmony_ci strcat_s(fullname, len, "/"); 1122cb93a386Sopenharmony_ci } 1123cb93a386Sopenharmony_ci#endif 1124cb93a386Sopenharmony_ci strcat_s(fullname, len, fname); 1125cb93a386Sopenharmony_ci loadFont(fontScanner, fullname); 1126cb93a386Sopenharmony_ci } 1127cb93a386Sopenharmony_ci closedir(dir); 1128cb93a386Sopenharmony_ci } 1129cb93a386Sopenharmony_ci fontDirSet.clear(); 1130cb93a386Sopenharmony_ci return err; 1131cb93a386Sopenharmony_ci} 1132cb93a386Sopenharmony_ci 1133cb93a386Sopenharmony_ci/*! To reset the generic family 1134cb93a386Sopenharmony_ci * \n 1. To sort the typefaces for each font style set in generic list 1135cb93a386Sopenharmony_ci * \n 2. To build typeface set for those font style sets which have single weight value 1136cb93a386Sopenharmony_ci */ 1137cb93a386Sopenharmony_civoid FontConfig_OHOS::resetGenericValue() 1138cb93a386Sopenharmony_ci{ 1139cb93a386Sopenharmony_ci aliasMap.foreach([this](SkString& key, std::vector<AliasInfo>* pAliasSet) { 1140cb93a386Sopenharmony_ci std::vector<AliasInfo>& aliasSet = *pAliasSet; 1141cb93a386Sopenharmony_ci int index = aliasSet[0].pos; 1142cb93a386Sopenharmony_ci if (genericFamilySet[index]->typefaceSet->size() == 0) { 1143cb93a386Sopenharmony_ci this->logErrInfo(ERROR_FAMILY_NOT_FOUND, key.c_str()); 1144cb93a386Sopenharmony_ci } else { 1145cb93a386Sopenharmony_ci sortTypefaceSet(genericFamilySet[index]->typefaceSet); 1146cb93a386Sopenharmony_ci for (unsigned int i = 1; i < aliasSet.size(); i++) { 1147cb93a386Sopenharmony_ci if (aliasSet[i].weight == 0) { 1148cb93a386Sopenharmony_ci continue; 1149cb93a386Sopenharmony_ci } 1150cb93a386Sopenharmony_ci buildSubTypefaceSet(genericFamilySet[index]->typefaceSet, 1151cb93a386Sopenharmony_ci genericFamilySet[index + i]->typefaceSet, 1152cb93a386Sopenharmony_ci genericFamilySet[index + i]->familyName, 1153cb93a386Sopenharmony_ci aliasSet[i].weight); 1154cb93a386Sopenharmony_ci if (genericFamilySet[index + i]->typefaceSet->size() == 0) { 1155cb93a386Sopenharmony_ci this->logErrInfo(ERROR_FAMILY_NOT_FOUND, 1156cb93a386Sopenharmony_ci genericFamilySet[index + i]->familyName.c_str()); 1157cb93a386Sopenharmony_ci } 1158cb93a386Sopenharmony_ci } 1159cb93a386Sopenharmony_ci } 1160cb93a386Sopenharmony_ci }); 1161cb93a386Sopenharmony_ci 1162cb93a386Sopenharmony_ci aliasMap.reset(); 1163cb93a386Sopenharmony_ci adjustMap.reset(); 1164cb93a386Sopenharmony_ci variationMap.reset(); 1165cb93a386Sopenharmony_ci ttcIndexMap.reset(); 1166cb93a386Sopenharmony_ci} 1167cb93a386Sopenharmony_ci 1168cb93a386Sopenharmony_ci/*! To build a sub typeface set according to weight from a typeface set 1169cb93a386Sopenharmony_ci * \param typefaceSet the parent typeface set 1170cb93a386Sopenharmony_ci * \param[out] subSet the sub typeface set returned to the caller 1171cb93a386Sopenharmony_ci * \param familyName the family name of the sub typeface set 1172cb93a386Sopenharmony_ci * \param weight the weight of the sub typeface set 1173cb93a386Sopenharmony_ci */ 1174cb93a386Sopenharmony_civoid FontConfig_OHOS::buildSubTypefaceSet(const std::shared_ptr<TypefaceSet>& typefaceSet, 1175cb93a386Sopenharmony_ci std::shared_ptr<TypefaceSet>& subSet, const SkString& familyName, int weight) 1176cb93a386Sopenharmony_ci{ 1177cb93a386Sopenharmony_ci if (typefaceSet->size() == 0) { 1178cb93a386Sopenharmony_ci return; 1179cb93a386Sopenharmony_ci } 1180cb93a386Sopenharmony_ci for (unsigned int i = 0; i < typefaceSet->size(); i++) { 1181cb93a386Sopenharmony_ci const SkTypeface_OHOS* typeface = (*typefaceSet)[i].get(); 1182cb93a386Sopenharmony_ci if (typeface && typeface->fontStyle().weight() == weight) { 1183cb93a386Sopenharmony_ci const FontInfo* pFont = typeface->getFontInfo(); 1184cb93a386Sopenharmony_ci if (pFont == nullptr) { 1185cb93a386Sopenharmony_ci continue; 1186cb93a386Sopenharmony_ci } 1187cb93a386Sopenharmony_ci FontInfo font(*pFont); 1188cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> newTypeface = sk_make_sp<SkTypeface_OHOS>(familyName, font); 1189cb93a386Sopenharmony_ci subSet->push_back(std::move(newTypeface)); 1190cb93a386Sopenharmony_ci } 1191cb93a386Sopenharmony_ci } 1192cb93a386Sopenharmony_ci} 1193cb93a386Sopenharmony_ci 1194cb93a386Sopenharmony_ci/*! To reset the fallback value 1195cb93a386Sopenharmony_ci * \n To sort the typefaces for each font style set in fallback list. 1196cb93a386Sopenharmony_ci */ 1197cb93a386Sopenharmony_civoid FontConfig_OHOS::resetFallbackValue() 1198cb93a386Sopenharmony_ci{ 1199cb93a386Sopenharmony_ci for (unsigned int i = 0; i < fallbackSet.size(); i++) { 1200cb93a386Sopenharmony_ci if (fallbackSet[i]->typefaceSet->size() == 0) { 1201cb93a386Sopenharmony_ci logErrInfo(ERROR_FAMILY_NOT_FOUND, fallbackSet[i]->familyName.c_str()); 1202cb93a386Sopenharmony_ci } 1203cb93a386Sopenharmony_ci sortTypefaceSet(fallbackSet[i]->typefaceSet); 1204cb93a386Sopenharmony_ci } 1205cb93a386Sopenharmony_ci} 1206cb93a386Sopenharmony_ci 1207cb93a386Sopenharmony_ci/*! To check if an error happened 1208cb93a386Sopenharmony_ci * \param err the id of an error 1209cb93a386Sopenharmony_ci * \param text the key to indicate the part with the error happened 1210cb93a386Sopenharmony_ci * \return false, this kind of error did not happen 1211cb93a386Sopenharmony_ci * \return true, the error happened 1212cb93a386Sopenharmony_ci */ 1213cb93a386Sopenharmony_cibool FontConfig_OHOS::hasError(int err, const SkString& text) const 1214cb93a386Sopenharmony_ci{ 1215cb93a386Sopenharmony_ci for (unsigned int i = 0; i < errSet.size(); i++) { 1216cb93a386Sopenharmony_ci if (errSet[i].err == err && errSet[i].text == text) { 1217cb93a386Sopenharmony_ci return true; 1218cb93a386Sopenharmony_ci } 1219cb93a386Sopenharmony_ci } 1220cb93a386Sopenharmony_ci return false; 1221cb93a386Sopenharmony_ci} 1222cb93a386Sopenharmony_ci 1223cb93a386Sopenharmony_ci/*! To get the total count of errors happened 1224cb93a386Sopenharmony_ci * \return The count of errors 1225cb93a386Sopenharmony_ci */ 1226cb93a386Sopenharmony_ciint FontConfig_OHOS::getErrorCount() const 1227cb93a386Sopenharmony_ci{ 1228cb93a386Sopenharmony_ci return errSet.size(); 1229cb93a386Sopenharmony_ci} 1230cb93a386Sopenharmony_ci 1231cb93a386Sopenharmony_ci/*! To sort the typeface set 1232cb93a386Sopenharmony_ci * \param typefaceSet the typeface set to be sorted 1233cb93a386Sopenharmony_ci */ 1234cb93a386Sopenharmony_civoid FontConfig_OHOS::sortTypefaceSet(std::shared_ptr<TypefaceSet>& typefaceSet) 1235cb93a386Sopenharmony_ci{ 1236cb93a386Sopenharmony_ci if (typefaceSet.get() == nullptr || typefaceSet->size() <= 1) { 1237cb93a386Sopenharmony_ci return; 1238cb93a386Sopenharmony_ci } 1239cb93a386Sopenharmony_ci TypefaceSet& tpSet = *(typefaceSet.get()); 1240cb93a386Sopenharmony_ci for (unsigned int i = 0; i < tpSet.size(); i++) 1241cb93a386Sopenharmony_ci for (unsigned int j = 0; j < tpSet.size() - 1; j++) { 1242cb93a386Sopenharmony_ci if ((tpSet[j]->fontStyle().weight() > tpSet[j + 1]->fontStyle().weight()) || 1243cb93a386Sopenharmony_ci (tpSet[j]->fontStyle().weight() == tpSet[j + 1]->fontStyle().weight() && 1244cb93a386Sopenharmony_ci tpSet[j]->fontStyle().slant() > tpSet[j + 1]->fontStyle().slant())) { 1245cb93a386Sopenharmony_ci tpSet[j].swap(tpSet[j + 1]); 1246cb93a386Sopenharmony_ci } 1247cb93a386Sopenharmony_ci } 1248cb93a386Sopenharmony_ci} 1249cb93a386Sopenharmony_ci 1250cb93a386Sopenharmony_ci/*! To get the display text of an error 1251cb93a386Sopenharmony_ci * \param err the id of an error 1252cb93a386Sopenharmony_ci * \return The text to explain the error 1253cb93a386Sopenharmony_ci */ 1254cb93a386Sopenharmony_ciconst char* FontConfig_OHOS::errToString(int err) 1255cb93a386Sopenharmony_ci{ 1256cb93a386Sopenharmony_ci const static std::array<const char*, ERROR_TYPE_COUNT> errToString{ 1257cb93a386Sopenharmony_ci "successful", // NO_ERROR = 0 1258cb93a386Sopenharmony_ci "config file is not found", // ERROR_CONFIG_NOT_FOUND 1259cb93a386Sopenharmony_ci "the format of config file is not supported", // ERROR_CONFIG_FORMAT_NOT_SUPPORTED 1260cb93a386Sopenharmony_ci "missing tag", // ERROR_CONFIG_MISSING_TAG 1261cb93a386Sopenharmony_ci "invalid value type", // ERROR_CONFIG_INVALID_VALUE_TYPE 1262cb93a386Sopenharmony_ci "font file is not exist", // ERROR_FONT_NOT_EXIST 1263cb93a386Sopenharmony_ci "invalid font stream", // ERROR_FONT_INVALID_STREAM 1264cb93a386Sopenharmony_ci "no font stream", // ERROR_FONT_NO_STREAM 1265cb93a386Sopenharmony_ci "family is not found", // ERROR_FAMILY_NOT_FOUND 1266cb93a386Sopenharmony_ci "no available family in the system", //ERROR_NO_AVAILABLE_FAMILY 1267cb93a386Sopenharmony_ci "no such directory" // ERROR_DIR_NOT_FOUND 1268cb93a386Sopenharmony_ci }; 1269cb93a386Sopenharmony_ci if (err >= 0 && err < ERROR_TYPE_COUNT) { 1270cb93a386Sopenharmony_ci return errToString[err]; 1271cb93a386Sopenharmony_ci } 1272cb93a386Sopenharmony_ci return "unknown error"; 1273cb93a386Sopenharmony_ci} 1274cb93a386Sopenharmony_ci 1275cb93a386Sopenharmony_ci/*! To log the error information 1276cb93a386Sopenharmony_ci * \param err the id of an error 1277cb93a386Sopenharmony_ci * \param key the key which indicates the the part with the error 1278cb93a386Sopenharmony_ci * \param expected the expected type of json node. 1279cb93a386Sopenharmony_ci * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE' 1280cb93a386Sopenharmony_ci * \param actual the actual type of json node. 1281cb93a386Sopenharmony_ci * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE' 1282cb93a386Sopenharmony_ci * \return err 1283cb93a386Sopenharmony_ci */ 1284cb93a386Sopenharmony_ciint FontConfig_OHOS::logErrInfo(int err, const char* key, Json::ValueType expected, 1285cb93a386Sopenharmony_ci Json::ValueType actual) 1286cb93a386Sopenharmony_ci{ 1287cb93a386Sopenharmony_ci errSet.emplace_back(err, key); 1288cb93a386Sopenharmony_ci if (err != ERROR_CONFIG_INVALID_VALUE_TYPE) { 1289cb93a386Sopenharmony_ci LOGE("%s : %s\n", errToString(err), key); 1290cb93a386Sopenharmony_ci } else { 1291cb93a386Sopenharmony_ci const char* types[] = { 1292cb93a386Sopenharmony_ci "null", 1293cb93a386Sopenharmony_ci "int", 1294cb93a386Sopenharmony_ci "unit", 1295cb93a386Sopenharmony_ci "real", 1296cb93a386Sopenharmony_ci "string", 1297cb93a386Sopenharmony_ci "boolean", 1298cb93a386Sopenharmony_ci "array", 1299cb93a386Sopenharmony_ci "object", 1300cb93a386Sopenharmony_ci }; 1301cb93a386Sopenharmony_ci int size = sizeof(types) / sizeof(char*); 1302cb93a386Sopenharmony_ci if ((expected >= 0 && expected < size) && 1303cb93a386Sopenharmony_ci (actual >= 0 && actual < size)) { 1304cb93a386Sopenharmony_ci LOGE("%s : '%s' should be '%s', but here it's '%s'\n", 1305cb93a386Sopenharmony_ci errToString(err), key, types[expected], types[actual]); 1306cb93a386Sopenharmony_ci } else { 1307cb93a386Sopenharmony_ci LOGE("%s : %s\n", errToString(err), key); 1308cb93a386Sopenharmony_ci } 1309cb93a386Sopenharmony_ci } 1310cb93a386Sopenharmony_ci return err; 1311cb93a386Sopenharmony_ci} 1312cb93a386Sopenharmony_ci 1313cb93a386Sopenharmony_cibool FontConfig_OHOS::judgeFileExist() 1314cb93a386Sopenharmony_ci{ 1315cb93a386Sopenharmony_ci bool haveFile = false; 1316cb93a386Sopenharmony_ci for (unsigned int i = 0; i < fontDirSet.size(); i++) { 1317cb93a386Sopenharmony_ci DIR* dir = opendir(fontDirSet[i].c_str()); 1318cb93a386Sopenharmony_ci if (dir == nullptr) { 1319cb93a386Sopenharmony_ci logErrInfo(ERROR_DIR_NOT_FOUND, fontDirSet[i].c_str()); 1320cb93a386Sopenharmony_ci continue; 1321cb93a386Sopenharmony_ci } 1322cb93a386Sopenharmony_ci struct dirent* node = nullptr; 1323cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) 1324cb93a386Sopenharmony_ci struct stat fileStat; 1325cb93a386Sopenharmony_ci#endif 1326cb93a386Sopenharmony_ci while ((node = readdir(dir))) { 1327cb93a386Sopenharmony_ci#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) 1328cb93a386Sopenharmony_ci stat(node->d_name, &fileStat); 1329cb93a386Sopenharmony_ci if (S_ISDIR(fileStat.st_mode)) { 1330cb93a386Sopenharmony_ci continue; 1331cb93a386Sopenharmony_ci } 1332cb93a386Sopenharmony_ci#else 1333cb93a386Sopenharmony_ci if (node->d_type != DT_REG) { 1334cb93a386Sopenharmony_ci continue; 1335cb93a386Sopenharmony_ci } 1336cb93a386Sopenharmony_ci#endif 1337cb93a386Sopenharmony_ci const char* fileName = node->d_name; 1338cb93a386Sopenharmony_ci int len = strlen(fileName); 1339cb93a386Sopenharmony_ci int suffixLen = strlen(".ttf"); 1340cb93a386Sopenharmony_ci if (len < suffixLen || (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) && 1341cb93a386Sopenharmony_ci strncmp(fileName + len - suffixLen, ".otf", suffixLen) && 1342cb93a386Sopenharmony_ci strncmp(fileName + len - suffixLen, ".ttc", suffixLen) && 1343cb93a386Sopenharmony_ci strncmp(fileName + len - suffixLen, ".otc", suffixLen))) { 1344cb93a386Sopenharmony_ci continue; 1345cb93a386Sopenharmony_ci } 1346cb93a386Sopenharmony_ci haveFile = true; 1347cb93a386Sopenharmony_ci break; 1348cb93a386Sopenharmony_ci } 1349cb93a386Sopenharmony_ci (void)closedir(dir); 1350cb93a386Sopenharmony_ci if (haveFile) { 1351cb93a386Sopenharmony_ci break; 1352cb93a386Sopenharmony_ci } 1353cb93a386Sopenharmony_ci } 1354cb93a386Sopenharmony_ci return haveFile; 1355cb93a386Sopenharmony_ci} 1356cb93a386Sopenharmony_ci 1357cb93a386Sopenharmony_ciint FontConfig_OHOS::checkProductFile(const char* fname) 1358cb93a386Sopenharmony_ci{ 1359cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(fontMutex); 1360cb93a386Sopenharmony_ci int err = parseConfig(PRODUCT_DEFAULT_CONFIG); 1361cb93a386Sopenharmony_ci SkDebugf("parse productfontconfig json file err = %d", err); 1362cb93a386Sopenharmony_ci if ((err != NO_ERROR) || (!judgeFileExist())) { 1363cb93a386Sopenharmony_ci SkDebugf("parse productfontconfig json file error"); 1364cb93a386Sopenharmony_ci fontDirSet.clear(); 1365cb93a386Sopenharmony_ci fallbackForMap.reset(); 1366cb93a386Sopenharmony_ci genericFamilySet.clear(); 1367cb93a386Sopenharmony_ci fallbackSet.clear(); 1368cb93a386Sopenharmony_ci genericNames.reset(); 1369cb93a386Sopenharmony_ci fallbackNames.reset(); 1370cb93a386Sopenharmony_ci errSet.clear(); 1371cb93a386Sopenharmony_ci aliasMap.reset(); 1372cb93a386Sopenharmony_ci adjustMap.reset(); 1373cb93a386Sopenharmony_ci variationMap.reset(); 1374cb93a386Sopenharmony_ci ttcIndexMap.reset(); 1375cb93a386Sopenharmony_ci err = parseConfig(fname); 1376cb93a386Sopenharmony_ci } 1377cb93a386Sopenharmony_ci return err; 1378cb93a386Sopenharmony_ci}