2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkFontHost_FreeType_common.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontMgr.h"
11 #include "SkDescriptor.h"
18 #include "SkTSearch.h"
19 #include "SkTypefaceCache.h"
24 #ifndef SK_FONT_FILE_PREFIX
25 # define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
28 ///////////////////////////////////////////////////////////////////////////////
30 /** The base SkTypeface implementation for the custom font manager. */
31 class SkTypeface_Custom : public SkTypeface_FreeType {
33 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
34 bool sysFont, const SkString familyName, int index)
35 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
36 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
39 bool isSysFont() const { return fIsSysFont; }
41 virtual const char* getUniqueString() const = 0;
44 void onGetFamilyName(SkString* familyName) const override {
45 *familyName = fFamilyName;
48 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override {
49 desc->setFamilyName(fFamilyName.c_str());
50 desc->setFontFileName(this->getUniqueString());
51 desc->setFontIndex(fIndex);
52 *isLocal = !this->isSysFont();
55 int getIndex() const { return fIndex; }
58 const bool fIsSysFont;
59 const SkString fFamilyName;
62 typedef SkTypeface_FreeType INHERITED;
65 /** The empty SkTypeface implementation for the custom font manager.
66 * Used as the last resort fallback typeface.
68 class SkTypeface_Empty : public SkTypeface_Custom {
70 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
72 const char* getUniqueString() const override { return NULL; }
75 SkStreamAsset* onOpenStream(int*) const override { return NULL; }
78 typedef SkTypeface_Custom INHERITED;
81 /** The stream SkTypeface implementation for the custom font manager. */
82 class SkTypeface_Stream : public SkTypeface_Custom {
84 SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
85 const SkString familyName, SkStreamAsset* stream, int index)
86 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
90 const char* getUniqueString() const override { return NULL; }
93 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
94 *ttcIndex = this->getIndex();
95 return fStream->duplicate();
99 const SkAutoTDelete<const SkStreamAsset> fStream;
101 typedef SkTypeface_Custom INHERITED;
104 // This configuration option is useful if we need to open and hold handles to
105 // all found system font data (e.g., for skfiddle, where the application can't
106 // access the filesystem to read fonts on demand)
108 SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false,
109 "Retain the open stream for each found font on the system.");
111 /** The file SkTypeface implementation for the custom font manager. */
112 class SkTypeface_File : public SkTypeface_Custom {
114 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
115 const SkString familyName, const char path[], int index)
116 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
118 , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL)
121 const char* getUniqueString() const override {
122 const char* str = strrchr(fPath.c_str(), '/');
124 str += 1; // skip the '/'
130 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
131 *ttcIndex = this->getIndex();
133 return fStream->duplicate();
135 return SkStream::NewFromFile(fPath.c_str());
141 const SkAutoTDelete<SkStreamAsset> fStream;
143 typedef SkTypeface_Custom INHERITED;
146 ///////////////////////////////////////////////////////////////////////////////
149 * SkFontStyleSet_Custom
151 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
153 class SkFontStyleSet_Custom : public SkFontStyleSet {
155 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
157 int count() override {
158 return fStyles.count();
161 void getStyle(int index, SkFontStyle* style, SkString* name) override {
162 SkASSERT(index < fStyles.count());
163 bool bold = fStyles[index]->isBold();
164 bool italic = fStyles[index]->isItalic();
165 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
166 SkFontStyle::kNormal_Width,
167 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
171 SkTypeface* createTypeface(int index) override {
172 SkASSERT(index < fStyles.count());
173 return SkRef(fStyles[index].get());
176 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
178 score += (pattern.width() - candidate.width()) * 100;
179 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
180 score += pattern.weight() - candidate.weight();
184 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
185 if (0 == fStyles.count()) {
189 SkTypeface_Custom* closest = fStyles[0];
190 int minScore = std::numeric_limits<int>::max();
191 for (int i = 0; i < fStyles.count(); ++i) {
192 bool bold = fStyles[i]->isBold();
193 bool italic = fStyles[i]->isItalic();
194 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
195 : SkFontStyle::kNormal_Weight,
196 SkFontStyle::kNormal_Width,
197 italic ? SkFontStyle::kItalic_Slant
198 : SkFontStyle::kUpright_Slant);
200 int score = match_score(pattern, style);
201 if (score < minScore) {
202 closest = fStyles[i];
206 return SkRef(closest);
210 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
211 SkString fFamilyName;
213 void appendTypeface(SkTypeface_Custom* typeface) {
214 fStyles.push_back().reset(typeface);
217 friend class SkFontMgr_Custom;
223 * This class is essentially a collection of SkFontStyleSet_Custom,
224 * one SkFontStyleSet_Custom for each family. This class may be modified
225 * to load fonts from any source by changing the initialization.
227 class SkFontMgr_Custom : public SkFontMgr {
229 explicit SkFontMgr_Custom(const char* dir) {
230 this->load_system_fonts(dir);
234 int onCountFamilies() const override {
235 return fFamilies.count();
238 void onGetFamilyName(int index, SkString* familyName) const override {
239 SkASSERT(index < fFamilies.count());
240 familyName->set(fFamilies[index]->fFamilyName);
243 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
244 SkASSERT(index < fFamilies.count());
245 return SkRef(fFamilies[index].get());
248 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
249 for (int i = 0; i < fFamilies.count(); ++i) {
250 if (fFamilies[i]->fFamilyName.equals(familyName)) {
251 return SkRef(fFamilies[i].get());
257 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
258 const SkFontStyle& fontStyle) const override
260 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
261 return sset->matchStyle(fontStyle);
264 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
265 const char* bcp47[], int bcp47Count,
266 SkUnichar character) const override
271 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
272 const SkFontStyle& fontStyle) const override
274 for (int i = 0; i < fFamilies.count(); ++i) {
275 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
276 if (fFamilies[i]->fStyles[j] == familyMember) {
277 return fFamilies[i]->matchStyle(fontStyle);
284 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
285 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
288 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
289 SkAutoTDelete<SkStreamAsset> stream(bareStream);
290 if (NULL == stream || stream->getLength() <= 0) {
297 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
298 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name,
299 stream.detach(), ttcIndex));
305 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
306 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
307 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
310 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
311 unsigned styleBits) const override
313 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
314 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
315 ? SkFontStyle::kBold_Weight
316 : SkFontStyle::kNormal_Weight,
317 SkFontStyle::kNormal_Width,
318 oldStyle & SkTypeface::kItalic
319 ? SkFontStyle::kItalic_Slant
320 : SkFontStyle::kUpright_Slant);
321 SkTypeface* tf = NULL;
324 tf = this->onMatchFamilyStyle(familyName, style);
328 tf = gDefaultFamily->matchStyle(style);
331 return SkSafeRef(tf);
336 void load_directory_fonts(const SkString& directory, const char* suffix) {
337 SkOSFile::Iter iter(directory.c_str(), suffix);
340 while (iter.next(&name, false)) {
341 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
342 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
344 SkDebugf("---- failed to open <%s>\n", filename.c_str());
349 if (!fScanner.recognizedFont(stream, &numFaces)) {
350 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
354 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
357 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
358 if (!fScanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
359 SkDebugf("---- failed to open <%s> <%d> as a font\n",
360 filename.c_str(), faceIndex);
364 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
367 true, // system-font (cannot delete)
369 filename.c_str(), 0));
371 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
373 addTo = new SkFontStyleSet_Custom(realname);
374 fFamilies.push_back().reset(addTo);
376 addTo->appendTypeface(tf);
380 SkOSFile::Iter dirIter(directory.c_str());
381 while (dirIter.next(&name, true)) {
382 if (name.startsWith(".")) {
385 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
386 load_directory_fonts(dirname, suffix);
390 void load_system_fonts(const char* dir) {
391 SkString baseDirectory(dir);
392 load_directory_fonts(baseDirectory, ".ttf");
393 load_directory_fonts(baseDirectory, ".ttc");
394 load_directory_fonts(baseDirectory, ".otf");
395 load_directory_fonts(baseDirectory, ".pfb");
397 if (fFamilies.empty()) {
398 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
399 fFamilies.push_back().reset(family);
400 family->appendTypeface(SkNEW(SkTypeface_Empty));
403 // Try to pick a default font.
404 static const char* gDefaultNames[] = {
405 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
407 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
408 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
413 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
414 SkFontStyle::kNormal_Width,
415 SkFontStyle::kUpright_Slant));
420 gDefaultFamily = set;
424 if (NULL == gDefaultNormal) {
425 gDefaultFamily = fFamilies[0];
426 gDefaultNormal = gDefaultFamily->fStyles[0];
430 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
431 SkFontStyleSet_Custom* gDefaultFamily;
432 SkTypeface* gDefaultNormal;
433 SkTypeface_FreeType::Scanner fScanner;
436 SkFontMgr* SkFontMgr::Factory() {
437 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);