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