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 /** The base SkTypeface implementation for the custom font manager. */ 25 class SkTypeface_Custom : public SkTypeface_FreeType { 26 public: 27 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, 28 bool sysFont, const SkString familyName, int index) 29 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) 30 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index) 31 { } 32 33 bool isSysFont() const { return fIsSysFont; } 34 35 protected: 36 void onGetFamilyName(SkString* familyName) const override { 37 *familyName = fFamilyName; 38 } 39 40 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override { 41 desc->setFamilyName(fFamilyName.c_str()); 42 desc->setFontIndex(fIndex); 43 *isLocal = !this->isSysFont(); 44 } 45 46 int getIndex() const { return fIndex; } 47 48 private: 49 const bool fIsSysFont; 50 const SkString fFamilyName; 51 const int fIndex; 52 53 typedef SkTypeface_FreeType INHERITED; 54 }; 55 56 /** The empty SkTypeface implementation for the custom font manager. 57 * Used as the last resort fallback typeface. 58 */ 59 class SkTypeface_Empty : public SkTypeface_Custom { 60 public: 61 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} 62 63 protected: 64 SkStreamAsset* onOpenStream(int*) const override { return NULL; } 65 66 private: 67 typedef SkTypeface_Custom INHERITED; 68 }; 69 70 /** The stream SkTypeface implementation for the custom font manager. */ 71 class SkTypeface_Stream : public SkTypeface_Custom { 72 public: 73 SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont, 74 const SkString familyName, SkStreamAsset* stream, int index) 75 : INHERITED(style, isFixedPitch, sysFont, familyName, index) 76 , fStream(stream) 77 { } 78 79 protected: 80 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 81 *ttcIndex = this->getIndex(); 82 return fStream->duplicate(); 83 } 84 85 private: 86 const SkAutoTDelete<const SkStreamAsset> fStream; 87 88 typedef SkTypeface_Custom INHERITED; 89 }; 90 91 // This configuration option is useful if we need to open and hold handles to 92 // all found system font data (e.g., for skfiddle, where the application can't 93 // access the filesystem to read fonts on demand) 94 95 SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false, 96 "Retain the open stream for each found font on the system."); 97 98 /** The file SkTypeface implementation for the custom font manager. */ 99 class SkTypeface_File : public SkTypeface_Custom { 100 public: 101 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, 102 const SkString familyName, const char path[], int index) 103 : INHERITED(style, isFixedPitch, sysFont, familyName, index) 104 , fPath(path) 105 , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL) 106 { } 107 108 protected: 109 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 110 *ttcIndex = this->getIndex(); 111 if (fStream.get()) { 112 return fStream->duplicate(); 113 } else { 114 return SkStream::NewFromFile(fPath.c_str()); 115 } 116 } 117 118 private: 119 SkString fPath; 120 const SkAutoTDelete<SkStreamAsset> fStream; 121 122 typedef SkTypeface_Custom INHERITED; 123 }; 124 125 /////////////////////////////////////////////////////////////////////////////// 126 127 /** 128 * SkFontStyleSet_Custom 129 * 130 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. 131 */ 132 class SkFontStyleSet_Custom : public SkFontStyleSet { 133 public: 134 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } 135 136 /** Should only be called during the inital build phase. */ 137 void appendTypeface(SkTypeface_Custom* typeface) { 138 fStyles.push_back().reset(typeface); 139 } 140 141 int count() override { 142 return fStyles.count(); 143 } 144 145 void getStyle(int index, SkFontStyle* style, SkString* name) override { 146 SkASSERT(index < fStyles.count()); 147 bool bold = fStyles[index]->isBold(); 148 bool italic = fStyles[index]->isItalic(); 149 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, 150 SkFontStyle::kNormal_Width, 151 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); 152 name->reset(); 153 } 154 155 SkTypeface* createTypeface(int index) override { 156 SkASSERT(index < fStyles.count()); 157 return SkRef(fStyles[index].get()); 158 } 159 160 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 161 int score = 0; 162 score += (pattern.width() - candidate.width()) * 100; 163 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; 164 score += pattern.weight() - candidate.weight(); 165 return score; 166 } 167 168 SkTypeface* matchStyle(const SkFontStyle& pattern) override { 169 if (0 == fStyles.count()) { 170 return NULL; 171 } 172 173 SkTypeface_Custom* closest = fStyles[0]; 174 int minScore = std::numeric_limits<int>::max(); 175 for (int i = 0; i < fStyles.count(); ++i) { 176 bool bold = fStyles[i]->isBold(); 177 bool italic = fStyles[i]->isItalic(); 178 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight 179 : SkFontStyle::kNormal_Weight, 180 SkFontStyle::kNormal_Width, 181 italic ? SkFontStyle::kItalic_Slant 182 : SkFontStyle::kUpright_Slant); 183 184 int score = match_score(pattern, style); 185 if (score < minScore) { 186 closest = fStyles[i]; 187 minScore = score; 188 } 189 } 190 return SkRef(closest); 191 } 192 193 SkString getFamilyName() { return fFamilyName; } 194 195 private: 196 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; 197 SkString fFamilyName; 198 199 friend class SkFontMgr_Custom; 200 }; 201 202 /** 203 * SkFontMgr_Custom 204 * 205 * This class is essentially a collection of SkFontStyleSet_Custom, 206 * one SkFontStyleSet_Custom for each family. This class may be modified 207 * to load fonts from any source by changing the initialization. 208 */ 209 class SkFontMgr_Custom : public SkFontMgr { 210 public: 211 typedef SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> Families; 212 class SystemFontLoader { 213 public: 214 virtual ~SystemFontLoader() { } 215 virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0; 216 }; 217 explicit SkFontMgr_Custom(const SystemFontLoader& loader) { 218 loader.loadSystemFonts(fScanner, &fFamilies); 219 220 // Try to pick a default font. 221 static const char* defaultNames[] = { 222 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL 223 }; 224 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { 225 SkFontStyleSet_Custom* set = this->onMatchFamily(defaultNames[i]); 226 if (NULL == set) { 227 continue; 228 } 229 230 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 231 SkFontStyle::kNormal_Width, 232 SkFontStyle::kUpright_Slant)); 233 if (NULL == tf) { 234 continue; 235 } 236 237 fDefaultFamily = set; 238 break; 239 } 240 if (NULL == fDefaultFamily) { 241 fDefaultFamily = fFamilies[0]; 242 } 243 } 244 245 protected: 246 int onCountFamilies() const override { 247 return fFamilies.count(); 248 } 249 250 void onGetFamilyName(int index, SkString* familyName) const override { 251 SkASSERT(index < fFamilies.count()); 252 familyName->set(fFamilies[index]->getFamilyName()); 253 } 254 255 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override { 256 SkASSERT(index < fFamilies.count()); 257 return SkRef(fFamilies[index].get()); 258 } 259 260 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override { 261 for (int i = 0; i < fFamilies.count(); ++i) { 262 if (fFamilies[i]->getFamilyName().equals(familyName)) { 263 return SkRef(fFamilies[i].get()); 264 } 265 } 266 return NULL; 267 } 268 269 SkTypeface* onMatchFamilyStyle(const char familyName[], 270 const SkFontStyle& fontStyle) const override 271 { 272 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 273 return sset->matchStyle(fontStyle); 274 } 275 276 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 277 const char* bcp47[], int bcp47Count, 278 SkUnichar character) const override 279 { 280 return NULL; 281 } 282 283 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 284 const SkFontStyle& fontStyle) const override 285 { 286 for (int i = 0; i < fFamilies.count(); ++i) { 287 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { 288 if (fFamilies[i]->fStyles[j] == familyMember) { 289 return fFamilies[i]->matchStyle(fontStyle); 290 } 291 } 292 } 293 return NULL; 294 } 295 296 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { 297 return this->createFromStream(new SkMemoryStream(data), ttcIndex); 298 } 299 300 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { 301 SkAutoTDelete<SkStreamAsset> stream(bareStream); 302 if (NULL == stream || stream->getLength() <= 0) { 303 return NULL; 304 } 305 306 bool isFixedPitch; 307 SkFontStyle style; 308 SkString name; 309 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) { 310 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name, 311 stream.detach(), ttcIndex)); 312 } else { 313 return NULL; 314 } 315 } 316 317 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 318 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path)); 319 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL; 320 } 321 322 SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override { 323 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; 324 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold 325 ? SkFontStyle::kBold_Weight 326 : SkFontStyle::kNormal_Weight, 327 SkFontStyle::kNormal_Width, 328 oldStyle & SkTypeface::kItalic 329 ? SkFontStyle::kItalic_Slant 330 : SkFontStyle::kUpright_Slant); 331 SkTypeface* tf = NULL; 332 333 if (familyName) { 334 tf = this->onMatchFamilyStyle(familyName, style); 335 } 336 337 if (NULL == tf) { 338 tf = fDefaultFamily->matchStyle(style); 339 } 340 341 return SkSafeRef(tf); 342 } 343 344 private: 345 Families fFamilies; 346 SkFontStyleSet_Custom* fDefaultFamily; 347 SkTypeface_FreeType::Scanner fScanner; 348 }; 349 350 /////////////////////////////////////////////////////////////////////////////// 351 352 class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { 353 public: 354 DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { } 355 356 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, 357 SkFontMgr_Custom::Families* families) const override 358 { 359 load_directory_fonts(scanner, fBaseDirectory, ".ttf", families); 360 load_directory_fonts(scanner, fBaseDirectory, ".ttc", families); 361 load_directory_fonts(scanner, fBaseDirectory, ".otf", families); 362 load_directory_fonts(scanner, fBaseDirectory, ".pfb", families); 363 364 if (families->empty()) { 365 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 366 families->push_back().reset(family); 367 family->appendTypeface(SkNEW(SkTypeface_Empty)); 368 } 369 } 370 371 private: 372 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, 373 const char familyName[]) 374 { 375 for (int i = 0; i < families.count(); ++i) { 376 if (families[i]->getFamilyName().equals(familyName)) { 377 return families[i].get(); 378 } 379 } 380 return NULL; 381 } 382 383 static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, 384 const SkString& directory, const char* suffix, 385 SkFontMgr_Custom::Families* families) 386 { 387 SkOSFile::Iter iter(directory.c_str(), suffix); 388 SkString name; 389 390 while (iter.next(&name, false)) { 391 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); 392 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str())); 393 if (!stream.get()) { 394 SkDebugf("---- failed to open <%s>\n", filename.c_str()); 395 continue; 396 } 397 398 int numFaces; 399 if (!scanner.recognizedFont(stream, &numFaces)) { 400 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); 401 continue; 402 } 403 404 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 405 bool isFixedPitch; 406 SkString realname; 407 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning 408 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) { 409 SkDebugf("---- failed to open <%s> <%d> as a font\n", 410 filename.c_str(), faceIndex); 411 continue; 412 } 413 414 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( 415 style, 416 isFixedPitch, 417 true, // system-font (cannot delete) 418 realname, 419 filename.c_str(), 420 faceIndex)); 421 422 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); 423 if (NULL == addTo) { 424 addTo = new SkFontStyleSet_Custom(realname); 425 families->push_back().reset(addTo); 426 } 427 addTo->appendTypeface(tf); 428 } 429 } 430 431 SkOSFile::Iter dirIter(directory.c_str()); 432 while (dirIter.next(&name, true)) { 433 if (name.startsWith(".")) { 434 continue; 435 } 436 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); 437 load_directory_fonts(scanner, dirname, suffix, families); 438 } 439 } 440 441 SkString fBaseDirectory; 442 }; 443 444 struct SkEmbeddedResource { const uint8_t* data; size_t size; }; 445 struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; }; 446 447 class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { 448 public: 449 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { } 450 451 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, 452 SkFontMgr_Custom::Families* families) const override 453 { 454 for (int i = 0; i < fHeader->count; ++i) { 455 const SkEmbeddedResource& fontEntry = fHeader->entries[i]; 456 load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families); 457 } 458 459 if (families->empty()) { 460 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 461 families->push_back().reset(family); 462 family->appendTypeface(SkNEW(SkTypeface_Empty)); 463 } 464 } 465 466 private: 467 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, 468 const char familyName[]) 469 { 470 for (int i = 0; i < families.count(); ++i) { 471 if (families[i]->getFamilyName().equals(familyName)) { 472 return families[i].get(); 473 } 474 } 475 return NULL; 476 } 477 478 static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, 479 const uint8_t* data, size_t size, int index, 480 SkFontMgr_Custom::Families* families) 481 { 482 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false)); 483 484 int numFaces; 485 if (!scanner.recognizedFont(stream, &numFaces)) { 486 SkDebugf("---- failed to open <%d> as a font\n", index); 487 return; 488 } 489 490 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 491 bool isFixedPitch; 492 SkString realname; 493 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning 494 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) { 495 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); 496 return; 497 } 498 499 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_Stream, ( 500 style, 501 isFixedPitch, 502 true, // system-font (cannot delete) 503 realname, 504 stream.detach(), 505 faceIndex)); 506 507 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); 508 if (NULL == addTo) { 509 addTo = new SkFontStyleSet_Custom(realname); 510 families->push_back().reset(addTo); 511 } 512 addTo->appendTypeface(tf); 513 } 514 } 515 516 const SkEmbeddedResourceHeader* fHeader; 517 }; 518 519 #ifdef SK_EMBEDDED_FONTS 520 521 extern "C" const SkEmbeddedResourceHeader SK_EMBEDDED_FONTS; 522 SkFontMgr* SkFontMgr::Factory() { 523 return new SkFontMgr_Custom(EmbeddedSystemFontLoader(&SK_EMBEDDED_FONTS)); 524 } 525 526 #else 527 528 #ifndef SK_FONT_FILE_PREFIX 529 # define SK_FONT_FILE_PREFIX "/usr/share/fonts/" 530 #endif 531 SkFontMgr* SkFontMgr::Factory() { 532 return new SkFontMgr_Custom(DirectorySystemFontLoader(SK_FONT_FILE_PREFIX)); 533 } 534 535 #endif 536