1e9297d28Sopenharmony_ci/* 2e9297d28Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3e9297d28Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e9297d28Sopenharmony_ci * you may not use this file except in compliance with the License. 5e9297d28Sopenharmony_ci * You may obtain a copy of the License at 6e9297d28Sopenharmony_ci * 7e9297d28Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e9297d28Sopenharmony_ci * 9e9297d28Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e9297d28Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e9297d28Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e9297d28Sopenharmony_ci * See the License for the specific language governing permissions and 13e9297d28Sopenharmony_ci * limitations under the License. 14e9297d28Sopenharmony_ci */ 15e9297d28Sopenharmony_ci 16e9297d28Sopenharmony_ci#include "font_parser.h" 17e9297d28Sopenharmony_ci 18e9297d28Sopenharmony_ci#include <codecvt> 19e9297d28Sopenharmony_ci#include <dirent.h> 20e9297d28Sopenharmony_ci#include <map> 21e9297d28Sopenharmony_ci#include <list> 22e9297d28Sopenharmony_ci#include <algorithm> 23e9297d28Sopenharmony_ci#include <iostream> 24e9297d28Sopenharmony_ci#include <iomanip> 25e9297d28Sopenharmony_ci#include <securec.h> 26e9297d28Sopenharmony_ci#ifdef BUILD_NON_SDK_VER 27e9297d28Sopenharmony_ci#include <iconv.h> 28e9297d28Sopenharmony_ci#endif 29e9297d28Sopenharmony_ci 30e9297d28Sopenharmony_ci#include "font_config.h" 31e9297d28Sopenharmony_ci#include "texgine/utils/exlog.h" 32e9297d28Sopenharmony_ci 33e9297d28Sopenharmony_cinamespace OHOS { 34e9297d28Sopenharmony_cinamespace Rosen { 35e9297d28Sopenharmony_cinamespace TextEngine { 36e9297d28Sopenharmony_ci#define SUCCESSED 0 37e9297d28Sopenharmony_ci#define FAILED 1 38e9297d28Sopenharmony_ci 39e9297d28Sopenharmony_ci#define FONT_CONFIG_FILE "/system/fonts/visibility_list.json" 40e9297d28Sopenharmony_ci#define FONT_CONFIG_PROD_FILE "/sys_prod/fonts/visibility_list.json" 41e9297d28Sopenharmony_ci#define SYSTEM_FONT_PATH "/system/fonts/" 42e9297d28Sopenharmony_ci#define SYS_PROD_FONT_PATH "/sys_prod/fonts/" 43e9297d28Sopenharmony_ci 44e9297d28Sopenharmony_ci#define HALF(a) ((a) / 2) 45e9297d28Sopenharmony_ci 46e9297d28Sopenharmony_ciFontParser::FontParser() 47e9297d28Sopenharmony_ci{ 48e9297d28Sopenharmony_ci data_ = nullptr; 49e9297d28Sopenharmony_ci length_ = 0; 50e9297d28Sopenharmony_ci fontSet_.clear(); 51e9297d28Sopenharmony_ci FontConfig fontConfig(FONT_CONFIG_FILE); 52e9297d28Sopenharmony_ci auto fonts = fontConfig.GetFontSet(); 53e9297d28Sopenharmony_ci fontSet_.insert(fontSet_.end(), fonts.begin(), fonts.end()); 54e9297d28Sopenharmony_ci FontConfig fontProdConfig(FONT_CONFIG_PROD_FILE); 55e9297d28Sopenharmony_ci auto prodFonts = fontProdConfig.GetFontSet(); 56e9297d28Sopenharmony_ci fontSet_.insert(fontSet_.end(), prodFonts.begin(), prodFonts.end()); 57e9297d28Sopenharmony_ci} 58e9297d28Sopenharmony_ci 59e9297d28Sopenharmony_civoid FontParser::ProcessCmapTable(const struct CmapTables* cmapTable, FontParser::FontDescriptor& fontDescriptor) 60e9297d28Sopenharmony_ci{ 61e9297d28Sopenharmony_ci for (auto i = 0; i < cmapTable->numTables.Get(); ++i) { 62e9297d28Sopenharmony_ci const auto& record = cmapTable->encodingRecords[i]; 63e9297d28Sopenharmony_ci FontParser::PlatformId platformId = static_cast<FontParser::PlatformId>(record.platformID.Get()); 64e9297d28Sopenharmony_ci FontParser::EncodingIdWin encodingId = static_cast<FontParser::EncodingIdWin>(record.encodingID.Get()); 65e9297d28Sopenharmony_ci if (platformId == FontParser::PlatformId::WINDOWS && encodingId == FontParser::EncodingIdWin::SYMBOL) { 66e9297d28Sopenharmony_ci fontDescriptor.symbolic = true; 67e9297d28Sopenharmony_ci break; 68e9297d28Sopenharmony_ci } 69e9297d28Sopenharmony_ci } 70e9297d28Sopenharmony_ci} 71e9297d28Sopenharmony_ci 72e9297d28Sopenharmony_civoid FontParser::GetStringFromNameId(FontParser::NameId nameId, unsigned int languageId, const std::string& nameString, 73e9297d28Sopenharmony_ci FontParser::FontDescriptor& fontDescriptor) 74e9297d28Sopenharmony_ci{ 75e9297d28Sopenharmony_ci switch (nameId) { 76e9297d28Sopenharmony_ci case FontParser::NameId::FONT_FAMILY: { 77e9297d28Sopenharmony_ci SetNameString(fontDescriptor, fontDescriptor.fontFamily, fontDescriptor.fontFamilyLid, 78e9297d28Sopenharmony_ci languageId, nameString); 79e9297d28Sopenharmony_ci break; 80e9297d28Sopenharmony_ci } 81e9297d28Sopenharmony_ci case FontParser::NameId::FONT_SUBFAMILY: { 82e9297d28Sopenharmony_ci SetNameString(fontDescriptor, fontDescriptor.fontSubfamily, fontDescriptor.fontSubfamilyLid, 83e9297d28Sopenharmony_ci languageId, nameString); 84e9297d28Sopenharmony_ci break; 85e9297d28Sopenharmony_ci } 86e9297d28Sopenharmony_ci case FontParser::NameId::FULL_NAME: { 87e9297d28Sopenharmony_ci if (!fontDescriptor.requestedFullname.empty() && 88e9297d28Sopenharmony_ci fontDescriptor.fullName == fontDescriptor.requestedFullname) { 89e9297d28Sopenharmony_ci break; 90e9297d28Sopenharmony_ci } 91e9297d28Sopenharmony_ci 92e9297d28Sopenharmony_ci SetNameString(fontDescriptor, fontDescriptor.fullName, fontDescriptor.fullNameLid, 93e9297d28Sopenharmony_ci languageId, nameString); 94e9297d28Sopenharmony_ci break; 95e9297d28Sopenharmony_ci } 96e9297d28Sopenharmony_ci case FontParser::NameId::POSTSCRIPT_NAME: { 97e9297d28Sopenharmony_ci SetNameString(fontDescriptor, fontDescriptor.postScriptName, fontDescriptor.postScriptNameLid, 98e9297d28Sopenharmony_ci languageId, nameString); 99e9297d28Sopenharmony_ci break; 100e9297d28Sopenharmony_ci } 101e9297d28Sopenharmony_ci default: { 102e9297d28Sopenharmony_ci break; 103e9297d28Sopenharmony_ci } 104e9297d28Sopenharmony_ci } 105e9297d28Sopenharmony_ci} 106e9297d28Sopenharmony_ci 107e9297d28Sopenharmony_civoid FontParser::SetNameString(FontParser::FontDescriptor& fontDescriptor, std::string& field, unsigned int& fieldLid, 108e9297d28Sopenharmony_ci unsigned int languageId, const std::string& nameString) 109e9297d28Sopenharmony_ci{ 110e9297d28Sopenharmony_ci bool willSet = field.empty(); 111e9297d28Sopenharmony_ci if (!willSet) { 112e9297d28Sopenharmony_ci if (languageId == fontDescriptor.requestedLid) { 113e9297d28Sopenharmony_ci willSet = true; 114e9297d28Sopenharmony_ci } else if (fieldLid != fontDescriptor.requestedLid && languageId == LANGUAGE_DEFAULT) { 115e9297d28Sopenharmony_ci willSet = true; 116e9297d28Sopenharmony_ci } 117e9297d28Sopenharmony_ci } 118e9297d28Sopenharmony_ci 119e9297d28Sopenharmony_ci if (willSet) { 120e9297d28Sopenharmony_ci fieldLid = languageId; 121e9297d28Sopenharmony_ci field = nameString; 122e9297d28Sopenharmony_ci } 123e9297d28Sopenharmony_ci} 124e9297d28Sopenharmony_ci 125e9297d28Sopenharmony_ciint FontParser::ProcessNameTable(const struct NameTable* nameTable, FontParser::FontDescriptor& fontDescriptor) const 126e9297d28Sopenharmony_ci{ 127e9297d28Sopenharmony_ci auto count = nameTable->count.Get(); 128e9297d28Sopenharmony_ci auto storageOffset = nameTable->storageOffset.Get(); 129e9297d28Sopenharmony_ci auto stringStorage = data_ + storageOffset; 130e9297d28Sopenharmony_ci for (int i = 0; i < count; ++i) { 131e9297d28Sopenharmony_ci if (nameTable->nameRecord[i].stringOffset.Get() == 0 && nameTable->nameRecord[i].length.Get() == 0) { 132e9297d28Sopenharmony_ci continue; 133e9297d28Sopenharmony_ci } 134e9297d28Sopenharmony_ci FontParser::NameId nameId = static_cast<FontParser::NameId>(nameTable->nameRecord[i].nameId.Get()); 135e9297d28Sopenharmony_ci // Parsing fields with NameId greater than 7 is not currently supported. 136e9297d28Sopenharmony_ci if (nameId > FontParser::NameId::TRADEMARK) { 137e9297d28Sopenharmony_ci continue; 138e9297d28Sopenharmony_ci } 139e9297d28Sopenharmony_ci unsigned int languageId = static_cast<unsigned int>(nameTable->nameRecord[i].languageId.Get()); 140e9297d28Sopenharmony_ci FontParser::PlatformId platformId = 141e9297d28Sopenharmony_ci static_cast<FontParser::PlatformId>(nameTable->nameRecord[i].platformId.Get()); 142e9297d28Sopenharmony_ci auto len = nameTable->nameRecord[i].length.Get(); 143e9297d28Sopenharmony_ci auto stringOffset = nameTable->nameRecord[i].stringOffset.Get(); 144e9297d28Sopenharmony_ci const char* data = stringStorage + stringOffset; 145e9297d28Sopenharmony_ci if (platformId == FontParser::PlatformId::MACINTOSH) { 146e9297d28Sopenharmony_ci#ifdef BUILD_NON_SDK_VER 147e9297d28Sopenharmony_ci std::string nameString = ToUtf8(std::string(data, len)); 148e9297d28Sopenharmony_ci#else 149e9297d28Sopenharmony_ci std::string nameString(data, len); 150e9297d28Sopenharmony_ci#endif 151e9297d28Sopenharmony_ci GetStringFromNameId(nameId, languageId, nameString, fontDescriptor); 152e9297d28Sopenharmony_ci } else if (platformId == FontParser::PlatformId::WINDOWS) { 153e9297d28Sopenharmony_ci std::wstring_convert<std::codecvt_utf16<char16_t>, char16_t> converter; 154e9297d28Sopenharmony_ci std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converterUtf8; 155e9297d28Sopenharmony_ci const std::u16string u16str = converter.from_bytes(data, data + len); 156e9297d28Sopenharmony_ci std::string nameString = converterUtf8.to_bytes(u16str); 157e9297d28Sopenharmony_ci GetStringFromNameId(nameId, languageId, nameString, fontDescriptor); 158e9297d28Sopenharmony_ci } 159e9297d28Sopenharmony_ci } 160e9297d28Sopenharmony_ci 161e9297d28Sopenharmony_ci return SUCCESSED; 162e9297d28Sopenharmony_ci} 163e9297d28Sopenharmony_ci 164e9297d28Sopenharmony_civoid FontParser::ProcessPostTable(const struct PostTable* postTable, FontParser::FontDescriptor& fontDescriptor) 165e9297d28Sopenharmony_ci{ 166e9297d28Sopenharmony_ci if (postTable->italicAngle.Get() != 0) { 167e9297d28Sopenharmony_ci fontDescriptor.italic = 1; // means support italics 168e9297d28Sopenharmony_ci } else { 169e9297d28Sopenharmony_ci fontDescriptor.italic = 0; 170e9297d28Sopenharmony_ci } 171e9297d28Sopenharmony_ci if (postTable->isFixedPitch.Get() == 1) { 172e9297d28Sopenharmony_ci fontDescriptor.monoSpace = true; 173e9297d28Sopenharmony_ci } 174e9297d28Sopenharmony_ci} 175e9297d28Sopenharmony_ci 176e9297d28Sopenharmony_ciint FontParser::ParseCmapTable(std::shared_ptr<Drawing::Typeface> typeface, FontParser::FontDescriptor& fontDescriptor) 177e9297d28Sopenharmony_ci{ 178e9297d28Sopenharmony_ci auto tag = HB_TAG('c', 'm', 'a', 'p'); 179e9297d28Sopenharmony_ci auto size = typeface->GetTableSize(tag); 180e9297d28Sopenharmony_ci if (size <= 0) { 181e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "haven't cmap"; 182e9297d28Sopenharmony_ci return FAILED; 183e9297d28Sopenharmony_ci } 184e9297d28Sopenharmony_ci std::unique_ptr<char[]> tableData = nullptr; 185e9297d28Sopenharmony_ci tableData = std::make_unique<char[]>(size); 186e9297d28Sopenharmony_ci auto retTableData = typeface->GetTableData(tag, 0, size, tableData.get()); 187e9297d28Sopenharmony_ci if (size != retTableData) { 188e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData; 189e9297d28Sopenharmony_ci return FAILED; 190e9297d28Sopenharmony_ci } 191e9297d28Sopenharmony_ci hb_blob_t* hblob = nullptr; 192e9297d28Sopenharmony_ci hblob = hb_blob_create( 193e9297d28Sopenharmony_ci reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr); 194e9297d28Sopenharmony_ci if (hblob == nullptr) { 195e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr"; 196e9297d28Sopenharmony_ci return FAILED; 197e9297d28Sopenharmony_ci } 198e9297d28Sopenharmony_ci data_ = hb_blob_get_data(hblob, nullptr); 199e9297d28Sopenharmony_ci length_ = hb_blob_get_length(hblob); 200e9297d28Sopenharmony_ci auto parseCmap = std::make_shared<CmapTableParser>(data_, length_); 201e9297d28Sopenharmony_ci auto cmapTable = parseCmap->Parse(data_, length_); 202e9297d28Sopenharmony_ci ProcessCmapTable(cmapTable, fontDescriptor); 203e9297d28Sopenharmony_ci hb_blob_destroy(hblob); 204e9297d28Sopenharmony_ci return SUCCESSED; 205e9297d28Sopenharmony_ci} 206e9297d28Sopenharmony_ci 207e9297d28Sopenharmony_ciint FontParser::ParseNameTable(std::shared_ptr<Drawing::Typeface> typeface, FontParser::FontDescriptor& fontDescriptor) 208e9297d28Sopenharmony_ci{ 209e9297d28Sopenharmony_ci auto tag = HB_TAG('n', 'a', 'm', 'e'); 210e9297d28Sopenharmony_ci auto size = typeface->GetTableSize(tag); 211e9297d28Sopenharmony_ci if (size <= 0) { 212e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "haven't name"; 213e9297d28Sopenharmony_ci return FAILED; 214e9297d28Sopenharmony_ci } 215e9297d28Sopenharmony_ci std::unique_ptr<char[]> tableData = nullptr; 216e9297d28Sopenharmony_ci tableData = std::make_unique<char[]>(size); 217e9297d28Sopenharmony_ci auto retTableData = typeface->GetTableData(tag, 0, size, tableData.get()); 218e9297d28Sopenharmony_ci if (size != retTableData) { 219e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData; 220e9297d28Sopenharmony_ci return FAILED; 221e9297d28Sopenharmony_ci } 222e9297d28Sopenharmony_ci hb_blob_t* hblob = nullptr; 223e9297d28Sopenharmony_ci hblob = hb_blob_create( 224e9297d28Sopenharmony_ci reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr); 225e9297d28Sopenharmony_ci if (hblob == nullptr) { 226e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr"; 227e9297d28Sopenharmony_ci return FAILED; 228e9297d28Sopenharmony_ci } 229e9297d28Sopenharmony_ci data_ = hb_blob_get_data(hblob, nullptr); 230e9297d28Sopenharmony_ci length_ = hb_blob_get_length(hblob); 231e9297d28Sopenharmony_ci auto parseName = std::make_shared<NameTableParser>(data_, length_); 232e9297d28Sopenharmony_ci auto nameTable = parseName->Parse(data_, length_); 233e9297d28Sopenharmony_ci int ret = ProcessNameTable(nameTable, fontDescriptor); 234e9297d28Sopenharmony_ci if (ret != SUCCESSED) { 235e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "process name table failed"; 236e9297d28Sopenharmony_ci hb_blob_destroy(hblob); 237e9297d28Sopenharmony_ci return FAILED; 238e9297d28Sopenharmony_ci } 239e9297d28Sopenharmony_ci hb_blob_destroy(hblob); 240e9297d28Sopenharmony_ci return SUCCESSED; 241e9297d28Sopenharmony_ci} 242e9297d28Sopenharmony_ci 243e9297d28Sopenharmony_ciint FontParser::ParsePostTable(std::shared_ptr<Drawing::Typeface> typeface, FontParser::FontDescriptor& fontDescriptor) 244e9297d28Sopenharmony_ci{ 245e9297d28Sopenharmony_ci auto tag = HB_TAG('p', 'o', 's', 't'); 246e9297d28Sopenharmony_ci auto size = typeface->GetTableSize(tag); 247e9297d28Sopenharmony_ci if (size <= 0) { 248e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "haven't post"; 249e9297d28Sopenharmony_ci return FAILED; 250e9297d28Sopenharmony_ci } 251e9297d28Sopenharmony_ci std::unique_ptr<char[]> tableData = nullptr; 252e9297d28Sopenharmony_ci tableData = std::make_unique<char[]>(size); 253e9297d28Sopenharmony_ci auto retTableData = typeface->GetTableData(tag, 0, size, tableData.get()); 254e9297d28Sopenharmony_ci if (size != retTableData) { 255e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData; 256e9297d28Sopenharmony_ci return FAILED; 257e9297d28Sopenharmony_ci } 258e9297d28Sopenharmony_ci hb_blob_t* hblob = nullptr; 259e9297d28Sopenharmony_ci hblob = hb_blob_create( 260e9297d28Sopenharmony_ci reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr); 261e9297d28Sopenharmony_ci if (hblob == nullptr) { 262e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr"; 263e9297d28Sopenharmony_ci return FAILED; 264e9297d28Sopenharmony_ci } 265e9297d28Sopenharmony_ci data_ = hb_blob_get_data(hblob, nullptr); 266e9297d28Sopenharmony_ci length_ = hb_blob_get_length(hblob); 267e9297d28Sopenharmony_ci auto parsePost = std::make_shared<PostTableParser>(data_, length_); 268e9297d28Sopenharmony_ci auto postTable = parsePost->Parse(data_, length_); 269e9297d28Sopenharmony_ci ProcessPostTable(postTable, fontDescriptor); 270e9297d28Sopenharmony_ci hb_blob_destroy(hblob); 271e9297d28Sopenharmony_ci return SUCCESSED; 272e9297d28Sopenharmony_ci} 273e9297d28Sopenharmony_ci 274e9297d28Sopenharmony_ciint FontParser::ParseTable(std::shared_ptr<Drawing::Typeface> typeface, FontParser::FontDescriptor& fontDescriptor) 275e9297d28Sopenharmony_ci{ 276e9297d28Sopenharmony_ci if (ParseCmapTable(typeface, fontDescriptor) != SUCCESSED) { 277e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "parse cmap failed"; 278e9297d28Sopenharmony_ci return FAILED; 279e9297d28Sopenharmony_ci } 280e9297d28Sopenharmony_ci if (ParseNameTable(typeface, fontDescriptor) != SUCCESSED) { 281e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "parse name failed"; 282e9297d28Sopenharmony_ci return FAILED; 283e9297d28Sopenharmony_ci } 284e9297d28Sopenharmony_ci if (ParsePostTable(typeface, fontDescriptor) != SUCCESSED) { 285e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "parse post failed"; 286e9297d28Sopenharmony_ci return FAILED; 287e9297d28Sopenharmony_ci } 288e9297d28Sopenharmony_ci 289e9297d28Sopenharmony_ci return SUCCESSED; 290e9297d28Sopenharmony_ci} 291e9297d28Sopenharmony_ci 292e9297d28Sopenharmony_ciint FontParser::SetFontDescriptor(const unsigned int languageId) 293e9297d28Sopenharmony_ci{ 294e9297d28Sopenharmony_ci visibilityFonts_.clear(); 295e9297d28Sopenharmony_ci std::list<std::string> fontSetCache; 296e9297d28Sopenharmony_ci for (unsigned int i = 0; i < fontSet_.size(); ++i) { 297e9297d28Sopenharmony_ci FontParser::FontDescriptor fontDescriptor; 298e9297d28Sopenharmony_ci fontDescriptor.requestedLid = languageId; 299e9297d28Sopenharmony_ci fontDescriptor.path = fontSet_[i]; 300e9297d28Sopenharmony_ci const char* path = fontSet_[i].c_str(); 301e9297d28Sopenharmony_ci auto typeface = Drawing::Typeface::MakeFromFile(path); 302e9297d28Sopenharmony_ci if (typeface == nullptr) { 303e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "typeface is nullptr, can not parse: " << fontDescriptor.path; 304e9297d28Sopenharmony_ci continue; 305e9297d28Sopenharmony_ci } 306e9297d28Sopenharmony_ci auto fontStyle = typeface->GetFontStyle(); 307e9297d28Sopenharmony_ci fontDescriptor.weight = fontStyle.GetWeight(); 308e9297d28Sopenharmony_ci fontDescriptor.width = fontStyle.GetWidth(); 309e9297d28Sopenharmony_ci if (ParseTable(typeface, fontDescriptor) != SUCCESSED) { 310e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "parse table failed"; 311e9297d28Sopenharmony_ci return FAILED; 312e9297d28Sopenharmony_ci } 313e9297d28Sopenharmony_ci 314e9297d28Sopenharmony_ci size_t idx = fontSet_[i].rfind('/'); 315e9297d28Sopenharmony_ci std::string fontName = fontSet_[i].substr(idx + 1, fontSet_[i].size() - idx - 1); 316e9297d28Sopenharmony_ci if (std::find(fontSetCache.begin(), fontSetCache.end(), fontName) == fontSetCache.end()) { 317e9297d28Sopenharmony_ci fontSetCache.push_back(fontName); 318e9297d28Sopenharmony_ci visibilityFonts_.emplace_back(fontDescriptor); 319e9297d28Sopenharmony_ci } 320e9297d28Sopenharmony_ci } 321e9297d28Sopenharmony_ci 322e9297d28Sopenharmony_ci return SUCCESSED; 323e9297d28Sopenharmony_ci} 324e9297d28Sopenharmony_ci 325e9297d28Sopenharmony_ci#ifdef BUILD_NON_SDK_VER 326e9297d28Sopenharmony_cistd::string FontParser::ToUtf8(const std::string& str) 327e9297d28Sopenharmony_ci{ 328e9297d28Sopenharmony_ci std::string utf8Str; 329e9297d28Sopenharmony_ci // UTF-8 and GB2312 is encoding format of string 330e9297d28Sopenharmony_ci iconv_t conv = iconv_open("UTF-8", "GB2312"); 331e9297d28Sopenharmony_ci if (conv == (iconv_t)-1) { 332e9297d28Sopenharmony_ci return utf8Str; 333e9297d28Sopenharmony_ci } 334e9297d28Sopenharmony_ci char* inBuf = const_cast<char*>(str.c_str()); 335e9297d28Sopenharmony_ci size_t inBytesLeft = str.length(); 336e9297d28Sopenharmony_ci size_t outBytesLeft = inBytesLeft * 2; 337e9297d28Sopenharmony_ci char* outBuf = new char[outBytesLeft]; 338e9297d28Sopenharmony_ci char* outBufStart = outBuf; 339e9297d28Sopenharmony_ci size_t res = iconv(conv, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft); 340e9297d28Sopenharmony_ci if (res != (size_t)-1) { 341e9297d28Sopenharmony_ci utf8Str.assign(outBufStart, outBuf - outBufStart); 342e9297d28Sopenharmony_ci } 343e9297d28Sopenharmony_ci delete[] outBufStart; 344e9297d28Sopenharmony_ci iconv_close(conv); 345e9297d28Sopenharmony_ci return utf8Str; 346e9297d28Sopenharmony_ci} 347e9297d28Sopenharmony_ci#endif 348e9297d28Sopenharmony_ci 349e9297d28Sopenharmony_cistd::vector<FontParser::FontDescriptor> FontParser::GetVisibilityFonts(const std::string &locale) 350e9297d28Sopenharmony_ci{ 351e9297d28Sopenharmony_ci if (SetFontDescriptor(GetLanguageId(locale)) != SUCCESSED) { 352e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "set visibility font descriptor failed"; 353e9297d28Sopenharmony_ci } 354e9297d28Sopenharmony_ci 355e9297d28Sopenharmony_ci return visibilityFonts_; 356e9297d28Sopenharmony_ci} 357e9297d28Sopenharmony_ci 358e9297d28Sopenharmony_ciclass SystemFont { 359e9297d28Sopenharmony_cipublic: 360e9297d28Sopenharmony_ci explicit SystemFont(const char* fPath = SYSTEM_FONT_PATH) 361e9297d28Sopenharmony_ci { 362e9297d28Sopenharmony_ci ParseConfig(fPath); 363e9297d28Sopenharmony_ci } 364e9297d28Sopenharmony_ci 365e9297d28Sopenharmony_ci ~SystemFont() = default; 366e9297d28Sopenharmony_ci 367e9297d28Sopenharmony_ci std::shared_ptr<std::vector<std::string>> GetSystemFontSet() const 368e9297d28Sopenharmony_ci { 369e9297d28Sopenharmony_ci return systemFontSet_; 370e9297d28Sopenharmony_ci } 371e9297d28Sopenharmony_ci 372e9297d28Sopenharmony_ciprivate: 373e9297d28Sopenharmony_ci void ParseConfig(const char* fPath) 374e9297d28Sopenharmony_ci { 375e9297d28Sopenharmony_ci if (fPath == nullptr) { 376e9297d28Sopenharmony_ci return; 377e9297d28Sopenharmony_ci } 378e9297d28Sopenharmony_ci systemFontSet_ = std::make_shared<std::vector<std::string>>(); 379e9297d28Sopenharmony_ci DIR *dir = opendir(fPath); 380e9297d28Sopenharmony_ci if (dir == nullptr) { 381e9297d28Sopenharmony_ci return; 382e9297d28Sopenharmony_ci } 383e9297d28Sopenharmony_ci struct dirent *entry; 384e9297d28Sopenharmony_ci while ((entry = readdir(dir)) != nullptr) { 385e9297d28Sopenharmony_ci if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 386e9297d28Sopenharmony_ci continue; 387e9297d28Sopenharmony_ci } 388e9297d28Sopenharmony_ci std::string tmp = entry->d_name; 389e9297d28Sopenharmony_ci systemFontSet_->push_back(SYSTEM_FONT_PATH + tmp); 390e9297d28Sopenharmony_ci } 391e9297d28Sopenharmony_ci closedir(dir); 392e9297d28Sopenharmony_ci } 393e9297d28Sopenharmony_ci 394e9297d28Sopenharmony_ci std::shared_ptr<std::vector<std::string>> systemFontSet_; 395e9297d28Sopenharmony_ci}; 396e9297d28Sopenharmony_ci 397e9297d28Sopenharmony_cistd::vector<std::shared_ptr<FontParser::FontDescriptor>> FontParser::GetSystemFonts(const std::string locale) 398e9297d28Sopenharmony_ci{ 399e9297d28Sopenharmony_ci std::vector<std::shared_ptr<Drawing::Typeface>> typefaces = Drawing::Typeface::GetSystemFonts(); 400e9297d28Sopenharmony_ci if (typefaces.empty()) { 401e9297d28Sopenharmony_ci return {}; 402e9297d28Sopenharmony_ci } 403e9297d28Sopenharmony_ci 404e9297d28Sopenharmony_ci std::vector<std::shared_ptr<FontDescriptor>> descriptors; 405e9297d28Sopenharmony_ci descriptors.reserve(typefaces.size()); 406e9297d28Sopenharmony_ci for (auto& item : typefaces) { 407e9297d28Sopenharmony_ci FontDescriptor desc; 408e9297d28Sopenharmony_ci desc.requestedLid = GetLanguageId(locale); 409e9297d28Sopenharmony_ci desc.path = item->GetFontPath(); 410e9297d28Sopenharmony_ci auto fontStyle = item->GetFontStyle(); 411e9297d28Sopenharmony_ci desc.weight = fontStyle.GetWeight(); 412e9297d28Sopenharmony_ci desc.width = fontStyle.GetWidth(); 413e9297d28Sopenharmony_ci if (ParseTable(item, desc) != SUCCESSED) { 414e9297d28Sopenharmony_ci continue; 415e9297d28Sopenharmony_ci } 416e9297d28Sopenharmony_ci descriptors.emplace_back(std::make_shared<FontDescriptor>(desc)); 417e9297d28Sopenharmony_ci } 418e9297d28Sopenharmony_ci return descriptors; 419e9297d28Sopenharmony_ci} 420e9297d28Sopenharmony_ci 421e9297d28Sopenharmony_cibool FontParser::ParserFontDescriptorFromPath(const std::string& path, 422e9297d28Sopenharmony_ci std::vector<std::shared_ptr<FontDescriptor>>& descriptors, const std::string locale) 423e9297d28Sopenharmony_ci{ 424e9297d28Sopenharmony_ci std::shared_ptr<Drawing::Typeface> typeface; 425e9297d28Sopenharmony_ci int index = 0; 426e9297d28Sopenharmony_ci FontDescriptor desc; 427e9297d28Sopenharmony_ci desc.requestedLid = GetLanguageId(locale); 428e9297d28Sopenharmony_ci desc.path = path; 429e9297d28Sopenharmony_ci while ((typeface = Drawing::Typeface::MakeFromFile(path.c_str(), index)) != nullptr) { 430e9297d28Sopenharmony_ci index++; 431e9297d28Sopenharmony_ci auto fontStyle = typeface->GetFontStyle(); 432e9297d28Sopenharmony_ci desc.weight = fontStyle.GetWeight(); 433e9297d28Sopenharmony_ci desc.width = fontStyle.GetWidth(); 434e9297d28Sopenharmony_ci if (ParseTable(typeface, desc) != SUCCESSED) { 435e9297d28Sopenharmony_ci continue; 436e9297d28Sopenharmony_ci } 437e9297d28Sopenharmony_ci descriptors.emplace_back(std::make_shared<FontDescriptor>(desc)); 438e9297d28Sopenharmony_ci } 439e9297d28Sopenharmony_ci if (descriptors.size() > 0) { 440e9297d28Sopenharmony_ci return true; 441e9297d28Sopenharmony_ci } 442e9297d28Sopenharmony_ci return false; 443e9297d28Sopenharmony_ci} 444e9297d28Sopenharmony_ci 445e9297d28Sopenharmony_cistd::unique_ptr<FontParser::FontDescriptor> FontParser::ParseFontDescriptor(const std::string& fontName, 446e9297d28Sopenharmony_ci const unsigned int languageId) 447e9297d28Sopenharmony_ci{ 448e9297d28Sopenharmony_ci FontConfigJson fontConfigJson; 449e9297d28Sopenharmony_ci fontConfigJson.ParseFontFileMap(); 450e9297d28Sopenharmony_ci std::shared_ptr<FontFileMap> fontFileMap = fontConfigJson.GetFontFileMap(); 451e9297d28Sopenharmony_ci if (fontFileMap == nullptr || (*fontFileMap).empty()) { 452e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "fontFileMap is nullptr"; 453e9297d28Sopenharmony_ci return nullptr; 454e9297d28Sopenharmony_ci } 455e9297d28Sopenharmony_ci if ((*fontFileMap).find(fontName) == (*fontFileMap).end()) { 456e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "full name not found"; 457e9297d28Sopenharmony_ci return nullptr; 458e9297d28Sopenharmony_ci } 459e9297d28Sopenharmony_ci std::string path = SYSTEM_FONT_PATH + (*fontFileMap)[fontName]; 460e9297d28Sopenharmony_ci auto typeface = Drawing::Typeface::MakeFromFile(path.c_str()); 461e9297d28Sopenharmony_ci if (typeface == nullptr) { 462e9297d28Sopenharmony_ci path = SYS_PROD_FONT_PATH + (*fontFileMap)[fontName]; 463e9297d28Sopenharmony_ci typeface = Drawing::Typeface::MakeFromFile(path.c_str()); 464e9297d28Sopenharmony_ci if (typeface == nullptr) { 465e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "typeface is nullptr, can not parse: " << path.c_str(); 466e9297d28Sopenharmony_ci return nullptr; 467e9297d28Sopenharmony_ci } 468e9297d28Sopenharmony_ci } 469e9297d28Sopenharmony_ci FontParser::FontDescriptor fontDescriptor; 470e9297d28Sopenharmony_ci fontDescriptor.requestedLid = languageId; 471e9297d28Sopenharmony_ci fontDescriptor.path = path; 472e9297d28Sopenharmony_ci fontDescriptor.requestedFullname = fontName; 473e9297d28Sopenharmony_ci auto fontStyle = typeface->GetFontStyle(); 474e9297d28Sopenharmony_ci fontDescriptor.weight = fontStyle.GetWeight(); 475e9297d28Sopenharmony_ci fontDescriptor.width = fontStyle.GetWidth(); 476e9297d28Sopenharmony_ci if (ParseTable(typeface, fontDescriptor) != SUCCESSED) { 477e9297d28Sopenharmony_ci LOGSO_FUNC_LINE(ERROR) << "parse table failed"; 478e9297d28Sopenharmony_ci return nullptr; 479e9297d28Sopenharmony_ci } 480e9297d28Sopenharmony_ci if (fontDescriptor.fullName == fontName) { 481e9297d28Sopenharmony_ci return std::make_unique<FontDescriptor>(fontDescriptor); 482e9297d28Sopenharmony_ci } 483e9297d28Sopenharmony_ci return nullptr; 484e9297d28Sopenharmony_ci} 485e9297d28Sopenharmony_ci 486e9297d28Sopenharmony_cistd::unique_ptr<FontParser::FontDescriptor> FontParser::GetVisibilityFontByName(const std::string& fontName, 487e9297d28Sopenharmony_ci const std::string locale) 488e9297d28Sopenharmony_ci{ 489e9297d28Sopenharmony_ci return ParseFontDescriptor(fontName, GetLanguageId(locale)); 490e9297d28Sopenharmony_ci} 491e9297d28Sopenharmony_ci} // namespace TextEngine 492e9297d28Sopenharmony_ci} // namespace Rosen 493e9297d28Sopenharmony_ci} // namespace OHOS 494