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