1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci * 2021.9.9 SkFontMgr on previewer of ohos.
7cb93a386Sopenharmony_ci *           Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
8cb93a386Sopenharmony_ci */
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/ports/SkFontMgr_preview.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "src/core/SkTSearch.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ciSkFontMgr_Preview::SkFontMgr_Preview()
15cb93a386Sopenharmony_ci{
16cb93a386Sopenharmony_ci    SkTDArray<FontFamily*> families;
17cb93a386Sopenharmony_ci    SkFontMgr_Config_Parser::GetInstance().GetSystemFontFamilies(families);
18cb93a386Sopenharmony_ci    this->buildNameToFamilyMap(families);
19cb93a386Sopenharmony_ci    this->findDefaultStyleSet();
20cb93a386Sopenharmony_ci    families.deleteAll();
21cb93a386Sopenharmony_ci}
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ciint SkFontMgr_Preview::onCountFamilies() const
24cb93a386Sopenharmony_ci{
25cb93a386Sopenharmony_ci    return fNameToFamilyMap.count();
26cb93a386Sopenharmony_ci}
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_civoid SkFontMgr_Preview::onGetFamilyName(int index, SkString* familyName) const
29cb93a386Sopenharmony_ci{
30cb93a386Sopenharmony_ci    if (index < 0 || fNameToFamilyMap.count() <= index) {
31cb93a386Sopenharmony_ci        familyName->reset();
32cb93a386Sopenharmony_ci        return;
33cb93a386Sopenharmony_ci    }
34cb93a386Sopenharmony_ci    familyName->set(fNameToFamilyMap[index].name);
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ciSkFontStyleSet* SkFontMgr_Preview::onCreateStyleSet(int index) const
38cb93a386Sopenharmony_ci{
39cb93a386Sopenharmony_ci    if (index < 0 || fNameToFamilyMap.count() <= index) {
40cb93a386Sopenharmony_ci        return nullptr;
41cb93a386Sopenharmony_ci    }
42cb93a386Sopenharmony_ci    return SkRef(fNameToFamilyMap[index].styleSet);
43cb93a386Sopenharmony_ci}
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ciSkFontStyleSet* SkFontMgr_Preview::onMatchFamily(const char familyName[]) const
46cb93a386Sopenharmony_ci{
47cb93a386Sopenharmony_ci    if (!familyName) {
48cb93a386Sopenharmony_ci        return nullptr;
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci    SkAutoAsciiToLC tolc(familyName);
51cb93a386Sopenharmony_ci    for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
52cb93a386Sopenharmony_ci        if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
53cb93a386Sopenharmony_ci            return SkRef(fNameToFamilyMap[i].styleSet);
54cb93a386Sopenharmony_ci        }
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci    // TODO: eventually we should not need to name fallback families.
57cb93a386Sopenharmony_ci    for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
58cb93a386Sopenharmony_ci        if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
59cb93a386Sopenharmony_ci            return SkRef(fFallbackNameToFamilyMap[i].styleSet);
60cb93a386Sopenharmony_ci        }
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci    return nullptr;
63cb93a386Sopenharmony_ci}
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_Preview::onMatchFamilyStyle(const char familyName[], const SkFontStyle& style) const
66cb93a386Sopenharmony_ci{
67cb93a386Sopenharmony_ci    sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
68cb93a386Sopenharmony_ci    return sset->matchStyle(style);
69cb93a386Sopenharmony_ci}
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_Preview::onMatchFaceStyle(const SkTypeface* typeface, const SkFontStyle& style) const
72cb93a386Sopenharmony_ci{
73cb93a386Sopenharmony_ci    for (int i = 0; i < fStyleSets.count(); ++i) {
74cb93a386Sopenharmony_ci        for (int j = 0; j < fStyleSets[i]->fStyles.count(); ++j) {
75cb93a386Sopenharmony_ci            if (fStyleSets[i]->fStyles[j].get() == typeface) {
76cb93a386Sopenharmony_ci                return fStyleSets[i]->matchStyle(style);
77cb93a386Sopenharmony_ci            }
78cb93a386Sopenharmony_ci        }
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci    return nullptr;
81cb93a386Sopenharmony_ci}
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_cisk_sp<SkTypeface_PreviewSystem> SkFontMgr_Preview::find_family_style_character(
84cb93a386Sopenharmony_ci    const SkString& familyName,
85cb93a386Sopenharmony_ci    const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap,
86cb93a386Sopenharmony_ci    const SkFontStyle& style, bool elegant,
87cb93a386Sopenharmony_ci    const SkString& langTag, SkUnichar character)
88cb93a386Sopenharmony_ci{
89cb93a386Sopenharmony_ci    for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
90cb93a386Sopenharmony_ci        SkFontStyleSet_Preview* family = fallbackNameToFamilyMap[i].styleSet;
91cb93a386Sopenharmony_ci        if (familyName != family->fFallbackFor) {
92cb93a386Sopenharmony_ci            continue;
93cb93a386Sopenharmony_ci        }
94cb93a386Sopenharmony_ci        sk_sp<SkTypeface_PreviewSystem> face(family->matchStyle(style));
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci        if (!langTag.isEmpty() &&
97cb93a386Sopenharmony_ci            std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang) {
98cb93a386Sopenharmony_ci                return lang.getTag().startsWith(langTag.c_str()); })) {
99cb93a386Sopenharmony_ci            continue;
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci        if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
103cb93a386Sopenharmony_ci            continue;
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci        if (face->unicharToGlyph(character) != 0) {
107cb93a386Sopenharmony_ci            return face;
108cb93a386Sopenharmony_ci        }
109cb93a386Sopenharmony_ci    }
110cb93a386Sopenharmony_ci    return nullptr;
111cb93a386Sopenharmony_ci}
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ciSkTypeface* SkFontMgr_Preview::onMatchFamilyStyleCharacter(const char familyName[],
114cb93a386Sopenharmony_ci                                                       const SkFontStyle& style,
115cb93a386Sopenharmony_ci                                                       const char* bcp47[],
116cb93a386Sopenharmony_ci                                                       int bcp47Count,
117cb93a386Sopenharmony_ci                                                       SkUnichar character) const
118cb93a386Sopenharmony_ci{
119cb93a386Sopenharmony_ci    // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
120cb93a386Sopenharmony_ci    // The variant 'default' means 'compact and elegant'.
121cb93a386Sopenharmony_ci    // As a result, it is not possible to know the variant context from the font alone.
122cb93a386Sopenharmony_ci    // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
123cb93a386Sopenharmony_ci    SkString familyNameString(familyName);
124cb93a386Sopenharmony_ci    for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
125cb93a386Sopenharmony_ci        // The first time match anything elegant, second time anything not elegant.
126cb93a386Sopenharmony_ci        for (int elegant = 2; elegant-- > 0;) {
127cb93a386Sopenharmony_ci            for (int bcp47Index = bcp47Count; bcp47Index-- > 0;) {
128cb93a386Sopenharmony_ci                SkLanguage lang(bcp47[bcp47Index]);
129cb93a386Sopenharmony_ci                while (!lang.getTag().isEmpty()) {
130cb93a386Sopenharmony_ci                    sk_sp<SkTypeface_PreviewSystem> matchingTypeface =
131cb93a386Sopenharmony_ci                        find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
132cb93a386Sopenharmony_ci                                                    style, SkToBool(elegant),
133cb93a386Sopenharmony_ci                                                    lang.getTag(), character);
134cb93a386Sopenharmony_ci                    if (matchingTypeface) {
135cb93a386Sopenharmony_ci                        return matchingTypeface.release();
136cb93a386Sopenharmony_ci                    }
137cb93a386Sopenharmony_ci                    lang = lang.getParent();
138cb93a386Sopenharmony_ci                }
139cb93a386Sopenharmony_ci            }
140cb93a386Sopenharmony_ci            sk_sp<SkTypeface_PreviewSystem> matchingTypeface =
141cb93a386Sopenharmony_ci                find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
142cb93a386Sopenharmony_ci                                            style, SkToBool(elegant),
143cb93a386Sopenharmony_ci                                            SkString(), character);
144cb93a386Sopenharmony_ci            if (matchingTypeface) {
145cb93a386Sopenharmony_ci                return matchingTypeface.release();
146cb93a386Sopenharmony_ci            }
147cb93a386Sopenharmony_ci        }
148cb93a386Sopenharmony_ci    }
149cb93a386Sopenharmony_ci    return nullptr;
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const
153cb93a386Sopenharmony_ci{
154cb93a386Sopenharmony_ci    return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
155cb93a386Sopenharmony_ci                                ttcIndex);
156cb93a386Sopenharmony_ci}
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromFile(const char path[], int ttcIndex) const
159cb93a386Sopenharmony_ci{
160cb93a386Sopenharmony_ci    std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
161cb93a386Sopenharmony_ci    return stream.get() ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
162cb93a386Sopenharmony_ci}
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, int ttcIndex) const
165cb93a386Sopenharmony_ci{
166cb93a386Sopenharmony_ci    bool isFixedPitch;
167cb93a386Sopenharmony_ci    SkFontStyle style;
168cb93a386Sopenharmony_ci    SkString name;
169cb93a386Sopenharmony_ci    if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
170cb93a386Sopenharmony_ci        return nullptr;
171cb93a386Sopenharmony_ci    }
172cb93a386Sopenharmony_ci    auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
173cb93a386Sopenharmony_ci    return sk_sp<SkTypeface>(new SkTypeface_PreviewStream(std::move(data), style, isFixedPitch, name));
174cb93a386Sopenharmony_ci}
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_Preview::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
177cb93a386Sopenharmony_ci                                                      const SkFontArguments& args) const
178cb93a386Sopenharmony_ci{
179cb93a386Sopenharmony_ci    using Scanner = SkTypeface_FreeType::Scanner;
180cb93a386Sopenharmony_ci    bool isFixedPitch;
181cb93a386Sopenharmony_ci    SkFontStyle style;
182cb93a386Sopenharmony_ci    SkString name;
183cb93a386Sopenharmony_ci    Scanner::AxisDefinitions axisDefinitions;
184cb93a386Sopenharmony_ci    if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
185cb93a386Sopenharmony_ci                           &name, &style, &isFixedPitch, &axisDefinitions)) {
186cb93a386Sopenharmony_ci        return nullptr;
187cb93a386Sopenharmony_ci    }
188cb93a386Sopenharmony_ci    SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
189cb93a386Sopenharmony_ci    Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
190cb93a386Sopenharmony_ci                               axisValues, name);
191cb93a386Sopenharmony_ci    auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
192cb93a386Sopenharmony_ci                                               axisValues.get(), axisDefinitions.count());
193cb93a386Sopenharmony_ci    return sk_sp<SkTypeface>(new SkTypeface_PreviewStream(std::move(data), style, isFixedPitch, name));
194cb93a386Sopenharmony_ci}
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_cisk_sp<SkTypeface> SkFontMgr_Preview::onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const
197cb93a386Sopenharmony_ci{
198cb93a386Sopenharmony_ci    if (familyName) {
199cb93a386Sopenharmony_ci        return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci    return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
202cb93a386Sopenharmony_ci}
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_civoid SkFontMgr_Preview::addFamily(FontFamily& family, int familyIndex)
205cb93a386Sopenharmony_ci{
206cb93a386Sopenharmony_ci    SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
207cb93a386Sopenharmony_ci    if (family.fIsFallbackFont) {
208cb93a386Sopenharmony_ci        nameToFamily = &fFallbackNameToFamilyMap;
209cb93a386Sopenharmony_ci        if (0 == family.fNames.count()) {
210cb93a386Sopenharmony_ci            SkString& fallbackName = family.fNames.push_back();
211cb93a386Sopenharmony_ci            fallbackName.printf("%.2x##fallback", familyIndex);
212cb93a386Sopenharmony_ci        }
213cb93a386Sopenharmony_ci    }
214cb93a386Sopenharmony_ci    sk_sp<SkFontStyleSet_Preview> newSet =
215cb93a386Sopenharmony_ci        sk_make_sp<SkFontStyleSet_Preview>(family, fScanner);
216cb93a386Sopenharmony_ci    if (0 == newSet->count()) {
217cb93a386Sopenharmony_ci        return;
218cb93a386Sopenharmony_ci    }
219cb93a386Sopenharmony_ci    for (const SkString& name : family.fNames) {
220cb93a386Sopenharmony_ci        nameToFamily->emplace_back(NameToFamily { name, newSet.get() });
221cb93a386Sopenharmony_ci    }
222cb93a386Sopenharmony_ci    fStyleSets.emplace_back(std::move(newSet));
223cb93a386Sopenharmony_ci}
224cb93a386Sopenharmony_ci
225cb93a386Sopenharmony_civoid SkFontMgr_Preview::buildNameToFamilyMap(SkTDArray<FontFamily*> families)
226cb93a386Sopenharmony_ci{
227cb93a386Sopenharmony_ci    int familyIndex = 0;
228cb93a386Sopenharmony_ci    for (FontFamily* family : families) {
229cb93a386Sopenharmony_ci        addFamily(*family, familyIndex++);
230cb93a386Sopenharmony_ci        family->fallbackFamilies.foreach([this, &familyIndex]
231cb93a386Sopenharmony_ci            (SkString, std::unique_ptr<FontFamily>* fallbackFamily) {
232cb93a386Sopenharmony_ci                addFamily(*(*fallbackFamily).get(), familyIndex++);
233cb93a386Sopenharmony_ci            }
234cb93a386Sopenharmony_ci        );
235cb93a386Sopenharmony_ci    }
236cb93a386Sopenharmony_ci}
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_civoid SkFontMgr_Preview::findDefaultStyleSet()
239cb93a386Sopenharmony_ci{
240cb93a386Sopenharmony_ci    SkASSERT(!fStyleSets.empty());
241cb93a386Sopenharmony_ci    static const char* defaultNames[] = { "sans-serif" };
242cb93a386Sopenharmony_ci    for (const char* defaultName : defaultNames) {
243cb93a386Sopenharmony_ci        fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
244cb93a386Sopenharmony_ci        if (fDefaultStyleSet) {
245cb93a386Sopenharmony_ci            break;
246cb93a386Sopenharmony_ci        }
247cb93a386Sopenharmony_ci    }
248cb93a386Sopenharmony_ci    if (nullptr == fDefaultStyleSet) {
249cb93a386Sopenharmony_ci        fDefaultStyleSet = fStyleSets[0];
250cb93a386Sopenharmony_ci    }
251cb93a386Sopenharmony_ci    SkASSERT(fDefaultStyleSet);
252cb93a386Sopenharmony_ci}
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_cisk_sp<SkFontMgr> SkFontMgr_New_Preview()
255cb93a386Sopenharmony_ci{
256cb93a386Sopenharmony_ci    return sk_make_sp<SkFontMgr_Preview>();
257cb93a386Sopenharmony_ci}