blob: b6fab622e8fcc776195f6e8719d66cde18aacd60 [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;
scroggoa1193e42015-01-21 12:09:53 -0800142 const SkAutoTDelete<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 {
scroggoa1193e42015-01-21 12:09:53 -0800286 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000287 }
288
mtklein72c9faa2015-01-09 10:06:39 -0800289 SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
scroggoa1193e42015-01-21 12:09:53 -0800290 SkAutoTDelete<SkStream> streamDeleter(stream);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000291 if (NULL == stream || stream->getLength() <= 0) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000292 return NULL;
293 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294
bungeman@google.comfe747652013-03-25 19:36:11 +0000295 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700296 SkFontStyle style;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000297 SkString name;
bungeman14df8332014-10-28 15:07:23 -0700298 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
bungeman3a21d612014-07-11 08:52:26 -0700299 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name,
scroggoa1193e42015-01-21 12:09:53 -0800300 streamDeleter.detach(), ttcIndex));
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000301 } else {
302 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 }
reed@android.comf244f1b2010-04-16 12:40:08 +0000304 }
305
mtklein72c9faa2015-01-09 10:06:39 -0800306 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
scroggoa1193e42015-01-21 12:09:53 -0800307 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
308 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000309 }
310
311 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
commit-bot@chromium.org967dee32014-02-04 22:35:01 +0000312 unsigned styleBits) const SK_OVERRIDE
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000313 {
314 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
315 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
316 ? SkFontStyle::kBold_Weight
317 : SkFontStyle::kNormal_Weight,
318 SkFontStyle::kNormal_Width,
319 oldStyle & SkTypeface::kItalic
320 ? SkFontStyle::kItalic_Slant
321 : SkFontStyle::kUpright_Slant);
322 SkTypeface* tf = NULL;
323
bsalomon49f085d2014-09-05 13:34:00 -0700324 if (familyName) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000325 tf = this->onMatchFamilyStyle(familyName, style);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000326 }
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000327
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000328 if (NULL == tf) {
329 tf = gDefaultFamily->matchStyle(style);
330 }
331
332 return SkSafeRef(tf);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000333 }
334
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000335private:
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000336
bungeman14df8332014-10-28 15:07:23 -0700337 void load_directory_fonts(const SkString& directory, const char* suffix) {
338 SkOSFile::Iter iter(directory.c_str(), suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000339 SkString name;
340
341 while (iter.next(&name, false)) {
bungeman14df8332014-10-28 15:07:23 -0700342 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
scroggoa1193e42015-01-21 12:09:53 -0800343 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
bungeman14df8332014-10-28 15:07:23 -0700344 if (!stream.get()) {
345 SkDebugf("---- failed to open <%s>\n", filename.c_str());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000346 continue;
347 }
348
bungeman14df8332014-10-28 15:07:23 -0700349 int numFaces;
350 if (!fScanner.recognizedFont(stream, &numFaces)) {
351 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
352 continue;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000353 }
bungeman14df8332014-10-28 15:07:23 -0700354
355 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
356 bool isFixedPitch;
357 SkString realname;
358 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
359 if (!fScanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
360 SkDebugf("---- failed to open <%s> <%d> as a font\n",
361 filename.c_str(), faceIndex);
362 continue;
363 }
364
365 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
366 style,
367 isFixedPitch,
368 true, // system-font (cannot delete)
369 realname,
370 filename.c_str(), 0));
371
372 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
373 if (NULL == addTo) {
374 addTo = new SkFontStyleSet_Custom(realname);
375 fFamilies.push_back().reset(addTo);
376 }
377 addTo->appendTypeface(tf);
378 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000379 }
380
381 SkOSFile::Iter dirIter(directory.c_str());
382 while (dirIter.next(&name, true)) {
383 if (name.startsWith(".")) {
384 continue;
385 }
tfarinaa8e2e152014-07-28 19:26:58 -0700386 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
bungeman14df8332014-10-28 15:07:23 -0700387 load_directory_fonts(dirname, suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000388 }
389 }
390
391 void load_system_fonts(const char* dir) {
392 SkString baseDirectory(dir);
bungeman14df8332014-10-28 15:07:23 -0700393 load_directory_fonts(baseDirectory, ".ttf");
394 load_directory_fonts(baseDirectory, ".ttc");
395 load_directory_fonts(baseDirectory, ".otf");
396 load_directory_fonts(baseDirectory, ".pfb");
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000397
398 if (fFamilies.empty()) {
399 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
400 fFamilies.push_back().reset(family);
401 family->appendTypeface(SkNEW(SkTypeface_Empty));
402 }
403
404 // Try to pick a default font.
405 static const char* gDefaultNames[] = {
commit-bot@chromium.orgea163cc2014-03-13 16:24:49 +0000406 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000407 };
408 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
409 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
410 if (NULL == set) {
411 continue;
412 }
413
414 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
415 SkFontStyle::kNormal_Width,
416 SkFontStyle::kUpright_Slant));
417 if (NULL == tf) {
418 continue;
419 }
420
421 gDefaultFamily = set;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422 gDefaultNormal = tf;
423 break;
424 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000425 if (NULL == gDefaultNormal) {
426 gDefaultFamily = fFamilies[0];
427 gDefaultNormal = gDefaultFamily->fStyles[0];
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 }
429 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000431 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
432 SkFontStyleSet_Custom* gDefaultFamily;
433 SkTypeface* gDefaultNormal;
bungeman14df8332014-10-28 15:07:23 -0700434 SkTypeface_FreeType::Scanner fScanner;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000435};
reed@google.com070da5e2013-03-27 20:01:49 +0000436
437SkFontMgr* SkFontMgr::Factory() {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000438 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
reed@google.com070da5e2013-03-27 20:01:49 +0000439}