SkFontHost_linux.cpp revision 36352bf5e38f45a70ee4f4fc132a38048d38206d
1/* 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. 6 */ 7 8#include "SkFontHost_FreeType_common.h" 9#include "SkFontDescriptor.h" 10#include "SkFontMgr.h" 11#include "SkDescriptor.h" 12#include "SkOSFile.h" 13#include "SkPaint.h" 14#include "SkRTConf.h" 15#include "SkString.h" 16#include "SkStream.h" 17#include "SkThread.h" 18#include "SkTSearch.h" 19#include "SkTypefaceCache.h" 20#include "SkTArray.h" 21 22#include <limits> 23 24#ifndef SK_FONT_FILE_PREFIX 25# define SK_FONT_FILE_PREFIX "/usr/share/fonts/" 26#endif 27 28/////////////////////////////////////////////////////////////////////////////// 29 30/** The base SkTypeface implementation for the custom font manager. */ 31class SkTypeface_Custom : public SkTypeface_FreeType { 32public: 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) 37 { } 38 39 bool isSysFont() const { return fIsSysFont; } 40 41 virtual const char* getUniqueString() const = 0; 42 43protected: 44 void onGetFamilyName(SkString* familyName) const override { 45 *familyName = fFamilyName; 46 } 47 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(); 53 } 54 55 int getIndex() const { return fIndex; } 56 57private: 58 const bool fIsSysFont; 59 const SkString fFamilyName; 60 const int fIndex; 61 62 typedef SkTypeface_FreeType INHERITED; 63}; 64 65/** The empty SkTypeface implementation for the custom font manager. 66 * Used as the last resort fallback typeface. 67 */ 68class SkTypeface_Empty : public SkTypeface_Custom { 69public: 70 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} 71 72 const char* getUniqueString() const override { return NULL; } 73 74protected: 75 SkStreamAsset* onOpenStream(int*) const override { return NULL; } 76 77private: 78 typedef SkTypeface_Custom INHERITED; 79}; 80 81/** The stream SkTypeface implementation for the custom font manager. */ 82class SkTypeface_Stream : public SkTypeface_Custom { 83public: 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) 87 , fStream(stream) 88 { } 89 90 const char* getUniqueString() const override { return NULL; } 91 92protected: 93 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 94 *ttcIndex = this->getIndex(); 95 return fStream->duplicate(); 96 } 97 98private: 99 const SkAutoTDelete<const SkStreamAsset> fStream; 100 101 typedef SkTypeface_Custom INHERITED; 102}; 103 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) 107 108SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false, 109 "Retain the open stream for each found font on the system."); 110 111/** The file SkTypeface implementation for the custom font manager. */ 112class SkTypeface_File : public SkTypeface_Custom { 113public: 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) 117 , fPath(path) 118 , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL) 119 { } 120 121 const char* getUniqueString() const override { 122 const char* str = strrchr(fPath.c_str(), '/'); 123 if (str) { 124 str += 1; // skip the '/' 125 } 126 return str; 127 } 128 129protected: 130 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 131 *ttcIndex = this->getIndex(); 132 if (fStream.get()) { 133 return fStream->duplicate(); 134 } else { 135 return SkStream::NewFromFile(fPath.c_str()); 136 } 137 } 138 139private: 140 SkString fPath; 141 const SkAutoTDelete<SkStreamAsset> fStream; 142 143 typedef SkTypeface_Custom INHERITED; 144}; 145 146/////////////////////////////////////////////////////////////////////////////// 147 148/** 149 * SkFontStyleSet_Custom 150 * 151 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. 152 */ 153class SkFontStyleSet_Custom : public SkFontStyleSet { 154public: 155 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } 156 157 int count() override { 158 return fStyles.count(); 159 } 160 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); 168 name->reset(); 169 } 170 171 SkTypeface* createTypeface(int index) override { 172 SkASSERT(index < fStyles.count()); 173 return SkRef(fStyles[index].get()); 174 } 175 176 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 177 int score = 0; 178 score += (pattern.width() - candidate.width()) * 100; 179 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; 180 score += pattern.weight() - candidate.weight(); 181 return score; 182 } 183 184 SkTypeface* matchStyle(const SkFontStyle& pattern) override { 185 if (0 == fStyles.count()) { 186 return NULL; 187 } 188 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); 199 200 int score = match_score(pattern, style); 201 if (score < minScore) { 202 closest = fStyles[i]; 203 minScore = score; 204 } 205 } 206 return SkRef(closest); 207 } 208 209private: 210 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; 211 SkString fFamilyName; 212 213 void appendTypeface(SkTypeface_Custom* typeface) { 214 fStyles.push_back().reset(typeface); 215 } 216 217 friend class SkFontMgr_Custom; 218}; 219 220/** 221 * SkFontMgr_Custom 222 * 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. 226 */ 227class SkFontMgr_Custom : public SkFontMgr { 228public: 229 explicit SkFontMgr_Custom(const char* dir) { 230 this->load_system_fonts(dir); 231 } 232 233protected: 234 int onCountFamilies() const override { 235 return fFamilies.count(); 236 } 237 238 void onGetFamilyName(int index, SkString* familyName) const override { 239 SkASSERT(index < fFamilies.count()); 240 familyName->set(fFamilies[index]->fFamilyName); 241 } 242 243 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override { 244 SkASSERT(index < fFamilies.count()); 245 return SkRef(fFamilies[index].get()); 246 } 247 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()); 252 } 253 } 254 return NULL; 255 } 256 257 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 258 const SkFontStyle& fontStyle) const override 259 { 260 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 261 return sset->matchStyle(fontStyle); 262 } 263 264 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 265 const char* bcp47[], int bcp47Count, 266 SkUnichar character) const override 267 { 268 return NULL; 269 } 270 271 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 272 const SkFontStyle& fontStyle) const override 273 { 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); 278 } 279 } 280 } 281 return NULL; 282 } 283 284 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { 285 return this->createFromStream(new SkMemoryStream(data), ttcIndex); 286 } 287 288 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { 289 SkAutoTDelete<SkStreamAsset> stream(bareStream); 290 if (NULL == stream || stream->getLength() <= 0) { 291 return NULL; 292 } 293 294 bool isFixedPitch; 295 SkFontStyle style; 296 SkString name; 297 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) { 298 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name, 299 stream.detach(), ttcIndex)); 300 } else { 301 return NULL; 302 } 303 } 304 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; 308 } 309 310 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 311 unsigned styleBits) const override 312 { 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; 322 323 if (familyName) { 324 tf = this->onMatchFamilyStyle(familyName, style); 325 } 326 327 if (NULL == tf) { 328 tf = gDefaultFamily->matchStyle(style); 329 } 330 331 return SkSafeRef(tf); 332 } 333 334private: 335 336 void load_directory_fonts(const SkString& directory, const char* suffix) { 337 SkOSFile::Iter iter(directory.c_str(), suffix); 338 SkString name; 339 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())); 343 if (!stream.get()) { 344 SkDebugf("---- failed to open <%s>\n", filename.c_str()); 345 continue; 346 } 347 348 int numFaces; 349 if (!fScanner.recognizedFont(stream, &numFaces)) { 350 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); 351 continue; 352 } 353 354 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 355 bool isFixedPitch; 356 SkString realname; 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); 361 continue; 362 } 363 364 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( 365 style, 366 isFixedPitch, 367 true, // system-font (cannot delete) 368 realname, 369 filename.c_str(), 0)); 370 371 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str()); 372 if (NULL == addTo) { 373 addTo = new SkFontStyleSet_Custom(realname); 374 fFamilies.push_back().reset(addTo); 375 } 376 addTo->appendTypeface(tf); 377 } 378 } 379 380 SkOSFile::Iter dirIter(directory.c_str()); 381 while (dirIter.next(&name, true)) { 382 if (name.startsWith(".")) { 383 continue; 384 } 385 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); 386 load_directory_fonts(dirname, suffix); 387 } 388 } 389 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"); 396 397 if (fFamilies.empty()) { 398 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 399 fFamilies.push_back().reset(family); 400 family->appendTypeface(SkNEW(SkTypeface_Empty)); 401 } 402 403 // Try to pick a default font. 404 static const char* gDefaultNames[] = { 405 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL 406 }; 407 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 408 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]); 409 if (NULL == set) { 410 continue; 411 } 412 413 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 414 SkFontStyle::kNormal_Width, 415 SkFontStyle::kUpright_Slant)); 416 if (NULL == tf) { 417 continue; 418 } 419 420 gDefaultFamily = set; 421 gDefaultNormal = tf; 422 break; 423 } 424 if (NULL == gDefaultNormal) { 425 gDefaultFamily = fFamilies[0]; 426 gDefaultNormal = gDefaultFamily->fStyles[0]; 427 } 428 } 429 430 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies; 431 SkFontStyleSet_Custom* gDefaultFamily; 432 SkTypeface* gDefaultNormal; 433 SkTypeface_FreeType::Scanner fScanner; 434}; 435 436SkFontMgr* SkFontMgr::Factory() { 437 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX); 438} 439