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 */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkData.h"
11cb93a386Sopenharmony_ci#include "include/core/SkFontMgr.h"
12cb93a386Sopenharmony_ci#include "include/core/SkFontStyle.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
14cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
15cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
16cb93a386Sopenharmony_ci#include "include/core/SkString.h"
17cb93a386Sopenharmony_ci#include "include/ports/SkFontMgr_android.h"
18cb93a386Sopenharmony_ci#include "include/private/SkFixed.h"
19cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
20cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h"
21cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h"
22cb93a386Sopenharmony_ci#include "src/core/SkFontDescriptor.h"
23cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h"
24cb93a386Sopenharmony_ci#include "src/core/SkTSearch.h"
25cb93a386Sopenharmony_ci#include "src/core/SkTypefaceCache.h"
26cb93a386Sopenharmony_ci#include "src/ports/SkFontHost_FreeType_common.h"
27cb93a386Sopenharmony_ci#include "src/ports/SkFontMgr_android_parser.h"
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci#include <algorithm>
30cb93a386Sopenharmony_ci#include <limits>
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ciclass SkData;
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ciclass SkTypeface_Android : public SkTypeface_FreeType {
35cb93a386Sopenharmony_cipublic:
36cb93a386Sopenharmony_ci    SkTypeface_Android(const SkFontStyle& style,
37cb93a386Sopenharmony_ci                       bool isFixedPitch,
38cb93a386Sopenharmony_ci                       const SkString& familyName)
39cb93a386Sopenharmony_ci        : INHERITED(style, isFixedPitch)
40cb93a386Sopenharmony_ci        , fFamilyName(familyName)
41cb93a386Sopenharmony_ci        { }
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ciprotected:
44cb93a386Sopenharmony_ci    void onGetFamilyName(SkString* familyName) const override {
45cb93a386Sopenharmony_ci        *familyName = fFamilyName;
46cb93a386Sopenharmony_ci    }
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    SkString fFamilyName;
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ciprivate:
51cb93a386Sopenharmony_ci    using INHERITED = SkTypeface_FreeType;
52cb93a386Sopenharmony_ci};
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ciclass SkTypeface_AndroidSystem : public SkTypeface_Android {
55cb93a386Sopenharmony_cipublic:
56cb93a386Sopenharmony_ci    SkTypeface_AndroidSystem(const SkString& pathName,
57cb93a386Sopenharmony_ci                             const bool cacheFontFiles,
58cb93a386Sopenharmony_ci                             int index,
59cb93a386Sopenharmony_ci                             const SkFixed* axes, int axesCount,
60cb93a386Sopenharmony_ci                             const SkFontStyle& style,
61cb93a386Sopenharmony_ci                             bool isFixedPitch,
62cb93a386Sopenharmony_ci                             const SkString& familyName,
63cb93a386Sopenharmony_ci                             const SkTArray<SkLanguage, true>& lang,
64cb93a386Sopenharmony_ci                             FontVariant variantStyle)
65cb93a386Sopenharmony_ci        : INHERITED(style, isFixedPitch, familyName)
66cb93a386Sopenharmony_ci        , fPathName(pathName)
67cb93a386Sopenharmony_ci        , fIndex(index)
68cb93a386Sopenharmony_ci        , fAxes(axes, axesCount)
69cb93a386Sopenharmony_ci        , fLang(lang)
70cb93a386Sopenharmony_ci        , fVariantStyle(variantStyle)
71cb93a386Sopenharmony_ci        , fFile(cacheFontFiles ? sk_fopen(fPathName.c_str(), kRead_SkFILE_Flag) : nullptr) {
72cb93a386Sopenharmony_ci        if (cacheFontFiles) {
73cb93a386Sopenharmony_ci            SkASSERT(fFile);
74cb93a386Sopenharmony_ci        }
75cb93a386Sopenharmony_ci    }
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    std::unique_ptr<SkStreamAsset> makeStream() const {
78cb93a386Sopenharmony_ci        if (fFile) {
79cb93a386Sopenharmony_ci            sk_sp<SkData> data(SkData::MakeFromFILE(fFile));
80cb93a386Sopenharmony_ci            return data ? std::make_unique<SkMemoryStream>(std::move(data)) : nullptr;
81cb93a386Sopenharmony_ci        }
82cb93a386Sopenharmony_ci        return SkStream::MakeFromFile(fPathName.c_str());
83cb93a386Sopenharmony_ci    }
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
86cb93a386Sopenharmony_ci        SkASSERT(desc);
87cb93a386Sopenharmony_ci        SkASSERT(serialize);
88cb93a386Sopenharmony_ci        desc->setFamilyName(fFamilyName.c_str());
89cb93a386Sopenharmony_ci        desc->setStyle(this->fontStyle());
90cb93a386Sopenharmony_ci        *serialize = false;
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci    std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override {
93cb93a386Sopenharmony_ci        *ttcIndex = fIndex;
94cb93a386Sopenharmony_ci        return this->makeStream();
95cb93a386Sopenharmony_ci    }
96cb93a386Sopenharmony_ci    std::unique_ptr<SkFontData> onMakeFontData() const override {
97cb93a386Sopenharmony_ci        return std::make_unique<SkFontData>(this->makeStream(), fIndex,
98cb93a386Sopenharmony_ci                                              fAxes.begin(), fAxes.count());
99cb93a386Sopenharmony_ci    }
100cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
101cb93a386Sopenharmony_ci        std::unique_ptr<SkFontData> data = this->cloneFontData(args);
102cb93a386Sopenharmony_ci        if (!data) {
103cb93a386Sopenharmony_ci            return nullptr;
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci        return sk_make_sp<SkTypeface_AndroidSystem>(fPathName,
106cb93a386Sopenharmony_ci                                                    fFile,
107cb93a386Sopenharmony_ci                                                    fIndex,
108cb93a386Sopenharmony_ci                                                    data->getAxis(),
109cb93a386Sopenharmony_ci                                                    data->getAxisCount(),
110cb93a386Sopenharmony_ci                                                    this->fontStyle(),
111cb93a386Sopenharmony_ci                                                    this->isFixedPitch(),
112cb93a386Sopenharmony_ci                                                    fFamilyName,
113cb93a386Sopenharmony_ci                                                    fLang,
114cb93a386Sopenharmony_ci                                                    fVariantStyle);
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    const SkString fPathName;
118cb93a386Sopenharmony_ci    int fIndex;
119cb93a386Sopenharmony_ci    const SkSTArray<4, SkFixed, true> fAxes;
120cb93a386Sopenharmony_ci    const SkSTArray<4, SkLanguage, true> fLang;
121cb93a386Sopenharmony_ci    const FontVariant fVariantStyle;
122cb93a386Sopenharmony_ci    SkAutoTCallVProc<FILE, sk_fclose> fFile;
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    using INHERITED = SkTypeface_Android;
125cb93a386Sopenharmony_ci};
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ciclass SkTypeface_AndroidStream : public SkTypeface_Android {
128cb93a386Sopenharmony_cipublic:
129cb93a386Sopenharmony_ci    SkTypeface_AndroidStream(std::unique_ptr<SkFontData> data,
130cb93a386Sopenharmony_ci                             const SkFontStyle& style,
131cb93a386Sopenharmony_ci                             bool isFixedPitch,
132cb93a386Sopenharmony_ci                             const SkString& familyName)
133cb93a386Sopenharmony_ci        : INHERITED(style, isFixedPitch, familyName)
134cb93a386Sopenharmony_ci        , fData(std::move(data))
135cb93a386Sopenharmony_ci    { }
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
138cb93a386Sopenharmony_ci        SkASSERT(desc);
139cb93a386Sopenharmony_ci        SkASSERT(serialize);
140cb93a386Sopenharmony_ci        desc->setFamilyName(fFamilyName.c_str());
141cb93a386Sopenharmony_ci        *serialize = true;
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override {
145cb93a386Sopenharmony_ci        *ttcIndex = fData->getIndex();
146cb93a386Sopenharmony_ci        return fData->getStream()->duplicate();
147cb93a386Sopenharmony_ci    }
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    std::unique_ptr<SkFontData> onMakeFontData() const override {
150cb93a386Sopenharmony_ci        return std::make_unique<SkFontData>(*fData);
151cb93a386Sopenharmony_ci    }
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
154cb93a386Sopenharmony_ci        std::unique_ptr<SkFontData> data = this->cloneFontData(args);
155cb93a386Sopenharmony_ci        if (!data) {
156cb93a386Sopenharmony_ci            return nullptr;
157cb93a386Sopenharmony_ci        }
158cb93a386Sopenharmony_ci        return sk_make_sp<SkTypeface_AndroidStream>(std::move(data),
159cb93a386Sopenharmony_ci                                                    this->fontStyle(),
160cb93a386Sopenharmony_ci                                                    this->isFixedPitch(),
161cb93a386Sopenharmony_ci                                                    fFamilyName);
162cb93a386Sopenharmony_ci    }
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ciprivate:
165cb93a386Sopenharmony_ci    const std::unique_ptr<const SkFontData> fData;
166cb93a386Sopenharmony_ci    using INHERITED = SkTypeface_Android;
167cb93a386Sopenharmony_ci};
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ciclass SkFontStyleSet_Android : public SkFontStyleSet {
170cb93a386Sopenharmony_ci    typedef SkTypeface_FreeType::Scanner Scanner;
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_cipublic:
173cb93a386Sopenharmony_ci    explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner,
174cb93a386Sopenharmony_ci                                    const bool cacheFontFiles) {
175cb93a386Sopenharmony_ci        const SkString* cannonicalFamilyName = nullptr;
176cb93a386Sopenharmony_ci        if (family.fNames.count() > 0) {
177cb93a386Sopenharmony_ci            cannonicalFamilyName = &family.fNames[0];
178cb93a386Sopenharmony_ci        }
179cb93a386Sopenharmony_ci        fFallbackFor = family.fFallbackFor;
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci        // TODO? make this lazy
182cb93a386Sopenharmony_ci        for (int i = 0; i < family.fFonts.count(); ++i) {
183cb93a386Sopenharmony_ci            const FontFileInfo& fontFile = family.fFonts[i];
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ci            SkString pathName(family.fBasePath);
186cb93a386Sopenharmony_ci            pathName.append(fontFile.fFileName);
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci            std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(pathName.c_str());
189cb93a386Sopenharmony_ci            if (!stream) {
190cb93a386Sopenharmony_ci                SkDEBUGF("Requested font file %s does not exist or cannot be opened.\n",
191cb93a386Sopenharmony_ci                         pathName.c_str());
192cb93a386Sopenharmony_ci                continue;
193cb93a386Sopenharmony_ci            }
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci            const int ttcIndex = fontFile.fIndex;
196cb93a386Sopenharmony_ci            SkString familyName;
197cb93a386Sopenharmony_ci            SkFontStyle style;
198cb93a386Sopenharmony_ci            bool isFixedWidth;
199cb93a386Sopenharmony_ci            Scanner::AxisDefinitions axisDefinitions;
200cb93a386Sopenharmony_ci            if (!scanner.scanFont(stream.get(), ttcIndex,
201cb93a386Sopenharmony_ci                                  &familyName, &style, &isFixedWidth, &axisDefinitions))
202cb93a386Sopenharmony_ci            {
203cb93a386Sopenharmony_ci                SkDEBUGF("Requested font file %s exists, but is not a valid font.\n",
204cb93a386Sopenharmony_ci                         pathName.c_str());
205cb93a386Sopenharmony_ci                continue;
206cb93a386Sopenharmony_ci            }
207cb93a386Sopenharmony_ci
208cb93a386Sopenharmony_ci            int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
209cb93a386Sopenharmony_ci            SkFontStyle::Slant slant = style.slant();
210cb93a386Sopenharmony_ci            switch (fontFile.fStyle) {
211cb93a386Sopenharmony_ci                case FontFileInfo::Style::kAuto: slant = style.slant(); break;
212cb93a386Sopenharmony_ci                case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
213cb93a386Sopenharmony_ci                case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
214cb93a386Sopenharmony_ci                default: SkASSERT(false); break;
215cb93a386Sopenharmony_ci            }
216cb93a386Sopenharmony_ci            style = SkFontStyle(weight, style.width(), slant);
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci            uint32_t variant = family.fVariant;
219cb93a386Sopenharmony_ci            if (kDefault_FontVariant == variant) {
220cb93a386Sopenharmony_ci                variant = kCompact_FontVariant | kElegant_FontVariant;
221cb93a386Sopenharmony_ci            }
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci            // The first specified family name overrides the family name found in the font.
224cb93a386Sopenharmony_ci            // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
225cb93a386Sopenharmony_ci            // all of the specified family names in addition to the names found in the font.
226cb93a386Sopenharmony_ci            if (cannonicalFamilyName != nullptr) {
227cb93a386Sopenharmony_ci                familyName = *cannonicalFamilyName;
228cb93a386Sopenharmony_ci            }
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci            SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
231cb93a386Sopenharmony_ci            SkFontArguments::VariationPosition position = {
232cb93a386Sopenharmony_ci                fontFile.fVariationDesignPosition.begin(),
233cb93a386Sopenharmony_ci                fontFile.fVariationDesignPosition.count()
234cb93a386Sopenharmony_ci            };
235cb93a386Sopenharmony_ci            Scanner::computeAxisValues(axisDefinitions, position,
236cb93a386Sopenharmony_ci                                       axisValues, familyName);
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_ci            fStyles.push_back().reset(new SkTypeface_AndroidSystem(
239cb93a386Sopenharmony_ci                    pathName, cacheFontFiles, ttcIndex, axisValues.get(), axisDefinitions.count(),
240cb93a386Sopenharmony_ci                    style, isFixedWidth, familyName, family.fLanguages, variant));
241cb93a386Sopenharmony_ci        }
242cb93a386Sopenharmony_ci    }
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci    int count() override {
245cb93a386Sopenharmony_ci        return fStyles.count();
246cb93a386Sopenharmony_ci    }
247cb93a386Sopenharmony_ci    void getStyle(int index, SkFontStyle* style, SkString* name) override {
248cb93a386Sopenharmony_ci        if (index < 0 || fStyles.count() <= index) {
249cb93a386Sopenharmony_ci            return;
250cb93a386Sopenharmony_ci        }
251cb93a386Sopenharmony_ci        if (style) {
252cb93a386Sopenharmony_ci            *style = fStyles[index]->fontStyle();
253cb93a386Sopenharmony_ci        }
254cb93a386Sopenharmony_ci        if (name) {
255cb93a386Sopenharmony_ci            name->reset();
256cb93a386Sopenharmony_ci        }
257cb93a386Sopenharmony_ci    }
258cb93a386Sopenharmony_ci    SkTypeface_AndroidSystem* createTypeface(int index) override {
259cb93a386Sopenharmony_ci        if (index < 0 || fStyles.count() <= index) {
260cb93a386Sopenharmony_ci            return nullptr;
261cb93a386Sopenharmony_ci        }
262cb93a386Sopenharmony_ci        return SkRef(fStyles[index].get());
263cb93a386Sopenharmony_ci    }
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) override {
266cb93a386Sopenharmony_ci        return static_cast<SkTypeface_AndroidSystem*>(this->matchStyleCSS3(pattern));
267cb93a386Sopenharmony_ci    }
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ciprivate:
270cb93a386Sopenharmony_ci    SkTArray<sk_sp<SkTypeface_AndroidSystem>> fStyles;
271cb93a386Sopenharmony_ci    SkString fFallbackFor;
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    friend struct NameToFamily;
274cb93a386Sopenharmony_ci    friend class SkFontMgr_Android;
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci    using INHERITED = SkFontStyleSet;
277cb93a386Sopenharmony_ci};
278cb93a386Sopenharmony_ci
279cb93a386Sopenharmony_ci/** On Android a single family can have many names, but our API assumes unique names.
280cb93a386Sopenharmony_ci *  Map names to the back end so that all names for a given family refer to the same
281cb93a386Sopenharmony_ci *  (non-replicated) set of typefaces.
282cb93a386Sopenharmony_ci *  SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
283cb93a386Sopenharmony_ci */
284cb93a386Sopenharmony_cistruct NameToFamily {
285cb93a386Sopenharmony_ci    SkString name;
286cb93a386Sopenharmony_ci    SkFontStyleSet_Android* styleSet;
287cb93a386Sopenharmony_ci};
288cb93a386Sopenharmony_ci
289cb93a386Sopenharmony_ciclass SkFontMgr_Android : public SkFontMgr {
290cb93a386Sopenharmony_cipublic:
291cb93a386Sopenharmony_ci    SkFontMgr_Android(const SkFontMgr_Android_CustomFonts* custom) {
292cb93a386Sopenharmony_ci        SkTDArray<FontFamily*> families;
293cb93a386Sopenharmony_ci        if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem != custom->fSystemFontUse) {
294cb93a386Sopenharmony_ci            SkString base(custom->fBasePath);
295cb93a386Sopenharmony_ci            SkFontMgr_Android_Parser::GetCustomFontFamilies(
296cb93a386Sopenharmony_ci                families, base, custom->fFontsXml, custom->fFallbackFontsXml);
297cb93a386Sopenharmony_ci        }
298cb93a386Sopenharmony_ci        if (!custom ||
299cb93a386Sopenharmony_ci            (custom && SkFontMgr_Android_CustomFonts::kOnlyCustom != custom->fSystemFontUse))
300cb93a386Sopenharmony_ci        {
301cb93a386Sopenharmony_ci            SkFontMgr_Android_Parser::GetSystemFontFamilies(families);
302cb93a386Sopenharmony_ci        }
303cb93a386Sopenharmony_ci        if (custom && SkFontMgr_Android_CustomFonts::kPreferSystem == custom->fSystemFontUse) {
304cb93a386Sopenharmony_ci            SkString base(custom->fBasePath);
305cb93a386Sopenharmony_ci            SkFontMgr_Android_Parser::GetCustomFontFamilies(
306cb93a386Sopenharmony_ci                families, base, custom->fFontsXml, custom->fFallbackFontsXml);
307cb93a386Sopenharmony_ci        }
308cb93a386Sopenharmony_ci        this->buildNameToFamilyMap(families, custom ? custom->fIsolated : false);
309cb93a386Sopenharmony_ci        this->findDefaultStyleSet();
310cb93a386Sopenharmony_ci        families.deleteAll();
311cb93a386Sopenharmony_ci    }
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_ciprotected:
314cb93a386Sopenharmony_ci    /** Returns not how many families we have, but how many unique names
315cb93a386Sopenharmony_ci     *  exist among the families.
316cb93a386Sopenharmony_ci     */
317cb93a386Sopenharmony_ci    int onCountFamilies() const override {
318cb93a386Sopenharmony_ci        return fNameToFamilyMap.count();
319cb93a386Sopenharmony_ci    }
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    void onGetFamilyName(int index, SkString* familyName) const override {
322cb93a386Sopenharmony_ci        if (index < 0 || fNameToFamilyMap.count() <= index) {
323cb93a386Sopenharmony_ci            familyName->reset();
324cb93a386Sopenharmony_ci            return;
325cb93a386Sopenharmony_ci        }
326cb93a386Sopenharmony_ci        familyName->set(fNameToFamilyMap[index].name);
327cb93a386Sopenharmony_ci    }
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    SkFontStyleSet* onCreateStyleSet(int index) const override {
330cb93a386Sopenharmony_ci        if (index < 0 || fNameToFamilyMap.count() <= index) {
331cb93a386Sopenharmony_ci            return nullptr;
332cb93a386Sopenharmony_ci        }
333cb93a386Sopenharmony_ci        return SkRef(fNameToFamilyMap[index].styleSet);
334cb93a386Sopenharmony_ci    }
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci    SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
337cb93a386Sopenharmony_ci        if (!familyName) {
338cb93a386Sopenharmony_ci            return nullptr;
339cb93a386Sopenharmony_ci        }
340cb93a386Sopenharmony_ci        SkAutoAsciiToLC tolc(familyName);
341cb93a386Sopenharmony_ci        for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
342cb93a386Sopenharmony_ci            if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
343cb93a386Sopenharmony_ci                return SkRef(fNameToFamilyMap[i].styleSet);
344cb93a386Sopenharmony_ci            }
345cb93a386Sopenharmony_ci        }
346cb93a386Sopenharmony_ci        // TODO: eventually we should not need to name fallback families.
347cb93a386Sopenharmony_ci        for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
348cb93a386Sopenharmony_ci            if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
349cb93a386Sopenharmony_ci                return SkRef(fFallbackNameToFamilyMap[i].styleSet);
350cb93a386Sopenharmony_ci            }
351cb93a386Sopenharmony_ci        }
352cb93a386Sopenharmony_ci        return nullptr;
353cb93a386Sopenharmony_ci    }
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci    SkTypeface* onMatchFamilyStyle(const char familyName[],
356cb93a386Sopenharmony_ci                                   const SkFontStyle& style) const override {
357cb93a386Sopenharmony_ci        sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
358cb93a386Sopenharmony_ci        return sset->matchStyle(style);
359cb93a386Sopenharmony_ci    }
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_ci    static sk_sp<SkTypeface_AndroidSystem> find_family_style_character(
362cb93a386Sopenharmony_ci            const SkString& familyName,
363cb93a386Sopenharmony_ci            const SkTArray<NameToFamily, true>& fallbackNameToFamilyMap,
364cb93a386Sopenharmony_ci            const SkFontStyle& style, bool elegant,
365cb93a386Sopenharmony_ci            const SkString& langTag, SkUnichar character)
366cb93a386Sopenharmony_ci    {
367cb93a386Sopenharmony_ci        for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
368cb93a386Sopenharmony_ci            SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
369cb93a386Sopenharmony_ci            if (familyName != family->fFallbackFor) {
370cb93a386Sopenharmony_ci                continue;
371cb93a386Sopenharmony_ci            }
372cb93a386Sopenharmony_ci            sk_sp<SkTypeface_AndroidSystem> face(family->matchStyle(style));
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ci            if (!langTag.isEmpty() &&
375cb93a386Sopenharmony_ci                std::none_of(face->fLang.begin(), face->fLang.end(), [&](SkLanguage lang){
376cb93a386Sopenharmony_ci                    return lang.getTag().startsWith(langTag.c_str());
377cb93a386Sopenharmony_ci                }))
378cb93a386Sopenharmony_ci            {
379cb93a386Sopenharmony_ci                continue;
380cb93a386Sopenharmony_ci            }
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci            if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
383cb93a386Sopenharmony_ci                continue;
384cb93a386Sopenharmony_ci            }
385cb93a386Sopenharmony_ci
386cb93a386Sopenharmony_ci            if (face->unicharToGlyph(character) != 0) {
387cb93a386Sopenharmony_ci                return face;
388cb93a386Sopenharmony_ci            }
389cb93a386Sopenharmony_ci        }
390cb93a386Sopenharmony_ci        return nullptr;
391cb93a386Sopenharmony_ci    }
392cb93a386Sopenharmony_ci
393cb93a386Sopenharmony_ci    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
394cb93a386Sopenharmony_ci                                            const SkFontStyle& style,
395cb93a386Sopenharmony_ci                                            const char* bcp47[],
396cb93a386Sopenharmony_ci                                            int bcp47Count,
397cb93a386Sopenharmony_ci                                            SkUnichar character) const override {
398cb93a386Sopenharmony_ci        // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
399cb93a386Sopenharmony_ci        // The variant 'default' means 'compact and elegant'.
400cb93a386Sopenharmony_ci        // As a result, it is not possible to know the variant context from the font alone.
401cb93a386Sopenharmony_ci        // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
402cb93a386Sopenharmony_ci
403cb93a386Sopenharmony_ci        SkString familyNameString(familyName);
404cb93a386Sopenharmony_ci        for (const SkString& currentFamilyName : { familyNameString, SkString() }) {
405cb93a386Sopenharmony_ci            // The first time match anything elegant, second time anything not elegant.
406cb93a386Sopenharmony_ci            for (int elegant = 2; elegant --> 0;) {
407cb93a386Sopenharmony_ci                for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
408cb93a386Sopenharmony_ci                    SkLanguage lang(bcp47[bcp47Index]);
409cb93a386Sopenharmony_ci                    while (!lang.getTag().isEmpty()) {
410cb93a386Sopenharmony_ci                        sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
411cb93a386Sopenharmony_ci                            find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
412cb93a386Sopenharmony_ci                                                        style, SkToBool(elegant),
413cb93a386Sopenharmony_ci                                                        lang.getTag(), character);
414cb93a386Sopenharmony_ci                        if (matchingTypeface) {
415cb93a386Sopenharmony_ci                            return matchingTypeface.release();
416cb93a386Sopenharmony_ci                        }
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci                        lang = lang.getParent();
419cb93a386Sopenharmony_ci                    }
420cb93a386Sopenharmony_ci                }
421cb93a386Sopenharmony_ci                sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
422cb93a386Sopenharmony_ci                    find_family_style_character(currentFamilyName, fFallbackNameToFamilyMap,
423cb93a386Sopenharmony_ci                                                style, SkToBool(elegant),
424cb93a386Sopenharmony_ci                                                SkString(), character);
425cb93a386Sopenharmony_ci                if (matchingTypeface) {
426cb93a386Sopenharmony_ci                    return matchingTypeface.release();
427cb93a386Sopenharmony_ci                }
428cb93a386Sopenharmony_ci            }
429cb93a386Sopenharmony_ci        }
430cb93a386Sopenharmony_ci        return nullptr;
431cb93a386Sopenharmony_ci    }
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
434cb93a386Sopenharmony_ci        return this->makeFromStream(std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data))),
435cb93a386Sopenharmony_ci                                    ttcIndex);
436cb93a386Sopenharmony_ci    }
437cb93a386Sopenharmony_ci
438cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
439cb93a386Sopenharmony_ci        std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
440cb93a386Sopenharmony_ci        return stream ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr;
441cb93a386Sopenharmony_ci    }
442cb93a386Sopenharmony_ci
443cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
444cb93a386Sopenharmony_ci                                            int ttcIndex) const override {
445cb93a386Sopenharmony_ci        bool isFixedPitch;
446cb93a386Sopenharmony_ci        SkFontStyle style;
447cb93a386Sopenharmony_ci        SkString name;
448cb93a386Sopenharmony_ci        if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
449cb93a386Sopenharmony_ci            return nullptr;
450cb93a386Sopenharmony_ci        }
451cb93a386Sopenharmony_ci        auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
452cb93a386Sopenharmony_ci        return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
453cb93a386Sopenharmony_ci                                                              style, isFixedPitch, name));
454cb93a386Sopenharmony_ci    }
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
457cb93a386Sopenharmony_ci                                           const SkFontArguments& args) const override {
458cb93a386Sopenharmony_ci        using Scanner = SkTypeface_FreeType::Scanner;
459cb93a386Sopenharmony_ci        bool isFixedPitch;
460cb93a386Sopenharmony_ci        SkFontStyle style;
461cb93a386Sopenharmony_ci        SkString name;
462cb93a386Sopenharmony_ci        Scanner::AxisDefinitions axisDefinitions;
463cb93a386Sopenharmony_ci        if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
464cb93a386Sopenharmony_ci                               &name, &style, &isFixedPitch, &axisDefinitions))
465cb93a386Sopenharmony_ci        {
466cb93a386Sopenharmony_ci            return nullptr;
467cb93a386Sopenharmony_ci        }
468cb93a386Sopenharmony_ci
469cb93a386Sopenharmony_ci        SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
470cb93a386Sopenharmony_ci        Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
471cb93a386Sopenharmony_ci                                   axisValues, name);
472cb93a386Sopenharmony_ci
473cb93a386Sopenharmony_ci        auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
474cb93a386Sopenharmony_ci                                                   axisValues.get(), axisDefinitions.count());
475cb93a386Sopenharmony_ci        return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
476cb93a386Sopenharmony_ci                                                              style, isFixedPitch, name));
477cb93a386Sopenharmony_ci    }
478cb93a386Sopenharmony_ci
479cb93a386Sopenharmony_ci    sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
480cb93a386Sopenharmony_ci        if (familyName) {
481cb93a386Sopenharmony_ci            // On Android, we must return nullptr when we can't find the requested
482cb93a386Sopenharmony_ci            // named typeface so that the system/app can provide their own recovery
483cb93a386Sopenharmony_ci            // mechanism. On other platforms we'd provide a typeface from the
484cb93a386Sopenharmony_ci            // default family instead.
485cb93a386Sopenharmony_ci            return sk_sp<SkTypeface>(this->onMatchFamilyStyle(familyName, style));
486cb93a386Sopenharmony_ci        }
487cb93a386Sopenharmony_ci        return sk_sp<SkTypeface>(fDefaultStyleSet->matchStyle(style));
488cb93a386Sopenharmony_ci    }
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_ci
491cb93a386Sopenharmony_ciprivate:
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_ci    SkTypeface_FreeType::Scanner fScanner;
494cb93a386Sopenharmony_ci
495cb93a386Sopenharmony_ci    SkTArray<sk_sp<SkFontStyleSet_Android>> fStyleSets;
496cb93a386Sopenharmony_ci    sk_sp<SkFontStyleSet> fDefaultStyleSet;
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_ci    SkTArray<NameToFamily, true> fNameToFamilyMap;
499cb93a386Sopenharmony_ci    SkTArray<NameToFamily, true> fFallbackNameToFamilyMap;
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci    void addFamily(FontFamily& family, const bool isolated, int familyIndex) {
502cb93a386Sopenharmony_ci        SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
503cb93a386Sopenharmony_ci        if (family.fIsFallbackFont) {
504cb93a386Sopenharmony_ci            nameToFamily = &fFallbackNameToFamilyMap;
505cb93a386Sopenharmony_ci
506cb93a386Sopenharmony_ci            if (0 == family.fNames.count()) {
507cb93a386Sopenharmony_ci                SkString& fallbackName = family.fNames.push_back();
508cb93a386Sopenharmony_ci                fallbackName.printf("%.2x##fallback", familyIndex);
509cb93a386Sopenharmony_ci            }
510cb93a386Sopenharmony_ci        }
511cb93a386Sopenharmony_ci
512cb93a386Sopenharmony_ci        sk_sp<SkFontStyleSet_Android> newSet =
513cb93a386Sopenharmony_ci            sk_make_sp<SkFontStyleSet_Android>(family, fScanner, isolated);
514cb93a386Sopenharmony_ci        if (0 == newSet->count()) {
515cb93a386Sopenharmony_ci            return;
516cb93a386Sopenharmony_ci        }
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ci        for (const SkString& name : family.fNames) {
519cb93a386Sopenharmony_ci            nameToFamily->emplace_back(NameToFamily{name, newSet.get()});
520cb93a386Sopenharmony_ci        }
521cb93a386Sopenharmony_ci        fStyleSets.emplace_back(std::move(newSet));
522cb93a386Sopenharmony_ci    }
523cb93a386Sopenharmony_ci    void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
524cb93a386Sopenharmony_ci        int familyIndex = 0;
525cb93a386Sopenharmony_ci        for (FontFamily* family : families) {
526cb93a386Sopenharmony_ci            addFamily(*family, isolated, familyIndex++);
527cb93a386Sopenharmony_ci            for (const auto& [unused, fallbackFamily] : family->fallbackFamilies) {
528cb93a386Sopenharmony_ci                addFamily(*fallbackFamily, isolated, familyIndex++);
529cb93a386Sopenharmony_ci            }
530cb93a386Sopenharmony_ci        }
531cb93a386Sopenharmony_ci    }
532cb93a386Sopenharmony_ci
533cb93a386Sopenharmony_ci    void findDefaultStyleSet() {
534cb93a386Sopenharmony_ci        SkASSERT(!fStyleSets.empty());
535cb93a386Sopenharmony_ci
536cb93a386Sopenharmony_ci        static const char* defaultNames[] = { "sans-serif" };
537cb93a386Sopenharmony_ci        for (const char* defaultName : defaultNames) {
538cb93a386Sopenharmony_ci            fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
539cb93a386Sopenharmony_ci            if (fDefaultStyleSet) {
540cb93a386Sopenharmony_ci                break;
541cb93a386Sopenharmony_ci            }
542cb93a386Sopenharmony_ci        }
543cb93a386Sopenharmony_ci        if (nullptr == fDefaultStyleSet) {
544cb93a386Sopenharmony_ci            fDefaultStyleSet = fStyleSets[0];
545cb93a386Sopenharmony_ci        }
546cb93a386Sopenharmony_ci        SkASSERT(fDefaultStyleSet);
547cb93a386Sopenharmony_ci    }
548cb93a386Sopenharmony_ci
549cb93a386Sopenharmony_ci    using INHERITED = SkFontMgr;
550cb93a386Sopenharmony_ci};
551cb93a386Sopenharmony_ci
552cb93a386Sopenharmony_ci#ifdef SK_DEBUG
553cb93a386Sopenharmony_cistatic char const * const gSystemFontUseStrings[] = {
554cb93a386Sopenharmony_ci    "OnlyCustom", "PreferCustom", "PreferSystem"
555cb93a386Sopenharmony_ci};
556cb93a386Sopenharmony_ci#endif
557cb93a386Sopenharmony_ci
558cb93a386Sopenharmony_cisk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
559cb93a386Sopenharmony_ci    if (custom) {
560cb93a386Sopenharmony_ci        SkASSERT(0 <= custom->fSystemFontUse);
561cb93a386Sopenharmony_ci        SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
562cb93a386Sopenharmony_ci        SkDEBUGF("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
563cb93a386Sopenharmony_ci                 gSystemFontUseStrings[custom->fSystemFontUse],
564cb93a386Sopenharmony_ci                 custom->fBasePath,
565cb93a386Sopenharmony_ci                 custom->fFontsXml,
566cb93a386Sopenharmony_ci                 custom->fFallbackFontsXml);
567cb93a386Sopenharmony_ci    }
568cb93a386Sopenharmony_ci    return sk_make_sp<SkFontMgr_Android>(custom);
569cb93a386Sopenharmony_ci}
570