blob: 97489de50d6fba69b71303722349a2d304379941 [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)
bungemane3aea102016-07-13 05:16:58 -070033 : INHERITED(style, 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());
bungemanb8113782016-07-25 16:54:59 -070046 desc->setStyle(this->fontStyle());
bungeman@google.comb3d154d2013-11-11 15:53:29 +000047 *isLocal = !this->isSysFont();
48 }
reed@google.com5526ede2013-03-25 13:03:37 +000049
bungemand71b7572014-09-18 10:55:32 -070050 int getIndex() const { return fIndex; }
51
reed@android.com8a1c16f2008-12-17 15:59:43 +000052private:
bungemand71b7572014-09-18 10:55:32 -070053 const bool fIsSysFont;
54 const SkString fFamilyName;
55 const int fIndex;
chudy@google.comada44802012-07-30 12:59:12 +000056
reed@google.com032fbb82013-03-21 13:38:18 +000057 typedef SkTypeface_FreeType INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000058};
59
bungeman@google.comb3d154d2013-11-11 15:53:29 +000060/** The empty SkTypeface implementation for the custom font manager.
61 * Used as the last resort fallback typeface.
reed@android.comf244f1b2010-04-16 12:40:08 +000062 */
bungeman@google.comb3d154d2013-11-11 15:53:29 +000063class SkTypeface_Empty : public SkTypeface_Custom {
reed@android.comf244f1b2010-04-16 12:40:08 +000064public:
bungemana4c4a2d2014-10-20 13:33:19 -070065 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
chudy@google.comada44802012-07-30 12:59:12 +000066
reed@google.com292b1d42013-03-22 17:21:59 +000067protected:
halcanary96fcdcc2015-08-27 07:41:13 -070068 SkStreamAsset* onOpenStream(int*) const override { return nullptr; }
reed@google.com292b1d42013-03-22 17:21:59 +000069
reed@android.comf244f1b2010-04-16 12:40:08 +000070private:
bungeman@google.comb3d154d2013-11-11 15:53:29 +000071 typedef SkTypeface_Custom INHERITED;
reed@android.comf244f1b2010-04-16 12:40:08 +000072};
73
bungeman@google.comb3d154d2013-11-11 15:53:29 +000074/** The stream SkTypeface implementation for the custom font manager. */
75class SkTypeface_Stream : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076public:
bungeman4772bd52016-06-10 04:14:51 -070077 SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
78 const SkFontStyle& style, bool isFixedPitch, bool sysFont,
79 const SkString familyName)
80 : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
81 , fData(std::move(fontData))
bungeman@google.comb3d154d2013-11-11 15:53:29 +000082 { }
chudy@google.comada44802012-07-30 12:59:12 +000083
reed@google.com292b1d42013-03-22 17:21:59 +000084protected:
mtklein36352bf2015-03-25 18:17:31 -070085 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman4772bd52016-06-10 04:14:51 -070086 *ttcIndex = fData->getIndex();
87 return fData->duplicateStream();
88 }
89
90 SkFontData* onCreateFontData() const override {
91 return new SkFontData(*fData.get());
reed@google.com292b1d42013-03-22 17:21:59 +000092 }
93
reed@android.com8a1c16f2008-12-17 15:59:43 +000094private:
bungeman4772bd52016-06-10 04:14:51 -070095 std::unique_ptr<const SkFontData> fData;
chudy@google.comada44802012-07-30 12:59:12 +000096
bungeman@google.comb3d154d2013-11-11 15:53:29 +000097 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000098};
99
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000100/** The file SkTypeface implementation for the custom font manager. */
101class SkTypeface_File : public SkTypeface_Custom {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102public:
bungemana4c4a2d2014-10-20 13:33:19 -0700103 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
104 const SkString familyName, const char path[], int index)
bungemand71b7572014-09-18 10:55:32 -0700105 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000106 , fPath(path)
107 { }
chudy@google.comada44802012-07-30 12:59:12 +0000108
reed@google.com292b1d42013-03-22 17:21:59 +0000109protected:
mtklein36352bf2015-03-25 18:17:31 -0700110 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungemand71b7572014-09-18 10:55:32 -0700111 *ttcIndex = this->getIndex();
bungeman5cf19492015-06-15 15:17:21 -0700112 return SkStream::NewFromFile(fPath.c_str());
reed@google.com292b1d42013-03-22 17:21:59 +0000113 }
114
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115private:
116 SkString fPath;
chudy@google.comada44802012-07-30 12:59:12 +0000117
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000118 typedef SkTypeface_Custom INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119};
120
121///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000123/**
124 * SkFontStyleSet_Custom
125 *
126 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
127 */
128class SkFontStyleSet_Custom : public SkFontStyleSet {
129public:
130 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
131
bungeman5c9fa282015-03-30 12:53:48 -0700132 /** Should only be called during the inital build phase. */
bungeman4772bd52016-06-10 04:14:51 -0700133 void appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
134 fStyles.emplace_back(std::move(typeface));
bungeman5c9fa282015-03-30 12:53:48 -0700135 }
136
mtklein36352bf2015-03-25 18:17:31 -0700137 int count() override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000138 return fStyles.count();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140
mtklein36352bf2015-03-25 18:17:31 -0700141 void getStyle(int index, SkFontStyle* style, SkString* name) override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000142 SkASSERT(index < fStyles.count());
bungeman77a8ab22016-04-27 12:30:25 -0700143 if (style) {
144 *style = fStyles[index]->fontStyle();
145 }
146 if (name) {
147 name->reset();
148 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000149 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150
mtklein36352bf2015-03-25 18:17:31 -0700151 SkTypeface* createTypeface(int index) override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000152 SkASSERT(index < fStyles.count());
153 return SkRef(fStyles[index].get());
154 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155
mtklein36352bf2015-03-25 18:17:31 -0700156 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
bungeman77a8ab22016-04-27 12:30:25 -0700157 return this->matchStyleCSS3(pattern);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000158 }
159
bungeman5c9fa282015-03-30 12:53:48 -0700160 SkString getFamilyName() { return fFamilyName; }
161
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000162private:
bungeman4772bd52016-06-10 04:14:51 -0700163 SkTArray<sk_sp<SkTypeface_Custom>> fStyles;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000164 SkString fFamilyName;
165
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000166 friend class SkFontMgr_Custom;
167};
168
169/**
170 * SkFontMgr_Custom
171 *
172 * This class is essentially a collection of SkFontStyleSet_Custom,
173 * one SkFontStyleSet_Custom for each family. This class may be modified
174 * to load fonts from any source by changing the initialization.
175 */
176class SkFontMgr_Custom : public SkFontMgr {
177public:
bungeman4772bd52016-06-10 04:14:51 -0700178 typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families;
bungeman5c9fa282015-03-30 12:53:48 -0700179 class SystemFontLoader {
180 public:
181 virtual ~SystemFontLoader() { }
182 virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0;
183 };
halcanary96fcdcc2015-08-27 07:41:13 -0700184 explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
bungeman5c9fa282015-03-30 12:53:48 -0700185 loader.loadSystemFonts(fScanner, &fFamilies);
186
187 // Try to pick a default font.
188 static const char* defaultNames[] = {
halcanary96fcdcc2015-08-27 07:41:13 -0700189 "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
bungeman5c9fa282015-03-30 12:53:48 -0700190 };
191 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
bungeman4772bd52016-06-10 04:14:51 -0700192 sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
halcanary96fcdcc2015-08-27 07:41:13 -0700193 if (nullptr == set) {
bungeman5c9fa282015-03-30 12:53:48 -0700194 continue;
195 }
196
bungeman4772bd52016-06-10 04:14:51 -0700197 sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
198 SkFontStyle::kNormal_Width,
199 SkFontStyle::kUpright_Slant)));
halcanary96fcdcc2015-08-27 07:41:13 -0700200 if (nullptr == tf) {
bungeman5c9fa282015-03-30 12:53:48 -0700201 continue;
202 }
203
bungeman4772bd52016-06-10 04:14:51 -0700204 fDefaultFamily = set.get();
bungeman5c9fa282015-03-30 12:53:48 -0700205 break;
206 }
halcanary96fcdcc2015-08-27 07:41:13 -0700207 if (nullptr == fDefaultFamily) {
bungeman4772bd52016-06-10 04:14:51 -0700208 fDefaultFamily = fFamilies[0].get();
bungeman5c9fa282015-03-30 12:53:48 -0700209 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000210 }
211
212protected:
mtklein36352bf2015-03-25 18:17:31 -0700213 int onCountFamilies() const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000214 return fFamilies.count();
215 }
216
mtklein36352bf2015-03-25 18:17:31 -0700217 void onGetFamilyName(int index, SkString* familyName) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000218 SkASSERT(index < fFamilies.count());
bungeman5c9fa282015-03-30 12:53:48 -0700219 familyName->set(fFamilies[index]->getFamilyName());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000220 }
221
mtklein36352bf2015-03-25 18:17:31 -0700222 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000223 SkASSERT(index < fFamilies.count());
224 return SkRef(fFamilies[index].get());
225 }
226
mtklein36352bf2015-03-25 18:17:31 -0700227 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000228 for (int i = 0; i < fFamilies.count(); ++i) {
bungeman5c9fa282015-03-30 12:53:48 -0700229 if (fFamilies[i]->getFamilyName().equals(familyName)) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000230 return SkRef(fFamilies[i].get());
231 }
232 }
halcanary96fcdcc2015-08-27 07:41:13 -0700233 return nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000234 }
235
bungeman5c9fa282015-03-30 12:53:48 -0700236 SkTypeface* onMatchFamilyStyle(const char familyName[],
237 const SkFontStyle& fontStyle) const override
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000238 {
239 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
240 return sset->matchStyle(fontStyle);
241 }
242
bungeman5c9fa282015-03-30 12:53:48 -0700243 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
244 const char* bcp47[], int bcp47Count,
245 SkUnichar character) const override
djsollen33068c12014-11-14 10:52:53 -0800246 {
halcanary96fcdcc2015-08-27 07:41:13 -0700247 return nullptr;
djsollen33068c12014-11-14 10:52:53 -0800248 }
249
bungeman5c9fa282015-03-30 12:53:48 -0700250 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
251 const SkFontStyle& fontStyle) const override
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000252 {
253 for (int i = 0; i < fFamilies.count(); ++i) {
254 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
bungeman4772bd52016-06-10 04:14:51 -0700255 if (fFamilies[i]->fStyles[j].get() == familyMember) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000256 return fFamilies[i]->matchStyle(fontStyle);
257 }
258 }
259 }
halcanary96fcdcc2015-08-27 07:41:13 -0700260 return nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000261 }
262
mtklein36352bf2015-03-25 18:17:31 -0700263 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
reed42943c82016-09-12 12:01:44 -0700264 return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000265 }
266
mtklein36352bf2015-03-25 18:17:31 -0700267 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman4772bd52016-06-10 04:14:51 -0700268 return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
269 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270
bungeman4772bd52016-06-10 04:14:51 -0700271 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
272 using Scanner = SkTypeface_FreeType::Scanner;
273 SkAutoTDelete<SkStreamAsset> stream(s);
bungeman@google.comfe747652013-03-25 19:36:11 +0000274 bool isFixedPitch;
bungemana4c4a2d2014-10-20 13:33:19 -0700275 SkFontStyle style;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000276 SkString name;
bungeman4772bd52016-06-10 04:14:51 -0700277 Scanner::AxisDefinitions axisDefinitions;
278 if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
279 &axisDefinitions))
280 {
halcanary96fcdcc2015-08-27 07:41:13 -0700281 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282 }
bungeman4772bd52016-06-10 04:14:51 -0700283
284 int paramAxisCount;
285 const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
286 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
287 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
288
289 std::unique_ptr<SkFontData> data(new SkFontData(stream.release(),
290 params.getCollectionIndex(),
291 axisValues.get(), axisDefinitions.count()));
292 return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
reed@android.comf244f1b2010-04-16 12:40:08 +0000293 }
294
bungeman57c94822016-06-10 12:43:17 -0700295 SkTypeface* onCreateFromFontData(SkFontData* data) const override {
296 bool isFixedPitch;
297 SkFontStyle style;
298 SkString name;
299 if (!fScanner.scanFont(data->getStream(), data->getIndex(),
300 &name, &style, &isFixedPitch, nullptr))
301 {
302 return nullptr;
303 }
304 std::unique_ptr<SkFontData> unique_data(data);
305 return new SkTypeface_Stream(std::move(unique_data), style, isFixedPitch, false, name);
306 }
307
mtklein36352bf2015-03-25 18:17:31 -0700308 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800309 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
mtklein18300a32016-03-16 13:53:35 -0700310 return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000311 }
312
bungeman11a77c62016-04-12 13:45:06 -0700313 SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
halcanary96fcdcc2015-08-27 07:41:13 -0700314 SkTypeface* tf = nullptr;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000315
bsalomon49f085d2014-09-05 13:34:00 -0700316 if (familyName) {
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000317 tf = this->onMatchFamilyStyle(familyName, style);
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000318 }
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000319
halcanary96fcdcc2015-08-27 07:41:13 -0700320 if (nullptr == tf) {
bungeman5c9fa282015-03-30 12:53:48 -0700321 tf = fDefaultFamily->matchStyle(style);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000322 }
323
bungeman4772bd52016-06-10 04:14:51 -0700324 return tf;
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000325 }
326
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000327private:
bungeman5c9fa282015-03-30 12:53:48 -0700328 Families fFamilies;
329 SkFontStyleSet_Custom* fDefaultFamily;
330 SkTypeface_FreeType::Scanner fScanner;
331};
bungeman@google.com2cf84ec2012-09-26 19:16:54 +0000332
bungeman5c9fa282015-03-30 12:53:48 -0700333///////////////////////////////////////////////////////////////////////////////
334
335class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
336public:
337 DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
338
339 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
340 SkFontMgr_Custom::Families* families) const override
341 {
342 load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
343 load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
344 load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
345 load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
346
347 if (families->empty()) {
348 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
349 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700350 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
bungeman5c9fa282015-03-30 12:53:48 -0700351 }
352 }
353
354private:
355 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
356 const char familyName[])
357 {
358 for (int i = 0; i < families.count(); ++i) {
359 if (families[i]->getFamilyName().equals(familyName)) {
360 return families[i].get();
361 }
362 }
halcanary96fcdcc2015-08-27 07:41:13 -0700363 return nullptr;
bungeman5c9fa282015-03-30 12:53:48 -0700364 }
365
366 static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
367 const SkString& directory, const char* suffix,
368 SkFontMgr_Custom::Families* families)
369 {
bungeman14df8332014-10-28 15:07:23 -0700370 SkOSFile::Iter iter(directory.c_str(), suffix);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000371 SkString name;
372
373 while (iter.next(&name, false)) {
bungeman14df8332014-10-28 15:07:23 -0700374 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
scroggoa1193e42015-01-21 12:09:53 -0800375 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
bungeman14df8332014-10-28 15:07:23 -0700376 if (!stream.get()) {
377 SkDebugf("---- failed to open <%s>\n", filename.c_str());
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000378 continue;
379 }
380
bungeman14df8332014-10-28 15:07:23 -0700381 int numFaces;
bungeman5c9fa282015-03-30 12:53:48 -0700382 if (!scanner.recognizedFont(stream, &numFaces)) {
bungeman14df8332014-10-28 15:07:23 -0700383 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
384 continue;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000385 }
bungeman14df8332014-10-28 15:07:23 -0700386
387 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
388 bool isFixedPitch;
389 SkString realname;
390 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
halcanary96fcdcc2015-08-27 07:41:13 -0700391 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) {
bungeman14df8332014-10-28 15:07:23 -0700392 SkDebugf("---- failed to open <%s> <%d> as a font\n",
393 filename.c_str(), faceIndex);
394 continue;
395 }
396
bungeman5c9fa282015-03-30 12:53:48 -0700397 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
halcanary96fcdcc2015-08-27 07:41:13 -0700398 if (nullptr == addTo) {
bungeman14df8332014-10-28 15:07:23 -0700399 addTo = new SkFontStyleSet_Custom(realname);
bungeman5c9fa282015-03-30 12:53:48 -0700400 families->push_back().reset(addTo);
bungeman14df8332014-10-28 15:07:23 -0700401 }
bungeman4772bd52016-06-10 04:14:51 -0700402 addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
403 realname, filename.c_str(),
404 faceIndex));
bungeman14df8332014-10-28 15:07:23 -0700405 }
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000406 }
407
408 SkOSFile::Iter dirIter(directory.c_str());
409 while (dirIter.next(&name, true)) {
410 if (name.startsWith(".")) {
411 continue;
412 }
tfarinaa8e2e152014-07-28 19:26:58 -0700413 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
bungeman5c9fa282015-03-30 12:53:48 -0700414 load_directory_fonts(scanner, dirname, suffix, families);
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000415 }
416 }
417
bungeman5c9fa282015-03-30 12:53:48 -0700418 SkString fBaseDirectory;
bungeman@google.comb3d154d2013-11-11 15:53:29 +0000419};
reed@google.com070da5e2013-03-27 20:01:49 +0000420
bungeman5cf19492015-06-15 15:17:21 -0700421SK_API SkFontMgr* SkFontMgr_New_Custom_Directory(const char* dir) {
422 return new SkFontMgr_Custom(DirectorySystemFontLoader(dir));
423}
424
425///////////////////////////////////////////////////////////////////////////////
426
bungeman5c9fa282015-03-30 12:53:48 -0700427struct SkEmbeddedResource { const uint8_t* data; size_t size; };
428struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
429
430class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
431public:
432 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
433
434 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
435 SkFontMgr_Custom::Families* families) const override
436 {
437 for (int i = 0; i < fHeader->count; ++i) {
438 const SkEmbeddedResource& fontEntry = fHeader->entries[i];
439 load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families);
440 }
441
442 if (families->empty()) {
443 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
444 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700445 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
bungeman5c9fa282015-03-30 12:53:48 -0700446 }
447 }
448
449private:
450 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
451 const char familyName[])
452 {
453 for (int i = 0; i < families.count(); ++i) {
454 if (families[i]->getFamilyName().equals(familyName)) {
455 return families[i].get();
456 }
457 }
halcanary96fcdcc2015-08-27 07:41:13 -0700458 return nullptr;
bungeman5c9fa282015-03-30 12:53:48 -0700459 }
460
461 static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
462 const uint8_t* data, size_t size, int index,
463 SkFontMgr_Custom::Families* families)
464 {
465 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false));
466
467 int numFaces;
468 if (!scanner.recognizedFont(stream, &numFaces)) {
469 SkDebugf("---- failed to open <%d> as a font\n", index);
470 return;
471 }
472
473 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
474 bool isFixedPitch;
475 SkString realname;
476 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
halcanary96fcdcc2015-08-27 07:41:13 -0700477 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) {
bungeman5c9fa282015-03-30 12:53:48 -0700478 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
479 return;
480 }
481
bungeman5c9fa282015-03-30 12:53:48 -0700482 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
halcanary96fcdcc2015-08-27 07:41:13 -0700483 if (nullptr == addTo) {
bungeman5c9fa282015-03-30 12:53:48 -0700484 addTo = new SkFontStyleSet_Custom(realname);
485 families->push_back().reset(addTo);
486 }
bungeman4772bd52016-06-10 04:14:51 -0700487 std::unique_ptr<SkFontData> data(
488 new SkFontData(stream.release(), faceIndex, nullptr, 0));
489 addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
490 style, isFixedPitch,
491 true, realname));
bungeman5c9fa282015-03-30 12:53:48 -0700492 }
493 }
494
495 const SkEmbeddedResourceHeader* fHeader;
496};
497
bungeman5cf19492015-06-15 15:17:21 -0700498SkFontMgr* SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
499 return new SkFontMgr_Custom(EmbeddedSystemFontLoader(header));
reed@google.com070da5e2013-03-27 20:01:49 +0000500}
caryclarkfe7ada72016-03-21 06:55:52 -0700501
502///////////////////////////////////////////////////////////////////////////////
503
504class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader {
505public:
506 EmptyFontLoader() { }
507
508 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
509 SkFontMgr_Custom::Families* families) const override
510 {
511 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
512 families->push_back().reset(family);
bungeman4772bd52016-06-10 04:14:51 -0700513 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
caryclarkfe7ada72016-03-21 06:55:52 -0700514 }
515
516};
517
518SK_API SkFontMgr* SkFontMgr_New_Custom_Empty() {
519 return new SkFontMgr_Custom(EmptyFontLoader());
520}