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