From e8e23b72752618bda1dfcafc676248d4a821ea0f Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Wed, 25 Dec 2024 15:30:54 +0800 Subject: [PATCH 1/6] use fontconfig_ohos.json Change-Id: Iee54766c142f8d1955c01a903ee13c8f24f126ec Signed-off-by: liumingxiang --- BUILD.gn | 25 +- src/ports/skia_ohos/FontConfig_ohos.cpp | 1198 +++------------------ src/ports/skia_ohos/FontConfig_ohos.h | 322 +++--- src/ports/skia_ohos/SkFontMgr_ohos.cpp | 185 ++-- src/ports/skia_ohos/SkFontMgr_ohos.h | 41 +- src/ports/skia_ohos/SkFontStyleSet_ohos.h | 10 +- src/ports/skia_ohos/SkTypeface_ohos.h | 14 +- 7 files changed, 408 insertions(+), 1387 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 8f43a03dd2..cf23287bb8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -556,7 +556,11 @@ optional("fontmgr_symbol_load") { } } - deps += [ ":ohos_fontconfig.json" ] + deps += [ + ":ohos_font_file_map.json", + ":ohos_fontconfig.json", + ":ohos_fontconfig_old.json", + ] public = [ "src/ports/skia_ohos/HmSymbolConfig_ohos.h" ] sources = [ "src/ports/skia_ohos/HmSymbolConfig_ohos.cpp" ] } @@ -792,11 +796,24 @@ optional("fontmgr_win") { if (use_oh_skia && !is_arkui_x) { ohos_prebuilt_etc("ohos_fontconfig.json") { + source = + "//third_party/skia/src/ports/skia_ohos/config/fontconfig_ohos.json" + part_name = "skia" + subsystem_name = "thirdparty" + } + + ohos_prebuilt_etc("ohos_fontconfig_old.json") { source = "//third_party/skia/src/ports/skia_ohos/config/fontconfig.json" part_name = "skia" subsystem_name = "thirdparty" } + ohos_prebuilt_etc("ohos_font_file_map.json") { + source = "//third_party/skia/src/ports/skia_ohos/config/font_file_map.json" + part_name = "skia" + subsystem_name = "thirdparty" + } + optional("fontmgr_ohos") { enabled = skia_enable_fontmgr_ohos @@ -835,7 +852,11 @@ if (use_oh_skia && !is_arkui_x) { external_deps += [ "bounds_checking_function:libsec_static" ] } - deps += [ ":ohos_fontconfig.json" ] + deps += [ + ":ohos_font_file_map.json", + ":ohos_fontconfig.json", + ":ohos_fontconfig_old.json", + ] if (skia_feature_wuji_enable) { deps += [ "$ace_graphic_ext:ohos_fonts_wuji" ] diff --git a/src/ports/skia_ohos/FontConfig_ohos.cpp b/src/ports/skia_ohos/FontConfig_ohos.cpp index 426f1a5674..1e3ee5fc82 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.cpp +++ b/src/ports/skia_ohos/FontConfig_ohos.cpp @@ -4,108 +4,99 @@ #include "FontConfig_ohos.h" -#include +#include +#include #include #include +#include +#include #include #include #include #include +#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) +#define SK_BUILD_FONT_MGR_FOR_PREVIEW +#endif + #ifdef SK_BUILD_FONT_MGR_FOR_OHOS #include #endif -#include "securec.h" - #include "SkFontStyle.h" #include "SkString.h" +#include "securec.h" using namespace ErrorCode; static const char* PRODUCT_DEFAULT_CONFIG = "/system/etc/productfontconfig.json"; +static const char* DEFAULT_CONFIG = "/system/etc/fontconfig_ohos.json"; #ifdef SK_BUILD_FONT_MGR_FOR_OHOS - static const bool G_IS_HMSYMBOL_ENABLE = - (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymbolcfg.enable", "1").c_str()) != 0); +static const bool G_IS_HMSYMBOL_ENABLE = + (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymbolcfg.enable", "1").c_str()) != 0); #else - static const bool G_IS_HMSYMBOL_ENABLE = true; +static const bool G_IS_HMSYMBOL_ENABLE = true; #endif -#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) -static const char* OHOS_DEFAULT_CONFIG = "fontconfig.json"; +#ifdef SK_BUILD_FONT_MGR_FOR_PREVIEW +static const char* OHOS_DEFAULT_CONFIG = "fontconfig_ohos.json"; /*! Constructor * \param fontScanner the scanner to get the font information from a font file * \param fname the full name of system font configuration document. * \n The default value is '/system/etc/fontconfig.json', if fname is given null */ -FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, - const char* fname) +FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, const char* fname) + : fFontScanner(fontScanner) { int err = parseConfig(fname); if (err != NO_ERROR) { return; } - scanFonts(fontScanner); - resetGenericValue(); - resetFallbackValue(); + loadHMSymbol(); } #else -static const char* OHOS_DEFAULT_CONFIG = "/system/etc/fontconfig.json"; /*! Constructor * \param fontScanner the scanner to get the font information from a font file * \param fname the full name of system font configuration document. * \n The default value is '/system/etc/fontconfig.json', if fname is given null */ -FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, - const char* fname) +FontConfig_OHOS::FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, const char* fname) + : fFontScanner(fontScanner) { int err = checkProductFile(fname); if (err != NO_ERROR) { return; } - scanFonts(fontScanner); - resetGenericValue(); - resetFallbackValue(); + loadHMSymbol(); } #endif -/*! To get the fallbackForMap - * \return The reference of fallbackForMap - */ -const FallbackForMap& FontConfig_OHOS::getFallbackForMap() const -{ - return fallbackForMap; -} - -/*! To get the fallback set - * \return The reference of fallbackSet - */ -const FallbackSet& FontConfig_OHOS::getFallbackSet() const -{ - return fallbackSet; -} - /*! To get the count of font style sets supported in the system * \return The count of font style sets in generic family */ int FontConfig_OHOS::getFamilyCount() const { - return genericFamilySet.size(); + return fFontCollection.fGeneric.size(); +} + +const std::vector& FontConfig_OHOS::getFallbackSet() const +{ + return fFontCollection.fFallback; } sk_sp FontConfig_OHOS::getFallbackTypeface(const SkString& familyName, const SkFontStyle& style) const { - int* index = fallbackNames.find(familyName); - if (index == nullptr) { + std::pair res; + if (!fFontCollection.getIndexByFamilyName(familyName.c_str(), res)) { return nullptr; } - const TypefaceSet& tpSet = *(fallbackSet[*index]->typefaceSet.get()); + const auto& tpSet = fFontCollection.getSet(true)[res.first].typefaces; if (tpSet.size() == 0) { return nullptr; } - sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); - return typeface; + return FontConfig_OHOS::matchFontStyle(tpSet, style); } /*! To get the family name of the default font style set @@ -113,7 +104,7 @@ sk_sp FontConfig_OHOS::getFallbackTypeface(const SkString& fami * \return The count of typeface in this font style set * \n Return -1, if there is no any font style set in the system. */ -int FontConfig_OHOS::getDefaultFamily(SkString* familyName) const +int FontConfig_OHOS::getDefaultFamily(SkString& familyName) const { return getFamilyName(0, familyName); } @@ -124,18 +115,14 @@ int FontConfig_OHOS::getDefaultFamily(SkString* familyName) const * \return The count of typeface in the font style set * \n Return -1, if the 'index' is out of range */ -int FontConfig_OHOS::getFamilyName(int index, SkString* familyName) const +int FontConfig_OHOS::getFamilyName(size_t index, SkString& familyName) const { - if (index < 0 || index >= this->getFamilyCount()) { - if (familyName) { - familyName->reset(); - } + if (index >= getFamilyCount()) { + familyName = ""; return -1; } - if (familyName) { - *familyName = genericFamilySet[index]->familyName; - } - return genericFamilySet[index]->typefaceSet->size(); + familyName = fFontCollection.fGeneric[index].alias.c_str(); + return fFontCollection.fGeneric[index].typefaces.size(); } /*! To get the count of a font style set @@ -145,21 +132,10 @@ int FontConfig_OHOS::getFamilyName(int index, SkString* familyName) const * \n true, the font style set is from fallback family list * \return The count of typeface in the font style set */ -int FontConfig_OHOS::getTypefaceCount(int styleIndex, bool isFallback) const +size_t FontConfig_OHOS::getTypefaceCount(size_t styleIndex, bool isFallback) const { - if (styleIndex < 0) { - return -1; - } - if (isFallback) { - if ((unsigned int)styleIndex < fallbackSet.size()) { - return fallbackSet[styleIndex]->typefaceSet->size(); - } - } else { - if ((unsigned int)styleIndex < genericFamilySet.size()) { - return genericFamilySet[styleIndex]->typefaceSet->size(); - } - } - return -1; + auto& set = fFontCollection.getSet(isFallback); + return styleIndex < set.size() ? set[styleIndex].typefaces.size() : 0; } /*! To get a typeface @@ -170,30 +146,18 @@ int FontConfig_OHOS::getTypefaceCount(int styleIndex, bool isFallback) const * \return The pointer of a typeface * \n Return null, if 'styleIndex' or 'index' is out of range */ -SkTypeface_OHOS* FontConfig_OHOS::getTypeface(int styleIndex, int index, - bool isFallback) const +SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, size_t index, bool isFallback) const { sk_sp typeface = getTypefaceSP(styleIndex, index, isFallback); return (typeface == nullptr) ? nullptr : typeface.get(); } -sk_sp FontConfig_OHOS::getTypefaceSP(int styleIndex, int index, bool isFallback) const +sk_sp FontConfig_OHOS::getTypefaceSP(size_t styleIndex, size_t index, bool isFallback) const { - if (styleIndex < 0 || index < 0 || - (isFallback && (unsigned int)styleIndex >= fallbackSet.size()) || - (!isFallback && (unsigned int)styleIndex >= genericFamilySet.size())) { - return nullptr; - } - if (isFallback) { - const TypefaceSet& tpSet = *(fallbackSet[styleIndex]->typefaceSet.get()); - if ((unsigned int)index < tpSet.size()) { - return tpSet[index]; - } - } else { - const TypefaceSet& tpSet = *(genericFamilySet[styleIndex]->typefaceSet.get()); - if ((unsigned int)index < tpSet.size()) { - return tpSet[index]; - } + auto& set = fFontCollection.getSet(isFallback); + if (styleIndex <= set.size()) { + // if index less than typefaces' size, return the ptr + return index < set[styleIndex].typefaces.size() ? set[styleIndex].typefaces[index] : nullptr; } return nullptr; } @@ -206,21 +170,15 @@ sk_sp FontConfig_OHOS::getTypefaceSP(int styleIndex, int index, * \return An object of typeface whose font style is the closest matching to 'style' * \n Return null, if 'styleIndex' is out of range */ -SkTypeface_OHOS* FontConfig_OHOS::getTypeface(int styleIndex, const SkFontStyle& style, - bool isFallback) const +SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, const SkFontStyle& style, bool isFallback) const { - if (styleIndex < 0 || - (isFallback && (unsigned int)styleIndex >= fallbackSet.size()) || - (!isFallback && (unsigned int)styleIndex >= genericFamilySet.size())) { + auto& set = fFontCollection.getSet(isFallback); + if (styleIndex >= set.size()) { return nullptr; } - const TypefaceSet* pSet = nullptr; - if (isFallback) { - pSet = fallbackSet[styleIndex]->typefaceSet.get(); - } else { - pSet = genericFamilySet[styleIndex]->typefaceSet.get(); - } - sk_sp tp = matchFontStyle(*pSet, style); + + const std::vector>& pSet = set[styleIndex].typefaces; + sk_sp tp = matchFontStyle(pSet, style); return tp.get(); } @@ -233,35 +191,21 @@ SkTypeface_OHOS* FontConfig_OHOS::getTypeface(int styleIndex, const SkFontStyle& * \return The index of the font style set * \n Return -1, if 'familyName' is not found in the system */ -int FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback) const +bool FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback, size_t& index) const { if (familyName == nullptr) { isFallback = false; - return 0; + return true; } - std::lock_guard lock(fontMutex); - if (genericNames.count() == 0) { - return -1; + std::lock_guard lock(fFontMutex); + std::pair res; + if (fFontCollection.getIndexByFamilyName(familyName, res)) { + isFallback = res.second == FontType::Fallback; + index = res.first; + return true; } - - SkString fname(familyName); - int* p = genericNames.find(fname); - if (p) { - isFallback = false; - return *p; - } else { - if (fallbackNames.count() == 0) { - return -1; - } - - p = fallbackNames.find(fname); - if (p) { - isFallback = true; - return *p; - } - } - return -1; + return false; } /*! Find the closest matching typeface @@ -270,8 +214,8 @@ int FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback) con * \return The typeface object which is the closest matching to 'pattern' * \n Return null, if the count of typeface is 0 */ -sk_sp FontConfig_OHOS::matchFontStyle(const TypefaceSet& typefaceSet, - const SkFontStyle& pattern) +sk_sp FontConfig_OHOS::matchFontStyle( + const std::vector>& typefaceSet, const SkFontStyle& pattern) { int count = typefaceSet.size(); if (count == 1) { @@ -325,7 +269,6 @@ uint32_t FontConfig_OHOS::getFontStyleDifference(const SkFontStyle& dstStyle, }; if (dstStyle.slant() < 0 || dstStyle.slant() >= SLANT_RANGE || srcStyle.slant() < 0 || srcStyle.slant() >= SLANT_RANGE) { - LOGE("Slant out of range, dst:%{public}d, src:%{public}d", dstStyle.slant(), srcStyle.slant()); return 0; } uint32_t slantDiff = diffSlantValue[dstStyle.slant()][srcStyle.slant()]; @@ -353,985 +296,181 @@ uint32_t FontConfig_OHOS::getFontStyleDifference(const SkFontStyle& dstStyle, return diff; } -/*! To get the data of font configuration file - * \param fname the full name of the font configuration file - * \param[out] size the size of data returned to the caller - * \return The pointer of content of the file - * \note The returned pointer should be freed by the caller - */ -char* FontConfig_OHOS::getFileData(const char* fname, int& size) -{ - FILE* fp = fopen(fname, "r"); - if (fp == nullptr) { - return nullptr; - } - fseek(fp, 0L, SEEK_END); - size = ftell(fp) + 1; - rewind(fp); - void* data = malloc(size); - if (data == nullptr) { - fclose(fp); - return nullptr; - } - memset_s(data, size, 0, size); - (void) fread(data, size, 1, fp); - fclose(fp); - return (char*)data; -} - -/*! parse the system font configuration document - * \param fname the full name of the font configuration document - * \return NO_ERROR successful - * \return ERROR_CONFIG_NOT_FOUND config document is not found - * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported - * \return ERROR_CONFIG_INVALID_VALUE_TYPE wrong type of value in the configuration - */ int FontConfig_OHOS::parseConfig(const char* fname) { - if (fname == nullptr) { - fname = OHOS_DEFAULT_CONFIG; - } Json::Value root; int err = checkConfigFile(fname, root); if (err != NO_ERROR) { return err; } - // "fontdir" - optional, the data type should be string - const char* key = "fontdir"; - if (root.isMember(key)) { - if (root[key].isArray()) { + + for (const auto& key : root.getMemberNames()) { + if (root[key].isArray() && key == "font_dir") { parseFontDir(fname, root[key]); - } else { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key); + } else if (root[key].isArray() && key == "fonts") { + parseFonts(root[key]); } } - // "generic", "fallback" - necessary, the data type should be array - const char* keys[] = {"generic", "fallback", nullptr}; - int index = 0; - while (true) { - if (keys[index] == nullptr) { - break; - } - key = keys[index++]; - if (!root.isMember(key)) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); - } else if (!root[key].isArray()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); - } - const Json::Value& arr = root[key]; - for (unsigned int i = 0; i < arr.size(); i++) { - if (arr[i].isObject()) { - if (!strcmp(key, "generic")) { - parseGeneric(arr[i]); - } else if (!strcmp(key, "fallback")) { - parseFallback(arr[i]); - } - } else { - SkString errKey; - errKey.appendf("%s#%d", key, i + 1); - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, errKey.c_str(), - Json::objectValue, arr[i].type()); - } - } - } - root.clear(); - return NO_ERROR; -} - -/*! check the system font configuration document - * \param fname the full name of the font configuration document - * \return NO_ERROR successful - * \return ERROR_CONFIG_NOT_FOUND config document is not found - * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported - */ -int FontConfig_OHOS::checkConfigFile(const char* fname, Json::Value& root) -{ - int size = 0; - char* data = getFileData(fname, size); - if (data == nullptr) { - return logErrInfo(ERROR_CONFIG_NOT_FOUND, fname); - } - JSONCPP_STRING errs; - Json::CharReaderBuilder charReaderBuilder; - std::unique_ptr jsonReader(charReaderBuilder.newCharReader()); - bool isJson = jsonReader->parse(data, data + size, &root, &errs); - free((void*)data); - data = nullptr; - if (!isJson || !errs.empty()) { - return logErrInfo(ERROR_CONFIG_FORMAT_NOT_SUPPORTED, fname); - } return NO_ERROR; } -#if ENABLE_DEBUG -/*! To print out the font information - * \param font the font object to be printed - */ -void FontConfig_OHOS::dumpFont(const FontInfo& font) const -{ - LOGI("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", - font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), - font.index); - int count = font.axisSet.axis.size(); - if (count > 0) { - SkString str; - for (unsigned int i = 0; i < count; i++) { - str.appendU32(SkFixedFloorToInt(font.axisSet.axis[i])); - if (i < count - 1) { - str.append(","); - } - } - LOGI("axis={%s}\n", str.c_str()); - } -} -/*! To print out the information of generic font style set - */ -void FontConfig_OHOS::dumpGeneric() const +template +void GetValue(T& v, const Json::Value& root) { - LOGI("\n"); - for (unsigned int i = 0; i < genericFamilySet.size(); i++) { - LOGI("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), - static_cast(genericFamilySet[i]->typefaceSet->size())); - for (int j = 0; j < genericFamilySet[i]->typefaceSet->size(); j++) { - if ((*(genericFamilySet[i]->typefaceSet))[j].get()) { - const FontInfo* font = (*(genericFamilySet[i]->typefaceSet))[j]->getFontInfo(); - if (font) { - dumpFont(*font); - } else { - LOGE("font [%d] is null\n", j); - } - } else { - LOGE("typefeace [%d] is null\n", j); - } - } + if (root.is()) { + v = std::move(root.as()); } } -/*! To print out the information of fallback font style set - */ -void FontConfig_OHOS::dumpFallback() const -{ - LOGI("\n"); - int count = 0; - fallbackForMap.foreach([this, &count](const SkString& key, - const FallbackSetPos& setIndex) { - LOGI("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); - for (unsigned int i = setIndex.index; i < setIndex.index + setIndex.count; i++) { - const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); - LOGI("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast(tpSet.size())); +#define GEN_GET_FONT_FUNC(f, member) ([](FontJson&(f), const Json::Value& value) { GetValue((f).member, value); }) - for (unsigned int j = 0; j < tpSet.size(); j++) { - const FontInfo* font = tpSet[j]->getFontInfo(); - if (font) { - this->dumpFont(*font); - } else { - LOGE("font [%d] is null\n", j); - } - } - } - }); -} -#endif -/*! To parse 'fontdir' attribute - * \param root the root node of 'fontdir' +/*! parse the font item from the json document + * \param array the font array from the json document * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type */ -int FontConfig_OHOS::parseFontDir(const char* fname, const Json::Value& root) +int FontConfig_OHOS::parseFonts(const Json::Value& array) { - for (unsigned int i = 0; i < root.size(); i++) { - if (root[i].isString()) { - const char* dir; -#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) - if (strcmp(fname, OHOS_DEFAULT_CONFIG) == 0) { - dir = strcmp(root[i].asCString(), "/system/fonts/") ? root[i].asCString() : "fonts"; - } else { - dir = strcmp(root[i].asCString(), "/system/fonts/") ? - root[i].asCString() : "../../../../hms/previewer/resources/fonts"; - } -#else - dir = root[i].asCString(); -#endif - fontDirSet.emplace_back(SkString(dir)); - } else { - SkString text; - text.appendf("fontdir#%d", i + 1); - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::stringValue, root[i].type()); - } - } - return NO_ERROR; -} + const std::unordered_map> + funcMap = { { "type", GEN_GET_FONT_FUNC(f, type) }, { "family", GEN_GET_FONT_FUNC(f, family) }, + { "index", GEN_GET_FONT_FUNC(f, index) }, { "weight", GEN_GET_FONT_FUNC(f, weight) }, + { "lang", GEN_GET_FONT_FUNC(f, lang) }, { "file", GEN_GET_FONT_FUNC(f, file) }, + { "alias", GEN_GET_FONT_FUNC(f, alias) } }; -/*! To parse an item of 'generic' family - * \param root the root node of an item in 'generic' list - * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of 'family' or 'alias' - */ -int FontConfig_OHOS::parseGeneric(const Json::Value& root) -{ - // "family" - necessary, the data type should be String - const char* key = "family"; - if (!root.isMember(key)) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); - } else if (!root[key].isString()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::stringValue, root[key].type()); - } - SkString familyName = SkString(root[key].asCString()); - // "alias" - necessary, the data type should be Array - if (!root.isMember("alias")) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, "alias"); - } - // "adjust", "variation" - optional - const char* tags[] = {"alias", "adjust", "variations", "index"}; - std::vector aliasSet; - std::vector adjustSet; - std::vector variationSet; - for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { - key = tags[i]; - if (!root.isMember(key)) { + std::vector fonts; + + for (const auto& font : array) { + if (!font.isObject()) { continue; } - if (root[key].isArray()) { - if (!strcmp(key, "index")) { - parseTtcIndex(root[key], familyName); - continue; - } - const Json::Value& arr = root[key]; - for (unsigned int j = 0; j < arr.size(); j++) { - if (arr[j].isObject()) { - if (!strcmp(key, "alias")) { - parseAlias(arr[j], aliasSet); - } else if (!strcmp(key, "adjust")) { - parseAdjust(arr[j], adjustSet); - } else { - parseVariation(arr[j], variationSet); - } - } else { - SkString text; - text.appendf("%s#%d", key, j + 1); - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::objectValue, - arr[j].type()); - } + + FontJson f; + for (const auto& key : font.getMemberNames()) { + if (funcMap.count(key)) { + funcMap.at(key)(f, font[key]); } - } else { - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); } - if (root.size() == 2) { - break; - } - } - if (aliasSet.size()) { - aliasMap.set(SkString(familyName), aliasSet); - } - if (adjustSet.size()) { - adjustMap.set(SkString(familyName), adjustSet); - } - if (variationSet.size()) { - variationMap.set(SkString(familyName), variationSet); - } - return NO_ERROR; -} -/*! To parse an item of 'alias' attribute - * \param root the root node of an item in an 'alias' list - * \param[out] aliasSet the value of AliasInfo will be written to and returned to the caller - * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of alias name - */ -int FontConfig_OHOS::parseAlias(const Json::Value& root, std::vector& aliasSet) -{ - if (root.empty()) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, "generic-alias-name"); - } - Json::Value::Members members = root.getMemberNames(); - const char* key = members[0].c_str(); - if (!root[key].isInt()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "generic-alias-weight", - Json::intValue, root[key].type()); - } - - SkString aliasName = SkString(key); - int weight = root[key].asInt(); - std::unique_ptr genericFamily = std::make_unique(); - genericFamily->familyName = SkString(key); - if (aliasSet.size() == 0 || weight > 0) { - genericFamily->typefaceSet = std::make_shared(); - } else { - int index = aliasSet[0].pos; - genericFamily->typefaceSet = genericFamilySet[index]->typefaceSet; - } - genericNames.set(SkString(genericFamily->familyName), genericFamilySet.size()); - - AliasInfo info = {static_cast(genericFamilySet.size()), weight}; - aliasSet.emplace_back(std::move(info)); - genericFamilySet.emplace_back(std::move(genericFamily)); - return NO_ERROR; -} - -/*! To parse an item of 'adjust' attribute - * \param root the root node of an item in an 'adjust' list - * \param[out] adjustSet the value of AdjustInfo will be written to and returned to the caller - * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of 'weight' or 'to' - */ -int FontConfig_OHOS::parseAdjust(const Json::Value& root, std::vector& adjustSet) -{ - const char* tags[] = {"weight", "to"}; - int values[2]; // value[0] - to save 'weight', value[1] - to save 'to' - for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { - const char* key = tags[i]; - if (!root.isMember(key)) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); - } else if (!root[key].isInt()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, - Json::intValue, root[key].type()); - } else { - values[i] = root[key].asInt(); + sk_sp typeface = nullptr; + for (auto& dir : fFontDir) { + std::string path = dir + f.file; + if (loadFont(path.c_str(), f, typeface) == 0) { + fFontCollection.emplaceFont(std::move(f), std::move(typeface)); + break; + } } } - AdjustInfo info = {values[0], values[1]}; - adjustSet.push_back(info); + forAll([this](Font& f) { sortTypefaceSet(f.typefaces); }); return NO_ERROR; } -/*! To parse an item of 'fallback' attribute - * \param root the root node of an item in 'fallback' list +/*! check the system font configuration document + * \param fname the full name of the font configuration document * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of fallbackFor + * \return ERROR_CONFIG_NOT_FOUND config document is not found + * \return ERROR_CONFIG_FORMAT_NOT_SUPPORTED config document format is not supported */ -int FontConfig_OHOS::parseFallback(const Json::Value& root) +int FontConfig_OHOS::checkConfigFile(const char* fname, Json::Value& root) { - if (root.empty()) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-fallbackFor"); - } - Json::Value::Members members = root.getMemberNames(); - const char* key = members[0].c_str(); - if (!root[key].isArray()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "fallback-items", - Json::arrayValue, root[key].type()); - } - unsigned int startPos = fallbackSet.size(); - SkString fallbackFor = SkString(key); - const Json::Value& fallbackArr = root[key]; - for (unsigned int i = 0; i < fallbackArr.size(); i++) { - if (!fallbackArr[i].isObject()) { - SkString text; - text.appendf("fallback-%s#%d", key, i + 1); - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), Json::objectValue, - fallbackArr[i].type()); - continue; - } - parseFallbackItem(fallbackArr[i]); - } - FallbackSetPos setPos = {startPos, (unsigned int)(fallbackSet.size() - startPos)}; - fallbackForMap.set(fallbackFor, setPos); - return NO_ERROR; -} + std::ifstream fstream(fname); -/*! To parse an item of fallback family - * \param root the root node of a fallback item - * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of language - */ -int FontConfig_OHOS::parseFallbackItem(const Json::Value& root) -{ - if (root.empty()) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-item-lang"); - } - Json::Value::Members members = root.getMemberNames(); - const char* key = nullptr; - bool hasIndex = false; - bool hasVariations = false; - for (unsigned int i = 0; i < members.size(); i++) { - if (members[i] == "variations") { - hasVariations = true; - } else if (members[i] == "index") { - hasIndex = true; - } else { - key = members[i].c_str(); - } - } - if (key == nullptr) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, "fallback-item-lang"); - } - if (!root[key].isString()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, "fallback-item-family", - Json::stringValue, root[key].type()); + if (!fstream.is_open()) { + return ERROR_CONFIG_NOT_FOUND; } - SkString lang = SkString(key); - SkString familyName = SkString(root[key].asCString()); - if (hasVariations) { - key = "variations"; - if (root[key].isArray()) { - const Json::Value& varArr = root[key]; - std::vector variationSet; - for (unsigned int i = 0; i < varArr.size(); i++) { - if (varArr[i].isObject()) { - parseVariation(varArr[i], variationSet); - } else { - SkString text = SkString("variations#"); - text.appendU32(i + 1); - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), - Json::objectValue, varArr[i].type()); - } - } - if (variationSet.size()) { - variationMap.set(SkString(familyName), variationSet); - } - } else { - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, - root[key].type()); - } - } - if (hasIndex) { - key = "index"; - if (root[key].isArray()) { - parseTtcIndex(root[key], familyName); - } else { - (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::arrayValue, root[key].type()); - } - } - std::unique_ptr fallback = std::make_unique(); - fallback->familyName = familyName; - fallback->langs = lang; - fallback->typefaceSet = std::make_shared(); - fallbackNames.set(SkString(familyName), fallbackSet.size()); - fallbackSet.emplace_back(std::move(fallback)); - return NO_ERROR; -} -/*! To parse an item of 'variations' attribute - * \param root the root node of an item in 'variations' list - * \param[out] variationSet the value of VariationInfo is written to and returned to the caller - * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute - * \return ERROR_CONFIG_MISSING_TAG missing tag of 'weight' or 'wght' - */ -int FontConfig_OHOS::parseVariation(const Json::Value& root, std::vector& variationSet) -{ - const char* key = nullptr; - const char* tags[] = {"wght", "wdth", "slnt", "weight", "width", "slant"}; - VariationInfo info; - for (unsigned int i = 0; i < sizeof(tags) / sizeof(char*); i++) { - key = tags[i]; - if ((!strcmp(key, "wght") || !strcmp(key, "weight")) && - !root.isMember(key)) { - return logErrInfo(ERROR_CONFIG_MISSING_TAG, key); - } - if (!root.isMember(key)) { - continue; - } - if (!strcmp(key, "weight")) { - if (!root[key].isInt()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::intValue, root[key].type()); - } - info.weight = root[key].asInt(); - } else if (!strcmp(key, "width")) { - if (!root[key].isInt()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::intValue, root[key].type()); - } - info.width = root[key].asInt(); - } else if (!strcmp(key, "slant")) { - if (!root[key].isString()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::stringValue, root[key].type()); - } - const char* str = root[key].asCString(); - if (!strcmp(str, "normal")) { - info.slant = static_cast(SkFontStyle::kUpright_Slant); - } else if (!strcmp(str, "italic")) { - info.slant = static_cast(SkFontStyle::kItalic_Slant); - } else if (!strcmp(str, "oblique")) { - info.slant = static_cast(SkFontStyle::kOblique_Slant); - } - } else { - if (!root[key].isNumeric()) { - return logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, key, Json::realValue, root[key].type()); - } - Coordinate axis; - axis.axis = SkSetFourByteTag(key[0], key[1], key[2], key[3]); - axis.value = root[key].asFloat(); - info.axis.emplace_back(axis); - } + Json::Reader reader; + bool isJson = reader.parse(fstream, root, false); + if (!isJson) { + return ERROR_CONFIG_FORMAT_NOT_SUPPORTED; } - variationSet.emplace_back(info); return NO_ERROR; } -/*! To parse 'index' attribute - * \param root the root node of 'index' attribute - * \param familyName the name of the family which the root node belongs to +/*! To parse 'fontdir' attribute + * \param root the root node of 'fontdir' * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type for an attribute + * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type */ -int FontConfig_OHOS::parseTtcIndex(const Json::Value& root, const SkString& familyName) +int FontConfig_OHOS::parseFontDir(const char* fname, const Json::Value& root) { - unsigned int keyCount = 2; // the value of 'index' is an array with 2 items. - if (root.size() == keyCount && root[0].isString() && root[1].isNumeric()) { - TtcIndexInfo item = { SkString(root[0].asCString()), root[1].asInt() }; - if (item.ttcIndex != 0 && ttcIndexMap.find(item.familyName) == nullptr) { - ttcIndexMap.set(SkString(item.familyName), {SkString(item.familyName), 0}); + for (auto& path : root) { + if (!path.isString()) { + continue; } - ttcIndexMap.set(SkString(familyName), item); - } else { - int ret = ERROR_CONFIG_INVALID_VALUE_TYPE; - SkString text; - const char* key = "index"; - if (root.size() != keyCount) { - text.appendf("%s#0", key); - errSet.emplace_back(ret, text.c_str()); - LOGE("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); - return ret; - } else if (!root[0].isString()) { - text.appendf("%s#1", key); - return logErrInfo(ret, text.c_str(), Json::stringValue, root[0].type()); + std::string dir; +#ifdef SK_BUILD_FONT_MGR_FOR_PREVIEW + if (strcmp(fname, OHOS_DEFAULT_CONFIG) == 0) { + dir = path.asString() != "/system/fonts/" ? path.asString() : "fonts"; } else { - text.appendf("%s#2", key); - return logErrInfo(ret, text.c_str(), Json::intValue, root[1].type()); + dir = path.asString() != "/system/fonts/" ? path.asString() : "../../../../hms/previewer/resources/fonts"; } +#else + dir = path.asString(); +#endif + fFontDir.push_back(std::move(dir)); } return NO_ERROR; } -/*! To get the axis value and set to 'font' - * \param axisDefs the axis ranges of a font - * \param variation the variation data from which axis values are generated - * \param[out] font the axis values will be written to and returned to the caller - */ -void FontConfig_OHOS::getAxisValues(const AxisDefinitions& axisDefs, - const VariationInfo& variation, FontInfo& font) const -{ - SkFontArguments::VariationPosition position; - position.coordinateCount = variation.axis.size(); - position.coordinates = variation.axis.data(); - - int count = axisDefs.count(); - if (count <= 0) { - LOGE("Invalid axis count:%{public}d", count); - return; - } - SkFixed axisValues[count]; - SkTypeface_FreeType::Scanner::computeAxisValues(axisDefs, position, - axisValues, font.familyName); - font.axisSet.axis.clear(); - font.axisSet.range.clear(); - for (int i = 0; i < count; i++) { - font.axisSet.axis.emplace_back(axisValues[i]); - font.axisSet.range.emplace_back(axisDefs[i]); - } -} - -/*! To insert a ttc font into a font style set - * \param count the count of typeface in a ttc font - * \param font an object of the FontInfo with font information - * \return true, if the font is a ttc font and added to corresponding font style set - * \return false, if the font is not a ttc font - */ -bool FontConfig_OHOS::insertTtcFont(int count, FontInfo& font) -{ - bool ret = false; - ttcIndexMap.foreach([this, count, &font, &ret] - (const SkString& familyName, TtcIndexInfo* info) { - if (info->familyName == font.familyName && info->ttcIndex < count) { - SkString specifiedName; - TypefaceSet* tpSet = this->getTypefaceSet(familyName, specifiedName); - if (tpSet) { - FontInfo newFont(font); - newFont.familyName = familyName; - newFont.index = info->ttcIndex; - sk_sp typeface = sk_make_sp(specifiedName, newFont); - tpSet->push_back(std::move(typeface)); - ret = true; - } - } - }); - return ret; -} - -/*! To insert a variable font into a font style set - * \param axisDefs the axis ranges of a variable font - * \param font an object of the FontInfo with font information - * \return true, if the font is a variable and some typefaces are added to the corresponding font style set - * \return false, if the font is not variable - */ -bool FontConfig_OHOS::insertVariableFont(const AxisDefinitions& axisDefs, FontInfo& font) -{ - const SkString& key = font.familyName; - if (variationMap.find(key) == nullptr || axisDefs.count() == 0) { - return false; - } - SkString specifiedName; - TypefaceSet* tpSet = getTypefaceSet(key, specifiedName); - if (tpSet == nullptr) { - return false; - } - const std::vector& variationSet = *(variationMap.find(key)); - for (unsigned int i = 0; i < variationSet.size(); i++) { - FontInfo newFont(font); - getAxisValues(axisDefs, variationSet[i], newFont); - int width = font.style.width(); - SkFontStyle::Slant slant = font.style.slant(); - if (variationSet[i].width != -1) { - width = variationSet[i].width; - } - if (variationSet[i].slant != -1) { - slant = (SkFontStyle::Slant) variationSet[i].slant; - } - newFont.style = SkFontStyle(variationSet[i].weight, width, slant); - sk_sp typeface = sk_make_sp(specifiedName, newFont); - tpSet->push_back(std::move(typeface)); - } - return true; -} - -/*! To get the typeface set of a font style set - * \param familyName the family name of a font style set - * \param[out] specifiedName the specified family name of a font style set returned to the caller - * \return The object of typeface set - * \n Return null, if the family name is not found in the system - */ -TypefaceSet* FontConfig_OHOS::getTypefaceSet(const SkString& familyName, - SkString& specifiedName) const -{ - std::lock_guard lock(fontMutex); - if (aliasMap.find(familyName) != nullptr) { - const std::vector& aliasSet = *(aliasMap.find(familyName)); - if (aliasSet.size()) { - int index = aliasSet[0].pos; - specifiedName = genericFamilySet[index]->familyName; - return genericFamilySet[index]->typefaceSet.get(); - } - } else if (fallbackNames.find(familyName) != nullptr) { - int index = *(fallbackNames.find(familyName)); - return fallbackSet[index]->typefaceSet.get(); - } - return nullptr; -} - /*! To load font information from a font file - * \param scanner a scanner used to parse the font file * \param fname the full name of a font file + * \param info the font information read from json document + * \param typeface the typeface to be loaded * \return NO_ERROR successful * \return ERROR_FONT_NOT_EXIST font file is not exist * \return ERROR_FONT_INVALID_STREAM the stream is not recognized */ -int FontConfig_OHOS::loadFont(const SkTypeface_FreeType::Scanner& scanner, const char* fname) +int FontConfig_OHOS::loadFont(const char* fname, FontJson& info, sk_sp& typeface) { std::unique_ptr stream = SkStream::MakeFromFile(fname); - int count = 1; - SkTypeface_FreeType::Scanner::AxisDefinitions axisDefs; - FontInfo font(fname, 0); - if (stream == nullptr || - scanner.recognizedFont(stream.get(), &count) == false || - scanner.scanFont(stream.get(), 0, &font.familyName, &font.style, - &font.isFixedWidth, &axisDefs) == false) { - int err = NO_ERROR; - if (stream == nullptr) { - err = ERROR_FONT_NOT_EXIST; - } else { - err = ERROR_FONT_INVALID_STREAM; - } - LOGE("%s : %s\n", errToString(err), fname); - char* fnameCopy = strdup(fname); - errSet.emplace_back(err, basename(fnameCopy)); - free(fnameCopy); - return err; - } - // for adjustMap - update weight - if (adjustMap.find(font.familyName) != nullptr) { - const std::vector adjustSet = *(adjustMap.find(font.familyName)); - for (unsigned int i = 0; i < adjustSet.size(); i++) { - if (font.style.weight() == adjustSet[i].origValue) { - font.style = SkFontStyle(adjustSet[i].newValue, font.style.width(), font.style.slant()); - break; - } - } - } - bool ret = false; - if (count > 1) { - ret = insertTtcFont(count, font); - } else if (axisDefs.count() > 0) { - ret = insertVariableFont(axisDefs, font); - } - if (!ret) { - SkString specifiedName; - TypefaceSet* tpSet = getTypefaceSet(font.familyName, specifiedName); - if (tpSet) { - sk_sp typeface = sk_make_sp(specifiedName, font); - tpSet->push_back(std::move(typeface)); - } - } - return NO_ERROR; -} - -/*! To scan the system font directories - * \param fontScanner the scanner used to parse a font file - * \return NO_ERROR success - * \return ERROR_DIR_NOT_FOUND a font directory is not exist - */ -int FontConfig_OHOS::scanFonts(const SkTypeface_FreeType::Scanner& fontScanner) -{ - int err = NO_ERROR; - if (fontDirSet.size() == 0) { -#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) - fontDirSet.emplace_back(SkString("fonts")); -#else - fontDirSet.emplace_back(SkString("/system/fonts/")); -#endif + if (stream == nullptr) { + return ERROR_FONT_NOT_EXIST; } - for (unsigned int i = 0; i < fontDirSet.size(); i++) { - DIR* dir = opendir(fontDirSet[i].c_str()); - if (dir == nullptr) { - err = logErrInfo(ERROR_DIR_NOT_FOUND, fontDirSet[i].c_str()); - continue; - } - struct dirent* node = nullptr; -#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) - struct stat filestat; -#endif - while ((node = readdir(dir))) { -#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) - stat(node->d_name, &filestat); - if(S_ISDIR(filestat.st_mode)) { - continue; - } -#else - if (node->d_type != DT_REG) { - continue; - } -#endif - const char* fname = node->d_name; - - if (G_IS_HMSYMBOL_ENABLE && (strcmp(fname, "hm_symbol_config_next.json") == 0)) { - HmSymbolConfig_OHOS::GetInstance()->ParseConfigOfHmSymbol(fname, fontDirSet[i]); - continue; - } - - int len = strlen(fname); - int suffixLen = strlen(".ttf"); - if (len < suffixLen || (strncmp(fname + len - suffixLen, ".ttf", suffixLen) && - strncmp(fname + len - suffixLen, ".otf", suffixLen) && - strncmp(fname + len - suffixLen, ".ttc", suffixLen) && - strncmp(fname + len - suffixLen, ".otc", suffixLen))) { - continue; - } - len += (fontDirSet[i].size() + 2); // 2 more characters for '/' and '\0' - char fullname[len]; - memset_s(fullname, len, 0, len); - strcpy_s(fullname, len, fontDirSet[i].c_str()); -#if defined(SK_BUILD_FONT_MGR_FOR_PREVIEW_WIN) - if (fontDirSet[i][fontDirSet[i].size() - 1] != '\\') { - strcat_s(fullname, len, "\\"); - } -#else - if (fontDirSet[i][fontDirSet[i].size() - 1] != '/') { - strcat_s(fullname, len, "/"); - } -#endif - strcat_s(fullname, len, fname); - loadFont(fontScanner, fullname); - } - closedir(dir); + int count = 1; + FontInfo font(fname, info.index); + if (!fFontScanner.recognizedFont(stream.get(), &count) || + !fFontScanner.scanFont(stream.get(), 0, &font.familyName, &font.style, &font.isFixedWidth, nullptr)) { + return ERROR_FONT_INVALID_STREAM; } - fontDirSet.clear(); - return err; -} - -/*! To reset the generic family - * \n 1. To sort the typefaces for each font style set in generic list - * \n 2. To build typeface set for those font style sets which have single weight value - */ -void FontConfig_OHOS::resetGenericValue() -{ - aliasMap.foreach([this](SkString& key, std::vector* pAliasSet) { - std::vector& aliasSet = *pAliasSet; - int index = aliasSet[0].pos; - if (genericFamilySet[index]->typefaceSet->size() == 0) { - this->logErrInfo(ERROR_FAMILY_NOT_FOUND, key.c_str()); - } else { - sortTypefaceSet(genericFamilySet[index]->typefaceSet); - for (unsigned int i = 1; i < aliasSet.size(); i++) { - if (aliasSet[i].weight == 0) { - continue; - } - buildSubTypefaceSet(genericFamilySet[index]->typefaceSet, - genericFamilySet[index + i]->typefaceSet, - genericFamilySet[index + i]->familyName, - aliasSet[i].weight); - if (genericFamilySet[index + i]->typefaceSet->size() == 0) { - this->logErrInfo(ERROR_FAMILY_NOT_FOUND, - genericFamilySet[index + i]->familyName.c_str()); - } - } - } - }); - - aliasMap.reset(); - adjustMap.reset(); - variationMap.reset(); - ttcIndexMap.reset(); -} -/*! To build a sub typeface set according to weight from a typeface set - * \param typefaceSet the parent typeface set - * \param[out] subSet the sub typeface set returned to the caller - * \param familyName the family name of the sub typeface set - * \param weight the weight of the sub typeface set - */ -void FontConfig_OHOS::buildSubTypefaceSet(const std::shared_ptr& typefaceSet, - std::shared_ptr& subSet, const SkString& familyName, int weight) -{ - if (typefaceSet->size() == 0) { - return; - } - for (unsigned int i = 0; i < typefaceSet->size(); i++) { - const SkTypeface_OHOS* typeface = (*typefaceSet)[i].get(); - if (typeface && typeface->fontStyle().weight() == weight) { - const FontInfo* pFont = typeface->getFontInfo(); - if (pFont == nullptr) { - continue; - } - FontInfo font(*pFont); - sk_sp newTypeface = sk_make_sp(familyName, font); - subSet->push_back(std::move(newTypeface)); - } - } + const char* temp = info.type == FontType::Generic ? info.alias.c_str() : ""; + SkString family(temp); + typeface = sk_make_sp(family, font); + return NO_ERROR; } -/*! To reset the fallback value - * \n To sort the typefaces for each font style set in fallback list. - */ -void FontConfig_OHOS::resetFallbackValue() -{ - for (unsigned int i = 0; i < fallbackSet.size(); i++) { - if (fallbackSet[i]->typefaceSet->size() == 0) { - logErrInfo(ERROR_FAMILY_NOT_FOUND, fallbackSet[i]->familyName.c_str()); - } - sortTypefaceSet(fallbackSet[i]->typefaceSet); - } -} -/*! To check if an error happened - * \param err the id of an error - * \param text the key to indicate the part with the error happened - * \return false, this kind of error did not happen - * \return true, the error happened - */ -bool FontConfig_OHOS::hasError(int err, const SkString& text) const +void FontConfig_OHOS::loadHMSymbol() { - for (unsigned int i = 0; i < errSet.size(); i++) { - if (errSet[i].err == err && errSet[i].text == text) { - return true; + for (auto& dir : fFontDir) { + if (G_IS_HMSYMBOL_ENABLE && + HmSymbolConfig_OHOS::GetInstance()->ParseConfigOfHmSymbol( + "hm_symbol_config_next.json", SkString(dir.c_str())) == + NO_ERROR) { + break; } } - return false; -} - -/*! To get the total count of errors happened - * \return The count of errors - */ -int FontConfig_OHOS::getErrorCount() const -{ - return errSet.size(); } /*! To sort the typeface set * \param typefaceSet the typeface set to be sorted */ -void FontConfig_OHOS::sortTypefaceSet(std::shared_ptr& typefaceSet) -{ - if (typefaceSet.get() == nullptr || typefaceSet->size() <= 1) { - return; - } - TypefaceSet& tpSet = *(typefaceSet.get()); - for (unsigned int i = 0; i < tpSet.size(); i++) - for (unsigned int j = 0; j < tpSet.size() - 1; j++) { - if ((tpSet[j]->fontStyle().weight() > tpSet[j + 1]->fontStyle().weight()) || - (tpSet[j]->fontStyle().weight() == tpSet[j + 1]->fontStyle().weight() && - tpSet[j]->fontStyle().slant() > tpSet[j + 1]->fontStyle().slant())) { - tpSet[j].swap(tpSet[j + 1]); - } - } -} - -/*! To get the display text of an error - * \param err the id of an error - * \return The text to explain the error - */ -const char* FontConfig_OHOS::errToString(int err) +void FontConfig_OHOS::sortTypefaceSet(std::vector>& typefaceSet) { - const static std::array errToString{ - "successful", // NO_ERROR = 0 - "config file is not found", // ERROR_CONFIG_NOT_FOUND - "the format of config file is not supported", // ERROR_CONFIG_FORMAT_NOT_SUPPORTED - "missing tag", // ERROR_CONFIG_MISSING_TAG - "invalid value type", // ERROR_CONFIG_INVALID_VALUE_TYPE - "font file is not exist", // ERROR_FONT_NOT_EXIST - "invalid font stream", // ERROR_FONT_INVALID_STREAM - "no font stream", // ERROR_FONT_NO_STREAM - "family is not found", // ERROR_FAMILY_NOT_FOUND - "no available family in the system", //ERROR_NO_AVAILABLE_FAMILY - "no such directory" // ERROR_DIR_NOT_FOUND - }; - if (err >= 0 && err < ERROR_TYPE_COUNT) { - return errToString[err]; - } - return "unknown error"; + std::sort(typefaceSet.begin(), typefaceSet.end(), [](const auto& a, const auto& b) { + return (a->fontStyle().weight() < b->fontStyle().weight()) || + (a->fontStyle().weight() == b->fontStyle().weight() && a->fontStyle().slant() < b->fontStyle().slant()); + }); } -/*! To log the error information - * \param err the id of an error - * \param key the key which indicates the the part with the error - * \param expected the expected type of json node. - * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE' - * \param actual the actual type of json node. - * \n It's used only for err 'ERROR_CONFIG_INVALID_VALUE_TYPE' - * \return err - */ -int FontConfig_OHOS::logErrInfo(int err, const char* key, Json::ValueType expected, - Json::ValueType actual) -{ - errSet.emplace_back(err, key); - if (err != ERROR_CONFIG_INVALID_VALUE_TYPE) { - LOGE("%s : %s\n", errToString(err), key); - } else { - const char* types[] = { - "null", - "int", - "unit", - "real", - "string", - "boolean", - "array", - "object", - }; - int size = sizeof(types) / sizeof(char*); - if ((expected >= 0 && expected < size) && - (actual >= 0 && actual < size)) { - LOGE("%s : '%s' should be '%s', but here it's '%s'\n", - errToString(err), key, types[expected], types[actual]); - } else { - LOGE("%s : %s\n", errToString(err), key); - } - } - return err; -} bool FontConfig_OHOS::judgeFileExist() { bool haveFile = false; - for (unsigned int i = 0; i < fontDirSet.size(); i++) { - DIR* dir = opendir(fontDirSet[i].c_str()); + for (const auto& path : fFontDir) { + DIR* dir = opendir(path.c_str()); if (dir == nullptr) { - logErrInfo(ERROR_DIR_NOT_FOUND, fontDirSet[i].c_str()); continue; } struct dirent* node = nullptr; @@ -1352,10 +491,10 @@ bool FontConfig_OHOS::judgeFileExist() const char* fileName = node->d_name; int len = strlen(fileName); int suffixLen = strlen(".ttf"); - if (len < suffixLen || (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) && - strncmp(fileName + len - suffixLen, ".otf", suffixLen) && - strncmp(fileName + len - suffixLen, ".ttc", suffixLen) && - strncmp(fileName + len - suffixLen, ".otc", suffixLen))) { + if (len < suffixLen || (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".otf", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".ttc", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".otc", suffixLen) != 0)) { continue; } haveFile = true; @@ -1371,23 +510,10 @@ bool FontConfig_OHOS::judgeFileExist() int FontConfig_OHOS::checkProductFile(const char* fname) { - std::lock_guard lock(fontMutex); + std::lock_guard lock(fFontMutex); int err = parseConfig(PRODUCT_DEFAULT_CONFIG); - SkDebugf("parse productfontconfig json file err = %d", err); - if ((err != NO_ERROR) || (!judgeFileExist())) { - SkDebugf("parse productfontconfig json file error"); - fontDirSet.clear(); - fallbackForMap.reset(); - genericFamilySet.clear(); - fallbackSet.clear(); - genericNames.reset(); - fallbackNames.reset(); - errSet.clear(); - aliasMap.reset(); - adjustMap.reset(); - variationMap.reset(); - ttcIndexMap.reset(); - err = parseConfig(fname); + if (err != NO_ERROR || !judgeFileExist()) { + err = parseConfig(DEFAULT_CONFIG); } return err; } \ No newline at end of file diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h index 4c3ec60792..b6cf9f972c 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.h +++ b/src/ports/skia_ohos/FontConfig_ohos.h @@ -6,50 +6,18 @@ #define FONTCONFIG_OHOS_H #include -#include #include +#include +#include "FontInfo_ohos.h" +#include "HmSymbolConfig_ohos.h" #include "SkFontDescriptor.h" #include "SkFontHost_FreeType_common.h" #include "SkFontStyle.h" #include "SkStream.h" #include "SkString.h" -#include "SkTypes.h" - -#include "FontInfo_ohos.h" #include "SkTypeface_ohos.h" - -#include "HmSymbolConfig_ohos.h" - -#ifdef ENABLE_DEBUG - -#define LOGE(fmt, args...) \ - printf("E %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) -#define LOGI(fmt, args...) \ - printf("I %s:%d - " fmt, __FUNCTION__, __LINE__, ##args) -#define LOGW(fmt, args...) \ - printf("W %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) - -#else - -#define LOGE SkDEBUGF -#define LOGI SkDEBUGF -#define LOGW SkDEBUGF - -#endif - -struct FontInfo; -struct FallbackInfo; -struct GenericFamily; -struct FallbackSetPos; - -using TypefaceSet = std::vector>; -using GenericFamilySet = std::vector>; -using FallbackSet = std::vector>; -using FallbackForMap = SkTHashMap; -using NamesMap = SkTHashMap; -using Coordinate = SkFontArguments::VariationPosition::Coordinate; -using AxisDefinitions = SkTypeface_FreeType::Scanner::AxisDefinitions; +#include "SkTypes.h" /*! * Error code definition @@ -57,189 +25,153 @@ using AxisDefinitions = SkTypeface_FreeType::Scanner::AxisDefinitions; namespace ErrorCode { enum { - NO_ERROR = 0, // no error - ERROR_CONFIG_NOT_FOUND, // the configuration document is not found - ERROR_CONFIG_FORMAT_NOT_SUPPORTED, // the formation of configuration is not supported - ERROR_CONFIG_MISSING_TAG, // missing tag in the configuration - ERROR_CONFIG_INVALID_VALUE_TYPE, // invalid value type in the configuration - ERROR_FONT_NOT_EXIST, // the font file is not exist - ERROR_FONT_INVALID_STREAM, // the stream is not recognized - ERROR_FONT_NO_STREAM, // no stream in the font data - ERROR_FAMILY_NOT_FOUND, // the family name is not found in the system - ERROR_NO_AVAILABLE_FAMILY, // no available family in the system - ERROR_DIR_NOT_FOUND, // the directory is not exist + NO_ERROR = 0, // no error + ERROR_CONFIG_NOT_FOUND, // the configuration document is not found + ERROR_CONFIG_FORMAT_NOT_SUPPORTED, // the formation of configuration is not supported + ERROR_CONFIG_MISSING_TAG, // missing tag in the configuration + ERROR_CONFIG_INVALID_VALUE_TYPE, // invalid value type in the configuration + ERROR_FONT_NOT_EXIST, // the font file is not exist + ERROR_FONT_INVALID_STREAM, // the stream is not recognized + ERROR_FONT_NO_STREAM, // no stream in the font data + ERROR_FAMILY_NOT_FOUND, // the family name is not found in the system + ERROR_NO_AVAILABLE_FAMILY, // no available family in the system + ERROR_DIR_NOT_FOUND, // the directory is not exist ERROR_TYPE_COUNT, }; - } /* namespace ErrorCode */ -/*! - * \brief To manage the related information of a 'fallbackFor' family name - */ -struct FallbackSetPos { - unsigned int index; // the index of the first font style set in the fallback set for a specified family name - unsigned int count; // the count of font style sets for a specified family name -}; - -/*! - * \brief To manage the information for a generic family item - */ -struct GenericFamily { - SkString familyName; // the specified family name of the font style set - std::shared_ptr typefaceSet; // the typeface set of the font style set - virtual ~GenericFamily() = default; -}; - -/*! - * \brief To manage the information for a fallback family item - */ -struct FallbackInfo : GenericFamily { - SkString langs; // the language for which the font style set is -}; - /*! * \brief To parse the font configuration document and manage the system fonts */ class FontConfig_OHOS { public: - explicit FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, - const char* fname = nullptr); - virtual ~FontConfig_OHOS() = default; - const FallbackForMap& getFallbackForMap() const; - const FallbackSet& getFallbackSet() const; - int getFamilyCount() const; - int getDefaultFamily(SkString* familyName) const; - int getFamilyName(int index, SkString* familyName) const; - int getTypefaceCount(int styleIndex, bool isFallback = false) const; - int getStyleIndex(const char* familyName, bool& isFallback) const; - sk_sp getFallbackTypeface(const SkString& familyName, const SkFontStyle& style) const; - - sk_sp getTypefaceSP(int styleIndex, int index, bool isFallback = false) const; - SkTypeface_OHOS* getTypeface(int styleIndex, int index, bool isFallback = false) const; - SkTypeface_OHOS* getTypeface(int styleIndex, const SkFontStyle& style, - bool isFallback = false) const; - -#if ENABLE_DEBUG - void dumpFont(const FontInfo& font) const; - void dumpGeneric() const; - void dumpFallback() const; -#endif - bool hasError(int err, const SkString& text) const; - int getErrorCount() const; - - static sk_sp matchFontStyle(const TypefaceSet& typefaceSet, const SkFontStyle& pattern); - - static const char* errToString(int err); -private: - const uint32_t defaultColorHexLen = 9; - const uint32_t defaultColorStrLen = 7; - const uint32_t hexFlag = 16; - const uint32_t twoBytesBitsLen = 16; - const uint32_t oneByteBitsLen = 8; - - struct AliasInfo; - struct AdjustInfo; - struct VariationInfo; - struct TtcIndexInfo; - using AliasMap = SkTHashMap>; - using AjdustMap = SkTHashMap>; - using VariationMap = SkTHashMap>; - using TtcIndexMap = SkTHashMap; - - /*! - * \brief To manage the adjust information - */ - struct AdjustInfo { - int origValue; // the real value of the font weight - int newValue; // the specified value of weight for a font + enum FontType : uint32_t { Generic = 0, Fallback, NumOfFontType }; + + // to map the json document's font object + struct FontJson { + uint32_t type = 0; + uint32_t slant = 0; + uint32_t index = 0; + uint32_t weight = 400; + std::string alias; + std::string family; + std::string lang; + std::string file; }; - /*! - * \brief To manage the alias information of - */ - struct AliasInfo { - int pos; // the index of a font style set in generic family list. - int weight; // the weight of the font style set. 0 means no specified weight + struct Font { + FontType type = FontType::Generic; + // slant: 0 - normal, 1 - italic, 2 - oblique + uint32_t slant = 0; + // the ttc font index, only valid for ttc font + uint32_t index = 0; + // only valid for the font with alias + uint32_t weight = 400; + std::string alias; + // essential for the every font + std::string family; + // only valid for the fallback font + std::string lang; + std::vector> typefaces; + + explicit Font(FontJson&& info) + : slant(info.slant), weight(info.weight), alias(info.alias), family(info.family), lang(info.lang) + { + this->type = info.type >= FontType::NumOfFontType ? FontType::Generic : static_cast(info.type); + } }; - /*! - * \brief To manage the variation information - */ - struct VariationInfo { - VariationInfo() : weight(-1), width(-1), slant(-1){} - std::vector axis; // the axis set such as 'wght', 'wdth' and 'slnt'. - int weight; // the value of mapping weight - int width; // the value of mapping width - int slant; // the value of mapping slant - }; - - /*! - * \brief To manage the 'index' information for ttc fonts - */ - struct TtcIndexInfo { - SkString familyName; // the family name of the first typeface in a ttc font - int ttcIndex; // the index of a typeface in a ttc font - }; - - /*! - * \brief To manage the information of errors happened - */ - struct ErrorInfo { - ErrorInfo(int err, const char* text) : err(err), text(SkString(text)){} - ErrorInfo(int err, SkString& text) : err(err), text(std::move(text)){} - int err; // error id - SkString text; // the part with error - }; - - std::vector fontDirSet; // the directories where the fonts are - - FallbackForMap fallbackForMap; // a hash table to save the fallbackFor pairs - GenericFamilySet genericFamilySet; // the font style set list of generic family - FallbackSet fallbackSet; // the font style set list of fallback family + explicit FontConfig_OHOS(const SkTypeface_FreeType::Scanner& fontScanner, const char* fname = nullptr); + virtual ~FontConfig_OHOS() = default; + const std::vector& getFallbackSet() const; + int getFamilyCount() const; + int getDefaultFamily(SkString& familyName) const; + int getFamilyName(size_t index, SkString& familyName) const; + size_t getTypefaceCount(size_t styleIndex, bool isFallback = false) const; + bool getStyleIndex(const char* familyName, bool& isFallback, size_t& index) const; + sk_sp getFallbackTypeface(const SkString& familyName, const SkFontStyle& style) const; + void forAll(std::function func) + { + fFontCollection.forAll(func); + } - NamesMap genericNames; // a map to store the index of a family for generic family - NamesMap fallbackNames; // a map to store the index of a family for fallback family + sk_sp getTypefaceSP(size_t styleIndex, size_t index, bool isFallback = false) const; + SkTypeface_OHOS* getTypeface(size_t styleIndex, size_t index, bool isFallback = false) const; + SkTypeface_OHOS* getTypeface(size_t styleIndex, const SkFontStyle& style, bool isFallback = false) const; - std::vector errSet; // the errors happened - AliasMap aliasMap; // to save alias information temporarily - AjdustMap adjustMap; // to save adjust information temporarily - VariationMap variationMap; // to save variation information temporarily - TtcIndexMap ttcIndexMap; // to save 'index' information temporarily + static sk_sp matchFontStyle( + const std::vector>& typefaceSet, const SkFontStyle& pattern); - mutable std::mutex fontMutex; +private: + struct { + std::vector fFallback; + std::vector fGeneric; + std::unordered_map> fIndexMap; + + void emplaceFont(FontJson&& fj, sk_sp&& typeface) + { + if (fj.family.empty()) { + return; + } + Font f(std::move(fj)); + auto& targetVec = f.type == FontType::Generic ? fGeneric : fFallback; + auto& targetName = f.type == FontType::Generic ? f.alias : f.family; + // generic must have alias + auto exist = fIndexMap.find(targetName); + // if not found, insert directly + if (exist == fIndexMap.end()) { + fIndexMap.emplace(targetName, std::make_pair(targetVec.size(), f.type)); + targetVec.emplace_back(f); + targetVec.back().typefaces.emplace_back(typeface); + } else { + // if exist, check the style + targetVec[exist->second.first].typefaces.emplace_back(typeface); + } + } + + bool getIndexByFamilyName(const std::string& family, std::pair& res) const + { + if (fIndexMap.count(family)) { + res = fIndexMap.at(family); + return true; + } + return false; + } + + const std::vector& getSet(bool isFallback) const + { + return isFallback ? fFallback : fGeneric; + } + + void forAll(std::function func) + { + for (auto& f : fFallback) { + func(f); + } + for (auto& f : fGeneric) { + func(f); + } + } + } fFontCollection; + + std::vector fFontDir; // the directories where the fonts are + const SkTypeface_FreeType::Scanner& fFontScanner; + mutable std::mutex fFontMutex; int parseConfig(const char* fname); int checkConfigFile(const char* fname, Json::Value& root); int parseFontDir(const char* fname, const Json::Value& root); - int parseGeneric(const Json::Value& root); - int parseFallback(const Json::Value& root); - int parseFallbackItem(const Json::Value& root); - int parseAlias(const Json::Value& root, std::vector& aliasSet); - int parseAdjust(const Json::Value& root, std::vector& adjustSet); - int parseVariation(const Json::Value& root, std::vector& variationSet); - int parseTtcIndex(const Json::Value& root, const SkString& familyName); - void getAxisValues(const AxisDefinitions& axisDefinitions, - const VariationInfo& variation, FontInfo& font) const; - bool insertTtcFont(int count, FontInfo& font); - bool insertVariableFont(const AxisDefinitions& axisDefinitions, FontInfo& font); - TypefaceSet* getTypefaceSet(const SkString& familyName, SkString& specifiedName) const; - - int loadFont(const SkTypeface_FreeType::Scanner& scanner, const char* fname); - int scanFonts(const SkTypeface_FreeType::Scanner& fontScanner); - void resetGenericValue(); - void buildSubTypefaceSet(const std::shared_ptr& typefaceSet, - std::shared_ptr& subSet, const SkString& familyName, int weight); - void resetFallbackValue(); - int logErrInfo(int err, const char* key, Json::ValueType expected = Json::nullValue, - Json::ValueType actual = Json::nullValue); - static void sortTypefaceSet(std::shared_ptr& typefaceSet); + int parseFonts(const Json::Value& root); + + int loadFont(const char* fname, FontJson& font, sk_sp& typeface); + void loadHMSymbol(); + static void sortTypefaceSet(std::vector>& typefaceSet); static uint32_t getFontStyleDifference(const SkFontStyle& style1, const SkFontStyle& style2); - static char* getFileData(const char* fname, int& size); FontConfig_OHOS(const FontConfig_OHOS&) = delete; - FontConfig_OHOS& operator = (const FontConfig_OHOS&) = delete; + FontConfig_OHOS& operator=(const FontConfig_OHOS&) = delete; FontConfig_OHOS(FontConfig_OHOS&&) = delete; - FontConfig_OHOS& operator = (FontConfig_OHOS&&) = delete; + FontConfig_OHOS& operator=(FontConfig_OHOS&&) = delete; int checkProductFile(const char* fname); bool judgeFileExist(); }; diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.cpp b/src/ports/skia_ohos/SkFontMgr_ohos.cpp index cebfa80962..73bb792bf3 100644 --- a/src/ports/skia_ohos/SkFontMgr_ohos.cpp +++ b/src/ports/skia_ohos/SkFontMgr_ohos.cpp @@ -4,10 +4,11 @@ #include "SkFontMgr_ohos.h" -#include "include/core/SkData.h" -#include "SkTypeface_ohos.h" #include +#include "SkTypeface_ohos.h" +#include "include/core/SkData.h" + using namespace ErrorCode; /*! Constructor @@ -15,8 +16,8 @@ using namespace ErrorCode; */ SkFontMgr_OHOS::SkFontMgr_OHOS(const char* path) { - fontConfig = std::make_shared(fontScanner, path); - familyCount = fontConfig->getFamilyCount(); + fFontConfig = std::make_shared(fFontScanner, path); + fFamilyCount = fFontConfig->getFamilyCount(); } /*! To get the count of families @@ -24,7 +25,7 @@ SkFontMgr_OHOS::SkFontMgr_OHOS(const char* path) */ int SkFontMgr_OHOS::onCountFamilies() const { - return familyCount; + return fFamilyCount; } /*! To get the family name for a font style set @@ -34,10 +35,10 @@ int SkFontMgr_OHOS::onCountFamilies() const */ void SkFontMgr_OHOS::onGetFamilyName(int index, SkString* familyName) const { - if (fontConfig == nullptr || familyName == nullptr) { + if (fFontConfig == nullptr || familyName == nullptr) { return; } - fontConfig->getFamilyName(index, familyName); + fFontConfig->getFamilyName(static_cast(index), *familyName); } /*! To create an object of SkFontStyleSet @@ -48,13 +49,13 @@ void SkFontMgr_OHOS::onGetFamilyName(int index, SkString* familyName) const */ SkFontStyleSet* SkFontMgr_OHOS::onCreateStyleSet(int index) const { - if (fontConfig == nullptr) { + if (fFontConfig == nullptr) { return nullptr; } if (index < 0 || index >= this->countFamilies()) { return nullptr; } - return new SkFontStyleSet_OHOS(fontConfig, index); + return new SkFontStyleSet_OHOS(fFontConfig, index); } /*! To get a matched object of SkFontStyleSet @@ -66,20 +67,20 @@ SkFontStyleSet* SkFontMgr_OHOS::onCreateStyleSet(int index) const */ SkFontStyleSet* SkFontMgr_OHOS::onMatchFamily(const char familyName[]) const { - if (fontConfig == nullptr) { + if (fFontConfig == nullptr) { return nullptr; } // return default system font when familyName is null if (familyName == nullptr) { - return new SkFontStyleSet_OHOS(fontConfig, 0); + return new SkFontStyleSet_OHOS(fFontConfig, 0); } bool isFallback = false; - int index = fontConfig->getStyleIndex(familyName, isFallback); - if (index == -1) { + size_t index = 0; + if (!fFontConfig->getStyleIndex(familyName, isFallback, index)) { return nullptr; } - return new SkFontStyleSet_OHOS(fontConfig, index, isFallback); + return new SkFontStyleSet_OHOS(fFontConfig, index, isFallback); } /*! To get a matched typeface @@ -92,15 +93,15 @@ SkFontStyleSet* SkFontMgr_OHOS::onMatchFamily(const char familyName[]) const */ SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const { - if (fontConfig == nullptr) { + if (fFontConfig == nullptr) { return nullptr; } bool isFallback = false; - int styleIndex = 0; - if (familyName) { - styleIndex = fontConfig->getStyleIndex(familyName, isFallback); + size_t styleIndex = 0; + if (!fFontConfig->getStyleIndex(familyName, isFallback, styleIndex)) { + return nullptr; } - return SkSafeRef(fontConfig->getTypeface(styleIndex, style, isFallback)); + return SkSafeRef(fFontConfig->getTypeface(styleIndex, style, isFallback)); } struct SpecialUnicodeFamilyName { @@ -123,7 +124,7 @@ SkTypeface* SkFontMgr_OHOS::findSpecialTypeface(SkUnichar character, const SkFon if (character >= 0x4E00 && character <= 0x9FA5) { name.assign("HarmonyOS Sans SC"); } - + for (int i = 0; i < specialLists.size() && name.empty(); i++) { if (character == specialLists[i].unicode) { name.assign(specialLists[i].familyName); @@ -136,7 +137,7 @@ SkTypeface* SkFontMgr_OHOS::findSpecialTypeface(SkUnichar character, const SkFon } SkString fname(name.c_str()); - sk_sp typeface = fontConfig->getFallbackTypeface(fname, style); + sk_sp typeface = fFontConfig->getFallbackTypeface(fname, style); return SkSafeRef(typeface.get()); } @@ -155,58 +156,24 @@ SkTypeface* SkFontMgr_OHOS::findSpecialTypeface(SkUnichar character, const SkFon SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const { - if (fontConfig == nullptr) { + if (fFontConfig == nullptr) { return nullptr; } - const FallbackForMap& fallbackForMap = fontConfig->getFallbackForMap(); - const FallbackSet& fallbackSet = fontConfig->getFallbackSet(); - SkString defaultFamily(""); - SkString key = defaultFamily; - FallbackSetPos* item = nullptr; - if (familyName == nullptr) { - item = fallbackForMap.find(defaultFamily); + + auto retTp = findTypeface(style, bcp47, bcp47Count, character); + if (retTp != nullptr) { + return retTp; } else { - item = fallbackForMap.find(SkString(familyName)); - if (item) { - key = SkString(familyName); - } else { - item = fallbackForMap.find(defaultFamily); + retTp = findSpecialTypeface(character, style); + if (retTp != nullptr) { + return retTp; } - } - if (item == nullptr) { - LOGE("%s : '%s' must be a fallback key in the config file\n", - FontConfig_OHOS::errToString(ERROR_FAMILY_NOT_FOUND), defaultFamily.c_str()); - return nullptr; - } - while (true) { - if (bcp47Count > 0) { - SkTypeface* retTp = findTypeface(*item, style, bcp47, bcp47Count, character); - if (retTp) { - return retTp; + for (auto& f: fFontConfig->getFallbackSet()) { + const auto& tpSet = f.typefaces; + if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { + auto typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); + return SkSafeRef(typeface.get()); } - if (key == defaultFamily) { - bcp47Count = 0; - continue; - } - item = fallbackForMap.find(defaultFamily); - key = defaultFamily; - } else { - SkTypeface* retTp = findSpecialTypeface(character, style); - if (retTp != nullptr) { - return retTp; - } - for (unsigned int i = item->index; i < item->index + item->count && i < fallbackSet.size(); i++) { - const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); - if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { - sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); - return SkSafeRef(typeface.get()); - } - } - if (key == defaultFamily) { - break; - } - item = fallbackForMap.find(defaultFamily); - key = defaultFamily; } } return nullptr; @@ -222,14 +189,14 @@ SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyleCharacter(const char familyName[], * \return An object of typeface which is for the given character * \return Return null, if the typeface is not found for the given character */ -SkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, const SkFontStyle& style, +SkTypeface* SkFontMgr_OHOS::findTypeface(const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const { - if (bcp47Count == 0) { + if (bcp47Count == 0 || fFontConfig == nullptr) { return nullptr; } - const FallbackSet& fallbackSet = fontConfig->getFallbackSet(); + const auto& fallbackSet = fFontConfig->getFallbackSet(); // example bcp47 code : 'zh-Hans' : ('zh' : iso639 code, 'Hans' : iso15924 code) // iso639 code will be taken from bcp47 code, so that we can try to match // bcp47 or only iso639. Therefore totalCount need to be 'bcp47Count * 2' @@ -239,9 +206,8 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, con tps[i] = -1; } // find the families matching the bcp47 list - for (unsigned int i = fallbackItem.index; i < fallbackItem.index + fallbackItem.count - && i < fallbackSet.size(); i++) { - int ret = compareLangs(fallbackSet[i]->langs, bcp47, bcp47Count, tps); + for (auto i = 0; i < fallbackSet.size(); i += 1) { + int ret = compareLangs(fallbackSet[i].lang, bcp47, bcp47Count, tps); if (ret == -1) { continue; } @@ -252,8 +218,8 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, con if (tps[i] == -1) { continue; } - const TypefaceSet& tpSet = *(fallbackSet[tps[i]]->typefaceSet.get()); - if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { + const auto& tpSet = fallbackSet[tps[i]].typefaces; + if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); return SkSafeRef(typeface.get()); } @@ -262,8 +228,8 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, con if (tps[i] == -1) { continue; } - const TypefaceSet& tpSet = *(fallbackSet[tps[i]]->typefaceSet.get()); - if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { + const auto& tpSet = fallbackSet[tps[i]].typefaces; + if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); return SkSafeRef(typeface.get()); } @@ -279,7 +245,7 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, con * \return The index of language in bcp47, if matching happens * \n Return -1, if no language matching happens */ -int SkFontMgr_OHOS::compareLangs(const SkString& langs, const char* bcp47[], +int SkFontMgr_OHOS::compareLangs(const std::string& langs, const char* bcp47[], int bcp47Count, const int tps[]) const { /* @@ -302,8 +268,8 @@ int SkFontMgr_OHOS::compareLangs(const SkString& langs, const char* bcp47[], iso15924++; int len = iso15924 - 1 - bcp47[i]; SkString country(bcp47[i], len); - if (langs.find(iso15924) != -1 || - (strncmp(bcp47[i], "und", strlen("und")) && langs.find(country.c_str()) != -1)) { + if (langs.find(iso15924) != std::string::npos || + (strncmp(bcp47[i], "und", strlen("und")) != 0 && langs.find(country.c_str()) != -1)) { return i + bcp47Count; } } @@ -390,13 +356,12 @@ sk_sp SkFontMgr_OHOS::onMakeFromStreamArgs(std::unique_ptr SkFontMgr_OHOS::onMakeFromFile(const char path[], int ttcIndex) const { - if (fontConfig == nullptr) { + if (fFontConfig == nullptr) { return nullptr; } std::unique_ptr stream = SkStreamAsset::MakeFromFile(path); if (stream == nullptr) { - LOGE("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); return nullptr; } SkFontArguments args; @@ -423,37 +388,23 @@ sk_sp SkFontMgr_OHOS::onLegacyMakeTypeface(const char familyName[], if (typeface) { return sk_sp(typeface); } - LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); return nullptr; } #ifdef OHOS_SUPPORT std::vector> SkFontMgr_OHOS::onGetSystemFonts() const { - if (fontConfig == nullptr) { - return; + if (fFontConfig == nullptr) { + return {}; } std::vector> skTypefaces; - int familyCount = fontConfig->getFamilyCount(); - for (int i = 0; i < familyCount; ++i) { - int typefaceCount = fontConfig->getTypefaceCount(i); - for (int j = 0; j < typefaceCount; ++j) { - sk_sp typeface = fontConfig->getTypefaceSP(i, j); - if (typeface == nullptr) { - continue; - } - skTypefaces.emplace_back(typeface); + fFontConfig->forAll([&skTypefaces](const auto& f) { + for (auto& iter : f.typefaces) { + skTypefaces.emplace_back(iter); } - } + }); - for (auto& item : fontConfig->getFallbackSet()) { - if (item->typefaceSet != nullptr) { - for (auto& iter : *(item->typefaceSet)) { - skTypefaces.emplace_back(iter); - } - } - } - return std::move(skTypefaces); + return skTypefaces; } #endif @@ -475,22 +426,20 @@ sk_sp SkFontMgr_OHOS::makeTypeface(std::unique_ptr st fontInfo.fname.set(path); } if (axisCount == 0) { - if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, - &fontInfo.isFixedWidth, nullptr)) { - LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + if (!fFontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, + &fontInfo.style, &fontInfo.isFixedWidth, nullptr)) { return nullptr; } } else { - AxisDefinitions axisDef; - if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, - &fontInfo.isFixedWidth, &axisDef)) { - LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + SkTypeface_FreeType::Scanner::AxisDefinitions axisDef; + if (!fFontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, + &fontInfo.style, &fontInfo.isFixedWidth, &axisDef)) { return nullptr; } if (axisDef.count() > 0) { SkFixed axis[axisDef.count()]; - fontScanner.computeAxisValues(axisDef, args.getVariationDesignPosition(), - axis, fontInfo.familyName); + SkTypeface_FreeType::Scanner::computeAxisValues( + axisDef, args.getVariationDesignPosition(), axis, fontInfo.familyName); fontInfo.setAxisSet(axisCount, axis, axisDef.data()); fontInfo.style = fontInfo.computeFontStyle(); } @@ -511,29 +460,25 @@ int SkFontMgr_OHOS::GetFontFullName(int fontFd, std::vector &fullna std::unique_ptr stream = std::make_unique(SkData::MakeFromFD(fontFd)); int errorCode = SUCCESSED; int numFaces = 0; - if (!fontScanner.recognizedFont(stream.get(), &numFaces)) { - SkDebugf("Failed to recognizedFont"); + if (!fFontScanner.recognizedFont(stream.get(), &numFaces)) { return ERROR_TYPE_OTHER; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch = false; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning - if (!fontScanner.scanFont(stream.get(), faceIndex, &realname, &style, &isFixedPitch, nullptr)) { - SkDebugf("Failed to scanFont, faceIndex:%d", faceIndex); + if (!fFontScanner.scanFont(stream.get(), faceIndex, &realname, &style, &isFixedPitch, nullptr)) { errorCode = ERROR_TYPE_OTHER; break; } SkByteArray skFullName = {nullptr, 0}; - if (!fontScanner.GetTypefaceFullname(stream.get(), faceIndex, skFullName)) { - SkDebugf("Failed to get fullname, faceIndex:%d", faceIndex); + if (!fFontScanner.GetTypefaceFullname(stream.get(), faceIndex, skFullName)) { errorCode = ERROR_TYPE_OTHER; break; } else { fullnameVec.push_back(std::move(skFullName)); } } - SkDebugf("GetFontFullName end, errorCode:%d, numFaces:%d, size:%zu", errorCode, numFaces, fullnameVec.size()); return errorCode; } diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.h b/src/ports/skia_ohos/SkFontMgr_ohos.h index 26b86696f4..5aa2da6b4b 100644 --- a/src/ports/skia_ohos/SkFontMgr_ohos.h +++ b/src/ports/skia_ohos/SkFontMgr_ohos.h @@ -22,55 +22,52 @@ class SK_API SkFontMgr_OHOS : public SkFontMgr { public: explicit SkFontMgr_OHOS(const char* path = nullptr); - virtual ~SkFontMgr_OHOS() override = default; + ~SkFontMgr_OHOS() override = default; int GetFontFullName(int fontFd, std::vector &fullnameVec) override; protected: - virtual int onCountFamilies() const override; - virtual void onGetFamilyName(int index, SkString* familyName) const override; - virtual SkFontStyleSet* onCreateStyleSet(int index)const override; + int onCountFamilies() const override; + void onGetFamilyName(int index, SkString* familyName) const override; + SkFontStyleSet* onCreateStyleSet(int index)const override; - virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const override; + SkFontStyleSet* onMatchFamily(const char familyName[]) const override; - virtual SkTypeface* onMatchFamilyStyle(const char familyName[], + SkTypeface* onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const override; - virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style, + SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const override; - virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, + SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, const SkFontStyle& style) const override; - virtual sk_sp onMakeFromData(sk_sp data, int ttcIndex) const override; - virtual sk_sp onMakeFromStreamIndex(std::unique_ptr stream, + sk_sp onMakeFromData(sk_sp data, int ttcIndex) const override; + sk_sp onMakeFromStreamIndex(std::unique_ptr stream, int ttcIndex) const override; - virtual sk_sp onMakeFromStreamArgs(std::unique_ptr stream, + sk_sp onMakeFromStreamArgs(std::unique_ptr stream, const SkFontArguments& args) const override; - virtual sk_sp onMakeFromFile(const char path[], int ttcIndex) const override; + sk_sp onMakeFromFile(const char path[], int ttcIndex) const override; - virtual sk_sp onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override; + sk_sp onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override; #ifdef OHOS_SUPPORT std::vector> onGetSystemFonts() const override; #endif private: - std::shared_ptr fontConfig = nullptr; // the pointer of FontConfig_OHOS - SkTypeface_FreeType::Scanner fontScanner; // the scanner to parse a font file - int familyCount = 0; // the count of font style sets in generic family list + std::shared_ptr fFontConfig = nullptr; // the pointer of FontConfig_OHOS + SkTypeface_FreeType::Scanner fFontScanner; // the scanner to parse a font file + int fFamilyCount = 0; // the count of font style sets in generic family list - int compareLangs(const SkString& langs, const char* bcp47[], int bcp47Count, const int tps[]) const; + int compareLangs(const std::string& langs, const char* bcp47[], int bcp47Count, const int tps[]) const; sk_sp makeTypeface(std::unique_ptr stream, const SkFontArguments& args, const char path[]) const; - SkTypeface* findTypeface(const FallbackSetPos& fallbackItem, const SkFontStyle& style, + SkTypeface* findTypeface(const SkFontStyle& style, const char* bcp47[], int bcp47Count, SkUnichar character) const; SkTypeface* findSpecialTypeface(SkUnichar character, const SkFontStyle& style) const; }; -SK_API sk_sp SkFontMgr_New_OHOS(const char* path); -SK_API sk_sp SkFontMgr_New_OHOS() { - return SkFontMgr_New_OHOS("/system/etc/fontconfig.json"); -} +SK_API sk_sp SkFontMgr_New_OHOS(const char* path = "/system/etc/fontconfig.json"); #endif /* SKFONTMGR_OHOS_H */ diff --git a/src/ports/skia_ohos/SkFontStyleSet_ohos.h b/src/ports/skia_ohos/SkFontStyleSet_ohos.h index 1cb8bf8822..4b687661bd 100644 --- a/src/ports/skia_ohos/SkFontStyleSet_ohos.h +++ b/src/ports/skia_ohos/SkFontStyleSet_ohos.h @@ -17,11 +17,11 @@ class SK_API SkFontStyleSet_OHOS : public SkFontStyleSet { public: SkFontStyleSet_OHOS(const std::shared_ptr& fontConfig, int index, bool isFallback = false); - virtual ~SkFontStyleSet_OHOS() override = default; - virtual int count() override; - virtual void getStyle(int index, SkFontStyle* style, SkString* styleName) override; - virtual SkTypeface* createTypeface(int index) override; - virtual SkTypeface* matchStyle(const SkFontStyle& pattern) override; + ~SkFontStyleSet_OHOS() override = default; + int count() override; + void getStyle(int index, SkFontStyle* style, SkString* styleName) override; + SkTypeface* createTypeface(int index) override; + SkTypeface* matchStyle(const SkFontStyle& pattern) override; private: std::shared_ptr fontConfig_ = nullptr; // the object of FontConfig_OHOS int styleIndex = 0; // the index of the font style set diff --git a/src/ports/skia_ohos/SkTypeface_ohos.h b/src/ports/skia_ohos/SkTypeface_ohos.h index 7553f1d302..ba0764b608 100644 --- a/src/ports/skia_ohos/SkTypeface_ohos.h +++ b/src/ports/skia_ohos/SkTypeface_ohos.h @@ -18,19 +18,19 @@ class SK_API SkTypeface_OHOS : public SkTypeface_FreeType { public: SkTypeface_OHOS(const SkString& specifiedName, FontInfo& info); explicit SkTypeface_OHOS(FontInfo& info); - virtual ~SkTypeface_OHOS() override = default; + ~SkTypeface_OHOS() override = default; const FontInfo* getFontInfo() const; protected: - virtual std::unique_ptr onOpenStream(int* ttcIndex) const override; - virtual std::unique_ptr onMakeFontData() const override; - virtual void onGetFontDescriptor(SkFontDescriptor* descriptor, bool* isLocal) const override; - virtual void onGetFamilyName(SkString* familyName) const override; + std::unique_ptr onOpenStream(int* ttcIndex) const override; + std::unique_ptr onMakeFontData() const override; + void onGetFontDescriptor(SkFontDescriptor* descriptor, bool* isLocal) const override; + void onGetFamilyName(SkString* familyName) const override; #ifdef OHOS_SUPPORT - virtual void onGetFontPath(SkString* path) const override; + void onGetFontPath(SkString* path) const override; #endif - virtual sk_sp onMakeClone(const SkFontArguments& args) const override; + sk_sp onMakeClone(const SkFontArguments& args) const override; private: SkString specifiedName; // specified family name which is defined in the configuration file std::unique_ptr fontInfo; // the font information of this typeface -- Gitee From b9994f2a47d2559eb5e695495c46fef36b921fe1 Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Thu, 26 Dec 2024 09:26:45 +0800 Subject: [PATCH 2/6] add comment Signed-off-by: liumingxiang Change-Id: Idc154e0f070d5b3d8fdf6443ec9891015eabbafb --- src/ports/skia_ohos/FontConfig_ohos.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h index b6cf9f972c..d8450d8020 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.h +++ b/src/ports/skia_ohos/FontConfig_ohos.h @@ -73,10 +73,13 @@ public: std::string family; // only valid for the fallback font std::string lang; + // all the typefaces of this font std::vector> typefaces; + // may be redundant move explicit Font(FontJson&& info) - : slant(info.slant), weight(info.weight), alias(info.alias), family(info.family), lang(info.lang) + : slant(info.slant), weight(info.weight), alias(std::move(info.alias)), + family(std::move(info.family)), lang(std::move(info.lang)) { this->type = info.type >= FontType::NumOfFontType ? FontType::Generic : static_cast(info.type); } -- Gitee From 2197da3b3ad8897c735bcc0b36a672fe7e897888 Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Thu, 26 Dec 2024 17:10:04 +0800 Subject: [PATCH 3/6] fix lang compare Signed-off-by: liumingxiang Change-Id: I1fde35afe1de7c26ecfe27789c41c9fe1454be40 --- src/ports/skia_ohos/FontConfig_ohos.cpp | 62 +++++++++++++++++- src/ports/skia_ohos/FontConfig_ohos.h | 4 +- src/ports/skia_ohos/SkFontMgr_ohos.cpp | 87 +++++++++---------------- src/ports/skia_ohos/SkFontMgr_ohos.h | 2 +- 4 files changed, 93 insertions(+), 62 deletions(-) diff --git a/src/ports/skia_ohos/FontConfig_ohos.cpp b/src/ports/skia_ohos/FontConfig_ohos.cpp index 1e3ee5fc82..16aeea7a91 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.cpp +++ b/src/ports/skia_ohos/FontConfig_ohos.cpp @@ -80,11 +80,67 @@ int FontConfig_OHOS::getFamilyCount() const return fFontCollection.fGeneric.size(); } -const std::vector& FontConfig_OHOS::getFallbackSet() const +/*! To match the fallback typeface by the given style and character + * this function will traverse all the fallback typefaces + * \param character the character to be matched + * \param style the style to be matched + * \return the matched typeface +*/ +SkTypeface* FontConfig_OHOS::matchFallback(SkUnichar character, const SkFontStyle& style) const { - return fFontCollection.fFallback; + for (auto& f : fFontCollection.fFallback) { + const auto& typefaces = f.typefaces; + if (!typefaces.empty() && typefaces[0]->unicharToGlyph(character)) { + auto typeface = matchFontStyle(typefaces, style); + return SkSafeRef(typeface.get()); + } + } + return nullptr; +} + + +/*! To match the fallback typeface by the given index style and character + * this function only traverse the fallback typefaces in the given index + * \param index the index of fallback typefaces + * \param character the character to be matched + * \param style the style to be matched + * \return the matched typeface +*/ +SkTypeface* FontConfig_OHOS::matchFallback(size_t index, SkUnichar character, const SkFontStyle& style) const +{ + if (index >= fFontCollection.fFallback.size()) { + return nullptr; + } + const auto& typefaces = fFontCollection.fFallback[index].typefaces; + if (!typefaces.empty() && typefaces[0]->unicharToGlyph(character)) { + auto typeface = matchFontStyle(typefaces, style); + return SkSafeRef(typeface.get()); + } + return nullptr; +} + +/*! To match the fallback typeface by the given function + * this function will traverse all the fallback typefaces + * \param func the judge func, if the func return -1, it means the language tag is not matched + * \return the matched fallback typefaces' index set +*/ +std::vector FontConfig_OHOS::matchFallbackByBCP47(std::function func) const +{ + std::vector res; + for (size_t i = 0; i < fFontCollection.fFallback.size(); i += 1) { + if (func(fFontCollection.fFallback[i].lang) != -1) { + res.push_back(i); + } + } + return res; } +/*! To get a typeface by the given family name and style + * this function will traverse both the fallback and general typefaces + * \param familyName the family name of the fallback typeface + * \param style the style of the fallback typeface + * \return the matched typeface +*/ sk_sp FontConfig_OHOS::getFallbackTypeface(const SkString& familyName, const SkFontStyle& style) const { std::pair res; @@ -430,7 +486,7 @@ int FontConfig_OHOS::loadFont(const char* fname, FontJson& info, sk_sp& getFallbackSet() const; + SkTypeface* matchFallback(SkUnichar character, const SkFontStyle& style) const; + SkTypeface* matchFallback(size_t index, SkUnichar character, const SkFontStyle& style) const; + std::vector matchFallbackByBCP47(std::function) const; int getFamilyCount() const; int getDefaultFamily(SkString& familyName) const; int getFamilyName(size_t index, SkString& familyName) const; diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.cpp b/src/ports/skia_ohos/SkFontMgr_ohos.cpp index 73bb792bf3..ac8cd173e1 100644 --- a/src/ports/skia_ohos/SkFontMgr_ohos.cpp +++ b/src/ports/skia_ohos/SkFontMgr_ohos.cpp @@ -160,23 +160,15 @@ SkTypeface* SkFontMgr_OHOS::onMatchFamilyStyleCharacter(const char familyName[], return nullptr; } - auto retTp = findTypeface(style, bcp47, bcp47Count, character); - if (retTp != nullptr) { - return retTp; - } else { - retTp = findSpecialTypeface(character, style); - if (retTp != nullptr) { - return retTp; - } - for (auto& f: fFontConfig->getFallbackSet()) { - const auto& tpSet = f.typefaces; - if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { - auto typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); - return SkSafeRef(typeface.get()); - } - } + auto res = findTypeface(style, bcp47, bcp47Count, character); + if (res != nullptr) { + return res; } - return nullptr; + res = findSpecialTypeface(character, style); + if (res != nullptr) { + return res; + } + return fFontConfig->matchFallback(character, style); } /*! To find the matched typeface for the given parameters @@ -196,44 +188,30 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const SkFontStyle& style, return nullptr; } - const auto& fallbackSet = fFontConfig->getFallbackSet(); - // example bcp47 code : 'zh-Hans' : ('zh' : iso639 code, 'Hans' : iso15924 code) - // iso639 code will be taken from bcp47 code, so that we can try to match - // bcp47 or only iso639. Therefore totalCount need to be 'bcp47Count * 2' - int totalCount = bcp47Count * 2; - int tps[totalCount]; - for (int i = 0; i < totalCount; i++) { - tps[i] = -1; - } - // find the families matching the bcp47 list - for (auto i = 0; i < fallbackSet.size(); i += 1) { - int ret = compareLangs(fallbackSet[i].lang, bcp47, bcp47Count, tps); - if (ret == -1) { - continue; - } - tps[ret] = i; - } - // match typeface in families - for (int i = bcp47Count - 1; i >= 0; i--) { - if (tps[i] == -1) { - continue; - } - const auto& tpSet = fallbackSet[tps[i]].typefaces; - if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { - sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); - return SkSafeRef(typeface.get()); - } - } - for (int i = totalCount - 1; i >= bcp47Count; i--) { - if (tps[i] == -1) { - continue; + std::vector> funcs = { + [&bcp47, &bcp47Count](const std::string& langs) -> int { + for (int i = 0; i < bcp47Count; i++) { + if (langs == bcp47[i]) { + return i; + } + } + return -1; + }, + [&bcp47, &bcp47Count](const std::string& langs) -> int { + return SkFontMgr_OHOS::compareLangs(langs, bcp47, bcp47Count); } - const auto& tpSet = fallbackSet[tps[i]].typefaces; - if (!tpSet.empty() && tpSet[0]->unicharToGlyph(character) != 0) { - sk_sp typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); - return SkSafeRef(typeface.get()); + }; + + for (auto& func : funcs) { + auto set = fFontConfig->matchFallbackByBCP47(func); + for (auto& index : set) { + auto res = fFontConfig->matchFallback(index, character, style); + if (res != nullptr) { + return res; + } } } + return nullptr; } @@ -241,12 +219,10 @@ SkTypeface* SkFontMgr_OHOS::findTypeface(const SkFontStyle& style, * \param langs the supported languages by an typeface * \param bcp47 the array of bcp47 language to be matching * \param bcp47Count the array size of bcp47 - * \param tps an array of the index of typeface which is matching one value of bcp47 * \return The index of language in bcp47, if matching happens * \n Return -1, if no language matching happens */ -int SkFontMgr_OHOS::compareLangs(const std::string& langs, const char* bcp47[], - int bcp47Count, const int tps[]) const +int SkFontMgr_OHOS::compareLangs(const std::string& langs, const char* bcp47[], int bcp47Count) { /* * zh-Hans : ('zh' : iso639 code, 'Hans' : iso15924 code) @@ -255,9 +231,6 @@ int SkFontMgr_OHOS::compareLangs(const std::string& langs, const char* bcp47[], return -1; } for (int i = bcp47Count - 1; i >= 0; i--) { - if (tps[i] != -1) { - continue; - } if (langs.find(bcp47[i]) != -1) { return i; } else { diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.h b/src/ports/skia_ohos/SkFontMgr_ohos.h index 5aa2da6b4b..0d383112bf 100644 --- a/src/ports/skia_ohos/SkFontMgr_ohos.h +++ b/src/ports/skia_ohos/SkFontMgr_ohos.h @@ -59,7 +59,7 @@ private: SkTypeface_FreeType::Scanner fFontScanner; // the scanner to parse a font file int fFamilyCount = 0; // the count of font style sets in generic family list - int compareLangs(const std::string& langs, const char* bcp47[], int bcp47Count, const int tps[]) const; + static int compareLangs(const std::string& langs, const char* bcp47[], int bcp47Count); sk_sp makeTypeface(std::unique_ptr stream, const SkFontArguments& args, const char path[]) const; SkTypeface* findTypeface(const SkFontStyle& style, -- Gitee From 1343e52a32688fb0c41b5464144111a6a985ca7d Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Thu, 26 Dec 2024 21:56:29 +0800 Subject: [PATCH 4/6] fix dm compile error Signed-off-by: liumingxiang Change-Id: Ifca47020f317ede76a33c47a321f22c6a89e68af --- src/ports/skia_ohos/SkFontMgr_ohos.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.h b/src/ports/skia_ohos/SkFontMgr_ohos.h index 0d383112bf..c83b6ba4ad 100644 --- a/src/ports/skia_ohos/SkFontMgr_ohos.h +++ b/src/ports/skia_ohos/SkFontMgr_ohos.h @@ -10,10 +10,9 @@ #ifndef SKFONTMGR_OHOS_H #define SKFONTMGR_OHOS_H +#include "FontConfig_ohos.h" #include "SkFontDescriptor.h" #include "SkFontMgr.h" - -#include "FontConfig_ohos.h" #include "SkFontStyleSet_ohos.h" /*! @@ -68,6 +67,10 @@ private: SkTypeface* findSpecialTypeface(SkUnichar character, const SkFontStyle& style) const; }; -SK_API sk_sp SkFontMgr_New_OHOS(const char* path = "/system/etc/fontconfig.json"); +SK_API sk_sp SkFontMgr_New_OHOS(const char* path); +SK_API sk_sp SkFontMgr_New_OHOS() { + return SkFontMgr_New_OHOS("/system/etc/fontconfig_ohos.json"); +} + #endif /* SKFONTMGR_OHOS_H */ -- Gitee From 8c15fe87885bc7c2d3700fe84fb673ddd94f0f3d Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Fri, 27 Dec 2024 09:30:57 +0800 Subject: [PATCH 5/6] code review Signed-off-by: liumingxiang Change-Id: I145dbb246620e847a70831c76d04c1be257c11b8 --- src/ports/skia_ohos/FontConfig_ohos.cpp | 40 +++++++++++++------------ src/ports/skia_ohos/FontConfig_ohos.h | 6 ++-- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/ports/skia_ohos/FontConfig_ohos.cpp b/src/ports/skia_ohos/FontConfig_ohos.cpp index 16aeea7a91..1a68ac8b20 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.cpp +++ b/src/ports/skia_ohos/FontConfig_ohos.cpp @@ -191,7 +191,7 @@ int FontConfig_OHOS::getFamilyName(size_t index, SkString& familyName) const size_t FontConfig_OHOS::getTypefaceCount(size_t styleIndex, bool isFallback) const { auto& set = fFontCollection.getSet(isFallback); - return styleIndex < set.size() ? set[styleIndex].typefaces.size() : 0; + return (styleIndex < set.size()) ? set[styleIndex].typefaces.size() : 0; } /*! To get a typeface @@ -210,10 +210,10 @@ SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, size_t index, b sk_sp FontConfig_OHOS::getTypefaceSP(size_t styleIndex, size_t index, bool isFallback) const { - auto& set = fFontCollection.getSet(isFallback); - if (styleIndex <= set.size()) { + auto& fontSet = fFontCollection.getSet(isFallback); + if (styleIndex <= fontSet.size()) { // if index less than typefaces' size, return the ptr - return index < set[styleIndex].typefaces.size() ? set[styleIndex].typefaces[index] : nullptr; + return (index < fontSet[styleIndex].typefaces.size()) ? fontSet[styleIndex].typefaces[index] : nullptr; } return nullptr; } @@ -228,12 +228,12 @@ sk_sp FontConfig_OHOS::getTypefaceSP(size_t styleIndex, size_t */ SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, const SkFontStyle& style, bool isFallback) const { - auto& set = fFontCollection.getSet(isFallback); - if (styleIndex >= set.size()) { + auto& fontSet = fFontCollection.getSet(isFallback); + if (styleIndex >= fontSet.size()) { return nullptr; } - const std::vector>& pSet = set[styleIndex].typefaces; + const std::vector>& pSet = fontSet[styleIndex].typefaces; sk_sp tp = matchFontStyle(pSet, style); return tp.get(); } @@ -244,8 +244,9 @@ SkTypeface_OHOS* FontConfig_OHOS::getTypeface(size_t styleIndex, const SkFontSty * \param[out] isFallback to tell if the family is from generic or fallback to the caller. * \n isFallback is false, if the font style is from generic family list * \n isFallback is true, if the font style is from fallback family list + * \param[out] index the index of the font set * \return The index of the font style set - * \n Return -1, if 'familyName' is not found in the system + * \n Return false, if 'familyName' is not found in the system */ bool FontConfig_OHOS::getStyleIndex(const char* familyName, bool& isFallback, size_t& index) const { @@ -446,7 +447,6 @@ int FontConfig_OHOS::checkConfigFile(const char* fname, Json::Value& root) /*! To parse 'fontdir' attribute * \param root the root node of 'fontdir' * \return NO_ERROR successful - * \return ERROR_CONFIG_INVALID_VALUE_TYPE invalid value type */ int FontConfig_OHOS::parseFontDir(const char* fname, const Json::Value& root) { @@ -490,7 +490,7 @@ int FontConfig_OHOS::loadFont(const char* fname, FontJson& info, sk_sp(family, font); return NO_ERROR; @@ -499,12 +499,13 @@ int FontConfig_OHOS::loadFont(const char* fname, FontJson& info, sk_spParseConfigOfHmSymbol( - "hm_symbol_config_next.json", SkString(dir.c_str())) == - NO_ERROR) { - break; + if (HmSymbolConfig_OHOS::GetInstance()->ParseConfigOfHmSymbol( + "hm_symbol_config_next.json", SkString(dir.c_str())) == NO_ERROR) { + return; } } } @@ -547,10 +548,11 @@ bool FontConfig_OHOS::judgeFileExist() const char* fileName = node->d_name; int len = strlen(fileName); int suffixLen = strlen(".ttf"); - if (len < suffixLen || (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) != 0 && - strncmp(fileName + len - suffixLen, ".otf", suffixLen) != 0 && - strncmp(fileName + len - suffixLen, ".ttc", suffixLen) != 0 && - strncmp(fileName + len - suffixLen, ".otc", suffixLen) != 0)) { + if (len < suffixLen || + (strncmp(fileName + len - suffixLen, ".ttf", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".otf", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".ttc", suffixLen) != 0 && + strncmp(fileName + len - suffixLen, ".otc", suffixLen) != 0)) { continue; } haveFile = true; diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h index 6747fb5e27..59aab24a0f 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.h +++ b/src/ports/skia_ohos/FontConfig_ohos.h @@ -120,8 +120,8 @@ private: return; } Font f(std::move(fj)); - auto& targetVec = f.type == FontType::Generic ? fGeneric : fFallback; - auto& targetName = f.type == FontType::Generic ? f.alias : f.family; + auto& targetVec = (f.type == FontType::Generic) ? fGeneric : fFallback; + auto& targetName = (f.type == FontType::Generic) ? f.alias : f.family; // generic must have alias auto exist = fIndexMap.find(targetName); // if not found, insert directly @@ -130,7 +130,7 @@ private: targetVec.emplace_back(f); targetVec.back().typefaces.emplace_back(typeface); } else { - // if exist, check the style + // if exist, add the typeface to the font targetVec[exist->second.first].typefaces.emplace_back(typeface); } } -- Gitee From fec47234ec4a52d4bfe03160432cd3115c7dab15 Mon Sep 17 00:00:00 2001 From: liumingxiang Date: Fri, 27 Dec 2024 09:47:36 +0800 Subject: [PATCH 6/6] weight reset 0 Signed-off-by: liumingxiang Change-Id: I6895ff239fb7ec31d45abda8ab4126849cdacc16 --- src/ports/skia_ohos/FontConfig_ohos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h index 59aab24a0f..3af5dc5a7b 100644 --- a/src/ports/skia_ohos/FontConfig_ohos.h +++ b/src/ports/skia_ohos/FontConfig_ohos.h @@ -67,7 +67,7 @@ public: // the ttc font index, only valid for ttc font uint32_t index = 0; // only valid for the font with alias - uint32_t weight = 400; + uint32_t weight = 0; std::string alias; // essential for the every font std::string family; -- Gitee