1cb93a386Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved 2cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 3cb93a386Sopenharmony_ci// found in the LICENSE file. 4cb93a386Sopenharmony_ci 5cb93a386Sopenharmony_ci#include "SkFontMgr_ohos.h" 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci#include "include/core/SkData.h" 8cb93a386Sopenharmony_ci#include "SkTypeface_ohos.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ciusing namespace ErrorCode; 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci/*! Constructor 13cb93a386Sopenharmony_ci * \param path the full path of system font configuration document 14cb93a386Sopenharmony_ci */ 15cb93a386Sopenharmony_ciSkFontMgr_OHOS::SkFontMgr_OHOS(const char* path) 16cb93a386Sopenharmony_ci{ 17cb93a386Sopenharmony_ci fontConfig = std::make_shared<FontConfig_OHOS>(fontScanner, path); 18cb93a386Sopenharmony_ci familyCount = fontConfig->getFamilyCount(); 19cb93a386Sopenharmony_ci} 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci/*! To get the count of families 22cb93a386Sopenharmony_ci * \return The count of families in the system 23cb93a386Sopenharmony_ci */ 24cb93a386Sopenharmony_ciint SkFontMgr_OHOS::onCountFamilies() const 25cb93a386Sopenharmony_ci{ 26cb93a386Sopenharmony_ci return familyCount; 27cb93a386Sopenharmony_ci} 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci/*! To get the family name for a font style set 30cb93a386Sopenharmony_ci * \param index the index of a font style set 31cb93a386Sopenharmony_ci * \param[out] familyName the family name returned to the caller 32cb93a386Sopenharmony_ci * \n The family name will be reset to "", if index is out of range 33cb93a386Sopenharmony_ci */ 34cb93a386Sopenharmony_civoid SkFontMgr_OHOS::onGetFamilyName(int index, SkString* familyName) const 35cb93a386Sopenharmony_ci{ 36cb93a386Sopenharmony_ci if (fontConfig == nullptr || familyName == nullptr) { 37cb93a386Sopenharmony_ci return; 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci fontConfig->getFamilyName(index, familyName); 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci/*! To create an object of SkFontStyleSet 43cb93a386Sopenharmony_ci * \param index the index of a font style set 44cb93a386Sopenharmony_ci * \return The pointer of SkFontStyleSet 45cb93a386Sopenharmony_ci * \n Return null, if index is out of range 46cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 47cb93a386Sopenharmony_ci */ 48cb93a386Sopenharmony_ciSkFontStyleSet* SkFontMgr_OHOS::onCreateStyleSet(int index) const 49cb93a386Sopenharmony_ci{ 50cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 51cb93a386Sopenharmony_ci return nullptr; 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci if (index < 0 || index >= this->countFamilies()) { 54cb93a386Sopenharmony_ci return nullptr; 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci return new SkFontStyleSet_OHOS(fontConfig, index); 57cb93a386Sopenharmony_ci} 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci/*! To get a matched object of SkFontStyleSet 60cb93a386Sopenharmony_ci * \param familyName the family name of a font style set 61cb93a386Sopenharmony_ci * \return The pointer of SkFontStyleSet 62cb93a386Sopenharmony_ci * \n Return the default font style set, if family name is null 63cb93a386Sopenharmony_ci * \n Return null, if family name is not found 64cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 65cb93a386Sopenharmony_ci */ 66cb93a386Sopenharmony_ciSkFontStyleSet* SkFontMgr_OHOS::onMatchFamily(const char familyName[]) const 67cb93a386Sopenharmony_ci{ 68cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 69cb93a386Sopenharmony_ci return nullptr; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci // return default system font when familyName is null 72cb93a386Sopenharmony_ci if (familyName == nullptr) { 73cb93a386Sopenharmony_ci return new SkFontStyleSet_OHOS(fontConfig, 0); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci bool isFallback = false; 77cb93a386Sopenharmony_ci int index = fontConfig->getStyleIndex(familyName, isFallback); 78cb93a386Sopenharmony_ci if (index == -1) { 79cb93a386Sopenharmony_ci return nullptr; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci return new SkFontStyleSet_OHOS(fontConfig, index, isFallback); 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci/*! To get a matched typeface 85cb93a386Sopenharmony_ci * \param familyName the family name of a font style set 86cb93a386Sopenharmony_ci * \param style the font style to be matched 87cb93a386Sopenharmony_ci * \return An object of typeface which is closest matching to 'style' 88cb93a386Sopenharmony_ci * \n Return the typeface in the default font style set, if family name is null 89cb93a386Sopenharmony_ci * \n Return null, if family name is not found 90cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 91cb93a386Sopenharmony_ci */ 92cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_OHOS::onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const 93cb93a386Sopenharmony_ci{ 94cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 95cb93a386Sopenharmony_ci return nullptr; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci bool isFallback = false; 98cb93a386Sopenharmony_ci int styleIndex = 0; 99cb93a386Sopenharmony_ci if (familyName) { 100cb93a386Sopenharmony_ci styleIndex = fontConfig->getStyleIndex(familyName, isFallback); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci return SkSafeRef(fontConfig->getTypeface(styleIndex, style, isFallback)); 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci/*! To get a matched typeface 106cb93a386Sopenharmony_ci * \n Use the system fallback to find a typeface for the given character. 107cb93a386Sopenharmony_ci * \param familyName the family name which the typeface is fallback For 108cb93a386Sopenharmony_ci * \param style the font style to be matched 109cb93a386Sopenharmony_ci * \param bcp47 an array of languages which indicate the language of 'character' 110cb93a386Sopenharmony_ci * \param bcp47Count the array size of bcp47 111cb93a386Sopenharmony_ci * \param character a UTF8 value to be matched 112cb93a386Sopenharmony_ci * \return An object of typeface which is for the given character 113cb93a386Sopenharmony_ci * \return Return the typeface in the default fallback set, if familyName is null 114cb93a386Sopenharmony_ci * \return Return null, if the typeface is not found for the given character 115cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 116cb93a386Sopenharmony_ci */ 117cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_OHOS::onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style, 118cb93a386Sopenharmony_ci const char* bcp47[], int bcp47Count, SkUnichar character) const 119cb93a386Sopenharmony_ci{ 120cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 121cb93a386Sopenharmony_ci return nullptr; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci const FallbackForMap& fallbackForMap = fontConfig->getFallbackForMap(); 124cb93a386Sopenharmony_ci const FallbackSet& fallbackSet = fontConfig->getFallbackSet(); 125cb93a386Sopenharmony_ci SkString defaultFamily(""); 126cb93a386Sopenharmony_ci SkString key = defaultFamily; 127cb93a386Sopenharmony_ci FallbackSetPos* item = nullptr; 128cb93a386Sopenharmony_ci if (familyName == nullptr) { 129cb93a386Sopenharmony_ci item = fallbackForMap.find(defaultFamily); 130cb93a386Sopenharmony_ci } else { 131cb93a386Sopenharmony_ci item = fallbackForMap.find(SkString(familyName)); 132cb93a386Sopenharmony_ci if (item) { 133cb93a386Sopenharmony_ci key = SkString(familyName); 134cb93a386Sopenharmony_ci } else { 135cb93a386Sopenharmony_ci item = fallbackForMap.find(defaultFamily); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci if (item == nullptr) { 139cb93a386Sopenharmony_ci LOGE("%s : '%s' must be a fallback key in the config file\n", 140cb93a386Sopenharmony_ci FontConfig_OHOS::errToString(ERROR_FAMILY_NOT_FOUND), defaultFamily.c_str()); 141cb93a386Sopenharmony_ci return nullptr; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci while (true) { 144cb93a386Sopenharmony_ci if (bcp47Count > 0) { 145cb93a386Sopenharmony_ci SkTypeface* retTp = findTypeface(*item, style, bcp47, bcp47Count, character); 146cb93a386Sopenharmony_ci if (retTp) { 147cb93a386Sopenharmony_ci return retTp; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci if (key == defaultFamily) { 150cb93a386Sopenharmony_ci bcp47Count = 0; 151cb93a386Sopenharmony_ci continue; 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci item = fallbackForMap.find(defaultFamily); 154cb93a386Sopenharmony_ci key = defaultFamily; 155cb93a386Sopenharmony_ci } else { 156cb93a386Sopenharmony_ci for (unsigned int i = item->index; i < item->index + item->count && i < fallbackSet.size(); i++) { 157cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); 158cb93a386Sopenharmony_ci if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { 159cb93a386Sopenharmony_ci sk_sp<SkTypeface> typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); 160cb93a386Sopenharmony_ci return SkSafeRef(typeface.get()); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci if (key == defaultFamily) { 164cb93a386Sopenharmony_ci break; 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci item = fallbackForMap.find(defaultFamily); 167cb93a386Sopenharmony_ci key = defaultFamily; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci return nullptr; 171cb93a386Sopenharmony_ci} 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci/*! To find the matched typeface for the given parameters 174cb93a386Sopenharmony_ci * \n Use the system fallback to find a typeface for the given character. 175cb93a386Sopenharmony_ci * \param fallbackItem the fallback items in which to find the typeface 176cb93a386Sopenharmony_ci * \param style the font style to be matched 177cb93a386Sopenharmony_ci * \param bcp47 an array of languages which indicate the language of 'character' 178cb93a386Sopenharmony_ci * \param bcp47Count the array size of bcp47 179cb93a386Sopenharmony_ci * \param character a UTF8 value to be matched 180cb93a386Sopenharmony_ci * \return An object of typeface which is for the given character 181cb93a386Sopenharmony_ci * \return Return null, if the typeface is not found for the given character 182cb93a386Sopenharmony_ci */ 183cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_OHOS::findTypeface(const FallbackSetPos& fallbackItem, const SkFontStyle& style, 184cb93a386Sopenharmony_ci const char* bcp47[], int bcp47Count, SkUnichar character) const 185cb93a386Sopenharmony_ci{ 186cb93a386Sopenharmony_ci if (bcp47Count == 0) { 187cb93a386Sopenharmony_ci return nullptr; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci const FallbackSet& fallbackSet = fontConfig->getFallbackSet(); 191cb93a386Sopenharmony_ci // example bcp47 code : 'zh-Hans' : ('zh' : iso639 code, 'Hans' : iso15924 code) 192cb93a386Sopenharmony_ci // iso639 code will be taken from bcp47 code, so that we can try to match 193cb93a386Sopenharmony_ci // bcp47 or only iso639. Therefore totalCount need to be 'bcp47Count * 2' 194cb93a386Sopenharmony_ci int totalCount = bcp47Count * 2; 195cb93a386Sopenharmony_ci int tps[totalCount]; 196cb93a386Sopenharmony_ci for (int i = 0; i < totalCount; i++) { 197cb93a386Sopenharmony_ci tps[i] = -1; 198cb93a386Sopenharmony_ci } 199cb93a386Sopenharmony_ci // find the families matching the bcp47 list 200cb93a386Sopenharmony_ci for (unsigned int i = fallbackItem.index; i < fallbackItem.index + fallbackItem.count 201cb93a386Sopenharmony_ci && i < fallbackSet.size(); i++) { 202cb93a386Sopenharmony_ci int ret = compareLangs(fallbackSet[i]->langs, bcp47, bcp47Count, tps); 203cb93a386Sopenharmony_ci if (ret == -1) { 204cb93a386Sopenharmony_ci continue; 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci tps[ret] = i; 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci // match typeface in families 209cb93a386Sopenharmony_ci for (int i = bcp47Count - 1; i >= 0; i--) { 210cb93a386Sopenharmony_ci if (tps[i] == -1) { 211cb93a386Sopenharmony_ci continue; 212cb93a386Sopenharmony_ci } 213cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(fallbackSet[tps[i]]->typefaceSet.get()); 214cb93a386Sopenharmony_ci if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { 215cb93a386Sopenharmony_ci sk_sp<SkTypeface> typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); 216cb93a386Sopenharmony_ci return SkSafeRef(typeface.get()); 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci for (int i = totalCount - 1; i >= bcp47Count; i--) { 220cb93a386Sopenharmony_ci if (tps[i] == -1) { 221cb93a386Sopenharmony_ci continue; 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci const TypefaceSet& tpSet = *(fallbackSet[tps[i]]->typefaceSet.get()); 224cb93a386Sopenharmony_ci if (tpSet.size() > 0 && tpSet[0]->unicharToGlyph(character) != 0) { 225cb93a386Sopenharmony_ci sk_sp<SkTypeface> typeface = FontConfig_OHOS::matchFontStyle(tpSet, style); 226cb93a386Sopenharmony_ci return SkSafeRef(typeface.get()); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci return nullptr; 230cb93a386Sopenharmony_ci} 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci/*! To compare the languages of an typeface with a bcp47 list 233cb93a386Sopenharmony_ci * \param langs the supported languages by an typeface 234cb93a386Sopenharmony_ci * \param bcp47 the array of bcp47 language to be matching 235cb93a386Sopenharmony_ci * \param bcp47Count the array size of bcp47 236cb93a386Sopenharmony_ci * \param tps an array of the index of typeface which is matching one value of bcp47 237cb93a386Sopenharmony_ci * \return The index of language in bcp47, if matching happens 238cb93a386Sopenharmony_ci * \n Return -1, if no language matching happens 239cb93a386Sopenharmony_ci */ 240cb93a386Sopenharmony_ciint SkFontMgr_OHOS::compareLangs(const SkString& langs, const char* bcp47[], 241cb93a386Sopenharmony_ci int bcp47Count, const int tps[]) const 242cb93a386Sopenharmony_ci{ 243cb93a386Sopenharmony_ci /* 244cb93a386Sopenharmony_ci * zh-Hans : ('zh' : iso639 code, 'Hans' : iso15924 code) 245cb93a386Sopenharmony_ci */ 246cb93a386Sopenharmony_ci if (bcp47 == nullptr || bcp47Count == 0) { 247cb93a386Sopenharmony_ci return -1; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci for (int i = bcp47Count - 1; i >= 0; i--) { 250cb93a386Sopenharmony_ci if (tps[i] != -1) { 251cb93a386Sopenharmony_ci continue; 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci if (langs.find(bcp47[i]) != -1) { 254cb93a386Sopenharmony_ci return i; 255cb93a386Sopenharmony_ci } else { 256cb93a386Sopenharmony_ci const char* iso15924 = strrchr(bcp47[i], '-'); 257cb93a386Sopenharmony_ci if (iso15924 == nullptr) { 258cb93a386Sopenharmony_ci continue; 259cb93a386Sopenharmony_ci } 260cb93a386Sopenharmony_ci iso15924++; 261cb93a386Sopenharmony_ci int len = iso15924 - 1 - bcp47[i]; 262cb93a386Sopenharmony_ci SkString country(bcp47[i], len); 263cb93a386Sopenharmony_ci if (langs.find(iso15924) != -1 || 264cb93a386Sopenharmony_ci (strncmp(bcp47[i], "und", strlen("und")) && langs.find(country.c_str()) != -1)) { 265cb93a386Sopenharmony_ci return i + bcp47Count; 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci } 268cb93a386Sopenharmony_ci } 269cb93a386Sopenharmony_ci return -1; 270cb93a386Sopenharmony_ci} 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci/*! To get a matched typeface 273cb93a386Sopenharmony_ci * \param typeface the given typeface with which the returned object should be in the same style set 274cb93a386Sopenharmony_ci * \param style the font style to be matching 275cb93a386Sopenharmony_ci * \return The object of typeface which is closest matching to the given 'style' 276cb93a386Sopenharmony_ci * \n Return null, if the family name of the given typeface is not found in the system 277cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 278cb93a386Sopenharmony_ci */ 279cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_OHOS::onMatchFaceStyle(const SkTypeface* typeface, const SkFontStyle& style) const 280cb93a386Sopenharmony_ci{ 281cb93a386Sopenharmony_ci if (typeface == nullptr) { 282cb93a386Sopenharmony_ci return nullptr; 283cb93a386Sopenharmony_ci } 284cb93a386Sopenharmony_ci SkString familyName; 285cb93a386Sopenharmony_ci typeface->getFamilyName(&familyName); 286cb93a386Sopenharmony_ci return this->onMatchFamilyStyle(familyName.c_str(), style); 287cb93a386Sopenharmony_ci} 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci/*! To create a typeface from the specified data and TTC index 290cb93a386Sopenharmony_ci * \param data the data to be parsed 291cb93a386Sopenharmony_ci * \param index the index of typeface. 0 for none 292cb93a386Sopenharmony_ci * \return The object of typeface, if successful 293cb93a386Sopenharmony_ci * \n Return null if the data is not recognized. 294cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 295cb93a386Sopenharmony_ci */ 296cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const 297cb93a386Sopenharmony_ci{ 298cb93a386Sopenharmony_ci if (data == nullptr) { 299cb93a386Sopenharmony_ci return nullptr; 300cb93a386Sopenharmony_ci } 301cb93a386Sopenharmony_ci std::unique_ptr<SkMemoryStream> memoryStream = std::make_unique<SkMemoryStream>(data); 302cb93a386Sopenharmony_ci SkFontArguments args; 303cb93a386Sopenharmony_ci args.setCollectionIndex(ttcIndex); 304cb93a386Sopenharmony_ci return this->makeTypeface(std::move(memoryStream), args, nullptr); 305cb93a386Sopenharmony_ci} 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_ci/*! To create a typeface from the specified stream and TTC index 308cb93a386Sopenharmony_ci * \param data the stream to be parsed 309cb93a386Sopenharmony_ci * \param index the index of typeface. 0 for none 310cb93a386Sopenharmony_ci * \return The object of typeface, if successful 311cb93a386Sopenharmony_ci * \n Return null if the stream is not recognized. 312cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 313cb93a386Sopenharmony_ci */ 314cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, 315cb93a386Sopenharmony_ci int ttcIndex) const 316cb93a386Sopenharmony_ci{ 317cb93a386Sopenharmony_ci if (stream == nullptr) { 318cb93a386Sopenharmony_ci return nullptr; 319cb93a386Sopenharmony_ci } 320cb93a386Sopenharmony_ci SkFontArguments args; 321cb93a386Sopenharmony_ci args.setCollectionIndex(ttcIndex); 322cb93a386Sopenharmony_ci return this->makeTypeface(std::move(stream), args, nullptr); 323cb93a386Sopenharmony_ci} 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci/*! To create a typeface from the specified stream and font arguments 326cb93a386Sopenharmony_ci * \param data the stream to be parsed 327cb93a386Sopenharmony_ci * \param args the arguments of font 328cb93a386Sopenharmony_ci * \return The object of typeface, if successful 329cb93a386Sopenharmony_ci * \n Return null if the stream is not recognized. 330cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 331cb93a386Sopenharmony_ci */ 332cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream, 333cb93a386Sopenharmony_ci const SkFontArguments& args) const 334cb93a386Sopenharmony_ci{ 335cb93a386Sopenharmony_ci if (stream == nullptr) { 336cb93a386Sopenharmony_ci return nullptr; 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci return this->makeTypeface(std::move(stream), args, nullptr); 340cb93a386Sopenharmony_ci} 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci/*! To create a typeface from the specified font file and TTC index 343cb93a386Sopenharmony_ci * \param path the full path of the given font file 344cb93a386Sopenharmony_ci * \param ttcIndex the index of typeface in a ttc font file. 0 means none. 345cb93a386Sopenharmony_ci * \return The object of typeface, if successful 346cb93a386Sopenharmony_ci * \n Return null if the font file is not found or the content of file is not recognized. 347cb93a386Sopenharmony_ci * \note The caller must call unref() on the returned object if it's not null 348cb93a386Sopenharmony_ci */ 349cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::onMakeFromFile(const char path[], int ttcIndex) const 350cb93a386Sopenharmony_ci{ 351cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 352cb93a386Sopenharmony_ci return nullptr; 353cb93a386Sopenharmony_ci } 354cb93a386Sopenharmony_ci 355cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream = SkStreamAsset::MakeFromFile(path); 356cb93a386Sopenharmony_ci if (stream == nullptr) { 357cb93a386Sopenharmony_ci LOGE("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); 358cb93a386Sopenharmony_ci return nullptr; 359cb93a386Sopenharmony_ci } 360cb93a386Sopenharmony_ci SkFontArguments args; 361cb93a386Sopenharmony_ci args.setCollectionIndex(ttcIndex); 362cb93a386Sopenharmony_ci return this->makeTypeface(std::move(stream), args, path); 363cb93a386Sopenharmony_ci} 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_ci/*! To get a typeface matching the specified family and style 366cb93a386Sopenharmony_ci * \param familyName the specified name to be matching 367cb93a386Sopenharmony_ci * \param style the specified style to be matching 368cb93a386Sopenharmony_ci * \return The object of typeface which is the closest matching 'style' when the familyName is found 369cb93a386Sopenharmony_ci * \return Return a typeface from the default family, if familyName is not found 370cb93a386Sopenharmony_ci * \return Return null, if there is no any typeface in the system 371cb93a386Sopenharmony_ci * \note The caller must caller unref() on the returned object is it's not null 372cb93a386Sopenharmony_ci */ 373cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const 374cb93a386Sopenharmony_ci{ 375cb93a386Sopenharmony_ci SkTypeface* typeface = this->onMatchFamilyStyle(familyName, style); 376cb93a386Sopenharmony_ci // if familyName is not found, then try the default family 377cb93a386Sopenharmony_ci if (typeface == nullptr && familyName != nullptr) { 378cb93a386Sopenharmony_ci typeface = this->onMatchFamilyStyle(nullptr, style); 379cb93a386Sopenharmony_ci } 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci if (typeface) { 382cb93a386Sopenharmony_ci return sk_sp<SkTypeface>(typeface); 383cb93a386Sopenharmony_ci } 384cb93a386Sopenharmony_ci LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); 385cb93a386Sopenharmony_ci return nullptr; 386cb93a386Sopenharmony_ci} 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci#ifdef OHOS_SUPPORT 389cb93a386Sopenharmony_cistd::vector<sk_sp<SkTypeface>> SkFontMgr_OHOS::onGetSystemFonts() const 390cb93a386Sopenharmony_ci{ 391cb93a386Sopenharmony_ci if (fontConfig == nullptr) { 392cb93a386Sopenharmony_ci return; 393cb93a386Sopenharmony_ci } 394cb93a386Sopenharmony_ci std::vector<sk_sp<SkTypeface>> skTypefaces; 395cb93a386Sopenharmony_ci int familyCount = fontConfig->getFamilyCount(); 396cb93a386Sopenharmony_ci for (int i = 0; i < familyCount; ++i) { 397cb93a386Sopenharmony_ci int typefaceCount = fontConfig->getTypefaceCount(i); 398cb93a386Sopenharmony_ci for (int j = 0; j < typefaceCount; ++j) { 399cb93a386Sopenharmony_ci sk_sp<SkTypeface_OHOS> typeface = fontConfig->getTypefaceSP(i, j); 400cb93a386Sopenharmony_ci if (typeface == nullptr) { 401cb93a386Sopenharmony_ci continue; 402cb93a386Sopenharmony_ci } 403cb93a386Sopenharmony_ci skTypefaces.emplace_back(typeface); 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ci for (auto& item : fontConfig->getFallbackSet()) { 408cb93a386Sopenharmony_ci if (item->typefaceSet != nullptr) { 409cb93a386Sopenharmony_ci for (auto& iter : *(item->typefaceSet)) { 410cb93a386Sopenharmony_ci skTypefaces.emplace_back(iter); 411cb93a386Sopenharmony_ci } 412cb93a386Sopenharmony_ci } 413cb93a386Sopenharmony_ci } 414cb93a386Sopenharmony_ci return std::move(skTypefaces); 415cb93a386Sopenharmony_ci} 416cb93a386Sopenharmony_ci#endif 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci/*! To make a typeface from the specified stream and font arguments 419cb93a386Sopenharmony_ci * \param stream the specified stream to be parsed to get font information 420cb93a386Sopenharmony_ci * \param args the arguments of index or axis values 421cb93a386Sopenharmony_ci * \param path the fullname of font file 422cb93a386Sopenharmony_ci * \return The object of typeface if successful 423cb93a386Sopenharmony_ci * \n Return null, if the stream is not recognized 424cb93a386Sopenharmony_ci */ 425cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_OHOS::makeTypeface(std::unique_ptr<SkStreamAsset> stream, 426cb93a386Sopenharmony_ci const SkFontArguments& args, const char path[]) const 427cb93a386Sopenharmony_ci{ 428cb93a386Sopenharmony_ci FontInfo fontInfo; 429cb93a386Sopenharmony_ci int ttcIndex = args.getCollectionIndex(); 430cb93a386Sopenharmony_ci int axisCount = args.getVariationDesignPosition().coordinateCount; 431cb93a386Sopenharmony_ci 432cb93a386Sopenharmony_ci if (path) { 433cb93a386Sopenharmony_ci fontInfo.fname.set(path); 434cb93a386Sopenharmony_ci } 435cb93a386Sopenharmony_ci if (axisCount == 0) { 436cb93a386Sopenharmony_ci if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, 437cb93a386Sopenharmony_ci &fontInfo.isFixedWidth, nullptr)) { 438cb93a386Sopenharmony_ci LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); 439cb93a386Sopenharmony_ci return nullptr; 440cb93a386Sopenharmony_ci } 441cb93a386Sopenharmony_ci } else { 442cb93a386Sopenharmony_ci AxisDefinitions axisDef; 443cb93a386Sopenharmony_ci if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, 444cb93a386Sopenharmony_ci &fontInfo.isFixedWidth, &axisDef)) { 445cb93a386Sopenharmony_ci LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); 446cb93a386Sopenharmony_ci return nullptr; 447cb93a386Sopenharmony_ci } 448cb93a386Sopenharmony_ci if (axisDef.count() > 0) { 449cb93a386Sopenharmony_ci SkFixed axis[axisDef.count()]; 450cb93a386Sopenharmony_ci fontScanner.computeAxisValues(axisDef, args.getVariationDesignPosition(), 451cb93a386Sopenharmony_ci axis, fontInfo.familyName); 452cb93a386Sopenharmony_ci fontInfo.setAxisSet(axisCount, axis, axisDef.data()); 453cb93a386Sopenharmony_ci fontInfo.style = fontInfo.computeFontStyle(); 454cb93a386Sopenharmony_ci } 455cb93a386Sopenharmony_ci } 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ci fontInfo.stream = std::move(stream); 458cb93a386Sopenharmony_ci fontInfo.index = ttcIndex; 459cb93a386Sopenharmony_ci return sk_make_sp<SkTypeface_OHOS>(fontInfo); 460cb93a386Sopenharmony_ci} 461cb93a386Sopenharmony_ci 462cb93a386Sopenharmony_ci/*! Get the fullname of font 463cb93a386Sopenharmony_ci * \param fontFd The file descriptor for the font file 464cb93a386Sopenharmony_ci * \param fullnameVec Read the font fullname list 465cb93a386Sopenharmony_ci * \return Returns Whether the fullnameVec was successfully obtained, 0 means success, see FontCheckCode for details 466cb93a386Sopenharmony_ci */ 467cb93a386Sopenharmony_ciint SkFontMgr_OHOS::GetFontFullName(int fontFd, std::vector<SkByteArray> &fullnameVec) 468cb93a386Sopenharmony_ci{ 469cb93a386Sopenharmony_ci std::unique_ptr<SkMemoryStream> stream = std::make_unique<SkMemoryStream>(SkData::MakeFromFD(fontFd)); 470cb93a386Sopenharmony_ci int errorCode = SUCCESSED; 471cb93a386Sopenharmony_ci int numFaces = 0; 472cb93a386Sopenharmony_ci if (!fontScanner.recognizedFont(stream.get(), &numFaces)) { 473cb93a386Sopenharmony_ci SkDebugf("Failed to recognizedFont"); 474cb93a386Sopenharmony_ci return ERROR_TYPE_OTHER; 475cb93a386Sopenharmony_ci } 476cb93a386Sopenharmony_ci for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 477cb93a386Sopenharmony_ci bool isFixedPitch = false; 478cb93a386Sopenharmony_ci SkString realname; 479cb93a386Sopenharmony_ci SkFontStyle style = SkFontStyle(); // avoid uninitialized warning 480cb93a386Sopenharmony_ci if (!fontScanner.scanFont(stream.get(), faceIndex, &realname, &style, &isFixedPitch, nullptr)) { 481cb93a386Sopenharmony_ci SkDebugf("Failed to scanFont, faceIndex:%d", faceIndex); 482cb93a386Sopenharmony_ci errorCode = ERROR_TYPE_OTHER; 483cb93a386Sopenharmony_ci break; 484cb93a386Sopenharmony_ci } 485cb93a386Sopenharmony_ci SkByteArray skFullName = {nullptr, 0}; 486cb93a386Sopenharmony_ci if (!fontScanner.GetTypefaceFullname(stream.get(), faceIndex, skFullName)) { 487cb93a386Sopenharmony_ci SkDebugf("Failed to get fullname, faceIndex:%d", faceIndex); 488cb93a386Sopenharmony_ci errorCode = ERROR_TYPE_OTHER; 489cb93a386Sopenharmony_ci break; 490cb93a386Sopenharmony_ci } else { 491cb93a386Sopenharmony_ci fullnameVec.push_back(std::move(skFullName)); 492cb93a386Sopenharmony_ci } 493cb93a386Sopenharmony_ci } 494cb93a386Sopenharmony_ci SkDebugf("GetFontFullName end, errorCode:%d, numFaces:%d, size:%zu", errorCode, numFaces, fullnameVec.size()); 495cb93a386Sopenharmony_ci return errorCode; 496cb93a386Sopenharmony_ci} 497cb93a386Sopenharmony_ci 498cb93a386Sopenharmony_ci/*! To create SkFontMgr object for Harmony platform 499cb93a386Sopenharmony_ci * \param fname the full name of system font configuration documents 500cb93a386Sopenharmony_ci * \return The object of SkFontMgr_OHOS 501cb93a386Sopenharmony_ci */ 502cb93a386Sopenharmony_cisk_sp<SkFontMgr> SkFontMgr_New_OHOS(const char* fname) 503cb93a386Sopenharmony_ci{ 504cb93a386Sopenharmony_ci return sk_make_sp<SkFontMgr_OHOS>(fname); 505cb93a386Sopenharmony_ci} 506