1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/core/SkFontDescriptor.h"
9#include "tools/ToolUtils.h"
10#include "tools/fonts/TestFontMgr.h"
11#include "tools/fonts/TestTypeface.h"
12
13#ifdef SK_XML
14#include "tools/fonts/TestSVGTypeface.h"
15#endif
16
17#include <vector>
18
19namespace {
20
21#include "test_font_monospace.inc"
22#include "test_font_sans_serif.inc"
23#include "test_font_serif.inc"
24
25#include "test_font_index.inc"
26
27class FontStyleSet final : public SkFontStyleSet {
28public:
29    FontStyleSet(const char* familyName) : fFamilyName(familyName) {}
30    struct TypefaceEntry {
31        TypefaceEntry(sk_sp<SkTypeface> typeface, SkFontStyle style, const char* styleName)
32                : fTypeface(std::move(typeface)), fStyle(style), fStyleName(styleName) {}
33        sk_sp<SkTypeface> fTypeface;
34        SkFontStyle       fStyle;
35        const char*       fStyleName;
36    };
37
38    int count() override { return fTypefaces.size(); }
39
40    void getStyle(int index, SkFontStyle* style, SkString* name) override {
41        if (style) {
42            *style = fTypefaces[index].fStyle;
43        }
44        if (name) {
45            *name = fTypefaces[index].fStyleName;
46        }
47    }
48
49    SkTypeface* createTypeface(int index) override {
50        return SkRef(fTypefaces[index].fTypeface.get());
51    }
52
53    SkTypeface* matchStyle(const SkFontStyle& pattern) override {
54        return this->matchStyleCSS3(pattern);
55    }
56
57    SkString getFamilyName() { return fFamilyName; }
58
59    std::vector<TypefaceEntry> fTypefaces;
60    SkString                   fFamilyName;
61};
62
63class FontMgr final : public SkFontMgr {
64public:
65    FontMgr() {
66        for (const auto& sub : gSubFonts) {
67            sk_sp<TestTypeface> typeface =
68                    sk_make_sp<TestTypeface>(sk_make_sp<SkTestFont>(sub.fFont), sub.fStyle);
69            bool defaultFamily = false;
70            if (&sub - gSubFonts == gDefaultFontIndex) {
71                defaultFamily    = true;
72                fDefaultTypeface = typeface;
73            }
74            bool found = false;
75            for (const auto& family : fFamilies) {
76                if (family->getFamilyName().equals(sub.fFamilyName)) {
77                    family->fTypefaces.emplace_back(
78                            std::move(typeface), sub.fStyle, sub.fStyleName);
79                    found = true;
80                    if (defaultFamily) {
81                        fDefaultFamily = family;
82                    }
83                    break;
84                }
85            }
86            if (!found) {
87                fFamilies.emplace_back(sk_make_sp<FontStyleSet>(sub.fFamilyName));
88                fFamilies.back()->fTypefaces.emplace_back(
89                        // NOLINTNEXTLINE(bugprone-use-after-move)
90                        std::move(typeface),
91                        sub.fStyle,
92                        sub.fStyleName);
93                if (defaultFamily) {
94                    fDefaultFamily = fFamilies.back();
95                }
96            }
97        }
98#if defined(SK_ENABLE_SVG)
99        fFamilies.emplace_back(sk_make_sp<FontStyleSet>("Emoji"));
100        fFamilies.back()->fTypefaces.emplace_back(
101                TestSVGTypeface::Default(), SkFontStyle::Normal(), "Normal");
102
103        fFamilies.emplace_back(sk_make_sp<FontStyleSet>("Planet"));
104        fFamilies.back()->fTypefaces.emplace_back(
105                TestSVGTypeface::Planets(), SkFontStyle::Normal(), "Normal");
106#endif
107    }
108
109    int onCountFamilies() const override { return fFamilies.size(); }
110
111    void onGetFamilyName(int index, SkString* familyName) const override {
112        *familyName = fFamilies[index]->getFamilyName();
113    }
114
115    SkFontStyleSet* onCreateStyleSet(int index) const override {
116        sk_sp<SkFontStyleSet> ref = fFamilies[index];
117        return ref.release();
118    }
119
120    SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
121        if (familyName) {
122            if (strstr(familyName, "ono")) {
123                return this->createStyleSet(0);
124            }
125            if (strstr(familyName, "ans")) {
126                return this->createStyleSet(1);
127            }
128            if (strstr(familyName, "erif")) {
129                return this->createStyleSet(2);
130            }
131#ifdef SK_XML
132            if (strstr(familyName, "oji")) {
133                return this->createStyleSet(6);
134            }
135            if (strstr(familyName, "Planet")) {
136                return this->createStyleSet(7);
137            }
138#endif
139        }
140        return nullptr;
141    }
142
143    SkTypeface* onMatchFamilyStyle(const char         familyName[],
144                                   const SkFontStyle& style) const override {
145        sk_sp<SkFontStyleSet> styleSet(this->matchFamily(familyName));
146        return styleSet->matchStyle(style);
147    }
148
149    SkTypeface* onMatchFamilyStyleCharacter(const char         familyName[],
150                                            const SkFontStyle& style,
151                                            const char*        bcp47[],
152                                            int                bcp47Count,
153                                            SkUnichar          character) const override {
154        (void)bcp47;
155        (void)bcp47Count;
156        (void)character;
157        return this->matchFamilyStyle(familyName, style);
158    }
159
160    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override { return nullptr; }
161    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
162                                            int ttcIndex) const override {
163        return nullptr;
164    }
165    sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
166                                           const SkFontArguments&) const override {
167        return nullptr;
168    }
169    sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
170        return nullptr;
171    }
172
173    sk_sp<SkTypeface> onLegacyMakeTypeface(const char  familyName[],
174                                           SkFontStyle style) const override {
175        if (familyName == nullptr) {
176            return sk_sp<SkTypeface>(fDefaultFamily->matchStyle(style));
177        }
178        sk_sp<SkTypeface> typeface = sk_sp<SkTypeface>(this->matchFamilyStyle(familyName, style));
179        if (!typeface) {
180            typeface = fDefaultTypeface;
181        }
182        return typeface;
183    }
184
185private:
186    std::vector<sk_sp<FontStyleSet>> fFamilies;
187    sk_sp<FontStyleSet>              fDefaultFamily;
188    sk_sp<SkTypeface>                fDefaultTypeface;
189};
190}  // namespace
191
192namespace ToolUtils {
193sk_sp<SkFontMgr> MakePortableFontMgr() { return sk_make_sp<FontMgr>(); }
194}  // namespace ToolUtils
195