1 2/* 3 * Copyright 2011 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkFontHost.h" 11#include "SkDescriptor.h" 12#include "SkMMapStream.h" 13#include "SkPaint.h" 14#include "SkString.h" 15#include "SkStream.h" 16#include "SkThread.h" 17#include "SkTSearch.h" 18#include <stdio.h> 19 20#ifdef SK_BUILD_FOR_MAC 21 #define SK_FONT_FILE_PREFIX "/Library/Fonts/" 22#else 23 #define SK_FONT_FILE_PREFIX "/skimages/" 24#endif 25 26bool find_name_and_attributes(SkStream* stream, SkString* name, 27 SkTypeface::Style* style, bool* isFixedWidth); 28 29static void GetFullPathForSysFonts(SkString* full, const char name[]) { 30 full->set(SK_FONT_FILE_PREFIX); 31 full->append(name); 32} 33 34/////////////////////////////////////////////////////////////////////////////// 35 36struct FamilyRec; 37 38/* This guy holds a mapping of a name -> family, used for looking up fonts. 39 Since it is stored in a stretchy array that doesn't preserve object 40 semantics, we don't use constructor/destructors, but just have explicit 41 helpers to manage our internal bookkeeping. 42*/ 43struct NameFamilyPair { 44 const char* fName; // we own this 45 FamilyRec* fFamily; // we don't own this, we just reference it 46 47 void construct(const char name[], FamilyRec* family) { 48 fName = strdup(name); 49 fFamily = family; // we don't own this, so just record the referene 50 } 51 52 void destruct() { 53 free((char*)fName); 54 // we don't own family, so just ignore our reference 55 } 56}; 57 58// we use atomic_inc to grow this for each typeface we create 59static int32_t gUniqueFontID; 60 61// this is the mutex that protects these globals 62SK_DECLARE_STATIC_MUTEX(gFamilyMutex); 63static FamilyRec* gFamilyHead; 64static SkTDArray<NameFamilyPair> gNameList; 65 66struct FamilyRec { 67 FamilyRec* fNext; 68 SkTypeface* fFaces[4]; 69 70 FamilyRec() 71 { 72 fNext = gFamilyHead; 73 memset(fFaces, 0, sizeof(fFaces)); 74 gFamilyHead = this; 75 } 76}; 77 78static SkTypeface* find_best_face(const FamilyRec* family, 79 SkTypeface::Style style) { 80 SkTypeface* const* faces = family->fFaces; 81 82 if (faces[style] != NULL) { // exact match 83 return faces[style]; 84 } 85 // look for a matching bold 86 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 87 if (faces[style] != NULL) { 88 return faces[style]; 89 } 90 // look for the plain 91 if (faces[SkTypeface::kNormal] != NULL) { 92 return faces[SkTypeface::kNormal]; 93 } 94 // look for anything 95 for (int i = 0; i < 4; i++) { 96 if (faces[i] != NULL) { 97 return faces[i]; 98 } 99 } 100 // should never get here, since the faces list should not be empty 101 SkDEBUGFAIL("faces list is empty"); 102 return NULL; 103} 104 105static FamilyRec* find_family(const SkTypeface* member) { 106 FamilyRec* curr = gFamilyHead; 107 while (curr != NULL) { 108 for (int i = 0; i < 4; i++) { 109 if (curr->fFaces[i] == member) { 110 return curr; 111 } 112 } 113 curr = curr->fNext; 114 } 115 return NULL; 116} 117 118/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt 119 is not modified. 120 */ 121static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { 122 FamilyRec* curr = gFamilyHead; 123 while (curr != NULL) { 124 for (int i = 0; i < 4; i++) { 125 SkTypeface* face = curr->fFaces[i]; 126 if (face != NULL && face->uniqueID() == uniqueID) { 127 return face; 128 } 129 } 130 curr = curr->fNext; 131 } 132 return NULL; 133} 134 135/* Remove reference to this face from its family. If the resulting family 136 is empty (has no faces), return that family, otherwise return NULL 137*/ 138static FamilyRec* remove_from_family(const SkTypeface* face) { 139 FamilyRec* family = find_family(face); 140 SkASSERT(family->fFaces[face->style()] == face); 141 family->fFaces[face->style()] = NULL; 142 143 for (int i = 0; i < 4; i++) { 144 if (family->fFaces[i] != NULL) { // family is non-empty 145 return NULL; 146 } 147 } 148 return family; // return the empty family 149} 150 151// maybe we should make FamilyRec be doubly-linked 152static void detach_and_delete_family(FamilyRec* family) { 153 FamilyRec* curr = gFamilyHead; 154 FamilyRec* prev = NULL; 155 156 while (curr != NULL) { 157 FamilyRec* next = curr->fNext; 158 if (curr == family) { 159 if (prev == NULL) { 160 gFamilyHead = next; 161 } else { 162 prev->fNext = next; 163 } 164 SkDELETE(family); 165 return; 166 } 167 prev = curr; 168 curr = next; 169 } 170 SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); 171} 172 173static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { 174 NameFamilyPair* list = gNameList.begin(); 175 int count = gNameList.count(); 176 177 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 178 179 if (index >= 0) { 180 return find_best_face(list[index].fFamily, style); 181 } 182 return NULL; 183} 184 185static SkTypeface* find_typeface(const SkTypeface* familyMember, 186 SkTypeface::Style style) { 187 const FamilyRec* family = find_family(familyMember); 188 return family ? find_best_face(family, style) : NULL; 189} 190 191static void add_name(const char name[], FamilyRec* family) { 192 SkAutoAsciiToLC tolc(name); 193 name = tolc.lc(); 194 195 NameFamilyPair* list = gNameList.begin(); 196 int count = gNameList.count(); 197 198 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 199 200 if (index < 0) { 201 list = gNameList.insert(~index); 202 list->construct(name, family); 203 } 204} 205 206static void remove_from_names(FamilyRec* emptyFamily) 207{ 208#ifdef SK_DEBUG 209 for (int i = 0; i < 4; i++) { 210 SkASSERT(emptyFamily->fFaces[i] == NULL); 211 } 212#endif 213 214 SkTDArray<NameFamilyPair>& list = gNameList; 215 216 // must go backwards when removing 217 for (int i = list.count() - 1; i >= 0; --i) { 218 NameFamilyPair* pair = &list[i]; 219 if (pair->fFamily == emptyFamily) { 220 pair->destruct(); 221 list.remove(i); 222 } 223 } 224} 225 226/////////////////////////////////////////////////////////////////////////////// 227 228class FamilyTypeface : public SkTypeface { 229public: 230 FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember) 231 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) { 232 fIsSysFont = sysFont; 233 234 SkAutoMutexAcquire ac(gFamilyMutex); 235 236 FamilyRec* rec = NULL; 237 if (familyMember) { 238 rec = find_family(familyMember); 239 SkASSERT(rec); 240 } else { 241 rec = SkNEW(FamilyRec); 242 } 243 rec->fFaces[style] = this; 244 } 245 246 virtual ~FamilyTypeface() { 247 SkAutoMutexAcquire ac(gFamilyMutex); 248 249 // remove us from our family. If the family is now empty, we return 250 // that and then remove that family from the name list 251 FamilyRec* family = remove_from_family(this); 252 if (NULL != family) { 253 remove_from_names(family); 254 detach_and_delete_family(family); 255 } 256 } 257 258 bool isSysFont() const { return fIsSysFont; } 259 260 virtual SkStream* openStream() = 0; 261 virtual const char* getUniqueString() const = 0; 262 virtual const char* getFilePath() const = 0; 263 264private: 265 bool fIsSysFont; 266 267 typedef SkTypeface INHERITED; 268}; 269 270/////////////////////////////////////////////////////////////////////////////// 271 272class StreamTypeface : public FamilyTypeface { 273public: 274 StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember, 275 SkStream* stream) 276 : INHERITED(style, sysFont, familyMember) { 277 SkASSERT(stream); 278 stream->ref(); 279 fStream = stream; 280 } 281 virtual ~StreamTypeface() { 282 fStream->unref(); 283 } 284 285 // overrides 286 virtual SkStream* openStream() { 287 // we just ref our existing stream, since the caller will call unref() 288 // when they are through 289 fStream->ref(); 290 return fStream; 291 } 292 virtual const char* getUniqueString() const { return NULL; } 293 virtual const char* getFilePath() const { return NULL; } 294 295private: 296 SkStream* fStream; 297 298 typedef FamilyTypeface INHERITED; 299}; 300 301class FileTypeface : public FamilyTypeface { 302public: 303 FileTypeface(Style style, bool sysFont, SkTypeface* familyMember, 304 const char path[]) 305 : INHERITED(style, sysFont, familyMember) { 306 SkString fullpath; 307 308 if (sysFont) { 309 GetFullPathForSysFonts(&fullpath, path); 310 path = fullpath.c_str(); 311 } 312 fPath.set(path); 313 } 314 315 // overrides 316 virtual SkStream* openStream() { 317 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); 318 319 // check for failure 320 if (stream->getLength() <= 0) { 321 SkDELETE(stream); 322 // maybe MMAP isn't supported. try FILE 323 stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); 324 if (stream->getLength() <= 0) { 325 SkDELETE(stream); 326 stream = NULL; 327 } 328 } 329 return stream; 330 } 331 virtual const char* getUniqueString() const { 332 const char* str = strrchr(fPath.c_str(), '/'); 333 if (str) { 334 str += 1; // skip the '/' 335 } 336 return str; 337 } 338 virtual const char* getFilePath() const { 339 return fPath.c_str(); 340 } 341 342private: 343 SkString fPath; 344 345 typedef FamilyTypeface INHERITED; 346}; 347 348/////////////////////////////////////////////////////////////////////////////// 349/////////////////////////////////////////////////////////////////////////////// 350 351static bool get_name_and_style(const char path[], SkString* name, 352 SkTypeface::Style* style, bool isExpected) { 353 SkString fullpath; 354 GetFullPathForSysFonts(&fullpath, path); 355 356 SkMMAPStream stream(fullpath.c_str()); 357 if (stream.getLength() > 0) { 358 return find_name_and_attributes(&stream, name, style, NULL); 359 } 360 else { 361 SkFILEStream stream(fullpath.c_str()); 362 if (stream.getLength() > 0) { 363 return find_name_and_attributes(&stream, name, style, NULL); 364 } 365 } 366 367 if (isExpected) { 368 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str()); 369 } 370 return false; 371} 372 373// used to record our notion of the pre-existing fonts 374struct FontInitRec { 375 const char* fFileName; 376 const char* const* fNames; // null-terminated list 377}; 378 379static const char* gSansNames[] = { 380 "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL 381}; 382 383static const char* gSerifNames[] = { 384 "serif", "times", "times new roman", "palatino", "georgia", "baskerville", 385 "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL 386}; 387 388static const char* gMonoNames[] = { 389 "monospace", "courier", "courier new", "monaco", NULL 390}; 391 392// deliberately empty, but we use the address to identify fallback fonts 393static const char* gFBNames[] = { NULL }; 394 395/* Fonts must be grouped by family, with the first font in a family having the 396 list of names (even if that list is empty), and the following members having 397 null for the list. The names list must be NULL-terminated 398*/ 399static const FontInitRec gSystemFonts[] = { 400 { "Arial.ttf", gSansNames }, 401 { "Times.ttf", gSerifNames }, 402 { "samplefont.ttf", gSansNames }, 403}; 404 405#define DEFAULT_NAMES gSansNames 406 407// these globals are assigned (once) by load_system_fonts() 408static FamilyRec* gDefaultFamily; 409static SkTypeface* gDefaultNormal; 410 411/* This is sized conservatively, assuming that it will never be a size issue. 412 It will be initialized in load_system_fonts(), and will be filled with the 413 fontIDs that can be used for fallback consideration, in sorted order (sorted 414 meaning element[0] should be used first, then element[1], etc. When we hit 415 a fontID==0 in the array, the list is done, hence our allocation size is 416 +1 the total number of possible system fonts. Also see NextLogicalFont(). 417 */ 418static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1]; 419 420/* Called once (ensured by the sentinel check at the beginning of our body). 421 Initializes all the globals, and register the system fonts. 422 */ 423static void load_system_fonts() { 424 // check if we've already be called 425 if (NULL != gDefaultNormal) { 426 return; 427 } 428 429 const FontInitRec* rec = gSystemFonts; 430 SkTypeface* firstInFamily = NULL; 431 int fallbackCount = 0; 432 433 for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { 434 // if we're the first in a new family, clear firstInFamily 435 if (rec[i].fNames != NULL) { 436 firstInFamily = NULL; 437 } 438 439 SkString name; 440 SkTypeface::Style style; 441 442 // we expect all the fonts, except the "fallback" fonts 443 bool isExpected = (rec[i].fNames != gFBNames); 444 if (!get_name_and_style(rec[i].fFileName, &name, &style, isExpected)) { 445 continue; 446 } 447 448 SkTypeface* tf = SkNEW_ARGS(FileTypeface, 449 (style, 450 true, // system-font (cannot delete) 451 firstInFamily, // what family to join 452 rec[i].fFileName) // filename 453 ); 454 455 if (rec[i].fNames != NULL) { 456 // see if this is one of our fallback fonts 457 if (rec[i].fNames == gFBNames) { 458 // SkDebugf("---- adding %s as fallback[%d] fontID %d\n", 459 // rec[i].fFileName, fallbackCount, tf->uniqueID()); 460 gFallbackFonts[fallbackCount++] = tf->uniqueID(); 461 } 462 463 firstInFamily = tf; 464 FamilyRec* family = find_family(tf); 465 const char* const* names = rec[i].fNames; 466 467 // record the default family if this is it 468 if (names == DEFAULT_NAMES) { 469 gDefaultFamily = family; 470 } 471 // add the names to map to this family 472 while (*names) { 473 add_name(*names, family); 474 names += 1; 475 } 476 } 477 } 478 479 // do this after all fonts are loaded. This is our default font, and it 480 // acts as a sentinel so we only execute load_system_fonts() once 481 gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); 482 // now terminate our fallback list with the sentinel value 483 gFallbackFonts[fallbackCount] = 0; 484} 485 486/////////////////////////////////////////////////////////////////////////////// 487 488void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 489 const char* name = ((FamilyTypeface*)face)->getUniqueString(); 490 491 stream->write8((uint8_t)face->style()); 492 493 if (NULL == name || 0 == *name) { 494 stream->writePackedUInt(0); 495// SkDebugf("--- fonthost serialize null\n"); 496 } else { 497 uint32_t len = strlen(name); 498 stream->writePackedUInt(len); 499 stream->write(name, len); 500// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); 501 } 502} 503 504SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 505 load_system_fonts(); 506 507 int style = stream->readU8(); 508 509 int len = stream->readPackedUInt(); 510 if (len > 0) { 511 SkString str; 512 str.resize(len); 513 stream->read(str.writable_str(), len); 514 515 const FontInitRec* rec = gSystemFonts; 516 for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { 517 if (strcmp(rec[i].fFileName, str.c_str()) == 0) { 518 // backup until we hit the fNames 519 for (int j = i; j >= 0; --j) { 520 if (rec[j].fNames != NULL) { 521 return SkFontHost::CreateTypeface(NULL, 522 rec[j].fNames[0], (SkTypeface::Style)style); 523 } 524 } 525 } 526 } 527 } 528 return NULL; 529} 530 531/////////////////////////////////////////////////////////////////////////////// 532 533SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 534 const char familyName[], 535 SkTypeface::Style style) { 536 load_system_fonts(); 537 538 SkAutoMutexAcquire ac(gFamilyMutex); 539 540 // clip to legal style bits 541 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 542 543 SkTypeface* tf = NULL; 544 545 if (NULL != familyFace) { 546 tf = find_typeface(familyFace, style); 547 } else if (NULL != familyName) { 548// SkDebugf("======= familyName <%s>\n", familyName); 549 tf = find_typeface(familyName, style); 550 } 551 552 if (NULL == tf) { 553 tf = find_best_face(gDefaultFamily, style); 554 } 555 556 // we ref(), since the symantic is to return a new instance 557 tf->ref(); 558 return tf; 559} 560 561SkStream* SkFontHost::OpenStream(uint32_t fontID) { 562 SkAutoMutexAcquire ac(gFamilyMutex); 563 564 FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID); 565 SkStream* stream = tf ? tf->openStream() : NULL; 566 567 if (stream && stream->getLength() == 0) { 568 stream->unref(); 569 stream = NULL; 570 } 571 return stream; 572} 573 574#if 0 575SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( 576 uint32_t fontID, 577 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 578 const uint32_t* glyphIDs, 579 uint32_t glyphIDsCount) { 580 SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); 581 return NULL; 582} 583#endif 584 585size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 586 int32_t* index) { 587 SkAutoMutexAcquire ac(gFamilyMutex); 588 589 FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID); 590 const char* src = tf ? tf->getFilePath() : NULL; 591 592 if (src) { 593 size_t size = strlen(src); 594 if (path) { 595 memcpy(path, src, SkMin32(size, length)); 596 } 597 if (index) { 598 *index = 0; // we don't have collections (yet) 599 } 600 return size; 601 } else { 602 return 0; 603 } 604} 605 606SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 607 load_system_fonts(); 608 609 /* First see if fontID is already one of our fallbacks. If so, return 610 its successor. If fontID is not in our list, then return the first one 611 in our list. Note: list is zero-terminated, and returning zero means 612 we have no more fonts to use for fallbacks. 613 */ 614 const uint32_t* list = gFallbackFonts; 615 for (int i = 0; list[i] != 0; i++) { 616 if (list[i] == currFontID) { 617 return list[i+1]; 618 } 619 } 620 return list[0]; 621} 622 623/////////////////////////////////////////////////////////////////////////////// 624 625SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 626 if (NULL == stream || stream->getLength() <= 0) { 627 return NULL; 628 } 629 630 SkTypeface::Style style; 631 if (find_name_and_attributes(stream, NULL, &style, NULL)) { 632 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream)); 633 } else { 634 return NULL; 635 } 636} 637 638SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 639 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path)); 640 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream); 641 // since we created the stream, we let go of our ref() here 642 stream->unref(); 643 return face; 644} 645