1 /* libs/graphics/ports/SkFontHost_android.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkFontHost.h" 19 #include "SkGraphics.h" 20 #include "SkDescriptor.h" 21 #include "SkMMapStream.h" 22 #include "SkPaint.h" 23 #include "SkString.h" 24 #include "SkStream.h" 25 #include "SkThread.h" 26 #include "SkTSearch.h" 27 #include "FontHostConfiguration_android.h" 28 #include <stdio.h> 29 #include <string.h> 30 31 //#define SkDEBUGF(args ) SkDebugf args 32 33 #ifndef SK_FONT_FILE_PREFIX 34 #define SK_FONT_FILE_PREFIX "/fonts/" 35 #endif 36 37 // Defined in SkFontHost_FreeType.cpp 38 bool find_name_and_attributes(SkStream* stream, SkString* name, 39 SkTypeface::Style* style, bool* isFixedWidth); 40 41 static void getFullPathForSysFonts(SkString* full, const char name[]) { 42 full->set(getenv("ANDROID_ROOT")); 43 full->append(SK_FONT_FILE_PREFIX); 44 full->append(name); 45 } 46 47 static bool getNameAndStyle(const char path[], SkString* name, 48 SkTypeface::Style* style, 49 bool* isFixedWidth, bool isExpected) { 50 SkString fullpath; 51 getFullPathForSysFonts(&fullpath, path); 52 53 SkMMAPStream stream(fullpath.c_str()); 54 if (stream.getLength() > 0) { 55 return find_name_and_attributes(&stream, name, style, isFixedWidth); 56 } 57 else { 58 SkFILEStream stream(fullpath.c_str()); 59 if (stream.getLength() > 0) { 60 return find_name_and_attributes(&stream, name, style, isFixedWidth); 61 } 62 } 63 64 if (isExpected) { 65 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str()); 66 } 67 return false; 68 } 69 70 static SkTypeface* deserializeLocked(SkStream* stream); 71 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace, 72 const char familyName[], const void* data, size_t bytelength, 73 SkTypeface::Style style); 74 static SkStream* openStreamLocked(uint32_t fontID); 75 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index); 76 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID); 77 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream); 78 79 /////////////////////////////////////////////////////////////////////////////// 80 81 struct FamilyRec; 82 83 /* This guy holds a mapping of a name -> family, used for looking up fonts. 84 Since it is stored in a stretchy array that doesn't preserve object 85 semantics, we don't use constructor/destructors, but just have explicit 86 helpers to manage our internal bookkeeping. 87 */ 88 struct NameFamilyPair { 89 const char* fName; // we own this 90 FamilyRec* fFamily; // we don't own this, we just reference it 91 92 void construct(const char name[], FamilyRec* family) { 93 fName = strdup(name); 94 fFamily = family; // we don't own this, so just record the reference 95 } 96 97 void destruct() { 98 free((char*)fName); 99 // we don't own family, so just ignore our reference 100 } 101 }; 102 typedef SkTDArray<NameFamilyPair> NameFamilyPairList; 103 104 // we use atomic_inc to grow this for each typeface we create 105 static int32_t gUniqueFontID; 106 107 // this is the mutex that protects all of the global data structures in this module 108 // functions with the Locked() suffix must be called while holding this mutex 109 SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex); 110 static FamilyRec* gFamilyHead = NULL; 111 static SkTDArray<NameFamilyPair> gFallbackFilenameList; 112 static NameFamilyPairList gNameList; 113 114 struct FamilyRec { 115 FamilyRec* fNext; 116 SkTypeface* fFaces[4]; 117 118 FamilyRec() : fNext(NULL) { 119 memset(fFaces, 0, sizeof(fFaces)); 120 } 121 }; 122 123 static SkTypeface* findBestFaceLocked(const FamilyRec* family, 124 SkTypeface::Style style) { 125 SkTypeface* const* faces = family->fFaces; 126 127 if (faces[style] != NULL) { // exact match 128 return faces[style]; 129 } 130 // look for a matching bold 131 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 132 if (faces[style] != NULL) { 133 return faces[style]; 134 } 135 // look for the plain 136 if (faces[SkTypeface::kNormal] != NULL) { 137 return faces[SkTypeface::kNormal]; 138 } 139 // look for anything 140 for (int i = 0; i < 4; i++) { 141 if (faces[i] != NULL) { 142 return faces[i]; 143 } 144 } 145 // should never get here, since the faces list should not be empty 146 SkDEBUGFAIL("faces list is empty"); 147 return NULL; 148 } 149 150 static FamilyRec* findFamilyLocked(const SkTypeface* member) { 151 FamilyRec* curr = gFamilyHead; 152 while (curr != NULL) { 153 for (int i = 0; i < 4; i++) { 154 if (curr->fFaces[i] == member) { 155 return curr; 156 } 157 } 158 curr = curr->fNext; 159 } 160 return NULL; 161 } 162 163 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt 164 is not modified. 165 */ 166 static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) { 167 FamilyRec* curr = gFamilyHead; 168 while (curr != NULL) { 169 for (int i = 0; i < 4; i++) { 170 SkTypeface* face = curr->fFaces[i]; 171 if (face != NULL && face->uniqueID() == uniqueID) { 172 return face; 173 } 174 } 175 curr = curr->fNext; 176 } 177 return NULL; 178 } 179 180 /* Remove reference to this face from its family. If the resulting family 181 is empty (has no faces), return that family, otherwise return NULL 182 */ 183 static FamilyRec* removeFromFamilyLocked(const SkTypeface* face) { 184 FamilyRec* family = findFamilyLocked(face); 185 if (family) { 186 SkASSERT(family->fFaces[face->style()] == face); 187 family->fFaces[face->style()] = NULL; 188 189 for (int i = 0; i < 4; i++) { 190 if (family->fFaces[i] != NULL) { // family is non-empty 191 return NULL; 192 } 193 } 194 } else { 195 // SkDebugf("removeFromFamilyLocked(%p) face not found", face); 196 } 197 return family; // return the empty family 198 } 199 200 // maybe we should make FamilyRec be doubly-linked 201 static void detachAndDeleteFamilyLocked(FamilyRec* family) { 202 FamilyRec* curr = gFamilyHead; 203 FamilyRec* prev = NULL; 204 205 while (curr != NULL) { 206 FamilyRec* next = curr->fNext; 207 if (curr == family) { 208 if (prev == NULL) { 209 gFamilyHead = next; 210 } else { 211 prev->fNext = next; 212 } 213 SkDELETE(family); 214 return; 215 } 216 prev = curr; 217 curr = next; 218 } 219 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); 220 } 221 222 static SkTypeface* findTypefaceLocked(const char name[], SkTypeface::Style style) { 223 int count = gNameList.count(); 224 NameFamilyPair* list = gNameList.begin(); 225 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 226 if (index >= 0) { 227 return findBestFaceLocked(list[index].fFamily, style); 228 } 229 return NULL; 230 } 231 232 static SkTypeface* findTypefaceLocked(const SkTypeface* familyMember, 233 SkTypeface::Style style) { 234 const FamilyRec* family = findFamilyLocked(familyMember); 235 return family ? findBestFaceLocked(family, style) : NULL; 236 } 237 238 static void addNameLocked(const char name[], FamilyRec* family) { 239 SkAutoAsciiToLC tolc(name); 240 name = tolc.lc(); 241 242 int count = gNameList.count(); 243 NameFamilyPair* list = gNameList.begin(); 244 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 245 if (index < 0) { 246 list = gNameList.insert(~index); 247 list->construct(name, family); 248 } 249 } 250 251 static void removeFromNamesLocked(FamilyRec* emptyFamily) { 252 #ifdef SK_DEBUG 253 for (int i = 0; i < 4; i++) { 254 SkASSERT(emptyFamily->fFaces[i] == NULL); 255 } 256 #endif 257 258 // must go backwards when removing 259 for (int i = gNameList.count() - 1; i >= 0; --i) { 260 NameFamilyPair& pair = gNameList[i]; 261 if (pair.fFamily == emptyFamily) { 262 pair.destruct(); 263 gNameList.remove(i); 264 } 265 } 266 } 267 268 static void addTypefaceLocked(SkTypeface* typeface, SkTypeface* familyMember) { 269 FamilyRec* rec = NULL; 270 if (familyMember) { 271 rec = findFamilyLocked(familyMember); 272 SkASSERT(rec); 273 } else { 274 rec = SkNEW(FamilyRec); 275 rec->fNext = gFamilyHead; 276 gFamilyHead = rec; 277 } 278 rec->fFaces[typeface->style()] = typeface; 279 } 280 281 static void removeTypeface(SkTypeface* typeface) { 282 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 283 284 // remove us from our family. If the family is now empty, we return 285 // that and then remove that family from the name list 286 FamilyRec* family = removeFromFamilyLocked(typeface); 287 if (NULL != family) { 288 removeFromNamesLocked(family); 289 detachAndDeleteFamilyLocked(family); 290 } 291 } 292 293 /////////////////////////////////////////////////////////////////////////////// 294 295 class FamilyTypeface : public SkTypeface { 296 protected: 297 FamilyTypeface(Style style, bool sysFont, bool isFixedWidth) 298 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { 299 fIsSysFont = sysFont; 300 } 301 302 public: 303 virtual ~FamilyTypeface() { 304 removeTypeface(this); 305 } 306 307 bool isSysFont() const { return fIsSysFont; } 308 309 virtual SkStream* openStream() = 0; 310 virtual const char* getUniqueString() const = 0; 311 virtual const char* getFilePath() const = 0; 312 313 private: 314 bool fIsSysFont; 315 316 typedef SkTypeface INHERITED; 317 }; 318 319 /////////////////////////////////////////////////////////////////////////////// 320 321 class StreamTypeface : public FamilyTypeface { 322 public: 323 StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedWidth) 324 : INHERITED(style, sysFont, isFixedWidth) { 325 SkASSERT(stream); 326 stream->ref(); 327 fStream = stream; 328 } 329 330 virtual ~StreamTypeface() { 331 fStream->unref(); 332 } 333 334 // overrides 335 virtual SkStream* openStream() { 336 // we just ref our existing stream, since the caller will call unref() 337 // when they are through 338 fStream->ref(); 339 // must rewind each time, since the caller assumes a "new" stream 340 fStream->rewind(); 341 return fStream; 342 } 343 virtual const char* getUniqueString() const { return NULL; } 344 virtual const char* getFilePath() const { return NULL; } 345 346 private: 347 SkStream* fStream; 348 349 typedef FamilyTypeface INHERITED; 350 }; 351 352 class FileTypeface : public FamilyTypeface { 353 public: 354 FileTypeface(Style style, bool sysFont, const char path[], bool isFixedWidth) 355 : INHERITED(style, sysFont, isFixedWidth) { 356 fPath.set(path); 357 } 358 359 // overrides 360 virtual SkStream* openStream() { 361 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); 362 363 // check for failure 364 if (stream->getLength() <= 0) { 365 SkDELETE(stream); 366 // maybe MMAP isn't supported. try FILE 367 stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); 368 if (stream->getLength() <= 0) { 369 SkDELETE(stream); 370 stream = NULL; 371 } 372 } 373 return stream; 374 } 375 virtual const char* getUniqueString() const { 376 const char* str = strrchr(fPath.c_str(), '/'); 377 if (str) { 378 str += 1; // skip the '/' 379 } 380 return str; 381 } 382 virtual const char* getFilePath() const { 383 return fPath.c_str(); 384 } 385 386 private: 387 SkString fPath; 388 389 typedef FamilyTypeface INHERITED; 390 }; 391 392 /////////////////////////////////////////////////////////////////////////////// 393 /////////////////////////////////////////////////////////////////////////////// 394 395 // used to record our notion of the pre-existing fonts 396 struct FontInitRec { 397 const char* fFileName; 398 const char* const* fNames; // null-terminated list 399 }; 400 401 // deliberately empty, but we use the address to identify fallback fonts 402 static const char* gFBNames[] = { NULL }; 403 404 405 /* Fonts are grouped by family, with the first font in a family having the 406 list of names (even if that list is empty), and the following members having 407 null for the list. The names list must be NULL-terminated. 408 */ 409 static SkTDArray<FontInitRec> gSystemFonts; 410 static SkTDArray<SkFontID> gFallbackFonts; 411 412 // these globals are assigned (once) by loadSystemFontsLocked() 413 static FamilyRec* gDefaultFamily = NULL; 414 static SkTypeface* gDefaultNormal = NULL; 415 static char** gDefaultNames = NULL; 416 417 static void dumpGlobalsLocked() { 418 SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal, 419 gDefaultNormal ? gDefaultNormal->uniqueID() : 0, 420 gDefaultNormal ? gDefaultNormal->getRefCnt() : 0); 421 422 if (gDefaultFamily) { 423 SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", 424 gDefaultFamily, 425 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0, 426 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0, 427 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0, 428 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0, 429 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0, 430 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0, 431 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0, 432 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0); 433 } else { 434 SkDebugf("gDefaultFamily=%p", gDefaultFamily); 435 } 436 437 SkDebugf("gSystemFonts.count()=%d gFallbackFonts.count()=%d", 438 gSystemFonts.count(), gFallbackFonts.count()); 439 440 for (int i = 0; i < gSystemFonts.count(); ++i) { 441 SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName); 442 size_t namesIndex = 0; 443 if (gSystemFonts[i].fNames) 444 for (const char* fontName = gSystemFonts[i].fNames[namesIndex]; 445 fontName != 0; 446 fontName = gSystemFonts[i].fNames[++namesIndex]) { 447 SkDebugf(" name[%u]=%s", namesIndex, fontName); 448 } 449 } 450 451 if (gFamilyHead) { 452 FamilyRec* rec = gFamilyHead; 453 int i=0; 454 while (rec) { 455 SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", 456 i++, rec, 457 rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0, 458 rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0, 459 rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0, 460 rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0, 461 rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0, 462 rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0, 463 rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0, 464 rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0); 465 rec = rec->fNext; 466 } 467 } else { 468 SkDebugf("gFamilyHead=%p", gFamilyHead); 469 } 470 471 } 472 473 474 static bool haveSystemFont(const char* filename) { 475 for (int i = 0; i < gSystemFonts.count(); i++) { 476 if (strcmp(gSystemFonts[i].fFileName, filename) == 0) { 477 return true; 478 } 479 } 480 return false; 481 } 482 483 /* Load info from a configuration file that populates the system/fallback font structures 484 */ 485 static void loadFontInfoLocked() { 486 SkTDArray<FontFamily*> fontFamilies; 487 getFontFamilies(fontFamilies); 488 489 gSystemFonts.reset(); 490 491 for (int i = 0; i < fontFamilies.count(); ++i) { 492 FontFamily *family = fontFamilies[i]; 493 for (int j = 0; j < family->fFileNames.count(); ++j) { 494 const char* filename = family->fFileNames[j]; 495 if (haveSystemFont(filename)) { 496 SkDebugf("---- system font and fallback font files specify a duplicate " 497 "font %s, skipping the second occurrence", filename); 498 continue; 499 } 500 501 FontInitRec fontInfoRecord; 502 fontInfoRecord.fFileName = filename; 503 if (j == 0) { 504 if (family->fNames.count() == 0) { 505 // Fallback font 506 fontInfoRecord.fNames = (char **)gFBNames; 507 } else { 508 SkTDArray<const char*> names = family->fNames; 509 const char **nameList = (const char**) 510 malloc((names.count() + 1) * sizeof(char*)); 511 if (nameList == NULL) { 512 // shouldn't get here 513 break; 514 } 515 if (gDefaultNames == NULL) { 516 gDefaultNames = (char**) nameList; 517 } 518 for (int i = 0; i < names.count(); ++i) { 519 nameList[i] = names[i]; 520 } 521 nameList[names.count()] = NULL; 522 fontInfoRecord.fNames = nameList; 523 } 524 } else { 525 fontInfoRecord.fNames = NULL; 526 } 527 *gSystemFonts.append() = fontInfoRecord; 528 } 529 } 530 fontFamilies.deleteAll(); 531 532 SkDEBUGF(("---- We have %d system fonts", gSystemFonts.count())); 533 for (int i = 0; i < gSystemFonts.count(); ++i) { 534 SkDEBUGF(("---- gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName)); 535 } 536 } 537 538 539 /* 540 * Called once (ensured by the sentinel check at the beginning of our body). 541 * Initializes all the globals, and register the system fonts. 542 */ 543 static void initSystemFontsLocked() { 544 // check if we've already been called 545 if (gDefaultNormal) { 546 return; 547 } 548 549 SkASSERT(gUniqueFontID == 0); 550 551 loadFontInfoLocked(); 552 553 gFallbackFonts.reset(); 554 555 SkTypeface* firstInFamily = NULL; 556 for (int i = 0; i < gSystemFonts.count(); i++) { 557 // if we're the first in a new family, clear firstInFamily 558 const char* const* names = gSystemFonts[i].fNames; 559 if (names != NULL) { 560 firstInFamily = NULL; 561 } 562 563 bool isFixedWidth; 564 SkString name; 565 SkTypeface::Style style; 566 567 // we expect all the fonts, except the "fallback" fonts 568 bool isExpected = (names != gFBNames); 569 if (!getNameAndStyle(gSystemFonts[i].fFileName, &name, &style, 570 &isFixedWidth, isExpected)) { 571 // We need to increase gUniqueFontID here so that the unique id of 572 // each font matches its index in gSystemFonts array, as expected 573 // by findUniqueIDLocked. 574 sk_atomic_inc(&gUniqueFontID); 575 continue; 576 } 577 578 SkString fullpath; 579 getFullPathForSysFonts(&fullpath, gSystemFonts[i].fFileName); 580 581 SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style, 582 true, // system-font (cannot delete) 583 fullpath.c_str(), // filename 584 isFixedWidth)); 585 addTypefaceLocked(tf, firstInFamily); 586 587 SkDEBUGF(("---- SkTypeface[%d] %s fontID %d\n", 588 i, gSystemFonts[i].fFileName, tf->uniqueID())); 589 590 if (names != NULL) { 591 // see if this is one of our fallback fonts 592 if (names == gFBNames) { 593 SkDEBUGF(("---- adding %s as fallback[%d] fontID %d\n", 594 gSystemFonts[i].fFileName, gFallbackFonts.count(), tf->uniqueID())); 595 *gFallbackFonts.append() = tf->uniqueID(); 596 } 597 598 firstInFamily = tf; 599 FamilyRec* family = findFamilyLocked(tf); 600 601 // record the default family if this is it 602 if (names == gDefaultNames) { 603 gDefaultFamily = family; 604 } 605 // add the names to map to this family 606 while (*names) { 607 addNameLocked(*names, family); 608 names += 1; 609 } 610 } 611 } 612 613 // do this after all fonts are loaded. This is our default font, and it 614 // acts as a sentinel so we only execute loadSystemFontsLocked() once 615 gDefaultNormal = findBestFaceLocked(gDefaultFamily, SkTypeface::kNormal); 616 617 SkDEBUGCODE(dumpGlobalsLocked()); 618 } 619 620 static SkFontID findUniqueIDLocked(const char* filename) { 621 // uniqueID is the index, offset by one, of the associated element in 622 // gSystemFonts[] (assumes system fonts are loaded before external fonts) 623 // return 0 if not found 624 for (int i = 0; i < gSystemFonts.count(); i++) { 625 if (strcmp(gSystemFonts[i].fFileName, filename) == 0) { 626 return i + 1; // assume unique id of i'th system font is i + 1 627 } 628 } 629 return 0; 630 } 631 632 static int findFallbackFontIndex(SkFontID fontId) { 633 for (int i = 0; i < gFallbackFonts.count(); i++) { 634 if (gFallbackFonts[i] == fontId) { 635 return i; 636 } 637 } 638 return -1; 639 } 640 641 static void reloadFallbackFontsLocked() { 642 SkGraphics::PurgeFontCache(); 643 644 SkTDArray<FontFamily*> fallbackFamilies; 645 getFallbackFontFamilies(fallbackFamilies); 646 647 gFallbackFonts.reset(); 648 649 for (int i = 0; i < fallbackFamilies.count(); ++i) { 650 FontFamily *family = fallbackFamilies[i]; 651 652 for (int j = 0; j < family->fFileNames.count(); ++j) { 653 const char* filename = family->fFileNames[j]; 654 if (filename) { 655 if (!haveSystemFont(filename)) { 656 SkDebugf("---- skipping fallback font %s because it was not " 657 "previously loaded as a system font", filename); 658 continue; 659 } 660 661 // ensure the fallback font exists before adding it to the list 662 bool isFixedWidth; 663 SkString name; 664 SkTypeface::Style style; 665 if (!getNameAndStyle(filename, &name, &style, 666 &isFixedWidth, false)) { 667 continue; 668 } 669 670 SkFontID uniqueID = findUniqueIDLocked(filename); 671 SkASSERT(uniqueID != 0); 672 if (findFallbackFontIndex(uniqueID) >= 0) { 673 SkDebugf("---- system font and fallback font files specify a duplicate " 674 "font %s, skipping the second occurrence", filename); 675 continue; 676 } 677 678 SkDEBUGF(("---- reload %s as fallback[%d] fontID %d\n", 679 filename, gFallbackFonts.count(), uniqueID)); 680 681 *gFallbackFonts.append() = uniqueID; 682 break; // The fallback set contains only the first font of each family 683 } 684 } 685 } 686 687 fallbackFamilies.deleteAll(); 688 } 689 690 static void loadSystemFontsLocked() { 691 #if !defined(SK_BUILD_FOR_ANDROID_NDK) 692 static char prevLanguage[3]; 693 static char prevRegion[3]; 694 char language[3] = ""; 695 char region[3] = ""; 696 697 getLocale(language, region); 698 699 if (!gDefaultNormal) { 700 strncpy(prevLanguage, language, 2); 701 strncpy(prevRegion, region, 2); 702 initSystemFontsLocked(); 703 } else if (strncmp(language, prevLanguage, 2) || strncmp(region, prevRegion, 2)) { 704 strncpy(prevLanguage, language, 2); 705 strncpy(prevRegion, region, 2); 706 reloadFallbackFontsLocked(); 707 } 708 #else 709 if (!gDefaultNormal) { 710 initSystemFontsLocked(); 711 reloadFallbackFontsLocked(); 712 } 713 #endif 714 } 715 716 /////////////////////////////////////////////////////////////////////////////// 717 718 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 719 // lookup and record if the font is custom (i.e. not a system font) 720 bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); 721 stream->writeBool(isCustomFont); 722 723 if (isCustomFont) { 724 SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); 725 726 // store the length of the custom font 727 uint32_t len = fontStream->getLength(); 728 stream->write32(len); 729 730 // store the entire font in the serialized stream 731 void* fontData = malloc(len); 732 733 fontStream->read(fontData, len); 734 stream->write(fontData, len); 735 736 fontStream->unref(); 737 free(fontData); 738 // SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len); 739 740 } else { 741 const char* name = ((FamilyTypeface*)face)->getUniqueString(); 742 743 stream->write8((uint8_t)face->style()); 744 745 if (NULL == name || 0 == *name) { 746 stream->writePackedUInt(0); 747 // SkDebugf("--- fonthost serialize null\n"); 748 } else { 749 uint32_t len = strlen(name); 750 stream->writePackedUInt(len); 751 stream->write(name, len); 752 // SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); 753 } 754 } 755 } 756 757 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 758 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 759 return deserializeLocked(stream); 760 } 761 762 static SkTypeface* deserializeLocked(SkStream* stream) { 763 loadSystemFontsLocked(); 764 765 // check if the font is a custom or system font 766 bool isCustomFont = stream->readBool(); 767 768 if (isCustomFont) { 769 770 // read the length of the custom font from the stream 771 uint32_t len = stream->readU32(); 772 773 // generate a new stream to store the custom typeface 774 SkMemoryStream* fontStream = new SkMemoryStream(len); 775 stream->read((void*)fontStream->getMemoryBase(), len); 776 777 SkTypeface* face = createTypefaceFromStreamLocked(fontStream); 778 779 fontStream->unref(); 780 781 // SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len); 782 return face; 783 784 } else { 785 int style = stream->readU8(); 786 787 int len = stream->readPackedUInt(); 788 if (len > 0) { 789 SkString str; 790 str.resize(len); 791 stream->read(str.writable_str(), len); 792 793 for (int i = 0; i < gSystemFonts.count(); i++) { 794 if (strcmp(gSystemFonts[i].fFileName, str.c_str()) == 0) { 795 // backup until we hit the fNames 796 for (int j = i; j >= 0; --j) { 797 if (gSystemFonts[j].fNames != NULL) { 798 return createTypefaceLocked(NULL, 799 gSystemFonts[j].fNames[0], NULL, 0, 800 (SkTypeface::Style)style); 801 } 802 } 803 } 804 } 805 } 806 } 807 return NULL; 808 } 809 810 /////////////////////////////////////////////////////////////////////////////// 811 812 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 813 const char familyName[], 814 const void* data, size_t bytelength, 815 SkTypeface::Style style) { 816 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 817 return createTypefaceLocked(familyFace, familyName, data, bytelength, style); 818 } 819 820 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace, 821 const char familyName[], const void* data, size_t bytelength, 822 SkTypeface::Style style) { 823 loadSystemFontsLocked(); 824 825 // clip to legal style bits 826 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 827 828 SkTypeface* tf = NULL; 829 830 if (NULL != familyFace) { 831 tf = findTypefaceLocked(familyFace, style); 832 } else if (NULL != familyName) { 833 // SkDebugf("======= familyName <%s>\n", familyName); 834 tf = findTypefaceLocked(familyName, style); 835 } 836 837 if (NULL == tf) { 838 tf = findBestFaceLocked(gDefaultFamily, style); 839 } 840 841 // we ref(), since the semantic is to return a new instance 842 tf->ref(); 843 return tf; 844 } 845 846 SkStream* SkFontHost::OpenStream(uint32_t fontID) { 847 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 848 return openStreamLocked(fontID); 849 } 850 851 static SkStream* openStreamLocked(uint32_t fontID) { 852 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID); 853 SkStream* stream = tf ? tf->openStream() : NULL; 854 855 if (stream && stream->getLength() == 0) { 856 stream->unref(); 857 stream = NULL; 858 } 859 return stream; 860 } 861 862 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 863 int32_t* index) { 864 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 865 return getFileNameLocked(fontID, path, length, index); 866 } 867 868 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index) { 869 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID); 870 const char* src = tf ? tf->getFilePath() : NULL; 871 872 if (src) { 873 size_t size = strlen(src); 874 if (path) { 875 memcpy(path, src, SkMin32(size, length)); 876 } 877 if (index) { 878 *index = 0; // we don't have collections (yet) 879 } 880 return size; 881 } else { 882 return 0; 883 } 884 } 885 886 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 887 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 888 return nextLogicalFontLocked(currFontID, origFontID); 889 } 890 891 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID) { 892 loadSystemFontsLocked(); 893 894 const SkTypeface* origTypeface = findFromUniqueIDLocked(origFontID); 895 const SkTypeface* currTypeface = findFromUniqueIDLocked(currFontID); 896 897 SkASSERT(origTypeface != 0); 898 SkASSERT(currTypeface != 0); 899 900 // Our fallback list always stores the id of the plain in each fallback 901 // family, so we transform currFontID to its plain equivalent. 902 SkFontID plainFontID = findTypefaceLocked(currTypeface, SkTypeface::kNormal)->uniqueID(); 903 904 /* First see if fontID is already one of our fallbacks. If so, return 905 its successor. If fontID is not in our list, then return the first one 906 in our list. Note: list is zero-terminated, and returning zero means 907 we have no more fonts to use for fallbacks. 908 */ 909 int plainFallbackFontIndex = findFallbackFontIndex(plainFontID); 910 int nextFallbackFontIndex = plainFallbackFontIndex + 1; 911 SkFontID nextFontID; 912 if (nextFallbackFontIndex == gFallbackFonts.count()) { 913 nextFontID = 0; // no more fallbacks 914 } else { 915 const SkTypeface* nextTypeface = findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex]); 916 nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID(); 917 } 918 919 SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, " 920 "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d " 921 "=> nextFontID=%d", currFontID, origFontID, plainFontID, 922 plainFallbackFontIndex, nextFallbackFontIndex, nextFontID)); 923 return nextFontID; 924 } 925 926 /////////////////////////////////////////////////////////////////////////////// 927 928 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 929 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 930 return createTypefaceFromStreamLocked(stream); 931 } 932 933 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream) { 934 if (NULL == stream || stream->getLength() <= 0) { 935 return NULL; 936 } 937 938 // Make sure system fonts are loaded first to comply with the assumption 939 // that the font's uniqueID can be found using the findUniqueIDLocked method. 940 loadSystemFontsLocked(); 941 942 bool isFixedWidth; 943 SkTypeface::Style style; 944 945 if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { 946 SkTypeface* typeface = SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedWidth)); 947 addTypefaceLocked(typeface, NULL); 948 return typeface; 949 } else { 950 return NULL; 951 } 952 } 953 954 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 955 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path)); 956 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream); 957 // since we created the stream, we let go of our ref() here 958 stream->unref(); 959 return face; 960 } 961