blob: ec8e33870ca9e94dd99582320821f596a6da999e [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
8#include "SkFontHost.h"
reed@google.com0fc17c32013-03-21 13:33:49 +00009#include "SkFontHost_FreeType_common.h"
djsollen@google.com97145162012-05-31 19:55:08 +000010#include "SkFontDescriptor.h"
bungeman@google.comb3d154d2013-11-11 15:53:29 +000011#include "SkFontMgr.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkDescriptor.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkOSFile.h"
14#include "SkPaint.h"
humperad5e9a52014-11-19 08:32:19 -080015#include "SkRTConf.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#include "SkString.h"
17#include "SkStream.h"
18#include "SkThread.h"
19#include "SkTSearch.h"
bungeman@google.comb3d154d2013-11-11 15:53:29 +000020#include "SkTypefaceCache.h"
21#include "SkTArray.h"
22
23#include <limits>
reed@android.com8a1c16f2008-12-17 15:59:43 +000024
reed@android.com8a1c16f2008-12-17 15:59:43 +000025#ifndef SK_FONT_FILE_PREFIX
bungeman14df8332014-10-28 15:07:23 -070026# define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
bungeman@google.com2cf84ec2012-09-26 19:16:54 +000027#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000028
reed@android.com8a1c16f2008-12-17 15:59:43 +000029///////////////////////////////////////////////////////////////////////////////
30
bungeman@google.comb3d154d2013-11-11 15:53:29 +000031/** The base SkTypeface implementation for the custom font manager. */
32class SkTypeface_Custom : public SkTypeface_FreeType {
reed@android.com8a1c16f2008-12-17 15:59:43 +000033public:
bungemana4c4a2d2014-10-20 13:33:19 -070034 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
bungemand71b7572014-09-18 10:55:32 -070035 bool sysFont, const SkString familyName, int index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +000036 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
bungemand71b7572014-09-18 10:55:32 -070037 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +000038 { }
chudy@google.comada44802012-07-30 12:59:12 +000039
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 bool isSysFont() const { return fIsSysFont; }
reed@google.com292b1d42013-03-22 17:21:59 +000041
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 virtual const char* getUniqueString() const = 0;
chudy@google.comada44802012-07-30 12:59:12 +000043
reed@google.com5526ede2013-03-25 13:03:37 +000044protected:
mtklein72c9faa2015-01-09 10:06:39 -080045 void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
bungemanb374d6a2014-09-17 07:48:59 -070046 *familyName = fFamilyName;
47 }
48
mtklein72c9faa2015-01-09 10:06:39 -080049 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +000050 desc->setFamilyName(fFamilyName.c_str());
51 desc->setFontFileName(this->getUniqueString());
bungemand71b7572014-09-18 10:55:32 -070052 desc->setFontIndex(fIndex);
bungeman@google.comb3d154d2013-11-11 15:53:29 +000053 *isLocal = !this->isSysFont();
54 }
reed@google.com5526ede2013-03-25 13:03:37 +000055
bungemand71b7572014-09-18 10:55:32 -070056 int getIndex() const { return fIndex; }
57
reed@android.com8a1c16f2008-12-17 15:59:43 +000058private:
bungemand71b7572014-09-18 10:55:32 -070059 const bool fIsSysFont;
60 const SkString fFamilyName;
61 const int fIndex;
chudy@google.comada44802012-07-30 12:59:12 +000062
reed@google.com032fbb82013-03-21 13:38:18 +000063 typedef SkTypeface_FreeType INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000064};
65
bungeman@google.comb3d154d2013-11-11 15:53:29 +000066/** The empty SkTypeface implementation for the custom font manager.
67 * Used as the last resort fallback typeface.
reed@android.comf244f1b2010-04-16 12:40:08 +000068 */
bungeman@google.comb3d154d2013-11-11 15:53:29 +000069class SkTypeface_Empty : public SkTypeface_Custom {
reed@android.comf244f1b2010-04-16 12:40:08 +000070public:
bungemana4c4a2d2014-10-20 13:33:19 -070071 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
chudy@google.comada44802012-07-30 12:59:12 +000072
mtklein72c9faa2015-01-09 10:06:39 -080073 const char* getUniqueString() const SK_OVERRIDE { return NULL; }
chudy@google.comada44802012-07-30 12:59:12 +000074
reed@google.com292b1d42013-03-22 17:21:59 +000075protected:
mtklein72c9faa2015-01-09 10:06:39 -080076 SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
reed@google.com292b1d42013-03-22 17:21:59 +000077
reed@android.comf244f1b2010-04-16 12:40:08 +000078private:
bungeman@google.comb3d154d2013-11-11 15:53:29 +000079 typedef SkTypeface_Custom INHERITED;
reed@android.comf244f1b2010-04-16 12:40:08 +000080};
81
bungeman@google.comb3d154d2013-11-11 15:53:29 +000082/** The stream SkTypeface implementation for the custom font manager. */
83class SkTypeface_Stream : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +000084public:
bungemana4c4a2d2014-10-20 13:33:19 -070085 SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
86 const SkString familyName, SkStream* stream, int index)
87 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
bungemand71b7572014-09-18 10:55:32 -070088 , fStream(SkRef(stream))
bungeman@google.comb3d154d2013-11-11 15:53:29 +000089 { }
chudy@google.comada44802012-07-30 12:59:12 +000090
mtklein72c9faa2015-01-09 10:06:39 -080091 const char* getUniqueString() const SK_OVERRIDE { return NULL; }
chudy@google.comada44802012-07-30 12:59:12 +000092
reed@google.com292b1d42013-03-22 17:21:59 +000093protected:
mtklein72c9faa2015-01-09 10:06:39 -080094 SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
bungemand71b7572014-09-18 10:55:32 -070095 *ttcIndex = this->getIndex();
commit-bot@chromium.orga2b44dc2014-03-24 21:42:01 +000096 return fStream->duplicate();
reed@google.com292b1d42013-03-22 17:21:59 +000097 }
98
reed@android.com8a1c16f2008-12-17 15:59:43 +000099private:
bungemand71b7572014-09-18 10:55:32 -0700100 const SkAutoTUnref<const SkStream> fStream;
chudy@google.comada44802012-07-30 12:59:12 +0000101
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000102 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103};
104
humperad5e9a52014-11-19 08:32:19 -0800105// This configuration option is useful if we need to open and hold handles to
106// all found system font data (e.g., for skfiddle, where the application can't
107// access the filesystem to read fonts on demand)
108
109SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false,
110 "Retain the open stream for each found font on the system.");
111
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000112/** The file SkTypeface implementation for the custom font manager. */
113class SkTypeface_File : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114public:
bungemana4c4a2d2014-10-20 13:33:19 -0700115 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
116 const SkString familyName, const char path[], int index)
bungemand71b7572014-09-18 10:55:32 -0700117 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000118 , fPath(path)
humperad5e9a52014-11-19 08:32:19 -0800119 , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL)
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000120 { }
chudy@google.comada44802012-07-30 12:59:12 +0000121
mtklein72c9faa2015-01-09 10:06:39 -0800122 const char* getUniqueString() const SK_OVERRIDE {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123 const char* str = strrchr(fPath.c_str(), '/');
124 if (str) {
125 str += 1; // skip the '/'
126 }
127 return str;
128 }
chudy@google.comada44802012-07-30 12:59:12 +0000129
reed@google.com292b1d42013-03-22 17:21:59 +0000130protected:
mtklein72c9faa2015-01-09 10:06:39 -0800131 SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
bungemand71b7572014-09-18 10:55:32 -0700132 *ttcIndex = this->getIndex();
humperad5e9a52014-11-19 08:32:19 -0800133 if (fStream.get()) {
134 return fStream->duplicate();
135 } else {
136 return SkStream::NewFromFile(fPath.c_str());
137 }
reed@google.com292b1d42013-03-22 17:21:59 +0000138 }
139
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140private:
141 SkString fPath;
humperad5e9a52014-11-19 08:32:19 -0800142 const SkAutoTUnref<SkStreamAsset> fStream;
chudy@google.comada44802012-07-30 12:59:12 +0000143
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000144 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145};
146
147///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000149/**
150 * SkFontStyleSet_Custom
151 *
152 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
153 */
154class SkFontStyleSet_Custom : public SkFontStyleSet {
155public:
156 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
157
mtklein72c9faa2015-01-09 10:06:39 -0800158 int count() SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000159 return fStyles.count();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161
mtklein72c9faa2015-01-09 10:06:39 -0800162 void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000163 SkASSERT(index < fStyles.count());
164 bool bold = fStyles[index]->isBold();
165 bool italic = fStyles[index]->isItalic();
166 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
167 SkFontStyle::kNormal_Width,
168 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
169 name->reset();
170 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171
mtklein72c9faa2015-01-09 10:06:39 -0800172 SkTypeface* createTypeface(int index) SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000173 SkASSERT(index < fStyles.count());
174 return SkRef(fStyles[index].get());
175 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000177 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
178 int score = 0;
179 score += (pattern.width() - candidate.width()) * 100;
180 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
181 score += pattern.weight() - candidate.weight();
182 return score;
183 }
184
mtklein72c9faa2015-01-09 10:06:39 -0800185 SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000186 if (0 == fStyles.count()) {
187 return NULL;
188 }
189
190 SkTypeface_Custom* closest = fStyles[0];
191 int minScore = std::numeric_limits<int>::max();
192 for (int i = 0; i < fStyles.count(); ++i) {
193 bool bold = fStyles[i]->isBold();
194 bool italic = fStyles[i]->isItalic();
195 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
196 : SkFontStyle::kNormal_Weight,
197 SkFontStyle::kNormal_Width,
198 italic ? SkFontStyle::kItalic_Slant
199 : SkFontStyle::kUpright_Slant);
200
201 int score = match_score(pattern, style);
202 if (score < minScore) {
203 closest = fStyles[i];
204 minScore = score;
205 }
206 }
207 return SkRef(closest);
208 }
209
210private:
211 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
212 SkString fFamilyName;
213
214 void appendTypeface(SkTypeface_Custom* typeface) {
215 fStyles.push_back().reset(typeface);
216 }
217
218 friend class SkFontMgr_Custom;
219};
220
221/**
222 * SkFontMgr_Custom
223 *
224 * This class is essentially a collection of SkFontStyleSet_Custom,
225 * one SkFontStyleSet_Custom for each family. This class may be modified
226 * to load fonts from any source by changing the initialization.
227 */
228class SkFontMgr_Custom : public SkFontMgr {
229public:
230 explicit SkFontMgr_Custom(const char* dir) {
231 this->load_system_fonts(dir);
232 }
233
234protected:
mtklein72c9faa2015-01-09 10:06:39 -0800235 int onCountFamilies() const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000236 return fFamilies.count();
237 }
238
mtklein72c9faa2015-01-09 10:06:39 -0800239 void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000240 SkASSERT(index < fFamilies.count());
241 familyName->set(fFamilies[index]->fFamilyName);
242 }
243
mtklein72c9faa2015-01-09 10:06:39 -0800244 SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000245 SkASSERT(index < fFamilies.count());
246 return SkRef(fFamilies[index].get());
247 }
248
mtklein72c9faa2015-01-09 10:06:39 -0800249 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000250 for (int i = 0; i < fFamilies.count(); ++i) {
251 if (fFamilies[i]->fFamilyName.equals(familyName)) {
252 return SkRef(fFamilies[i].get());
253 }
254 }
255 return NULL;
256 }
257
258 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
commit-bot@chromium.org967dee32014-02-04 22:35:01 +0000259 const SkFontStyle& fontStyle) const SK_OVERRIDE
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000260 {
261 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
262 return sset->matchStyle(fontStyle);
263 }
264
djsollen33068c12014-11-14 10:52:53 -0800265 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
266 const char* bcp47[], int bcp47Count,
267 SkUnichar character) const SK_OVERRIDE
268 {
269 return NULL;
270 }
271
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000272 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
commit-bot@chromium.org967dee32014-02-04 22:35:01 +0000273 const SkFontStyle& fontStyle) const SK_OVERRIDE
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000274 {
275 for (int i = 0; i < fFamilies.count(); ++i) {
276 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
277 if (fFamilies[i]->fStyles[j] == familyMember) {
278 return fFamilies[i]->matchStyle(fontStyle);
279 }
280 }
281 }
282 return NULL;
283 }
284
mtklein72c9faa2015-01-09 10:06:39 -0800285 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000286 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
287 return this->createFromStream(stream, ttcIndex);
288 }
289
mtklein72c9faa2015-01-09 10:06:39 -0800290 SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000291 if (NULL == stream || stream->getLength() <= 0) {
292 SkDELETE(stream);
293 return NULL;
294 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295
bungeman@google.comfe747652013-03-25 19:36:11 +0000296 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700297 SkFontStyle style;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000298 SkString name;
bungeman14df8332014-10-28 15:07:23 -0700299 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
bungeman3a21d612014-07-11 08:52:26 -0700300 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name,
301 stream, ttcIndex));
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000302 } else {
303 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 }
reed@android.comf244f1b2010-04-16 12:40:08 +0000305 }
306
mtklein72c9faa2015-01-09 10:06:39 -0800307 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000308 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
309 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
310 }
311
312 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
commit-bot@chromium.org967dee32014-02-04 22:35:01 +0000313 unsigned styleBits) const SK_OVERRIDE
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000314 {
315 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
316 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
317 ? SkFontStyle::kBold_Weight
318 : SkFontStyle::kNormal_Weight,
319 SkFontStyle::kNormal_Width,
320 oldStyle & SkTypeface::kItalic
321 ? SkFontStyle::kItalic_Slant
322 : SkFontStyle::kUpright_Slant);
323 SkTypeface* tf = NULL;
324
bsalomon49f085d2014-09-05 13:34:00 -0700325 if (familyName) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000326 tf = this->onMatchFamilyStyle(familyName, style);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000327 }
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000328
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000329 if (NULL == tf) {
330 tf = gDefaultFamily->matchStyle(style);
331 }
332
333 return SkSafeRef(tf);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000334 }
335
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000336private:
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000337
bungeman14df8332014-10-28 15:07:23 -0700338 void load_directory_fonts(const SkString& directory, const char* suffix) {
339 SkOSFile::Iter iter(directory.c_str(), suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000340 SkString name;
341
342 while (iter.next(&name, false)) {
bungeman14df8332014-10-28 15:07:23 -0700343 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
344 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
345 if (!stream.get()) {
346 SkDebugf("---- failed to open <%s>\n", filename.c_str());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000347 continue;
348 }
349
bungeman14df8332014-10-28 15:07:23 -0700350 int numFaces;
351 if (!fScanner.recognizedFont(stream, &numFaces)) {
352 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
353 continue;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000354 }
bungeman14df8332014-10-28 15:07:23 -0700355
356 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
357 bool isFixedPitch;
358 SkString realname;
359 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
360 if (!fScanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
361 SkDebugf("---- failed to open <%s> <%d> as a font\n",
362 filename.c_str(), faceIndex);
363 continue;
364 }
365
366 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
367 style,
368 isFixedPitch,
369 true, // system-font (cannot delete)
370 realname,
371 filename.c_str(), 0));
372
373 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
374 if (NULL == addTo) {
375 addTo = new SkFontStyleSet_Custom(realname);
376 fFamilies.push_back().reset(addTo);
377 }
378 addTo->appendTypeface(tf);
379 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000380 }
381
382 SkOSFile::Iter dirIter(directory.c_str());
383 while (dirIter.next(&name, true)) {
384 if (name.startsWith(".")) {
385 continue;
386 }
tfarinaa8e2e152014-07-28 19:26:58 -0700387 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
bungeman14df8332014-10-28 15:07:23 -0700388 load_directory_fonts(dirname, suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000389 }
390 }
391
392 void load_system_fonts(const char* dir) {
393 SkString baseDirectory(dir);
bungeman14df8332014-10-28 15:07:23 -0700394 load_directory_fonts(baseDirectory, ".ttf");
395 load_directory_fonts(baseDirectory, ".ttc");
396 load_directory_fonts(baseDirectory, ".otf");
397 load_directory_fonts(baseDirectory, ".pfb");
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000398
399 if (fFamilies.empty()) {
400 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
401 fFamilies.push_back().reset(family);
402 family->appendTypeface(SkNEW(SkTypeface_Empty));
403 }
404
405 // Try to pick a default font.
406 static const char* gDefaultNames[] = {
commit-bot@chromium.orgea163cc2014-03-13 16:24:49 +0000407 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000408 };
409 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
410 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
411 if (NULL == set) {
412 continue;
413 }
414
415 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
416 SkFontStyle::kNormal_Width,
417 SkFontStyle::kUpright_Slant));
418 if (NULL == tf) {
419 continue;
420 }
421
422 gDefaultFamily = set;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 gDefaultNormal = tf;
424 break;
425 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000426 if (NULL == gDefaultNormal) {
427 gDefaultFamily = fFamilies[0];
428 gDefaultNormal = gDefaultFamily->fStyles[0];
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429 }
430 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000432 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
433 SkFontStyleSet_Custom* gDefaultFamily;
434 SkTypeface* gDefaultNormal;
bungeman14df8332014-10-28 15:07:23 -0700435 SkTypeface_FreeType::Scanner fScanner;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000436};
reed@google.com070da5e2013-03-27 20:01:49 +0000437
438SkFontMgr* SkFontMgr::Factory() {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000439 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
reed@google.com070da5e2013-03-27 20:01:49 +0000440}