1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h" 90fc17c33f144956bb75650f991226a14e555f189reed@google.com#include "SkFontHost_FreeType_common.h" 109714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com#include "SkFontDescriptor.h" 11b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkFontMgr.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDescriptor.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTSearch.h" 19b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkTypefaceCache.h" 20b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkTArray.h" 21b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 22b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include <limits> 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SK_FONT_FILE_PREFIX 25b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com# define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" 262cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com#endif 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 284dc686d75353235260c716242f4ed596b70beb95djsollen@google.combool find_name_and_attributes(SkStream* stream, SkString* name, 29fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com SkTypeface::Style* style, bool* isFixedPitch); 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The base SkTypeface implementation for the custom font manager. */ 34b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Custom : public SkTypeface_FreeType { 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 36b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkString familyName) 37b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) 38b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com , fIsSysFont(sysFont), fFamilyName(familyName) 39b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { } 40ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isSysFont() const { return fIsSysFont; } 42292b1d4903a770a77282508054917b48fb989d49reed@google.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const char* getUniqueString() const = 0; 44ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 455526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.comprotected: 46b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE { 47b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com desc->setFamilyName(fFamilyName.c_str()); 48b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com desc->setFontFileName(this->getUniqueString()); 49b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *isLocal = !this->isSysFont(); 50b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 515526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 53b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool fIsSysFont; 54b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString fFamilyName; 55ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 56032fbb8ebff7816793b077b6113de702e48713c1reed@google.com typedef SkTypeface_FreeType INHERITED; 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 59b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The empty SkTypeface implementation for the custom font manager. 60b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * Used as the last resort fallback typeface. 61f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com */ 62b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Empty : public SkTypeface_Custom { 63f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.compublic: 64b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {} 65ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 66b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 67ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 68292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected: 69292b1d4903a770a77282508054917b48fb989d49reed@google.com virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } 70292b1d4903a770a77282508054917b48fb989d49reed@google.com 71f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.comprivate: 72b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com typedef SkTypeface_Custom INHERITED; 73f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com}; 74f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 75b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The stream SkTypeface implementation for the custom font manager. */ 76b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Stream : public SkTypeface_Custom { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 78b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_Stream(Style style, bool sysFont, SkStream* stream, 79b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool isFixedPitch, const SkString familyName) 80b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : INHERITED(style, sysFont, isFixedPitch, familyName) 81b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com , fStream(SkRef(stream)) 82b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { } 83ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 84e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 85ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 86292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected: 87292b1d4903a770a77282508054917b48fb989d49reed@google.com virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 88292b1d4903a770a77282508054917b48fb989d49reed@google.com *ttcIndex = 0; 89a2b44dc5882856b6ed3670f370819ab39998ada8commit-bot@chromium.org return fStream->duplicate(); 90292b1d4903a770a77282508054917b48fb989d49reed@google.com } 91292b1d4903a770a77282508054917b48fb989d49reed@google.com 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 93b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkAutoTUnref<SkStream> fStream; 94ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 95b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com typedef SkTypeface_Custom INHERITED; 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 98b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The file SkTypeface implementation for the custom font manager. */ 99b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_File : public SkTypeface_Custom { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 101b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_File(Style style, bool sysFont, const char path[], 102b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool isFixedPitch, const SkString familyName) 103b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : INHERITED(style, sysFont, isFixedPitch, familyName) 104b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com , fPath(path) 105b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { } 106ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 107e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com virtual const char* getUniqueString() const SK_OVERRIDE { 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* str = strrchr(fPath.c_str(), '/'); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (str) { 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com str += 1; // skip the '/' 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return str; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 114ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 115292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected: 116292b1d4903a770a77282508054917b48fb989d49reed@google.com virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 117292b1d4903a770a77282508054917b48fb989d49reed@google.com *ttcIndex = 0; 118292b1d4903a770a77282508054917b48fb989d49reed@google.com return SkStream::NewFromFile(fPath.c_str()); 119292b1d4903a770a77282508054917b48fb989d49reed@google.com } 120292b1d4903a770a77282508054917b48fb989d49reed@google.com 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString fPath; 123ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 124b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com typedef SkTypeface_Custom INHERITED; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 129b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** 130b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * SkFontStyleSet_Custom 131b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * 132b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. 133b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com */ 134b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkFontStyleSet_Custom : public SkFontStyleSet { 135b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.compublic: 136b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 138b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual int count() SK_OVERRIDE { 139b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return fStyles.count(); 140b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 142b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE { 143b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkASSERT(index < fStyles.count()); 144b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool bold = fStyles[index]->isBold(); 145b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool italic = fStyles[index]->isItalic(); 146b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, 147b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle::kNormal_Width, 148b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); 149b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com name->reset(); 150b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 152b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 153b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkASSERT(index < fStyles.count()); 154b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkRef(fStyles[index].get()); 155b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 157b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 158b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com int score = 0; 159b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com score += (pattern.width() - candidate.width()) * 100; 160b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; 161b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com score += pattern.weight() - candidate.weight(); 162b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return score; 163b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 164ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 165b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 166b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (0 == fStyles.count()) { 167b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return NULL; 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 169f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 170b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_Custom* closest = fStyles[0]; 171b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com int minScore = std::numeric_limits<int>::max(); 172b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com for (int i = 0; i < fStyles.count(); ++i) { 173b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool bold = fStyles[i]->isBold(); 174b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool italic = fStyles[i]->isItalic(); 175b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight 176b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : SkFontStyle::kNormal_Weight, 177b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle::kNormal_Width, 178b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com italic ? SkFontStyle::kItalic_Slant 179b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : SkFontStyle::kUpright_Slant); 180b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 181b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com int score = match_score(pattern, style); 182b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (score < minScore) { 183b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com closest = fStyles[i]; 184b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com minScore = score; 185b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 186887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com } 187b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkRef(closest); 188b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 189887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com 190b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprivate: 191b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; 192b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString fFamilyName; 193b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 194b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com void appendTypeface(SkTypeface_Custom* typeface) { 195b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com fStyles.push_back().reset(typeface); 196f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com } 197f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 198b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com friend class SkFontMgr_Custom; 199b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com}; 200b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 201b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** 202b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * SkFontMgr_Custom 203b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * 204b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * This class is essentially a collection of SkFontStyleSet_Custom, 205b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * one SkFontStyleSet_Custom for each family. This class may be modified 206b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com * to load fonts from any source by changing the initialization. 207b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com */ 208b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkFontMgr_Custom : public SkFontMgr { 209b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.compublic: 210b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com explicit SkFontMgr_Custom(const char* dir) { 211b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com this->load_system_fonts(dir); 2122cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com } 2132cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com 214b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprotected: 215967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual int onCountFamilies() const SK_OVERRIDE { 216b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return fFamilies.count(); 2172cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com } 2182cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com 219967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { 220b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkASSERT(index < fFamilies.count()); 221b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com familyName->set(fFamilies[index]->fFamilyName); 222b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 2232cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com 224967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE { 225b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkASSERT(index < fFamilies.count()); 226b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkRef(fFamilies[index].get()); 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 228f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 229967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE { 230b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com for (int i = 0; i < fFamilies.count(); ++i) { 231b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (fFamilies[i]->fFamilyName.equals(familyName)) { 232b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkRef(fFamilies[i].get()); 233b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 235b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return NULL; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 237b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 238b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 239967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org const SkFontStyle& fontStyle) const SK_OVERRIDE 240b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { 241b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 242b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return sset->matchStyle(fontStyle); 243b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 244b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 245b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 246967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org const SkFontStyle& fontStyle) const SK_OVERRIDE 247b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { 248b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com for (int i = 0; i < fFamilies.count(); ++i) { 249b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { 250b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (fFamilies[i]->fStyles[j] == familyMember) { 251b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return fFamilies[i]->matchStyle(fontStyle); 252b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 255b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return NULL; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 258967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE { 259b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); 260b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return this->createFromStream(stream, ttcIndex); 261b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 263967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE { 264b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == stream || stream->getLength() <= 0) { 265b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkDELETE(stream); 266b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return NULL; 267b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 269b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool isFixedPitch; 270b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface::Style style; 271b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString name; 272b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) { 273b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedPitch, name)); 274b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } else { 275b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return NULL; 276b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 277b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 278ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 279967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 280b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 281b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; 282b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 283ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 284b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 285967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org unsigned styleBits) const SK_OVERRIDE 286b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com { 287b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; 288b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold 289b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com ? SkFontStyle::kBold_Weight 290b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : SkFontStyle::kNormal_Weight, 291b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle::kNormal_Width, 292b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com oldStyle & SkTypeface::kItalic 293b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com ? SkFontStyle::kItalic_Slant 294b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com : SkFontStyle::kUpright_Slant); 295b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface* tf = NULL; 296b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 297b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL != familyName) { 298b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com tf = this->onMatchFamilyStyle(familyName, style); 299b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 300ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 301b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == tf) { 302b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com tf = gDefaultFamily->matchStyle(style); 303b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 304ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 305b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return SkSafeRef(tf); 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 307ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 308b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprivate: 309b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 310b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com static bool get_name_and_style(const char path[], SkString* name, 311b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface::Style* style, bool* isFixedPitch) { 312b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 313b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (stream.get()) { 314b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return find_name_and_attributes(stream, name, style, isFixedPitch); 315b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } else { 316b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkDebugf("---- failed to open <%s> as a font\n", path); 317b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return false; 318b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 320ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com 321b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com void load_directory_fonts(const SkString& directory) { 322b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkOSFile::Iter iter(directory.c_str(), ".ttf"); 323b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString name; 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 325b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com while (iter.next(&name, false)) { 326ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org SkString filename( 327ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org SkOSPath::SkPathJoin(directory.c_str(), name.c_str())); 328febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com 329b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com bool isFixedPitch; 330b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString realname; 331b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning 332febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com 333b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) { 334b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); 335b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com continue; 336b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 337febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com 338b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( 339b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com style, 340b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com true, // system-font (cannot delete) 341b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com filename.c_str(), 342b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com isFixedPitch, 343b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com realname)); 344b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 345b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str()); 346b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == addTo) { 347b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com addTo = new SkFontStyleSet_Custom(realname); 348b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com fFamilies.push_back().reset(addTo); 349b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 350b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com addTo->appendTypeface(tf); 351b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 352febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com 353b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkOSFile::Iter dirIter(directory.c_str()); 354b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com while (dirIter.next(&name, true)) { 355b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (name.startsWith(".")) { 356b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com continue; 357b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 358ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org SkString dirname( 359ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org SkOSPath::SkPathJoin(directory.c_str(), name.c_str())); 360b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com load_directory_fonts(dirname); 361b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3633681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com 364b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com void load_system_fonts(const char* dir) { 365b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkString baseDirectory(dir); 366b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com load_directory_fonts(baseDirectory); 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (fFamilies.empty()) { 369b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 370b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com fFamilies.push_back().reset(family); 371b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com family->appendTypeface(SkNEW(SkTypeface_Empty)); 372b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 373070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 374b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com // Try to pick a default font. 375b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com static const char* gDefaultNames[] = { 376ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL 377b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com }; 378b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 379b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]); 380b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == set) { 381b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com continue; 382b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 383ab44a17f376039cdcaba74f9fb8f282ea4caa63creed@google.com 384b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 385b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle::kNormal_Width, 386b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyle::kUpright_Slant)); 387b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == tf) { 388b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com continue; 389b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 390070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 391b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com gDefaultFamily = set; 392b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com gDefaultNormal = tf; 393b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com break; 394b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 395b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com if (NULL == gDefaultNormal) { 396b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com gDefaultFamily = fFamilies[0]; 397b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com gDefaultNormal = gDefaultFamily->fStyles[0]; 398b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 399b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com } 400b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com 401b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies; 402b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkFontStyleSet_Custom* gDefaultFamily; 403b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com SkTypeface* gDefaultNormal; 404b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com}; 405070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 406070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.comSkFontMgr* SkFontMgr::Factory() { 407b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX); 408070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com} 409