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