1/*
2 * Copyright 2006 The Android Open Source Project
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 "SkFontArguments.h"
9#include "SkFontDescriptor.h"
10#include "SkFontHost_FreeType_common.h"
11#include "SkFontMgr.h"
12#include "SkFontMgr_custom.h"
13#include "SkFontStyle.h"
14#include "SkMakeUnique.h"
15#include "SkRefCnt.h"
16#include "SkStream.h"
17#include "SkString.h"
18#include "SkTArray.h"
19#include "SkTemplates.h"
20#include "SkTypeface.h"
21#include "SkTypes.h"
22
23#include <limits>
24#include <memory>
25
26class SkData;
27
28SkTypeface_Custom::SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
29                                     bool sysFont, const SkString familyName, int index)
30    : INHERITED(style, isFixedPitch)
31    , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
32{ }
33
34bool SkTypeface_Custom::isSysFont() const { return fIsSysFont; }
35
36void SkTypeface_Custom::onGetFamilyName(SkString* familyName) const {
37    *familyName = fFamilyName;
38}
39
40void SkTypeface_Custom::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
41    desc->setFamilyName(fFamilyName.c_str());
42    desc->setStyle(this->fontStyle());
43    *isLocal = !this->isSysFont();
44}
45
46int SkTypeface_Custom::getIndex() const { return fIndex; }
47
48
49SkTypeface_Empty::SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
50
51SkStreamAsset* SkTypeface_Empty::onOpenStream(int*) const { return nullptr; }
52
53
54SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
55                                     const SkFontStyle& style, bool isFixedPitch, bool sysFont,
56                                     const SkString familyName)
57    : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
58    , fData(std::move(fontData))
59{ }
60
61SkStreamAsset* SkTypeface_Stream::onOpenStream(int* ttcIndex) const {
62    *ttcIndex = fData->getIndex();
63    return fData->getStream()->duplicate();
64}
65
66std::unique_ptr<SkFontData> SkTypeface_Stream::onMakeFontData() const {
67    return skstd::make_unique<SkFontData>(*fData);
68}
69
70
71SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
72                                 const SkString familyName, const char path[], int index)
73    : INHERITED(style, isFixedPitch, sysFont, familyName, index)
74    , fPath(path)
75{ }
76
77SkStreamAsset* SkTypeface_File::onOpenStream(int* ttcIndex) const {
78    *ttcIndex = this->getIndex();
79    return SkStream::MakeFromFile(fPath.c_str()).release();
80}
81
82///////////////////////////////////////////////////////////////////////////////
83
84SkFontStyleSet_Custom::SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {}
85
86void SkFontStyleSet_Custom::appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
87    fStyles.emplace_back(std::move(typeface));
88}
89
90int SkFontStyleSet_Custom::count() {
91    return fStyles.count();
92}
93
94void SkFontStyleSet_Custom::getStyle(int index, SkFontStyle* style, SkString* name) {
95    SkASSERT(index < fStyles.count());
96    if (style) {
97        *style = fStyles[index]->fontStyle();
98    }
99    if (name) {
100        name->reset();
101    }
102}
103
104SkTypeface* SkFontStyleSet_Custom::createTypeface(int index) {
105    SkASSERT(index < fStyles.count());
106    return SkRef(fStyles[index].get());
107}
108
109SkTypeface* SkFontStyleSet_Custom::matchStyle(const SkFontStyle& pattern) {
110    return this->matchStyleCSS3(pattern);
111}
112
113SkString SkFontStyleSet_Custom::getFamilyName() { return fFamilyName; }
114
115
116SkFontMgr_Custom::SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
117    loader.loadSystemFonts(fScanner, &fFamilies);
118
119    // Try to pick a default font.
120    static const char* defaultNames[] = {
121        "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
122    };
123    for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
124        sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
125        if (nullptr == set) {
126            continue;
127        }
128
129        sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
130                                                         SkFontStyle::kNormal_Width,
131                                                         SkFontStyle::kUpright_Slant)));
132        if (nullptr == tf) {
133            continue;
134        }
135
136        fDefaultFamily = set.get();
137        break;
138    }
139    if (nullptr == fDefaultFamily) {
140        fDefaultFamily = fFamilies[0].get();
141    }
142}
143
144int SkFontMgr_Custom::onCountFamilies() const {
145    return fFamilies.count();
146}
147
148void SkFontMgr_Custom::onGetFamilyName(int index, SkString* familyName) const {
149    SkASSERT(index < fFamilies.count());
150    familyName->set(fFamilies[index]->getFamilyName());
151}
152
153SkFontStyleSet_Custom* SkFontMgr_Custom::onCreateStyleSet(int index) const {
154    SkASSERT(index < fFamilies.count());
155    return SkRef(fFamilies[index].get());
156}
157
158SkFontStyleSet_Custom* SkFontMgr_Custom::onMatchFamily(const char familyName[]) const {
159    for (int i = 0; i < fFamilies.count(); ++i) {
160        if (fFamilies[i]->getFamilyName().equals(familyName)) {
161            return SkRef(fFamilies[i].get());
162        }
163    }
164    return nullptr;
165}
166
167SkTypeface* SkFontMgr_Custom::onMatchFamilyStyle(const char familyName[],
168                                const SkFontStyle& fontStyle) const
169{
170    sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
171    return sset->matchStyle(fontStyle);
172}
173
174SkTypeface* SkFontMgr_Custom::onMatchFamilyStyleCharacter(const char familyName[],
175                                                          const SkFontStyle&,
176                                                          const char* bcp47[], int bcp47Count,
177                                                          SkUnichar character) const
178{
179    return nullptr;
180}
181
182SkTypeface* SkFontMgr_Custom::onMatchFaceStyle(const SkTypeface* familyMember,
183                                               const SkFontStyle& fontStyle) const
184{
185    for (int i = 0; i < fFamilies.count(); ++i) {
186        for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
187            if (fFamilies[i]->fStyles[j].get() == familyMember) {
188                return fFamilies[i]->matchStyle(fontStyle);
189            }
190        }
191    }
192    return nullptr;
193}
194
195SkTypeface* SkFontMgr_Custom::onCreateFromData(SkData* data, int ttcIndex) const {
196    return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
197}
198
199SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const {
200    return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
201}
202
203SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* s,
204                                                 const SkFontArguments& args) const
205{
206    using Scanner = SkTypeface_FreeType::Scanner;
207    std::unique_ptr<SkStreamAsset> stream(s);
208    bool isFixedPitch;
209    SkFontStyle style;
210    SkString name;
211    Scanner::AxisDefinitions axisDefinitions;
212    if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
213                            &name, &style, &isFixedPitch, &axisDefinitions))
214    {
215        return nullptr;
216    }
217
218    const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
219    SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
220    Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
221
222    auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
223                                               axisValues.get(), axisDefinitions.count());
224    return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
225}
226
227SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr<SkFontData> data) const {
228    bool isFixedPitch;
229    SkFontStyle style;
230    SkString name;
231    if (!fScanner.scanFont(data->getStream(), data->getIndex(),
232                            &name, &style, &isFixedPitch, nullptr))
233    {
234        return nullptr;
235    }
236    return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
237}
238
239SkTypeface* SkFontMgr_Custom::onCreateFromFile(const char path[], int ttcIndex) const {
240    std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
241    return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
242}
243
244SkTypeface* SkFontMgr_Custom::onLegacyCreateTypeface(const char familyName[],
245                                                     SkFontStyle style) const
246{
247    SkTypeface* tf = nullptr;
248
249    if (familyName) {
250        tf = this->onMatchFamilyStyle(familyName, style);
251    }
252
253    if (nullptr == tf) {
254        tf = fDefaultFamily->matchStyle(style);
255    }
256
257    return tf;
258}
259