blob: 200173d987a4cf5030fcab2c188d1e640834eb70 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
djsollen@google.com97145162012-05-31 19:55:08 +00008#include "SkFontDescriptor.h"
bungemanf20488b2015-07-29 11:49:40 -07009#include "SkFontHost_FreeType_common.h"
bungeman@google.comb3d154d2013-11-11 15:53:29 +000010#include "SkFontMgr.h"
bungeman5cf19492015-06-15 15:17:21 -070011#include "SkFontMgr_custom.h"
bungemanf20488b2015-07-29 11:49:40 -070012#include "SkFontStyle.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkOSFile.h"
bungemanf20488b2015-07-29 11:49:40 -070014#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkStream.h"
bungemanf20488b2015-07-29 11:49:40 -070016#include "SkString.h"
bungeman@google.comb3d154d2013-11-11 15:53:29 +000017#include "SkTArray.h"
bungemanf20488b2015-07-29 11:49:40 -070018#include "SkTemplates.h"
19#include "SkTypeface.h"
20#include "SkTypefaceCache.h"
21#include "SkTypes.h"
bungeman@google.comb3d154d2013-11-11 15:53:29 +000022
23#include <limits>
bungeman4772bd52016-06-10 04:14:51 -070024#include <memory>
reed@android.com8a1c16f2008-12-17 15:59:43 +000025
bungemanf20488b2015-07-29 11:49:40 -070026class SkData;
27
bungeman@google.comb3d154d2013-11-11 15:53:29 +000028/** The base SkTypeface implementation for the custom font manager. */
29class SkTypeface_Custom : public SkTypeface_FreeType {
reed@android.com8a1c16f2008-12-17 15:59:43 +000030public:
bungemana4c4a2d2014-10-20 13:33:19 -070031 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
bungemand71b7572014-09-18 10:55:32 -070032 bool sysFont, const SkString familyName, int index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +000033 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungemand71b7572014-09-18 10:55:32 -070034 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +000035 { }
chudy@google.comada44802012-07-30 12:59:12 +000036
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 bool isSysFont() const { return fIsSysFont; }
reed@google.com292b1d42013-03-22 17:21:59 +000038
reed@google.com5526ede2013-03-25 13:03:37 +000039protected:
mtklein36352bf2015-03-25 18:17:31 -070040 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -070041 *familyName = fFamilyName;
42 }
43
mtklein36352bf2015-03-25 18:17:31 -070044 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +000045 desc->setFamilyName(fFamilyName.c_str());
bungeman@google.comb3d154d2013-11-11 15:53:29 +000046 *isLocal = !this->isSysFont();
47 }
reed@google.com5526ede2013-03-25 13:03:37 +000048
bungemand71b7572014-09-18 10:55:32 -070049 int getIndex() const { return fIndex; }
50
reed@android.com8a1c16f2008-12-17 15:59:43 +000051private:
bungemand71b7572014-09-18 10:55:32 -070052 const bool fIsSysFont;
53 const SkString fFamilyName;
54 const int fIndex;
chudy@google.comada44802012-07-30 12:59:12 +000055
reed@google.com032fbb82013-03-21 13:38:18 +000056 typedef SkTypeface_FreeType INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000057};
58
bungeman@google.comb3d154d2013-11-11 15:53:29 +000059/** The empty SkTypeface implementation for the custom font manager.
60 * Used as the last resort fallback typeface.
reed@android.comf244f1b2010-04-16 12:40:08 +000061 */
bungeman@google.comb3d154d2013-11-11 15:53:29 +000062class SkTypeface_Empty : public SkTypeface_Custom {
reed@android.comf244f1b2010-04-16 12:40:08 +000063public:
bungemana4c4a2d2014-10-20 13:33:19 -070064 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
chudy@google.comada44802012-07-30 12:59:12 +000065
reed@google.com292b1d42013-03-22 17:21:59 +000066protected:
halcanary96fcdcc2015-08-27 07:41:13 -070067 SkStreamAsset* onOpenStream(int*) const override { return nullptr; }
reed@google.com292b1d42013-03-22 17:21:59 +000068
reed@android.comf244f1b2010-04-16 12:40:08 +000069private:
bungeman@google.comb3d154d2013-11-11 15:53:29 +000070 typedef SkTypeface_Custom INHERITED;
reed@android.comf244f1b2010-04-16 12:40:08 +000071};
72
bungeman@google.comb3d154d2013-11-11 15:53:29 +000073/** The stream SkTypeface implementation for the custom font manager. */
74class SkTypeface_Stream : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +000075public:
bungeman4772bd52016-06-10 04:14:51 -070076 SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
77 const SkFontStyle& style, bool isFixedPitch, bool sysFont,
78 const SkString familyName)
79 : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
80 , fData(std::move(fontData))
bungeman@google.comb3d154d2013-11-11 15:53:29 +000081 { }
chudy@google.comada44802012-07-30 12:59:12 +000082
reed@google.com292b1d42013-03-22 17:21:59 +000083protected:
mtklein36352bf2015-03-25 18:17:31 -070084 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman4772bd52016-06-10 04:14:51 -070085 *ttcIndex = fData->getIndex();
86 return fData->duplicateStream();
87 }
88
89 SkFontData* onCreateFontData() const override {
90 return new SkFontData(*fData.get());
reed@google.com292b1d42013-03-22 17:21:59 +000091 }
92
reed@android.com8a1c16f2008-12-17 15:59:43 +000093private:
bungeman4772bd52016-06-10 04:14:51 -070094 std::unique_ptr<const SkFontData> fData;
chudy@google.comada44802012-07-30 12:59:12 +000095
bungeman@google.comb3d154d2013-11-11 15:53:29 +000096 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000097};
98
bungeman@google.comb3d154d2013-11-11 15:53:29 +000099/** The file SkTypeface implementation for the custom font manager. */
100class SkTypeface_File : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101public:
bungemana4c4a2d2014-10-20 13:33:19 -0700102 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
103 const SkString familyName, const char path[], int index)
bungemand71b7572014-09-18 10:55:32 -0700104 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000105 , fPath(path)
106 { }
chudy@google.comada44802012-07-30 12:59:12 +0000107
reed@google.com292b1d42013-03-22 17:21:59 +0000108protected:
mtklein36352bf2015-03-25 18:17:31 -0700109 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungemand71b7572014-09-18 10:55:32 -0700110 *ttcIndex = this->getIndex();
bungeman5cf19492015-06-15 15:17:21 -0700111 return SkStream::NewFromFile(fPath.c_str());
reed@google.com292b1d42013-03-22 17:21:59 +0000112 }
113
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114private:
115 SkString fPath;
chudy@google.comada44802012-07-30 12:59:12 +0000116
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000117 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118};
119
120///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000122/**
123 * SkFontStyleSet_Custom
124 *
125 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
126 */
127class SkFontStyleSet_Custom : public SkFontStyleSet {
128public:
129 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
130
bungeman5c9fa282015-03-30 12:53:48 -0700131 /** Should only be called during the inital build phase. */
bungeman4772bd52016-06-10 04:14:51 -0700132 void appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
133 fStyles.emplace_back(std::move(typeface));
bungeman5c9fa282015-03-30 12:53:48 -0700134 }
135
mtklein36352bf2015-03-25 18:17:31 -0700136 int count() override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000137 return fStyles.count();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
mtklein36352bf2015-03-25 18:17:31 -0700140 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000141 SkASSERT(index < fStyles.count());
bungeman77a8ab22016-04-27 12:30:25 -0700142 if (style) {
143 *style = fStyles[index]->fontStyle();
144 }
145 if (name) {
146 name->reset();
147 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000148 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149
mtklein36352bf2015-03-25 18:17:31 -0700150 SkTypeface* createTypeface(int index) override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000151 SkASSERT(index < fStyles.count());
152 return SkRef(fStyles[index].get());
153 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154
mtklein36352bf2015-03-25 18:17:31 -0700155 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
bungeman77a8ab22016-04-27 12:30:25 -0700156 return this->matchStyleCSS3(pattern);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000157 }
158
bungeman5c9fa282015-03-30 12:53:48 -0700159 SkString getFamilyName() { return fFamilyName; }
160
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000161private:
bungeman4772bd52016-06-10 04:14:51 -0700162 SkTArray<sk_sp<SkTypeface_Custom>> fStyles;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000163 SkString fFamilyName;
164
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000165 friend class SkFontMgr_Custom;
166};
167
168/**
169 * SkFontMgr_Custom
170 *
171 * This class is essentially a collection of SkFontStyleSet_Custom,
172 * one SkFontStyleSet_Custom for each family. This class may be modified
173 * to load fonts from any source by changing the initialization.
174 */
175class SkFontMgr_Custom : public SkFontMgr {
176public:
bungeman4772bd52016-06-10 04:14:51 -0700177 typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families;
bungeman5c9fa282015-03-30 12:53:48 -0700178 class SystemFontLoader {
179 public:
180 virtual ~SystemFontLoader() { }
181 virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0;
182 };
halcanary96fcdcc2015-08-27 07:41:13 -0700183 explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
bungeman5c9fa282015-03-30 12:53:48 -0700184 loader.loadSystemFonts(fScanner, &fFamilies);
185
186 // Try to pick a default font.
187 static const char* defaultNames[] = {
halcanary96fcdcc2015-08-27 07:41:13 -0700188 "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
bungeman5c9fa282015-03-30 12:53:48 -0700189 };
190 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
bungeman4772bd52016-06-10 04:14:51 -0700191 sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
halcanary96fcdcc2015-08-27 07:41:13 -0700192 if (nullptr == set) {
bungeman5c9fa282015-03-30 12:53:48 -0700193 continue;
194 }
195
bungeman4772bd52016-06-10 04:14:51 -0700196 sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
197 SkFontStyle::kNormal_Width,
198 SkFontStyle::kUpright_Slant)));
halcanary96fcdcc2015-08-27 07:41:13 -0700199 if (nullptr == tf) {
bungeman5c9fa282015-03-30 12:53:48 -0700200 continue;
201 }
202
bungeman4772bd52016-06-10 04:14:51 -0700203 fDefaultFamily = set.get();
bungeman5c9fa282015-03-30 12:53:48 -0700204 break;
205 }
halcanary96fcdcc2015-08-27 07:41:13 -0700206 if (nullptr == fDefaultFamily) {
bungeman4772bd52016-06-10 04:14:51 -0700207 fDefaultFamily = fFamilies[0].get();
bungeman5c9fa282015-03-30 12:53:48 -0700208 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000209 }
210
211protected:
mtklein36352bf2015-03-25 18:17:31 -0700212 int onCountFamilies() const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000213 return fFamilies.count();
214 }
215
mtklein36352bf2015-03-25 18:17:31 -0700216 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000217 SkASSERT(index < fFamilies.count());
bungeman5c9fa282015-03-30 12:53:48 -0700218 familyName->set(fFamilies[index]->getFamilyName());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000219 }
220
mtklein36352bf2015-03-25 18:17:31 -0700221 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000222 SkASSERT(index < fFamilies.count());
223 return SkRef(fFamilies[index].get());
224 }
225
mtklein36352bf2015-03-25 18:17:31 -0700226 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000227 for (int i = 0; i < fFamilies.count(); ++i) {
bungeman5c9fa282015-03-30 12:53:48 -0700228 if (fFamilies[i]->getFamilyName().equals(familyName)) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000229 return SkRef(fFamilies[i].get());
230 }
231 }
halcanary96fcdcc2015-08-27 07:41:13 -0700232 return nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000233 }
234
bungeman5c9fa282015-03-30 12:53:48 -0700235 SkTypeface* onMatchFamilyStyle(const char familyName[],
236 const SkFontStyle& fontStyle) const override
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000237 {
238 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
239 return sset->matchStyle(fontStyle);
240 }
241
bungeman5c9fa282015-03-30 12:53:48 -0700242 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
243 const char* bcp47[], int bcp47Count,
244 SkUnichar character) const override
djsollen33068c12014-11-14 10:52:53 -0800245 {
halcanary96fcdcc2015-08-27 07:41:13 -0700246 return nullptr;
djsollen33068c12014-11-14 10:52:53 -0800247 }
248
bungeman5c9fa282015-03-30 12:53:48 -0700249 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
250 const SkFontStyle& fontStyle) const override
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000251 {
252 for (int i = 0; i < fFamilies.count(); ++i) {
253 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
bungeman4772bd52016-06-10 04:14:51 -0700254 if (fFamilies[i]->fStyles[j].get() == familyMember) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000255 return fFamilies[i]->matchStyle(fontStyle);
256 }
257 }
258 }
halcanary96fcdcc2015-08-27 07:41:13 -0700259 return nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000260 }
261
mtklein36352bf2015-03-25 18:17:31 -0700262 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800263 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000264 }
265
mtklein36352bf2015-03-25 18:17:31 -0700266 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman4772bd52016-06-10 04:14:51 -0700267 return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
268 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269
bungeman4772bd52016-06-10 04:14:51 -0700270 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
271 using Scanner = SkTypeface_FreeType::Scanner;
272 SkAutoTDelete<SkStreamAsset> stream(s);
bungeman@google.comfe747652013-03-25 19:36:11 +0000273 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700274 SkFontStyle style;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000275 SkString name;
bungeman4772bd52016-06-10 04:14:51 -0700276 Scanner::AxisDefinitions axisDefinitions;
277 if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
278 &axisDefinitions))
279 {
halcanary96fcdcc2015-08-27 07:41:13 -0700280 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 }
bungeman4772bd52016-06-10 04:14:51 -0700282
283 int paramAxisCount;
284 const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
285 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
286 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
287
288 std::unique_ptr<SkFontData> data(new SkFontData(stream.release(),
289 params.getCollectionIndex(),
290 axisValues.get(), axisDefinitions.count()));
291 return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
reed@android.comf244f1b2010-04-16 12:40:08 +0000292 }
293
mtklein36352bf2015-03-25 18:17:31 -0700294 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800295 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
mtklein18300a32016-03-16 13:53:35 -0700296 return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000297 }
298
bungeman11a77c62016-04-12 13:45:06 -0700299 SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
halcanary96fcdcc2015-08-27 07:41:13 -0700300 SkTypeface* tf = nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000301
bsalomon49f085d2014-09-05 13:34:00 -0700302 if (familyName) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000303 tf = this->onMatchFamilyStyle(familyName, style);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000304 }
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000305
halcanary96fcdcc2015-08-27 07:41:13 -0700306 if (nullptr == tf) {
bungeman5c9fa282015-03-30 12:53:48 -0700307 tf = fDefaultFamily->matchStyle(style);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000308 }
309
bungeman4772bd52016-06-10 04:14:51 -0700310 return tf;
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000311 }
312
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000313private:
bungeman5c9fa282015-03-30 12:53:48 -0700314 Families fFamilies;
315 SkFontStyleSet_Custom* fDefaultFamily;
316 SkTypeface_FreeType::Scanner fScanner;
317};
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000318
bungeman5c9fa282015-03-30 12:53:48 -0700319///////////////////////////////////////////////////////////////////////////////
320
321class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
322public:
323 DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
324
325 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
326 SkFontMgr_Custom::Families* families) const override
327 {
328 load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
329 load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
330 load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
331 load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
332
333 if (families->empty()) {
334 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
335 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700336 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
bungeman5c9fa282015-03-30 12:53:48 -0700337 }
338 }
339
340private:
341 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
342 const char familyName[])
343 {
344 for (int i = 0; i < families.count(); ++i) {
345 if (families[i]->getFamilyName().equals(familyName)) {
346 return families[i].get();
347 }
348 }
halcanary96fcdcc2015-08-27 07:41:13 -0700349 return nullptr;
bungeman5c9fa282015-03-30 12:53:48 -0700350 }
351
352 static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
353 const SkString& directory, const char* suffix,
354 SkFontMgr_Custom::Families* families)
355 {
bungeman14df8332014-10-28 15:07:23 -0700356 SkOSFile::Iter iter(directory.c_str(), suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000357 SkString name;
358
359 while (iter.next(&name, false)) {
bungeman14df8332014-10-28 15:07:23 -0700360 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
scroggoa1193e42015-01-21 12:09:53 -0800361 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
bungeman14df8332014-10-28 15:07:23 -0700362 if (!stream.get()) {
363 SkDebugf("---- failed to open <%s>\n", filename.c_str());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000364 continue;
365 }
366
bungeman14df8332014-10-28 15:07:23 -0700367 int numFaces;
bungeman5c9fa282015-03-30 12:53:48 -0700368 if (!scanner.recognizedFont(stream, &numFaces)) {
bungeman14df8332014-10-28 15:07:23 -0700369 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
370 continue;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000371 }
bungeman14df8332014-10-28 15:07:23 -0700372
373 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
374 bool isFixedPitch;
375 SkString realname;
376 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
halcanary96fcdcc2015-08-27 07:41:13 -0700377 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) {
bungeman14df8332014-10-28 15:07:23 -0700378 SkDebugf("---- failed to open <%s> <%d> as a font\n",
379 filename.c_str(), faceIndex);
380 continue;
381 }
382
bungeman5c9fa282015-03-30 12:53:48 -0700383 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
halcanary96fcdcc2015-08-27 07:41:13 -0700384 if (nullptr == addTo) {
bungeman14df8332014-10-28 15:07:23 -0700385 addTo = new SkFontStyleSet_Custom(realname);
bungeman5c9fa282015-03-30 12:53:48 -0700386 families->push_back().reset(addTo);
bungeman14df8332014-10-28 15:07:23 -0700387 }
bungeman4772bd52016-06-10 04:14:51 -0700388 addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
389 realname, filename.c_str(),
390 faceIndex));
bungeman14df8332014-10-28 15:07:23 -0700391 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000392 }
393
394 SkOSFile::Iter dirIter(directory.c_str());
395 while (dirIter.next(&name, true)) {
396 if (name.startsWith(".")) {
397 continue;
398 }
tfarinaa8e2e152014-07-28 19:26:58 -0700399 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
bungeman5c9fa282015-03-30 12:53:48 -0700400 load_directory_fonts(scanner, dirname, suffix, families);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000401 }
402 }
403
bungeman5c9fa282015-03-30 12:53:48 -0700404 SkString fBaseDirectory;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000405};
reed@google.com070da5e2013-03-27 20:01:49 +0000406
bungeman5cf19492015-06-15 15:17:21 -0700407SK_API SkFontMgr* SkFontMgr_New_Custom_Directory(const char* dir) {
408 return new SkFontMgr_Custom(DirectorySystemFontLoader(dir));
409}
410
411///////////////////////////////////////////////////////////////////////////////
412
bungeman5c9fa282015-03-30 12:53:48 -0700413struct SkEmbeddedResource { const uint8_t* data; size_t size; };
414struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
415
416class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
417public:
418 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
419
420 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
421 SkFontMgr_Custom::Families* families) const override
422 {
423 for (int i = 0; i < fHeader->count; ++i) {
424 const SkEmbeddedResource& fontEntry = fHeader->entries[i];
425 load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families);
426 }
427
428 if (families->empty()) {
429 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
430 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700431 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
bungeman5c9fa282015-03-30 12:53:48 -0700432 }
433 }
434
435private:
436 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
437 const char familyName[])
438 {
439 for (int i = 0; i < families.count(); ++i) {
440 if (families[i]->getFamilyName().equals(familyName)) {
441 return families[i].get();
442 }
443 }
halcanary96fcdcc2015-08-27 07:41:13 -0700444 return nullptr;
bungeman5c9fa282015-03-30 12:53:48 -0700445 }
446
447 static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
448 const uint8_t* data, size_t size, int index,
449 SkFontMgr_Custom::Families* families)
450 {
451 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false));
452
453 int numFaces;
454 if (!scanner.recognizedFont(stream, &numFaces)) {
455 SkDebugf("---- failed to open <%d> as a font\n", index);
456 return;
457 }
458
459 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
460 bool isFixedPitch;
461 SkString realname;
462 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
halcanary96fcdcc2015-08-27 07:41:13 -0700463 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) {
bungeman5c9fa282015-03-30 12:53:48 -0700464 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
465 return;
466 }
467
bungeman5c9fa282015-03-30 12:53:48 -0700468 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
halcanary96fcdcc2015-08-27 07:41:13 -0700469 if (nullptr == addTo) {
bungeman5c9fa282015-03-30 12:53:48 -0700470 addTo = new SkFontStyleSet_Custom(realname);
471 families->push_back().reset(addTo);
472 }
bungeman4772bd52016-06-10 04:14:51 -0700473 std::unique_ptr<SkFontData> data(
474 new SkFontData(stream.release(), faceIndex, nullptr, 0));
475 addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
476 style, isFixedPitch,
477 true, realname));
bungeman5c9fa282015-03-30 12:53:48 -0700478 }
479 }
480
481 const SkEmbeddedResourceHeader* fHeader;
482};
483
bungeman5cf19492015-06-15 15:17:21 -0700484SkFontMgr* SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
485 return new SkFontMgr_Custom(EmbeddedSystemFontLoader(header));
reed@google.com070da5e2013-03-27 20:01:49 +0000486}
caryclarkfe7ada72016-03-21 06:55:52 -0700487
488///////////////////////////////////////////////////////////////////////////////
489
490class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader {
491public:
492 EmptyFontLoader() { }
493
494 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
495 SkFontMgr_Custom::Families* families) const override
496 {
497 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
498 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700499 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
caryclarkfe7ada72016-03-21 06:55:52 -0700500 }
501
502};
503
504SK_API SkFontMgr* SkFontMgr_New_Custom_Empty() {
505 return new SkFontMgr_Custom(EmptyFontLoader());
506}